Giới thiệu
Thông thường để debug Pod ở trên Kubernetes, ta thường sẽ dùng câu lệnh kubectl logs để xem logs lỗi hoặc dùng câu lệnh kubectl exec để ta có thể chạy câu lệnh ở bên trong container. Nhưng nếu ta gặp trường hợp container không có hỗ trợ shell, curl, bash hoặc container của ta ở trạng thái CrashLoopBackOff thì ta sẽ debug như thế nào?
Mục lục
- Debug Running Pods
- Container logs
- Container exec
- Debugging with an Ephemeral Debug Container
- Copying a Pod while changing its command
- Copying a Pod while changing container images
- Kết luận
- Bài viết liên quan
Để giải quyết vấn đề trên thì Kubernetes từ bản 1.23 đã cung cấp cho ta một tính năng đó là Ephemeral Debug Container.
Trước khi tìm hiểu về Ephemeral Container, ta sẽ xem qua các cách debug thông dụng ta hay xài.
Debug Running Pods
Container logs
Cách đầu tiên và thông dụng nhất là ta sử dụng câu lệnh logs, như sau.
kubectl logs ${POD_NAME} ${CONTAINER_NAME}Câu lệnh trên sẽ liệt kê toàn bộ logs của container ra, và ta sẽ kiểm tra logs để debug. Nếu ta muốn xem logs của container trước đó, ta thêm thuộc tính --previous vào.
kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}Container exec
Cách thứ hai mà ta hay xài là dùng câu lệnh kubectl exec, như sau.
kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}Nó sẽ cho phép ta thực thi câu command lên trên container của Pod đang chạy. Ví dụ ta muốn thực thi câu lệnh vào một Pod đang chạy NodeJS.
kubectl exec -it <pod-name> -- node -vHoặc thực thi câu lệnh shell ở trên container.
kubectl exec -it <pod-name> -- shMọi chuyện có vẻ ổn, nhưng nếu ta gặp trường hợp như ta đã nói ở đầu bài là container chạy không có hỗ trợ công cụ debug như shell, curl, bash hoặc container của ta ở trạng thái CrashLoopBackOff thì ta không thể dùng câu lệnh kubectl exec được, vì nó sẽ báo lỗi như bên dưới.
kubectl exec -it <pod-not-shell> -- shOCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknownCòn đối với Pod mà ở trang thái CrashLoopBackOff thì ta không thể thực hiện câu lệnh exec lên nó được luôn. Do đó để giải quyết vấn đề này và để việc debug dễ dàng hơn, Kubernetes cho ra một tính năng là Ephemeral Debug Container.
Debugging with an Ephemeral Debug Container
Đây là tính năng được giới thiệu ở Kubernetes bản 1.16 và ở bản 1.23 thì Ephemeral Debug Container đã được ra mắt với phiên bản beta.
Ta sẽ chạy câu lệnh kubectl debug để tạo một ephemeral container giúp ta debug container chính. Ví dụ ta có một container sau và nó sẽ không có hỗ trợ công cụ debug như shell, bash.
kubectl run pod-not-debug-tool --image=k8s.gcr.io/pause:3.1 --restart=NeverTa sẽ không thế chạy câu lệnh exec được.
$ kubectl exec -it pod-not-debug-tool -- shOCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknownTa có thể sử dụng ephemeral container để debug nó như sau.
kubectl debug pod-not-debug-tool --image=busybox --target=pod-not-debug-toolVới giá trị sau debug sẽ là tên của container, và giá trị sau --target sẽ là tên của Pod, và --image là tên image ta sẽ xài. Sau khi chạy câu lệnh trên thì terminal của ta sẽ hiển thị command promp của debug container, ta có thể dùng nó để debug container chính.
Defaulting debug container name to debugger-8xzrl.
If you don't see a command prompt, try pressing enter.
/ #Lưu ý một điểm là khi ta xài tính năng này thì khi khởi tạo Kubernetes Cluster ta phải bật nó lên, ví dụ Cluster của ta được tạo bằngkubeadmthì ta phải thêm thuộc tính--feature-gates=EphemeralContainers=truevào khi khởi tạo Cluster. Và thuộc tính--targetphải được hỗ trợ bởi Container Runtime.
Cách ở trên là ta dùng cho việc debug container mà không có công cụ debug, còn để debug container mà ở trạng CrashLoopBackOff, thì ta sẽ sử dụng ephemeral container theo một cách khác.
Copying a Pod while changing its command
Trong một số trường hợp container trong Pod của ta không thể chạy được, nó bị crash trước khi khởi động, thì dưới đây là cách ta sử dụng để debug các Pod mà ở trạng thái CrashLoopBackOff.
Ví dụ ta chạy Pod sau mà nó sẽ bị crash.
kubectl run pod-crashed --image=busybox -- falseKiểm tra thì ta sẽ thấy nó bị CrashLoopBackOff.
kubectl describe pod pod-crashedContainers:
myapp:
Image: busybox
...
Args:
false
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 1Ta sẽ chạy câu lệnh sau để debug nó.
kubectl debug pod-crashed -it --copy-to=pod-crashed-debug --container=container-crashed-debug -- shIf you don't see a command prompt, try pressing enter.
/ #Câu lệnh trên nó sẽ sao chép container pod-crashed vào trong container container-crashed-debug của pod-crashed-debug, và ta chạy câu lệnh sh ở trong container-crashed-debug để debug.
Copying a Pod while changing container images
Sẽ có một vài trường hợp là container ta chạy không đủ công cụ giúp ta debug một container crashed, thì ta có thể sao chép nó với một image khác mà có nhiều công cụ debug hơn. Ví dụ như sau:
kubectl run pod-crashed-two --image=busybox --restart=Never -- sleep 1dVí dụ trong busybox sẽ không có công cụ nslookup để ta debug DNS Server, ta có thể sao chép nó sang một image khác mà có sẵn công cụ nslookup, như là ubuntu chẳng hạn.
kubectl debug pod-crashed-two --copy-to=pod-crashed-debug-two --set-image=*=ubuntuCú pháp --set-image sẽ thay đổi image của toàn bộ container trong Pod đó thành ubuntu.
Kết luận
Vậy là chúng ta đã tìm hiểu xong về cách debug Pod dùng Ephemeral Container, đây là tip mà mình thấy là rất hữu ích cho việc debug trên môi trường production 😁, chỉ có cái là nó đang ở bản beta với không phải Kubernetes Cluster nào cũng hỗ trợ sẵn 😥. Nếu có thắc mắc hoặc cần giải thích ở chỗ nào thì các bạn hỏi ở đây nha: bình luận.
Cập nhật: Ephemeral Container đã stable ở phiên bản 1.25
Tác giả @Quân Huỳnh
First AI Journey for DevOps:
- PromptOps: From YAML to AI
- The DevOps AI Advantage
- The AIOps Book