← กลับ
KubernetesTroubleshootingkubectlDebugging

Kubernetes เข้า Pod ไม่ได้ (kubectl exec fail) ต้องไล่อะไรบ้าง

kubectl exec ค้าง / error / connection refused — สาเหตุที่เป็นไปได้และเช็คที่ pod, kubelet, container runtime ตามลำดับ

2025-12-05อ่าน 6 นาทีใหม่

อาการที่เจอ

$ kubectl exec -it myapp-abc123 -- sh
error: Internal error occurred: error executing command in container:
       failed to exec in container: container is in CONTAINER_EXITED state

หรือ:

$ kubectl exec -it myapp-abc123 -- sh
Error from server: error dialing backend: dial tcp 10.0.0.5:10250: i/o timeout

หรือ:

$ kubectl exec -it myapp-abc123 -- sh
OCI runtime exec failed: exec failed: unable to start container process:
   exec: "sh": executable file not found in $PATH

แต่ละ error มาจากคนละสาเหตุ — ต้องอ่าน message ก่อน

ลำดับสิ่งที่ต้องตรวจ

1. Pod ยังรันอยู่หรือเปล่า

kubectl get pod myapp-abc123 -n production

ถ้า:

  • Running 1/1 → pod ทำงานปกติ
  • Running 0/1 → ไม่ ready แต่ exec ได้
  • CrashLoopBackOff → container crash ทุกครั้งที่ start
  • Terminating → กำลังปิด ไม่รับ exec แล้ว
  • Completed → จบไปแล้ว exec ไม่ได้
# ดู status ละเอียด
kubectl describe pod myapp-abc123 -n production

2. Container ใน pod ตอนนี้คืออะไร

kubectl get pod myapp-abc123 -o jsonpath='{.status.containerStatuses[*].name}'

ถ้า pod มีหลาย container — ระบุชื่อ:

kubectl exec -it myapp-abc123 -c <container-name> -- sh

ถ้าไม่ระบุ — exec เข้า container แรก

3. Image มี shell มั้ย

Image base ต่างๆ:

  • alpine/bin/sh (ash)
  • ubuntu / debian/bin/bash
  • distrolessไม่มี shell เลย
  • scratch → ไม่มีอะไรเลย

ถ้าได้:

exec: "sh": executable file not found in $PATH

→ image ไม่มี shell ลอง:

kubectl exec -it myapp-abc123 -- /bin/bash
kubectl exec -it myapp-abc123 -- /bin/ash
kubectl exec -it myapp-abc123 -- /bin/sh

# ถ้า distroless รัน command ตรงๆ
kubectl exec -it myapp-abc123 -- ls /app

4. ใช้ ephemeral debug container

distroless image — ใช้ kubectl debug:

kubectl debug myapp-abc123 -it \
  --image=nicolaka/netshoot \
  --target=app

--target=app = share namespace กับ container ชื่อ app ใน pod

  • เห็น process ของ container เป้าหมาย
  • เข้า network เดียวกัน

ทำงานบน K8s 1.23+

5. RBAC permission

$ kubectl exec -it myapp-abc123 -- sh
Error from server (Forbidden): pods "myapp-abc123" is forbidden:
  User "developer" cannot create resource "pods/exec"

ตรวจ:

kubectl auth can-i create pods/exec --as=developer -n production

ถ้า no — เพิ่ม role:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-exec
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]

ปัญหาที่ deeper

kubelet ตอบไม่ได้

$ kubectl exec -it myapp-abc123 -- sh
Error from server: error dialing backend: dial tcp 10.0.0.5:10250: i/o timeout

apiserver พยายามต่อ kubelet ที่ port 10250 แต่เชื่อมไม่ได้

ตรวจ:

# 1. node ที่ pod อยู่ Ready มั้ย
kubectl get node $(kubectl get pod myapp-abc123 -o jsonpath='{.spec.nodeName}')

# 2. SSH เข้า node ตรวจ kubelet
ssh <node>
sudo systemctl status kubelet
sudo journalctl -u kubelet -n 50

# 3. ตรวจว่า apiserver เห็น kubelet
kubectl get --raw /api/v1/nodes/<node-name>/proxy/healthz

ถ้า kubelet ตาย:

sudo systemctl restart kubelet

Network ระหว่าง apiserver กับ node

# จาก master node
nc -zv <worker-node-ip> 10250

ถ้าเชื่อมไม่ได้ — firewall block port 10250 ระหว่าง master กับ worker

แก้ที่ firewall ให้อนุญาต port 10250 จาก master

Container Runtime ปัญหา

$ kubectl exec -it myapp-abc123 -- sh
error: Internal error: container runtime not ready

ที่ node:

sudo systemctl status containerd
# หรือ
sudo systemctl status docker

restart ถ้าตาย:

sudo systemctl restart containerd

Resource exhaustion

ถ้า node CPU/memory เต็ม — apiserver request timeout

kubectl top node <node-name>
kubectl describe node <node-name> | grep -A 3 -i pressure

ทางเลือก: เข้า node แล้วใช้ crictl

ถ้า kubectl exec ไม่ได้ — SSH เข้า node แล้วใช้ container runtime ตรงๆ:

ssh <node>

# หา container ID
sudo crictl ps | grep myapp

# exec
sudo crictl exec -it <container-id> sh

หรือ Docker:

sudo docker ps | grep myapp
sudo docker exec -it <container-id> sh

วิธีนี้ bypass apiserver — ใช้เมื่อ apiserver / kubelet มีปัญหา

ทางเลือก: kubectl debug

K8s 1.23+ มี kubectl debug:

# สร้าง debug container ใน pod เดิม share namespace
kubectl debug myapp-abc123 -it \
  --image=busybox \
  --target=app

# clone pod เป็น debug version
kubectl debug myapp-abc123 -it \
  --copy-to=myapp-debug \
  --container=app \
  --image=ubuntu

ดี: distroless image ก็ debug ได้, ทดสอบโดยไม่กระทบ pod จริง

TTY / stdin issue

$ kubectl exec myapp-abc123 -- sh
# (no error but no prompt)

ลืม -it:

kubectl exec -it myapp-abc123 -- sh

-i = interactive (stdin) -t = TTY allocate

ใช้ pipe:

echo "ls" | kubectl exec -i myapp-abc123 -- sh

Container exited แล้ว

$ kubectl exec myapp-abc123 -- sh
container "app" in pod "myapp-abc123" is waiting to start: ContainerCreating

→ container ยังไม่ start เสร็จ — รอสักครู่

$ kubectl exec myapp-abc123 -- sh
error: container "app" in pod "myapp-abc123" is not running: terminated

→ container ตายไปแล้ว — exec เข้าไม่ได้

ดู log แทน:

kubectl logs myapp-abc123 --previous

Cheat Sheet: เจอ error → ทำอะไร

| Error | สาเหตุ | แก้ | |---|---|---| | executable file not found | image ไม่มี shell | ใช้ kubectl debug หรือ command ตรง | | pods/exec is forbidden | RBAC | ขอ role pod-exec | | dial tcp ... i/o timeout | apiserver ↔ kubelet | ตรวจ network port 10250 | | container runtime not ready | containerd/docker ตาย | restart runtime | | is not running | container ตาย | ดู log แทน, fix crash | | is waiting to start | ยังไม่ start เสร็จ | รอ หรือดู event |

TLDR

  1. ตรวจ pod status ก่อน — kubectl get pod
  2. ตรวจ image มี shell มั้ย — ลอง /bin/sh, /bin/bash, /bin/ash
  3. ใช้ kubectl debug ถ้า distroless
  4. ตรวจ RBAC ถ้า forbidden
  5. ตรวจ kubelet + network ถ้า i/o timeout
  6. Bypass ด้วย SSH + crictl ถ้า apiserver/kubelet พัง

สรุป

kubectl exec ใช้ chain ยาว: apiserver → kubelet → container runtime → container ปัญหาเกิดได้ที่ link ใดก็ได้

อ่าน error message เป็นอย่างแรก — ส่วนใหญ่บอก root cause ตรงๆ

ถ้าจริงๆ exec เข้าไม่ได้เลย — kubectl debug หรือ SSH + crictl เป็น backup ที่ยังใช้งานได้ตอนวิกฤต

อ่านต่อ: Troubleshooting K8s Step-by-Step

← ดูบทความอื่น