Kubernetes Cơ Bản

Chào mừng đến Giai đoạn 3 của Lộ Trình Học Docker & Kubernetes! Bạn đã thành thạo Docker cơ bản, viết Dockerfile, và điều phối ứng dụng multi-container với Docker Compose. Giờ là lúc bước nhảy lớn — Kubernetes.
Docker Compose ngon lành cho deploy trên một máy. Nhưng khi app cần chạy trên nhiều server thì sao? Khi container crash lúc 3 giờ sáng mà không ai thức để restart? Khi traffic Black Friday đổ về và bạn cần 50 replicas thay vì 2? Đó là lúc Kubernetes xuất hiện.
Bạn Sẽ Học Được
✅ Hiểu kiến trúc Kubernetes (control plane và worker nodes)
✅ Cài đặt Kubernetes cluster local với minikube
✅ Tạo và quản lý Pods — đơn vị deploy nhỏ nhất
✅ Dùng Deployments cho rolling updates và rollbacks
✅ Expose ứng dụng với Services (ClusterIP, NodePort, LoadBalancer)
✅ Quản lý configuration với ConfigMaps và Secrets
✅ Tổ chức resources với Namespaces, Labels và Selectors
✅ Debug và troubleshoot Kubernetes workloads
Thời gian: 7–10 ngày, 1–2 giờ mỗi ngày
Yêu cầu: Giai đoạn 2: Docker Compose & Ứng Dụng Multi-Container
Phần 1: Kubernetes Là Gì?
Kubernetes (hay viết tắt là K8s — số 8 đại diện cho 8 ký tự giữa "K" và "s") là một platform orchestration container mã nguồn mở. Ban đầu được Google thiết kế, giờ do Cloud Native Computing Foundation (CNCF) duy trì, nó tự động hóa việc deploy, scale và quản lý ứng dụng container.
Tại Sao Cần Kubernetes?
Docker chạy containers. Kubernetes chạy containers ở quy mô lớn. Đây là những gì nó mang lại:
| Khả năng | Không có K8s | Có K8s |
|---|---|---|
| Scaling | Tự tay start thêm containers | kubectl scale --replicas=10 |
| Self-healing | Container crash → bạn phải restart | K8s tự động restart containers lỗi |
| Load balancing | Tự setup nginx/HAProxy | Built-in Service load balancing |
| Rolling updates | Tắt cũ → bật mới (downtime) | Zero-downtime rolling deployments |
| Service discovery | Hardcode IPs hoặc dùng external DNS | Built-in DNS cho mọi Service |
| Configuration | File environment trên từng server | Tập trung qua ConfigMaps và Secrets |
| Resource management | Cầu trời containers không ngốn hết tài nguyên | CPU/memory requests và limits |
Kubernetes vs Docker Compose vs Docker Swarm
| Feature | Docker Compose | Docker Swarm | Kubernetes |
|---|---|---|---|
| Độ phức tạp | Đơn giản | Trung bình | Phức tạp |
| Multi-node | Không | Có | Có |
| Auto-scaling | Không | Hạn chế | Nâng cao (HPA, VPA) |
| Self-healing | Không | Cơ bản | Nâng cao |
| Ecosystem | Chỉ Docker | Chỉ Docker | Khổng lồ (CNCF) |
| Learning curve | Thấp | Trung bình | Cao |
| Phù hợp cho | Development | Production nhỏ | Production quy mô lớn |
Các Bản Phân Phối Kubernetes
Không phải Kubernetes nào cũng giống nhau. Có nhiều distribution:
- Vanilla Kubernetes (kubeadm) — Bản tiêu chuẩn, tự cài đặt
- minikube — Cluster single-node cho development local
- kind (Kubernetes in Docker) — Chạy K8s nodes như Docker containers
- k3s — K8s nhẹ của Rancher (tuyệt vời cho edge/IoT)
- MicroK8s — K8s nhẹ của Canonical (dựa trên snap)
- OpenShift — Platform Kubernetes enterprise của Red Hat
- Managed services — EKS (AWS), GKE (Google), AKS (Azure)
Để học, chúng ta sẽ dùng minikube — cách dễ nhất để có Kubernetes cluster chạy trên laptop.
Phần 2: Kiến Trúc Kubernetes
Hiểu kiến trúc Kubernetes là điều cần thiết trước khi bạn deploy bất cứ thứ gì. Một Kubernetes cluster có hai phần chính: control plane và worker nodes.
Các Thành Phần Control Plane
Control plane là "bộ não" của cluster. Nó đưa ra quyết định về scheduling, phát hiện events và phản hồi thay đổi.
API Server (kube-apiserver)
- Cánh cửa chính vào Kubernetes — mọi command đều đi qua đây
kubectlgiao tiếp với API server- RESTful API validate và xử lý requests
- Thành phần duy nhất nói chuyện trực tiếp với etcd
etcd
- Key-value store phân tán lưu trữ toàn bộ cluster state
- Lưu configuration, secrets, service discovery data
- Nếu etcd chết, cluster mất bộ nhớ
- Luôn chạy với backup trong production
Scheduler (kube-scheduler)
- Quyết định node nào sẽ chạy Pod mới
- Xem xét: resource requirements, affinity rules, taints/tolerations
- Không chạy Pod — chỉ gán nó cho một node
Controller Manager (kube-controller-manager)
- Chạy các controller loop theo dõi cluster state và sửa chữa
- Deployment controller: đảm bảo đúng số replicas đang chạy
- Node controller: giám sát sức khỏe node
- Job controller: quản lý batch jobs
Các Thành Phần Worker Node
Worker nodes là các máy thực sự chạy containers.
kubelet
- Agent chạy trên mọi worker node
- Nhận Pod specs từ API server
- Đảm bảo containers đang chạy và healthy
- Báo cáo status của node và Pod về control plane
kube-proxy
- Network proxy trên mỗi node
- Duy trì network rules cho Service communication
- Implement Service abstraction (load balancing giữa các Pods)
Container Runtime
- Phần mềm chạy containers (containerd, CRI-O)
- Docker là runtime ban đầu nhưng Kubernetes đã bỏ hỗ trợ Docker từ v1.24
- containerd hiện là runtime phổ biến nhất
Mọi Thứ Kết Hợp Như Thế Nào
Khi bạn chạy kubectl apply -f deployment.yaml, đây là những gì xảy ra:
Phần 3: Cài Đặt Kubernetes
Cài Đặt minikube
minikube tạo một single-node Kubernetes cluster trên máy local.
macOS:
# Cài bằng Homebrew
brew install minikube
# Hoặc download trực tiếp
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-arm64
sudo install minikube-darwin-arm64 /usr/local/bin/minikubeLinux:
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikubeWindows (PowerShell):
winget install Kubernetes.minikubeKhởi Động Cluster
# Start minikube với cài đặt mặc định
minikube start
# Start với tài nguyên cụ thể
minikube start --cpus=4 --memory=8192 --driver=docker
# Kiểm tra cluster status
minikube statusOutput:
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: ConfiguredCài Đặt kubectl
kubectl là công cụ command-line để tương tác với Kubernetes.
macOS:
brew install kubectlLinux:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install kubectl /usr/local/bin/kubectlKiểm tra cài đặt:
# Kiểm tra kubectl version
kubectl version --client
# Kiểm tra kết nối cluster
kubectl cluster-info
# Xem cluster nodes
kubectl get nodesOutput:
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 2m v1.31.0Các Lệnh kubectl Cơ Bản
Đây là những commands bạn sẽ dùng hàng ngày:
# Lấy resources
kubectl get pods # Liệt kê tất cả pods
kubectl get pods -o wide # Với chi tiết thêm (IP, node)
kubectl get services # Liệt kê tất cả services
kubectl get all # Liệt kê mọi thứ
# Describe (thông tin chi tiết)
kubectl describe pod <pod-name> # Chi tiết pod
kubectl describe node minikube # Chi tiết node
# Tạo và apply
kubectl apply -f manifest.yaml # Apply manifest (tạo hoặc cập nhật)
kubectl create -f manifest.yaml # Tạo mới (lỗi nếu đã tồn tại)
# Xóa
kubectl delete pod <pod-name> # Xóa một pod
kubectl delete -f manifest.yaml # Xóa resources từ manifest
# Logs và debugging
kubectl logs <pod-name> # Xem pod logs
kubectl logs -f <pod-name> # Stream logs (follow)
kubectl exec -it <pod-name> -- sh # Shell vào pod
# Quản lý context
kubectl config get-contexts # Liệt kê contexts
kubectl config use-context minikube # Chuyển contextMẹo: Tạo alias để gõ nhanh hơn:
alias k=kubectl
Giờ bạn gõk get podsthay vìkubectl get pods.
Phần 4: Pods
Pod là đơn vị deploy nhỏ nhất trong Kubernetes. Nó là wrapper bao quanh một hoặc nhiều containers chia sẻ cùng network và storage.
Tại Sao Pod Chứ Không Phải Container?
Trong Docker, bạn nghĩ theo containers. Trong Kubernetes, bạn nghĩ theo Pods. Tại sao thêm một lớp nữa?
- Pods có thể chạy nhiều containers cần làm việc cùng nhau (sidecar pattern)
- Containers trong cùng Pod chia sẻ cùng IP address và localhost
- Containers trong cùng Pod chia sẻ volumes
- Pods là đơn vị scheduling — chúng luôn chạy trên cùng node
Hầu hết thời gian, một Pod chạy một container. Multi-container Pods dành cho các pattern cụ thể như logging sidecars, proxies, hoặc init containers.
Tạo Pod Đầu Tiên
Cách imperative (test nhanh):
# Chạy một pod trực tiếp
kubectl run nginx --image=nginx:alpine --port=80
# Kiểm tra nó đang chạy
kubectl get podsOutput:
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 10sCách declarative (khuyến khích):
Tạo file pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: my-app
labels:
app: my-app
environment: dev
spec:
containers:
- name: app
image: nginx:alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "250m"Apply:
kubectl apply -f pod.yaml
kubectl get pods
kubectl describe pod my-appVòng Đời Pod
Pods trải qua nhiều giai đoạn:
| Giai đoạn | Ý nghĩa |
|---|---|
| Pending | Pod được chấp nhận nhưng containers chưa chạy (đang pull images, scheduling) |
| Running | Ít nhất một container đang chạy |
| Succeeded | Tất cả containers thoát thành công (exit code 0) |
| Failed | Ít nhất một container thoát với lỗi |
| Unknown | Không xác định được state của Pod (thường do vấn đề giao tiếp node) |
Multi-Container Pods
Đôi khi containers cần làm việc cùng nhau chặt chẽ. Các pattern phổ biến:
Sidecar pattern — container phụ trợ bên cạnh app chính:
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
labels:
app: web
spec:
containers:
# Ứng dụng chính
- name: app
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
# Sidecar: gửi logs đến hệ thống tập trung
- name: log-shipper
image: busybox
command: ["sh", "-c", "tail -f /logs/access.log"]
volumeMounts:
- name: shared-logs
mountPath: /logs
volumes:
- name: shared-logs
emptyDir: {}Cả hai containers chia sẻ volume shared-logs. Container nginx ghi logs, container log-shipper đọc và chuyển tiếp chúng.
Init Containers
Init containers chạy trước khi containers chính start. Hoàn hảo cho các setup tasks:
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
labels:
app: web
spec:
initContainers:
# Đợi database sẵn sàng
- name: wait-for-db
image: busybox
command: ["sh", "-c", "until nc -z db-service 5432; do echo waiting for db; sleep 2; done"]
# Chạy database migrations
- name: run-migrations
image: my-app:latest
command: ["python", "manage.py", "migrate"]
containers:
- name: app
image: my-app:latest
ports:
- containerPort: 8000Init containers chạy tuần tự — mỗi cái phải hoàn thành trước khi cái tiếp theo bắt đầu. Container chính chỉ start sau khi tất cả init containers thành công.
Debug Pods
# Xem chi tiết pod (events ở cuối hữu ích nhất)
kubectl describe pod my-app
# Xem logs
kubectl logs my-app
kubectl logs my-app -c log-shipper # Container cụ thể trong multi-container pod
kubectl logs my-app --previous # Logs từ container đã crash
# Shell vào pod đang chạy
kubectl exec -it my-app -- /bin/sh
# Port-forward để truy cập pod từ local
kubectl port-forward my-app 8080:80
# Giờ truy cập http://localhost:8080
# Kiểm tra resource usage
kubectl top pod my-appCác vấn đề Pod thường gặp và cách fix:
| Status | Nguyên nhân phổ biến | Lệnh debug |
|---|---|---|
ImagePullBackOff | Sai tên image hoặc không có quyền truy cập registry | kubectl describe pod → check Events |
CrashLoopBackOff | App crash khi khởi động | kubectl logs --previous |
Pending | Không đủ resources trên nodes | kubectl describe pod → check Events |
OOMKilled | Container vượt quá memory limit | Tăng resources.limits.memory |
Phần 5: Deployments
Trong thực tế, bạn hầu như không bao giờ tạo Pods trực tiếp. Thay vào đó, bạn dùng Deployment — một resource cấp cao hơn quản lý Pods cho bạn.
Tại Sao Dùng Deployments?
| Feature | Pod đơn lẻ | Deployment |
|---|---|---|
| Self-healing | Pod chết → nằm chết luôn | Pod chết → tạo cái mới |
| Scaling | Tự tay tạo pod | kubectl scale --replicas=5 |
| Rolling updates | Tắt cũ, bật mới | Zero-downtime updates |
| Rollback | Không thể | kubectl rollout undo |
| History | Không có | Lịch sử revision đầy đủ |
Tạo Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "250m"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20Phân tích các phần quan trọng:
replicas: 3— Chạy 3 Pods giống nhauselector.matchLabels— Cách Deployment tìm Pods của nótemplate— Template cho Pod (mỗi replica trông thế nào)readinessProbe— Kiểm tra Pod đã sẵn sàng nhận traffic chưalivenessProbe— Kiểm tra Pod còn sống không (restart nếu không)
Apply và kiểm tra:
kubectl apply -f deployment.yaml
# Xem deployment
kubectl get deployments
kubectl get rs # ReplicaSet được tạo bởi Deployment
kubectl get pods # Pods được tạo bởi ReplicaSetOutput:
NAME READY UP-TO-DATE AVAILABLE AGE
my-app 3/3 3 3 30s
NAME DESIRED CURRENT READY AGE
my-app-7d9f8b6c5 3 3 3 30s
NAME READY STATUS RESTARTS AGE
my-app-7d9f8b6c5-abc12 1/1 Running 0 30s
my-app-7d9f8b6c5-def34 1/1 Running 0 30s
my-app-7d9f8b6c5-ghi56 1/1 Running 0 30sChú ý thứ bậc: Deployment → ReplicaSet → Pods. Deployment quản lý ReplicaSets, và ReplicaSets quản lý Pods.
Scaling
# Scale up
kubectl scale deployment my-app --replicas=5
# Scale down
kubectl scale deployment my-app --replicas=2
# Kiểm tra kết quả
kubectl get podsRolling Updates
Đây là nơi Deployments tỏa sáng. Khi bạn update container image, Kubernetes dần thay thế Pods cũ bằng mới — zero downtime.
# Cập nhật image
kubectl set image deployment/my-app app=nginx:1.26-alpine
# Theo dõi rollout
kubectl rollout status deployment/my-appĐiều gì xảy ra trong rolling update:
Bạn có thể kiểm soát update strategy:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Tối đa pods thêm trong lúc update
maxUnavailable: 0 # Zero downtime — không bao giờ xóa pod cho đến khi pod mới sẵn sàngRollbacks
Version mới có vấn đề? Roll back ngay lập tức:
# Xem rollout history
kubectl rollout history deployment/my-app
# Roll back về version trước
kubectl rollout undo deployment/my-app
# Roll back về revision cụ thể
kubectl rollout undo deployment/my-app --to-revision=2
# Kiểm tra rollout status
kubectl rollout status deployment/my-appHealth Checks (Probes)
Probes cho Kubernetes biết ứng dụng có healthy không:
| Probe | Mục đích | Hành động khi fail |
|---|---|---|
| livenessProbe | Container còn sống không? | Restart container |
| readinessProbe | Container sẵn sàng nhận traffic? | Gỡ khỏi Service endpoints |
| startupProbe | App đã khởi động xong chưa? | Kill và restart |
containers:
- name: app
image: my-app:latest
# Startup probe: cho app khởi động chậm thời gian boot
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
# Liveness probe: restart nếu app bị treo
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0
periodSeconds: 15
failureThreshold: 3
# Readiness probe: chỉ gửi traffic khi sẵn sàng
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5Phần 6: Services
Pods là tạm thời — chúng đến rồi đi, nhận IP address mới mỗi lần. Bạn không thể dựa vào Pod IPs. Services cung cấp network endpoint ổn định để truy cập nhóm Pods.
Services Hoạt Động Như Thế Nào
Service dùng label selectors để tìm Pods và điều hướng traffic đến chúng:
Các Loại Service
Kubernetes cung cấp bốn loại Service, mỗi loại với mức truy cập khác nhau:
1. ClusterIP (mặc định)
Chỉ truy cập được trong cluster. Hoàn hảo cho giao tiếp service-to-service nội bộ.
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP
selector:
app: backend
ports:
- port: 80 # Service port
targetPort: 8080 # Container port
protocol: TCPCác Pods khác có thể truy cập service này tại backend-service:80 hoặc backend-service.default.svc.cluster.local:80.
2. NodePort
Expose Service trên port cố định trên mọi node. Truy cập được từ bên ngoài cluster.
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: NodePort
selector:
app: frontend
ports:
- port: 80
targetPort: 3000
nodePort: 30080 # Port bên ngoài (30000-32767)Truy cập qua <node-ip>:30080. Với minikube:
minikube service frontend-service --url3. LoadBalancer
Tạo external load balancer (trên cloud providers như AWS, GKE, AKS). Trong minikube, dùng minikube tunnel để mô phỏng.
apiVersion: v1
kind: Service
metadata:
name: public-api
spec:
type: LoadBalancer
selector:
app: api
ports:
- port: 80
targetPort: 8080# Trong terminal riêng (cho minikube)
minikube tunnel
# Kiểm tra external IP
kubectl get service public-api4. ExternalName
Map Service đến external DNS name. Không proxy — chỉ là DNS alias.
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: db.example.comPods có thể truy cập external-db và nó resolve đến db.example.com.
Service Discovery
Kubernetes cung cấp built-in DNS cho Services. Mọi Service đều có DNS entry:
<service-name>.<namespace>.svc.cluster.localTrong cùng namespace, bạn chỉ cần dùng tên service:
# Bên trong Pod cùng namespace
import requests
# Dạng ngắn (cùng namespace)
response = requests.get("http://backend-service:80/api/users")
# Full DNS name (cross-namespace)
response = requests.get("http://backend-service.production.svc.cluster.local:80/api/users")Phần 7: ConfigMaps và Secrets
Hardcode configuration trong container images là practice tệ. ConfigMaps và Secrets cho phép bạn tách biệt configuration khỏi application code.
ConfigMaps
ConfigMaps lưu trữ configuration data không nhạy cảm dạng key-value pairs.
Tạo ConfigMaps:
# Từ literal values
kubectl create configmap app-config \
--from-literal=APP_ENV=production \
--from-literal=LOG_LEVEL=info \
--from-literal=MAX_CONNECTIONS=100
# Từ file
kubectl create configmap nginx-config --from-file=nginx.conf
# Xem ConfigMap
kubectl get configmap app-config -o yamlDeclarative YAML:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
# Multi-line config file
app.properties: |
server.port=8080
spring.profiles.active=production
logging.level.root=INFODùng ConfigMaps trong Pods:
apiVersion: v1
kind: Pod
metadata:
name: app-with-config
spec:
containers:
- name: app
image: my-app:latest
# Cách 1: Dạng environment variables
envFrom:
- configMapRef:
name: app-config
# Cách 2: Keys cụ thể làm env vars
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: APP_ENV
# Cách 3: Mount dạng files
volumeMounts:
- name: config-volume
mountPath: /etc/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: app-configSecrets
Secrets giống ConfigMaps nhưng cho dữ liệu nhạy cảm — passwords, API keys, TLS certificates. Values được base64-encoded (không encrypted mặc định).
Tạo Secrets:
# Từ literal values
kubectl create secret generic db-credentials \
--from-literal=DB_USER=admin \
--from-literal=DB_PASSWORD=s3cur3p@ss
# Từ files (ví dụ TLS certificates)
kubectl create secret tls my-tls-secret \
--cert=tls.crt \
--key=tls.key
# Xem secret (values là base64 encoded)
kubectl get secret db-credentials -o yamlDeclarative YAML:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
# Values phải base64 encoded
DB_USER: YWRtaW4= # echo -n "admin" | base64
DB_PASSWORD: czNjdXIzcEBzcw== # echo -n "s3cur3p@ss" | base64
---
# Hoặc dùng stringData cho plain text (Kubernetes tự encode)
apiVersion: v1
kind: Secret
metadata:
name: api-keys
type: Opaque
stringData:
API_KEY: "my-super-secret-api-key"
JWT_SECRET: "jwt-signing-secret-256-bit"Dùng Secrets trong Pods:
apiVersion: v1
kind: Pod
metadata:
name: app-with-secrets
spec:
containers:
- name: app
image: my-app:latest
# Dạng environment variables
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_USER
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_PASSWORD
# Mount dạng files
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-credentialsQuan trọng: Kubernetes Secrets được base64-encoded, không phải encrypted. Cho production, hãy cân nhắc:
- Bật encryption at rest cho etcd
- Dùng external secret managers (Vault, AWS Secrets Manager, Azure Key Vault)
- Dùng External Secrets Operator để sync từ external stores
Phần 8: Namespaces
Namespaces là clusters ảo trong một cluster vật lý. Chúng cung cấp isolation, tổ chức và quản lý resources.
Namespaces Mặc Định
Mọi Kubernetes cluster bắt đầu với các namespaces này:
kubectl get namespacesNAME STATUS AGE
default Active 1d # Nơi resources của bạn vào nếu không chỉ định
kube-system Active 1d # Kubernetes system components (API server, DNS, etc.)
kube-public Active 1d # Dữ liệu công khai (hiếm khi dùng)
kube-node-lease Active 1d # Node heartbeat leasesTạo và Sử Dụng Namespaces
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
environment: staging
---
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
environment: production# Tạo namespace
kubectl apply -f namespaces.yaml
# Tạo resources trong namespace cụ thể
kubectl apply -f deployment.yaml -n staging
# Liệt kê resources trong namespace
kubectl get pods -n staging
kubectl get all -n production
# Liệt kê resources trên tất cả namespaces
kubectl get pods --all-namespaces
kubectl get pods -A # Dạng ngắnĐặt Default Namespace
Chán gõ -n staging mỗi lần?
# Đặt default namespace cho context hiện tại
kubectl config set-context --current --namespace=staging
# Giờ tất cả commands nhắm vào 'staging' mặc định
kubectl get pods # Hiển thị pods trong 'staging'Resource Quotas
Kiểm soát namespace tiêu thụ bao nhiêu resources:
apiVersion: v1
kind: ResourceQuota
metadata:
name: staging-quota
namespace: staging
spec:
hard:
pods: "20"
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
services: "10"
persistentvolumeclaims: "5"Giao Tiếp Cross-Namespace
Services ở namespaces khác nhau có thể giao tiếp bằng full DNS name:
<service-name>.<namespace>.svc.cluster.local# Pod trong namespace 'staging' truy cập service trong namespace 'production'
env:
- name: API_URL
value: "http://api-service.production.svc.cluster.local:80"Phần 9: Labels và Selectors
Labels là cặp key-value gắn vào Kubernetes objects. Chúng là cách Kubernetes tổ chức và chọn resources.
Thêm Labels
apiVersion: v1
kind: Pod
metadata:
name: api-server
labels:
app: api
environment: production
team: backend
version: v2.1.0# Thêm label vào resource có sẵn
kubectl label pod api-server tier=backend
# Xóa label
kubectl label pod api-server tier-
# Cập nhật label
kubectl label pod api-server version=v2.2.0 --overwriteDùng Selectors
Selectors lọc resources theo labels:
# Equality-based selectors
kubectl get pods -l app=api
kubectl get pods -l environment=production
kubectl get pods -l 'environment!=staging'
# Set-based selectors
kubectl get pods -l 'environment in (production, staging)'
kubectl get pods -l 'team notin (frontend)'
kubectl get pods -l 'app, environment' # Có cả hai labels (bất kỳ value)
# Kết hợp selectors
kubectl get pods -l 'app=api,environment=production'Labels vs Annotations
| Feature | Labels | Annotations |
|---|---|---|
| Mục đích | Xác định và chọn resources | Gắn metadata không dùng để xác định |
| Dùng bởi selectors | Có | Không |
| Giới hạn size | 63 chars (value) | 256KB |
| Ví dụ | app=web, env=prod | description, git-commit, config-hash |
metadata:
labels:
app: api # Dùng cho selection
environment: production # Dùng cho selection
annotations:
description: "Main API server" # Không dùng cho selection
git-commit: "abc123def456" # Build metadata
kubectl.kubernetes.io/last-applied-configuration: "..." # System annotationLabel Best Practices
Theo convention labeling được khuyến nghị:
metadata:
labels:
# Labels khuyến nghị (kubernetes.io convention)
app.kubernetes.io/name: my-app
app.kubernetes.io/instance: my-app-prod
app.kubernetes.io/version: "2.1.0"
app.kubernetes.io/component: backend
app.kubernetes.io/part-of: ecommerce
app.kubernetes.io/managed-by: helm
# Custom labels cho tổ chức của bạn
team: platform
cost-center: engineeringPhần 10: Kết Hợp Tất Cả
Hãy deploy một ứng dụng hoàn chỉnh: Node.js API với PostgreSQL database.
Cấu Trúc Project
k8s/
├── namespace.yaml
├── configmap.yaml
├── secret.yaml
├── postgres-deployment.yaml
├── postgres-service.yaml
├── api-deployment.yaml
└── api-service.yamlBước 1: Namespace
# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: demo-app
labels:
app: demoBước 2: ConfigMap và Secret
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: demo-app
data:
NODE_ENV: "production"
PORT: "3000"
DB_HOST: "postgres-service"
DB_PORT: "5432"
DB_NAME: "myapp"# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: demo-app
type: Opaque
stringData:
DB_USER: "appuser"
DB_PASSWORD: "supersecretpassword"
POSTGRES_PASSWORD: "supersecretpassword"Bước 3: PostgreSQL
# k8s/postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: demo-app
labels:
app: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: api-config
key: DB_NAME
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: POSTGRES_PASSWORD
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
readinessProbe:
exec:
command: ["pg_isready", "-U", "appuser"]
initialDelaySeconds: 5
periodSeconds: 10
volumes:
- name: postgres-data
emptyDir: {} # Dùng PersistentVolume trong production!# k8s/postgres-service.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: demo-app
spec:
type: ClusterIP
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432Bước 4: Node.js API
# k8s/api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: demo-app
labels:
app: api
spec:
replicas: 3
selector:
matchLabels:
app: api
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: api
spec:
initContainers:
- name: wait-for-db
image: busybox
command: ["sh", "-c", "until nc -z postgres-service 5432; do echo waiting for postgres; sleep 2; done"]
containers:
- name: api
image: node:20-alpine
command: ["node", "server.js"]
ports:
- containerPort: 3000
envFrom:
- configMapRef:
name: api-config
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_USER
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: DB_PASSWORD
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 15# k8s/api-service.yaml
apiVersion: v1
kind: Service
metadata:
name: api-service
namespace: demo-app
spec:
type: NodePort
selector:
app: api
ports:
- port: 80
targetPort: 3000
nodePort: 30000Bước 5: Deploy Tất Cả
# Apply tất cả manifests theo thứ tự
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secret.yaml
kubectl apply -f k8s/postgres-deployment.yaml
kubectl apply -f k8s/postgres-service.yaml
kubectl apply -f k8s/api-deployment.yaml
kubectl apply -f k8s/api-service.yaml
# Hoặc apply tất cả cùng lúc
kubectl apply -f k8s/
# Kiểm tra mọi thứ đang chạy
kubectl get all -n demo-appOutput mong đợi:
NAME READY STATUS RESTARTS AGE
pod/api-7d9f8b6c5-abc12 1/1 Running 0 60s
pod/api-7d9f8b6c5-def34 1/1 Running 0 60s
pod/api-7d9f8b6c5-ghi56 1/1 Running 0 60s
pod/postgres-5c8f9d7b2-xyz89 1/1 Running 0 65s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
service/api-service NodePort 10.96.100.50 <none> 80:30000/TCP
service/postgres-service ClusterIP 10.96.100.51 <none> 5432/TCP
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/api 3/3 3 3 60s
deployment.apps/postgres 1/1 1 1 65s# Truy cập API (minikube)
minikube service api-service -n demo-app --url
# Test
curl http://<minikube-ip>:30000/healthDọn Dẹp
# Xóa tất cả resources trong namespace
kubectl delete namespace demo-app
# Hoặc xóa resources cụ thể
kubectl delete -f k8s/Bài Tập
Bài Tập 1: Deploy Web Application
Deploy nginx web server với:
- 3 replicas
- ConfigMap chứa custom
index.html - NodePort Service trên port 30080
- Liveness và readiness probes
Bài Tập 2: Thực Hành Rolling Update
- Deploy nginx:1.24 với 3 replicas
- Update lên nginx:1.25 và theo dõi rolling update
- Kiểm tra rollout history
- Roll back về 1.24
- Xác nhận rollback thành công
Bài Tập 3: Ứng Dụng Multi-Service
Deploy full stack trong namespace my-project:
- Redis deployment (1 replica) với ClusterIP Service
- Python/Node.js API (3 replicas) kết nối đến Redis
- Dùng ConfigMaps cho Redis connection settings
- Dùng Secrets cho authentication
- Init container đợi Redis sẵn sàng
Tiếp Theo
Trong bài tiếp theo, chúng ta sẽ đào sâu vào Dockerfile Best Practices & Multi-Stage Builds — làm chủ các kỹ thuật nâng cao để build container images production-ready:
- Tối ưu image size (alpine, slim, distroless, scratch)
- Chiến lược layer caching
- Multi-stage builds cho mọi ngôn ngữ
- Security hardening (non-root, read-only filesystem)
- BuildKit features (cache mounts, secrets, multi-platform)
Tóm Tắt và Điểm Chính
✅ Kubernetes orchestrate containers ở quy mô lớn với self-healing, scaling và rolling updates
✅ Control plane (API server, etcd, scheduler) quản lý cluster state; worker nodes chạy Pods
✅ Pods là đơn vị deploy nhỏ nhất — dùng Deployments để quản lý, đừng bao giờ tạo Pods trực tiếp
✅ Deployments cung cấp rolling updates, rollbacks và scaling với zero downtime
✅ Services cho Pods network endpoint ổn định — dùng ClusterIP cho internal, NodePort/LoadBalancer cho external
✅ ConfigMaps lưu configuration; Secrets lưu dữ liệu nhạy cảm (base64-encoded, không encrypted)
✅ Namespaces isolate resources và cho phép resource quotas theo team hoặc environment
✅ Labels và selectors là cách Kubernetes tổ chức và kết nối resources
✅ Luôn set resource requests/limits và health checks (liveness, readiness, startup probes)
✅ Dùng kubectl describe và kubectl logs làm công cụ debug chính
Series: Lộ Trình Học Docker & Kubernetes
Trước đó: Giai đoạn 2: Docker Compose & Ứng Dụng Multi-Container
Tiếp theo: Deep Dive: Dockerfile Best Practices & Multi-Stage Builds
Có câu hỏi về Kubernetes? Hãy liên hệ hoặc để lại comment!
📬 Đăng ký nhận bản tin
Nhận những bài viết mới nhất qua email mỗi tuần. Không spam, hủy đăng ký bất cứ lúc nào.
Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất cứ lúc nào.
💬 Comments
Đăng nhập để bình luận
Chúng tôi sẽ không đăng bất cứ điều gì mà không có sự cho phép của bạn.