Pod: Đơn Vị Nhỏ Nhất Trong Kubernetes

K
Kai··5 min read

Người mới thường tưởng đơn vị nhỏ nhất Kubernetes quản lý là container. Không hẳn — đó là Pod. Hiểu đúng pod ngay từ đầu giúp bạn tránh nhầm lẫn về sau, vì gần như mọi thứ trong Kubernetes (Deployment, Service, Job...) cuối cùng đều quy về "chạy pod thế nào".

Pod là gì

Pod là một nhóm gồm một hoặc nhiều container chạy cùng nhau, chia sẻ:

  • Cùng một network namespace — các container trong pod dùng chung một địa chỉ IP, gọi nhau qua localhost.
  • Có thể chia sẻ volume — cùng truy cập một vùng lưu trữ.
  • Cùng vòng đời — được lên lịch cùng nhau lên một node, sinh ra và mất đi cùng nhau.
   ┌──────────── POD (1 IP: 10.244.0.5) ────────────┐
   │                                                │
   │   [container chính]   [container phụ (sidecar)] │
   │         │  cùng localhost, cùng volume  │       │
   │         └──────────────┬────────────────┘       │
   └────────────────────────┼────────────────────────┘
                            ▼
                   chạy trên một node

Phần lớn pod chỉ có một container — đó là trường hợp thường gặp. Nhưng mô hình "nhiều container một pod" hữu ích cho pattern sidecar: ví dụ một container chạy app, một container phụ đẩy log hoặc làm proxy, hai cái cần dùng chung localhost và đĩa. Điểm cốt lõi: container trong cùng pod thân mật với nhau như hai tiến trình trên cùng một máy.

Một pod là phù du (ephemeral). Nó không "bền". Khi pod chết hoặc node hỏng, pod đó không sống lại — một pod mới (IP khác, tên khác) sẽ thay thế nếu có ai đó quản lý nó. Ý này dẫn thẳng tới Deployment ở Bài 4.

Viết pod bằng YAML

Lệnh kubectl run ở Bài 2 tiện cho thử nhanh, nhưng cách đúng để làm việc với Kubernetes là khai báo bằng YAML rồi apply. YAML là nguồn sự thật, lưu được vào Git, lặp lại được.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: web
spec:
  containers:
    - name: nginx
      image: nginx:1.27-alpine
      ports:
        - containerPort: 80

Bốn trường này có ở mọi đối tượng Kubernetes, nên quen sớm:

  • apiVersion — phiên bản API của loại đối tượng (Pod thuộc nhóm core v1).
  • kind — loại đối tượng (Pod).
  • metadata — tên, labels (nhãn để gắn thẻ và chọn lọc — Bài 6), namespace...
  • specmô tả trạng thái mong muốn. Với pod: chạy container nào, image gì, mở cổng nào.

Để ý ta không nói "hãy tạo container" — ta mô tả "pod này gồm container nginx nghe cổng 80". Tư duy khai báo (Bài 0) hiện diện ở mọi manifest.

apply và xem trạng thái

kubectl apply -f pod.yaml
pod/nginx-pod created
kubectl get pod nginx-pod -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE
nginx-pod   1/1     Running   0          12s   10.244.0.5   minikube   <none>

READY 1/1 (1 trên 1 container sẵn sàng), STATUS Running, IP nội bộ 10.244.0.5. Muốn biết chi tiết hơn — và đặc biệt là chuyện gì đã xảy ra — dùng describe:

kubectl describe pod nginx-pod

Phần Events ở cuối là vàng khi gỡ lỗi, nó kể lại đúng luồng Bài 1:

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  12s   default-scheduler  Successfully assigned default/nginx-pod to minikube
  Normal  Pulling    11s   kubelet            Pulling image "nginx:1.27-alpine"
  Normal  Pulled     1s    kubelet            Successfully pulled image ... in 9.648s
  Normal  Created    1s    kubelet            Container created
  Normal  Started    1s    kubelet            Container started

Đọc từ trên xuống: scheduler gán pod vào node minikube, rồi kubelet kéo image, tạo và khởi container. Đúng những gì Bài 1 mô tả, giờ tận mắt. Khi pod kẹt ở Pending hay ImagePullBackOff, đây là chỗ đầu tiên bạn nhìn.

Đọc log và exec vào pod

Xem log của container (như docker logs):

kubectl logs nginx-pod

Chạy lệnh bên trong pod (như docker exec):

kubectl exec nginx-pod -- nginx -v
nginx version: nginx/1.27.5

Thêm -it để vào shell tương tác: kubectl exec -it nginx-pod -- sh. Hai lệnh logsexec là cặp đôi bạn dùng nhiều nhất khi gỡ lỗi (đào kỹ ở Bài 13).

Truy cập pod: port-forward

Pod có IP 10.244.0.5 nhưng đó là IP nội bộ cluster — máy bạn không gọi thẳng được. Cách nhanh để thử trong lúc dev là port-forward:

kubectl port-forward pod/nginx-pod 8080:80

Giờ curl http://localhost:8080 trên máy bạn được chuyển vào cổng 80 của pod:

<title>Welcome to nginx!</title>

port-forward chỉ hợp để thử/gỡ lỗi. Cách đúng để mở dịch vụ ra ngoài một cách ổn định là Service (Bài 5) và Ingress (Bài 9).

Vì sao không ai chạy pod trần ở production

Đây là bài học quan trọng nhất của bài. Xóa pod đi:

kubectl delete pod nginx-pod
kubectl get pods
pod "nginx-pod" deleted from default namespace
No resources found in default namespace.

Pod biến mất — và không có gì dựng lại nó. Không có ai đứng ra giữ "phải luôn có pod này". Nếu đây là production và pod chết vì node hỏng, ứng dụng của bạn cứ thế biến mất. Một pod tự nó không có tính tự chữa lành, không scale, không rollout.

Đó là lý do trong thực tế gần như không ai tạo Pod trực tiếp. Thay vào đó ta dùng một đối tượng cấp cao hơn quản lý pod giúp mình — phổ biến nhất là Deployment. Nó là controller (nhớ control loop ở Bài 0–1) đảm bảo "luôn có đúng N pod chạy", tự dựng lại khi pod chết, và lo cả việc cập nhật phiên bản.

Tổng kết

Pod là đơn vị nhỏ nhất Kubernetes quản lý: một nhóm container chia sẻ IP/network, volumevòng đời — đa số chỉ một container, đôi khi kèm sidecar. Khai báo pod bằng YAML với bốn trường apiVersion/kind/metadata/spec, rồi kubectl apply. Dùng get/describe (xem Events), logs, exec, port-forward để quan sát và gỡ lỗi. Điều cốt yếu: pod phù du và không tự chữa lành — xóa là mất hẳn — nên production không chạy pod trần mà để Deployment quản lý.

Bài 4 gặp DeploymentReplicaSet: cách giữ N bản sao luôn sống, scale lên/xuống, và cập nhật phiên bản mà không gián đoạn.