Skip to content

Pod Lifecycle & Debugging: The "Cattle" Mindset

Trong Kubernetes, Pod là công dân hạng nhất, nhưng cũng là những thực thể vô thường (ephemeral). Hiểu rõ vòng đời và cách debug Pod là kỹ năng sinh tồn cơ bản nhất của một DevOps Engineer.

💡 Core Philosophy: Cattle, Not Pets

Hãy quên tư duy máy chủ vật lý (Pets) - nơi bạn đặt tên, cưng chiều và chữa bệnh cho từng server. Pod là Gia súc (Cattle) - hay đúng hơn là Disposable Worker Drones.

  • Chúng được sinh ra để làm việc.
  • Chúng không có danh tính vĩnh viễn (IP thay đổi sau mỗi lần restart).
  • Khi chúng bị bệnh (crash), chúng ta không chữa, chúng ta giết và thay thế (kill & replace).

1. The Lifecycle States (Vòng đời của Worker Drone)

Một Pod từ khi được sinh ra đến khi chết đi sẽ trải qua các trạng thái sau. Hiểu rõ trạng thái giúp bạn biết "nó đang bị kẹt ở đâu".

🟡 Pending (Hàng chờ)

Pod đã được chấp nhận bởi API Server, nhưng chưa được chạy trên Node nào.

  • Nguyên nhân thường gặp:
    • Cluster hết tài nguyên (CPU/RAM).
    • Không tìm được Node phù hợp (do Taints, Tolerations, Node Affinity).
    • Đang download Container Image (nếu Image quá nặng, nó sẽ ở Pending lâu).

🟢 Running (Đang làm việc)

Pod đã được gán vào một Node, container đã được khởi tạo và đang chạy.

  • Lưu ý: Running không có nghĩa là ứng dụng của bạn "sẵn sàng" (Ready). Nó chỉ có nghĩa là process đã start. Cần cấu hình Readiness Probe để K8s biết khi nào được phép gửi traffic vào.

Succeeded (Hoàn thành nhiệm vụ)

Tất cả container trong Pod đã chạy xong và exit với code 0.

  • Ngữ cảnh: Thường thấy ở Jobs hoặc CronJobs (Gửi email report, backup database, train AI model).

Failed (Thất bại)

Tất cả container đã terminat, và ít nhất một cái exit với code != 0.

  • Ngữ cảnh: Job chạy bị lỗi logic, code crash.

🔄 CrashLoopBackOff (Cơn ác mộng thường gặp)

Trạng thái này làm đau đầu newbie nhất. Quy trình: App start lên -> Gặp lỗi -> Chết (Crash) -> K8s restart lại -> Lại gặp lỗi -> Lại chết -> K8s restart... K8s sẽ tăng dần thời gian chờ giữa các lần restart (10s, 20s, 40s...) để tránh spam hệ thống. Đây gọi là "Back-off".

Nguyên nhân phổ biến:

  • Thiếu biến môi trường (ConfigMap/Secret).
  • Sai lệnh start (CMD/ENTRYPOINT).
  • Code lỗi (NullPointerException, Segmentation Fault).
  • Không kết nối được Database.

2. Debugging Workflow (The HPN Standard)

Khi một Pod gặp vấn đề, đừng đoán mò. Hãy tuân thủ quy trình "Tam Bộ" (3 bước) chuẩn mực sau của HPN Team.

Step 1: Check Status

Kiểm tra tổng quan xem Pod đang ở trạng thái nào.

bash
kubectl get pods
# Output:
# NAME          READY   STATUS             RESTARTS   AGE
# my-app-123    0/1     CrashLoopBackOff   5          2m

Step 2: Describe (The Truth Teller)

Lệnh quan trọng nhất để hiểu tại sao Pod ở trạng thái đó. Hãy nhìn vào phần Events ở cuối output.

bash
kubectl describe pod <pod-name>
👀 Bắt bệnh qua Events
  • Scheduled: Đã tìm được Node chưa?
  • Pulling: Đang kéo image. Nếu kẹt ở đây -> Sai tên image hoặc lỗi Authen Registry.
  • BackOff: Container start lên rồi chết ngay.
  • FailedScheduling: Không đủ RAM/CPU hoặc dính Taint.

Step 3: Logs (Tiếng nói từ bên trong)

Nếu Pod đã Running hoặc CrashLoopBackOff (tức là container đã từng chạy được), hãy xem logs của ứng dụng.

bash
kubectl logs <pod-name>
# Hoặc nếu Pod có nhiều container
kubectl logs <pod-name> -c <container-name>
# Xem logs của instance trước khi crash (Cực hữu ích cho CrashLoopBackOff)
kubectl logs <pod-name> --previous

3. Critical Rule: Never Create a Bare Pod

⛔ CẤM KỴ (Rule #1)

Không bao giờ được tạo một Pod lẻ loi (Bare Pod) bằng cách viết file YAML kind: Pod.

Tại sao? Pod lẻ loi không có khả năng tự phục hồi (Self-healing).

  • Nếu Node chết -> Pod chết theo (và biến mất vĩnh viễn).
  • Nếu lỡ tay xóa Pod -> Nó mất luôn.

Giải pháp: Luôn sử dụng Controller để quản lý Pod.

  • Deployment: Cho Stateless Apps (Web, API). Tự động tạo lại Pod mới nếu cái cũ chết.
  • StatefulSet: Cho Database, Queue.
  • Job/CronJob: Cho tác vụ chạy một lần.

Hãy nhớ: Bạn ra lệnh cho Controller (Tướng quân), và Controller quản lý Pods (Lính). Đừng đi vi mô từng người lính.


4. Interactive: Spot the Bug 🐛

Tình huống: Bạn deploy một con Web App xịn xò, nhưng nó cứ mãi ở trạng thái Pending. Bạn chạy kubectl describe pod web-app-xyz và thấy Event sau:

Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  1m    default-scheduler  0/3 nodes are available: 3 node(s) had taint {key: "gpu-intensive", effect: "NoSchedule"}, that the pod didn't tolerate.
🕵️‍♂️ Phân tích & Giải pháp (Bấm để xem)

Bệnh: Pod bị kẹt vì không có "Vé vào cửa" (Toleration).

Nguyên nhân: Cluster của bạn có 3 Node, và cả 3 đều bị đánh dấu (Taint) là gpu-intensive (chắc là dàn máy đào coin của sếp). Pod của bạn là dân thường, không có khai báo tolerations để chấp nhận taint này.

Giải pháp:

  1. Cách 1 (Clean): Xóa taint trên Node nếu không cần thiết. kubectl taint nodes --all key-
  2. Cách 2 (Proper): Thêm tolerations vào Pod Spec để nó chịu được môi trường này.
    yaml
    tolerations:
    - key: "gpu-intensive"
      operator: "Exists"
      effect: "NoSchedule"