← กลับ
KubernetesNetworkingTroubleshootingCNI

Ping ไม่ได้ 100% Packet Loss ใน Kubernetes Debug ยังไง

pod ใน cluster ping pod อื่นไม่ติด แต่ HTTP กลับใช้ได้ — สาเหตุที่เป็นไปได้และเช็คทีละขั้นตามลำดับเวลาที่ใช้น้อยสุด

2025-12-01อ่าน 5 นาทีใหม่

อาการ

$ kubectl exec -it pod-a -- ping pod-b-ip
PING 10.244.2.5: 56 data bytes
^C
--- 10.244.2.5 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss

ping ไม่เข้า — แต่ลอง:

$ kubectl exec -it pod-a -- curl http://pod-b:8080/
{"status": "ok"}

HTTP ใช้ได้! ทำไม ping ไม่ได้แต่ HTTP ผ่าน?

สาเหตุที่พบบ่อย

1. CNI plugin block ICMP

CNI บางตัว (เช่น Cilium, Calico ที่ตั้ง strict policy) — block ICMP โดย default แต่อนุญาต TCP/UDP บางตัวผ่าน

ตรวจสอบ:

# ดู CNI ที่ใช้
kubectl get pods -n kube-system | grep -E "calico|cilium|flannel|weave"

2. NetworkPolicy block ICMP

Manifest ที่ allow protocol: TCP อย่างเดียวจะ implicit deny ICMP:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-except-http
spec:
  podSelector:
    matchLabels:
      app: pod-b
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: pod-a
      ports:
        - protocol: TCP
          port: 8080

policy นี้ — TCP 8080 ผ่าน, ICMP block หมด

ตรวจสอบ:

kubectl get networkpolicy --all-namespaces
kubectl describe networkpolicy <name> -n <ns>

3. Container image ไม่มี ping command

alpine image base ไม่มี ping ต้องลงเอง:

$ kubectl exec -it pod-a -- ping
sh: ping: not found

ลองเช็ค:

kubectl exec -it pod-a -- which ping

ถ้าไม่มี — ใช้ tool อื่นแทน:

# nc (netcat) ทดสอบ TCP
kubectl exec -it pod-a -- nc -zv pod-b-ip 8080

# wget
kubectl exec -it pod-a -- wget -O- http://pod-b:8080

4. Pod ไม่มี privilege ส่ง raw socket

ICMP ใช้ raw socket — บาง pod รันด้วย user ที่ไม่ใช่ root + ไม่มี CAP_NET_RAW capability ส่ง ping ไม่ได้

ตรวจสอบ securityContext:

kubectl get pod pod-a -o yaml | grep -A 5 securityContext

ถ้าเป็นแบบนี้:

securityContext:
  runAsUser: 1000
  capabilities:
    drop: ["ALL"]

→ ping ไม่ได้แน่นอน (และดีแล้ว — production ควรเป็นแบบนี้)

5. CoreDNS / DNS ปัญหา

$ kubectl exec -it pod-a -- ping pod-b
ping: bad address 'pod-b'

= DNS resolve ไม่ได้ ดู NSLookup / DNS Debug

6. iptables / ipvs rule ผิดปกติ

ตรวจ rule บน node ที่ pod อยู่:

# หา node ของ pod
kubectl get pod pod-b -o wide

# SSH เข้า node แล้ว
sudo iptables -L -n -v | grep -i drop
sudo iptables -t nat -L -n

CNI ใหม่ (Cilium) ใช้ eBPF แทน iptables — ตรวจด้วย:

cilium connectivity test

Debug Flow ที่แนะนำ

Step 1: ทดสอบด้วย tool ที่ไม่ใช้ ICMP

# TCP ทดสอบ port
kubectl exec -it pod-a -- sh -c "nc -zv pod-b 8080"

# DNS ทดสอบ
kubectl exec -it pod-a -- nslookup pod-b

ถ้าทั้งหมดผ่าน → ไม่มีปัญหา network จริง — ICMP block อย่างเดียว

Step 2: ใช้ debug pod

ถ้า image production ไม่มี tool — spin pod ใหม่ที่มี:

kubectl run -it --rm debug --image=nicolaka/netshoot --restart=Never -- bash

netshoot มี: ping, curl, nc, dig, tcpdump, mtr, nslookup, ปอด tool ทุกตัว

# ใน debug pod
ping pod-b.default.svc.cluster.local
curl -v http://pod-b.default.svc.cluster.local:8080
mtr pod-b.default.svc.cluster.local

Step 3: ถ้าจริงๆ network down — ตรวจที่ node

# SSH เข้า node ที่ pod-a อยู่
NODE=$(kubectl get pod pod-a -o jsonpath='{.spec.nodeName}')

# ตรวจ pod's IP routable มั้ย
ssh $NODE
ip route
ping <pod-b-ip>   # จาก node

ถ้า node ตรงๆ ก็ ping ไม่เจอ — CNI overlay มีปัญหา

# ตรวจ CNI pod
kubectl get pods -n kube-system -l k8s-app=calico-node
kubectl logs -n kube-system <calico-pod> --previous

Step 4: ดู NetworkPolicy ที่อาจ block

kubectl get networkpolicy --all-namespaces

ลอง delete ชั่วคราว (dev cluster เท่านั้น!) เพื่อ confirm:

kubectl delete networkpolicy deny-all-except-http -n default
# ลอง ping อีกที

ถ้าทำงานได้ → policy block อยู่ — เพิ่ม rule ICMP:

ingress:
  - from:
      - podSelector:
          matchLabels:
            app: pod-a
    ports:
      - protocol: TCP
        port: 8080
  - from:
      - podSelector: {}
    # ICMP ไม่มี protocol ใน NetworkPolicy ปกติ ต้องใช้ Cilium / Calico extended

หมายเหตุ: Standard Kubernetes NetworkPolicy v1 รองรับแค่ TCP/UDP/SCTP — ไม่มี ICMP ต้องใช้ Cilium policy หรือ Calico GlobalNetworkPolicy

ตัวอย่าง Calico policy ที่อนุญาต ICMP:

apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-icmp
spec:
  selector: app == 'pod-b'
  ingress:
    - action: Allow
      protocol: ICMP

เครื่องมือที่ควรมีใน toolbox

| Tool | ใช้ทำอะไร | |---|---| | ping | ICMP echo | | nc -zv | TCP/UDP port check | | nslookup / dig | DNS query | | curl -v | HTTP request + verbose | | mtr | traceroute + ping continuous | | tcpdump | sniff packet (ต้อง privileged) | | iperf3 | throughput test |

netshoot image รวมไว้หมด — ตั้งเป็น debug pod ประจำ

เช็คลิสต์ TLDR

1. ลองด้วย nc / curl ก่อน — ไม่ใช่แค่ ping
2. เช็คว่า image มี ping มั้ย (ใช้ netshoot ถ้าไม่มี)
3. ดู NetworkPolicy block ICMP มั้ย
4. ดู securityContext มี CAP_NET_RAW มั้ย
5. ดู CNI plugin (Calico / Cilium) policy
6. SSH เข้า node ทดสอบ ping ตรงๆ
7. ตรวจ CNI pod logs

สรุป

อาการ "ping ไม่ติด แต่ HTTP ใช้ได้" เกือบทั้งหมดไม่ใช่ปัญหา network จริง — เป็น policy block ICMP

อย่าใช้ ping เป็นเครื่องมือ debug หลักใน Kubernetes — nc กับ curl บอกอะไรได้ตรงกว่า

ตั้ง debug pod (netshoot) ไว้ใน cluster ตอนต้องการ debug — เร็วกว่าการลงเครื่องมือใน image production

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