← กลับ
KubernetesControl PlaneTroubleshootingProduction

kube-apiserver ล่ม ส่งผลอะไรกับ Cluster บ้าง

API server เป็นหัวใจของ K8s — ตายแล้ว pod ที่รันอยู่ทำงานต่อมั้ย? scale, deploy, kubectl ทำอะไรไม่ได้บ้าง? วิธีกู้คืน

2026-04-22อ่าน 7 นาทีใหม่

API server ทำหน้าที่อะไร

API server = gateway เดียว ของทุกการสื่อสารใน K8s

ทุก action — kubectl, controller, kubelet, scheduler — ส่ง request ผ่าน API server และ API server เขียนเข้า etcd

kubectl ─→ API server ─→ etcd (data store)
                  ↑
           kubelet ─┘
           controller-manager
           scheduler

ถ้า API server ล่ม → ทุก component คุยกันไม่ได้

ผลกระทบเมื่อ API server ล่ม

✅ สิ่งที่ยังทำงานต่อ

  • Pod ที่รันอยู่ — ยัง run ปกติ traffic ผ่าน Service ที่ kube-proxy ตั้ง iptables ไว้แล้ว
  • Service routing — kube-proxy ใช้ rule ที่อยู่บน node ไม่ต้องถาม API server ทุก request
  • Ingress controller — ไม่กระทบ ทำงานต่อ
  • DNS resolution (CoreDNS) — ทำงานต่อด้วย config ที่ load ไว้

ผู้ใช้ปลายทางอาจไม่รู้สึกอะไร — ถ้า traffic ไปที่ pod ที่ healthy อยู่

❌ สิ่งที่หยุด

  • kubectl ใช้ไม่ได้:
    Unable to connect to the server: dial tcp 10.0.0.1:6443: connect: connection refused
    
  • Deploy ใหม่ไม่ได้ — apply manifest ทำไม่ได้
  • Auto-scale (HPA) — ไม่ทำงาน metric ส่งไม่ได้
  • Pod ที่ตายไม่ replace — controller scaling ไม่ได้
  • Liveness probe fail = restart pod — kubelet ตัดสินใจเอง (ทำงาน)
  • แต่ — ถ้า node ตาย pod บน node ตายตามไปด้วย controller ไม่รู้ — ไม่ schedule pod ใหม่
  • Secret/ConfigMap update — pod ใหม่อ่านไม่ได้
  • kubelet renew lease — ถ้านานเกินไป — node ถูก mark NotReady

ตรวจสอบว่า API server ล่ม

$ kubectl get nodes
The connection to the server 10.0.0.1:6443 was refused

หรือ:

Error from server: etcdserver: request timed out

SSH เข้า master node:

sudo systemctl status kubelet
ps aux | grep kube-apiserver
sudo journalctl -u kubelet -n 100

ถ้า kube-apiserver เป็น static pod (kubeadm install):

sudo crictl ps -a | grep apiserver
sudo crictl logs <container-id>

สาเหตุที่เป็นไปได้

1. etcd ตอบไม่ทัน / ตาย

API server ต้อง เขียน etcd ทุก request — etcd ช้า/ตาย = API server hang

# บน master node
sudo systemctl status etcd      # ถ้าเป็น systemd service
# หรือ
sudo crictl ps -a | grep etcd
sudo crictl logs <etcd-container>

ตรวจ etcd health:

sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
  --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
  endpoint health

ผลที่ดี:

https://127.0.0.1:2379 is healthy

ถ้า unhealthy — etcd มีปัญหา (disk เต็ม, quorum หาย ใน multi-master)

2. Disk เต็ม

API server / etcd ต้องเขียน disk

df -h /var/lib/etcd
df -h /var/log

ถ้าเต็ม:

# Compact etcd
sudo ETCDCTL_API=3 etcdctl ... compact <revision>

# Defrag
sudo ETCDCTL_API=3 etcdctl ... defrag

# ลบ log
sudo journalctl --vacuum-size=500M

3. Certificate หมดอายุ

sudo kubeadm certs check-expiration

ถ้า apiserver cert หมด — ดู K8s Cert Expired

4. Memory / CPU เต็มที่ master

free -h
top -b -n 1 | head -20

API server กิน RAM ตามจำนวน object — cluster ใหญ่ต้อง > 4GB

แก้: เพิ่ม RAM master, หรือเอา pod ของ workload ออกจาก master

5. Network problem

API server bind ที่ port 6443:

sudo ss -tlnp | grep 6443

ถ้าไม่มี — process ตาย ถ้ามี — firewall block

sudo ufw status
sudo iptables -L INPUT -n | grep 6443

6. Manifest ผิดของ static pod

API server เป็น static pod — kubelet load จาก /etc/kubernetes/manifests/kube-apiserver.yaml

ถ้าใครเผลอแก้ไฟล์นี้ผิด:

sudo journalctl -u kubelet -n 50 | grep -i apiserver

จะเห็น error ของ manifest

วิธีกู้

Step 1: ตรวจจุดที่พัง

ssh <master-node>

# ตรวจ kubelet
sudo systemctl status kubelet

# ตรวจ static pod
sudo crictl ps -a | grep -E "apiserver|etcd|controller|scheduler"

# ดู log
sudo crictl logs <apiserver-container-id>

Step 2: ลอง restart kubelet ก่อน

sudo systemctl restart kubelet

Kubelet จะ recreate static pod ที่หายไป

ดูว่า pod กลับมามั้ย:

sudo crictl ps | grep apiserver

Step 3: ถ้า manifest ผิด — restore

# ถ้ามี backup ก่อนหน้า
sudo cp /etc/kubernetes.bak/manifests/kube-apiserver.yaml \
        /etc/kubernetes/manifests/kube-apiserver.yaml

# kubelet จะ apply อัตโนมัติ

Step 4: ถ้า etcd พัง — restore จาก backup

# stop apiserver static pod
sudo mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/

# restore etcd
sudo ETCDCTL_API=3 etcdctl snapshot restore \
  /var/lib/etcd-backup/snapshot.db \
  --data-dir=/var/lib/etcd-restored

# stop etcd
sudo mv /etc/kubernetes/manifests/etcd.yaml /tmp/

# replace data
sudo mv /var/lib/etcd /var/lib/etcd.old
sudo mv /var/lib/etcd-restored /var/lib/etcd

# start back
sudo mv /tmp/etcd.yaml /etc/kubernetes/manifests/
sudo mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/

Multi-master HA — ป้องกัน single point of failure

cluster ที่ critical — 3 master นn HA:

              Load Balancer (HAProxy / keepalived)
                       │
        ┌──────────────┼──────────────┐
        ▼              ▼              ▼
   API server 1   API server 2   API server 3
   etcd 1         etcd 2         etcd 3

LB ที่ port 6443 — ถ้า master 1 ตาย → traffic ไป 2 + 3

etcd cluster ต้อง majority alive (3 → ทน 1 ตาย) ถึงจะรับ write

Backup ที่จำเป็น

ทุก master ต้อง backup:

1. etcd snapshot

sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save /var/backups/etcd-$(date +%F).db

ตั้ง cron ทุกวัน:

0 2 * * * /usr/local/bin/backup-etcd.sh

2. /etc/kubernetes ทั้งหมด

sudo tar czf /var/backups/kubernetes-$(date +%F).tar.gz /etc/kubernetes

3. /var/lib/kubelet

sudo tar czf /var/backups/kubelet-$(date +%F).tar.gz /var/lib/kubelet

ส่งทั้งหมดไป S3 / B2 / external — อ่าน Database backup

Monitoring

ตั้ง alert:

# Prometheus alert
- alert: KubeAPIDown
  expr: absent(up{job="apiserver"}) == 1
  for: 5m
  labels:
    severity: critical
  annotations:
    summary: "API server down"

- alert: KubeAPIHighLatency
  expr: histogram_quantile(0.99, rate(apiserver_request_duration_seconds_bucket[5m])) > 1
  for: 10m

หรือ external monitor (ดูจากนอก cluster):

# Uptime Kuma — TCP check 6443
curl -k https://master-lb:6443/healthz

คำสั่ง ที่ใช้บ่อยตอน emergency

# 1. ดู health
kubectl get --raw /healthz

# 2. ดู component status
kubectl get componentstatuses

# 3. ดู events ทั้ง cluster
kubectl get events -A --sort-by='.lastTimestamp' | tail -30

# 4. ดู API server log
sudo crictl logs $(sudo crictl ps -q --name kube-apiserver) --tail=100

# 5. force restart kubelet (recreate static pod)
sudo systemctl restart kubelet

# 6. test etcd
sudo ETCDCTL_API=3 etcdctl ... endpoint status -w table

Lessons Learned

  1. API down ≠ workload down — pod ยังทำงาน user ส่วนใหญ่ไม่กระทบ
  2. etcd backup คือ insurance — ทำทุกวัน ทดสอบ restore เป็นระยะ
  3. HA = 3 master ไม่ใช่ 2 (quorum ของ 2 = 2 ตายไป 1 = หยุด)
  4. Monitor จากนอก — Prometheus ใน cluster ไม่ส่ง alert ถ้าทั้ง cluster ล่ม
  5. Cert expiration ป้องกันด้วย cron renew + alert
  6. เพิ่ม RAM master ตามจำนวน object — cluster ใหญ่ต้อง 8GB+

TLDR

API server ตาย:

  • ✅ Pod ที่รันอยู่ทำงานต่อ
  • ❌ Deploy / scale / kubectl หยุด
  • ❌ Pod ใหม่ที่ควร schedule ไม่ขึ้น
  • ❌ Auto-recovery ไม่ทำงาน

แก้:

  1. Restart kubelet
  2. ดู static pod log
  3. ตรวจ etcd, disk, cert, network
  4. ถ้าจริง ๆ พัง — restore จาก backup

สรุป

API server เป็น single point of failure ใน cluster แบบ single master — ทำให้ HA ตั้งแต่แรกถ้า cluster สำคัญ

ถ้าทำ HA ไม่ได้ — backup etcd รายวัน + monitor + รู้ขั้นตอนกู้ =พอ

อ่านต่อ: Troubleshooting K8s Step-by-Step — checklist สำหรับ debug

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