Pod: Đơn Vị Nhỏ Nhất Trong Kubernetes
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 corev1).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...spec— mô 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 logs và exec 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, volume và vò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 Deployment và ReplicaSet: 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.