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?
Để 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 -v
Hoặc thực thi câu lệnh shell ở trên container.
kubectl exec -it <pod-name> -- sh
Mọ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> -- sh
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown
Cò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=Never
Ta sẽ không thế chạy câu lệnh exec được.
$ kubectl exec -it pod-not-debug-tool -- sh
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown
Ta có thể sử dụng ephemeral container để debug nó như sau.
kubectl debug pod-not-debug-tool --image=busybox --target=pod-not-debug-tool
Vớ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ằngkubeadm
thì ta phải thêm thuộc tính--feature-gates=EphemeralContainers=true
vào khi khởi tạo Cluster. Và thuộc tính--target
phả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 -- false
Kiểm tra thì ta sẽ thấy nó bị CrashLoopBackOff.
kubectl describe pod pod-crashed
Containers:
myapp:
Image: busybox
...
Args:
false
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 1
Ta sẽ chạy câu lệnh sau để debug nó.
kubectl debug pod-crashed -it --copy-to=pod-crashed-debug --container=container-crashed-debug -- sh
If 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 1d
Ví 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=*=ubuntu
Cú 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
Nếu bài viết có gì sai hoặc cần cập nhật thì liên hệ Admin.
Tham gia nhóm chat của DevOps VN tại Telegram.
Kém tiếng Anh và cần nâng cao trình độ giao tiếp: Tại sao bạn học không hiệu quả?