Docker for Developers · Part 9 — Kubernetes Fundamentals
Từ một host tới cluster: kiến trúc Kubernetes, Pod, Deployment, Service, kubectl, kind và lần deploy ứng dụng đầu tiên.
Đây là Phần 9 của chặng nền tảng về Docker → Compose → Kubernetes. Docker Compose chạy container trên một máy — bạn khai báo service trong YAML và docker compose up bật cả stack (Phần 5, Phần 6). Đủ cho dev local và nhiều triển khai nhỏ. Khi cần nhiều máy, tự phục hồi, rollout có kiểm soát và scale ngang trên nhiều node, bạn cần orchestrator — chuẩn công nghiệp là Kubernetes (k8s). Zero downtime còn phụ thuộc readiness, capacity, graceful shutdown và tính tương thích của ứng dụng; Kubernetes không tự bảo đảm chỉ vì dùng Deployment.
Thẳng thắn: Kubernetes nặng hơn Docker — nhiều khái niệm, YAML và bộ phận chuyển động. Nhưng nó không phải “Docker có thêm YAML”; nó là hệ control loop liên tục kéo trạng thái thật về trạng thái mong muốn. Bạn đúng chỗ vì đã hiểu image, container, mạng, volume, healthcheck và Compose từ Phần 1–8. Phần này giới thiệu mô hình tư duy và cluster đầu tiên trên laptop bằng kind. Phần 10 đi sâu config, probe và debug k8s.
Mỗi phần kết thúc bằng bài tập; hãy làm, đừng chỉ đọc.
Senior judgment: đừng dùng Kubernetes chỉ vì nghe “chuẩn production”. Nếu bạn có một app nhỏ, một server, traffic vừa phải và team chưa có năng lực vận hành cluster, Compose + systemd + backup + monitoring có thể tốt hơn. Kubernetes đáng giá khi bạn thật sự cần scheduling nhiều node, self-healing, policy deploy, tách quyền, và một nền tảng chung cho nhiều team/service.
Kiến trúc cluster
Một cluster Kubernetes là tập máy (vật lý hoặc ảo) phối hợp chạy workload của bạn. Một phía là control plane (bộ não); phía kia là worker node (nơi container thực sự chạy).
- API server — API REST;
kubectlvà controller đều nói chuyện qua đây. - Scheduler — chọn node phù hợp cho Pod mới.
- Controller manager — giữ Deployment/ReplicaSet/Job khớp trạng thái mong muốn.
- etcd — lưu trạng thái cluster.
- kubelet — agent trên mỗi node, chạy Pod qua container runtime.
- kube-proxy / networking — áp dụng quy tắc mạng Service → Pod.
Mô hình khai báo
Bạn không SSH vào node 3 rồi docker run. Bạn mô tả trạng thái mong muốn trong YAML rồi apply; Kubernetes điều chỉnh đến khi thực tế khớp. Pod chết thì controller tạo cái mới. Bạn yêu cầu ba replica thì hệ thống giữ ba.
Đây là bước nhảy tư duy lớn nhất: trong Docker bạn thường điều khiển một container; trong Kubernetes bạn điều khiển policy. Câu hỏi senior không còn là “làm sao start container này?”, mà là “nếu node chết, rollout fail, image pull lỗi, hoặc traffic đang vào pod chưa sẵn sàng thì hệ thống phản ứng thế nào?”
Các object lõi
Bạn sẽ sống với ba loại này khá lâu: Pod, Deployment, Service.
Pod — đơn vị lập lịch nhỏ nhất
Pod bọc một hoặc nhiều container dùng chung mạng và storage. Thực tế một container mỗi Pod là phổ biến. Pod ngắn hạn — chết thì IP mất; hiếm khi tạo Pod trần bằng tay.
Deployment — replica mong muốn & rolling update
Deployment sở hữu ReplicaSet, ReplicaSet sở hữu Pod. Bạn đặt replicas: 2 và Deployment đảm bảo hai Pod khớp, thay Pod hỏng, và rollout image từ từ.
Deployment "web"
│
│ manages
▼
ReplicaSet "web-7d4f9c8b6"
│
│ owns
├──────────┬──────────┐
▼ ▼ ▼
Pod web-1 Pod web-2 (scale adds more)
Service — mạng ổn định trước Pod
IP Pod đổi khi Pod restart. Service là tên DNS + IP ảo ổn định, cân bằng tải tới Pod khỏe khớp label selector.
ClusterIP — DNS nội bộ; NodePort — cổng trên mọi node; LoadBalancer — LB cloud trên prod.
Cơ bản kubectl
kubectl là CLI cho API Kubernetes — giống docker với một daemon, nhưng cho cả cluster. Cài cùng kind hoặc minikube. Lệnh hằng ngày:
kubectl get pods # list Pods (default namespace)
kubectl get pods -n kube-system # -n = namespace
kubectl get pods -o wide # Pod IP, node name, nominated/readiness gates
kubectl describe pod <name> # events, state, why Pending/CrashLoop
kubectl logs <pod> # stdout/stderr (like docker logs)
kubectl logs -f <pod> # follow
kubectl exec -it <pod> -- sh # shell inside (like docker exec)
kubectl apply -f manifest.yaml # create or update from YAML
kubectl delete -f manifest.yaml # remove resources in file
kubectl delete pod <name> # delete one Pod (Deployment recreates it)
Dùng -n cho kube-system, staging… — tutorial thường ở default. Quy trình: sửa YAML → apply → get/describe/logs, controller điều chỉnh nền.
Cluster local với kind
kind chạy cluster trong Docker; minikube là lựa chọn khác — cùng quy trình kubectl.
# Install: https://kind.sigs.k8s.io/docs/user/quick-start/
kind create cluster --name dev
kubectl cluster-info --context kind-dev
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# dev-control-plane Ready control-plane 1m v1.36.x
context kubectl giờ trỏ tới kind-dev. Kiểm tra bằng kubectl config current-context.
Nạp image local vào kind
Image build bằng docker build nằm trên Docker host, không có sẵn trong node kind. Trước khi Deployment kéo myapp:local, nạp vào:
docker build -t myapp:local .
kind load docker-image myapp:local --name dev
Không bước này, Pod thường kẹt ImagePullBackOff.
Dọn khi xong:
kind delete cluster --name dev
Deployment đầu tiên
Tạo thư mục k8s-lab-09/ và lưu hai file.
nginx, hai replica, label để Service chọn:
# deployment.yaml — desired state: 2 nginx Pods
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy # Deployment name (kubectl get deploy)
labels:
app: nginx
spec:
replicas: 2 # controller keeps 2 Pods running
selector:
matchLabels:
app: nginx # must match template labels below
template: # Pod template — each Pod looks like this
metadata:
labels:
app: nginx # Service selector targets this label
spec:
containers:
- name: nginx
image: nginx:1.28-alpine # public image; no kind load needed
ports:
- containerPort: 80 # container listens here (not published to host yet)
Service ClusterIP (truy cập bằng port-forward):
# service.yaml — stable VIP + DNS name → Pods with app=nginx
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: ClusterIP # default; internal cluster IP
selector:
app: nginx # must match Pod labels from Deployment
ports:
- port: 80 # Service port (what clients connect to)
targetPort: 80 # Pod containerPort
Apply và kiểm tra:
kubectl apply -f deployment.yaml -f service.yaml
kubectl get deploy,pods,svc
kubectl get pods -o wide
# wait until both Pods are Running (READY 1/1)
Truy cập từ laptop:
kubectl port-forward svc/nginx-svc 8080:80
# leave running; in another terminal:
curl -s http://localhost:8080 | head -5
port-forward tunnel tới Service — cách đơn giản nhất để curl từ laptop; NodePort cũng được nhưng cần map cổng thêm trên kind.
Từ Compose sang Kubernetes
Bạn đã nghĩ theo service từ Compose. Kubernetes tách trách nhiệm khác:
Compose (compose.yaml) | Kubernetes |
|---|---|
services.web | Deployment + Service |
ports: "8080:80" | Service hoặc port-forward |
volumes: | emptyDir, PV + PVC (Phần 16) |
environment: / env_file: | env, ConfigMap, Secret (Phần 10) |
healthcheck | startup/readiness/liveness probe (Phần 10) |
depends_on startup order | Không có tương đương trực tiếp; app phải retry hoặc dùng init container khi thật sự cần chờ |
docker compose up | kubectl apply -f … |
docker compose scale web=3 | kubectl scale deploy/nginx-deploy --replicas=3 |
kompose khởi tạo manifest từ Compose; viết tay dạy label, selector và nối Deployment ↔ Service.
Các bẫy thường gặp
- Cluster không tìm thấy image. Image public ổn; tag local cần
kind loadhoặc push registry. - Gọi thẳng IP Pod — IP ngắn hạn; luôn qua Service, và dùng Gateway/Ingress cho HTTP traffic từ ngoài cluster.
- context sai — xác nhận
kubectl config get-contextstrước khi xóa. - NodePort trên kind cần map cổng thêm;
port-forwardđơn giản hơn để curl từ máy bạn. - Không copy nguyên mạng Compose — DNS trong cluster là
http://<tên-service>(cùng namespace).
Bảng tra nhanh
# cluster & context
kubectl get nodes
kubectl config current-context
kubectl config use-context kind-dev
# workloads
kubectl apply -f .
kubectl get deploy,rs,pods,svc
kubectl describe deploy nginx-deploy
kubectl scale deploy/nginx-deploy --replicas=4
# debug (mirror Part 8 docker habits)
kubectl logs <pod> -f
kubectl exec -it <pod> -- sh
kubectl get events --sort-by='.lastTimestamp'
# access
kubectl port-forward svc/nginx-svc 8080:80
# cleanup
kubectl delete -f deployment.yaml -f service.yaml
kind delete cluster --name dev
Bài tập / Exercises
Làm trong k8s-lab-09/ với manifest trong bài (hoặc tên riêng). Cần kind (hoặc minikube) và kubectl.
1. Tạo cluster kind tên lab09, xác nhận node Ready, context là kind-lab09.
Lời giải
kind create cluster --name lab09
kubectl get nodes
kubectl config current-context # kind-lab092. Apply Deployment nginx replicas: 2, xác nhận hai Pod Running.
Lời giải
kubectl apply -f deployment.yaml
kubectl get pods -w
# Ctrl+C when both show 1/1 Running
kubectl get deploy nginx-deploy3. Xóa một Pod, xem Pod mới xuất hiện — tự phục hồi từ Deployment.
Lời giải
kubectl get pods
kubectl delete pod nginx-deploy-xxxxxxxxxx-xxxxx # pick one Pod name from get pods
kubectl get pods -w
# a new Pod is created; replica count stays at 24. Apply Service, port-forward cổng 8080, curl trang chào nginx.
Lời giải
kubectl apply -f service.yaml
kubectl port-forward svc/nginx-svc 8080:80 &
curl -s http://localhost:8080 | head -3
kill %1 # stop port-forward job5. Scale Deployment lên 4 replica, xác nhận bốn Pod, rồi scale về 2.
Lời giải
kubectl scale deploy/nginx-deploy --replicas=4
kubectl get pods
kubectl scale deploy/nginx-deploy --replicas=2
kubectl get podsNâng cao: Build image local, kind load, đổi image Deployment thành lab09-app:local với imagePullPolicy: Never, apply, xác nhận Pod chạy.
Lời giải
# in deployment.yaml container spec:
image: lab09-app:local
imagePullPolicy: Neverkind load docker-image lab09-app:local --name lab09
kubectl apply -f deployment.yaml
kubectl get podsĐiểm chính
- Compose = một host; Kubernetes = nhiều node với điều chỉnh, scale và rolling update.
- Pod chạy container; Deployment giữ số replica và phục hồi; Service cho tên/IP ổn định trước Pod.
kubectl applylà vòng lặp hằng ngày;get/describe/logs/execgiống debug Docker ở Phần 8.- kind (+
kind load) là cách nhanh nhất để luyện không tốn tiền cloud.
Tiếp theo
Phần 10 — Kubernetes thực hành & Debug — ConfigMap và Secret, probe startup/readiness/liveness, resource request/limit, rollout và checklist debug kubectl khi Pod không lên. Networking nâng cao nằm ở Phần 14; storage bền vững ở Phần 16.