Kubernetes: Triển khai ứng dụng đầu tiên
Hướng dẫn thực hành để triển khai ứng dụng trên Kubernetes. Từ cài đặt minikube đến Deployments, Services và ConfigMaps với các ví dụ cụ thể.

Kubernetes (K8s) đã trở thành tiêu chuẩn de facto cho việc điều phối container. Được thiết kế bởi Google và hiện được CNCF duy trì, Kubernetes tự động hóa việc triển khai, mở rộng và quản lý các ứng dụng được container hóa. Hướng dẫn này đi qua việc thiết lập một cluster cục bộ và triển khai ứng dụng đầu tiên.
Kiến thức cơ bản về Docker được khuyến nghị trước khi đi sâu vào Kubernetes. Container là các khối nền tảng mà Kubernetes điều phối. Đọc trước hướng dẫn Docker giúp việc hiểu các khái niệm được trình bày ở đây dễ dàng hơn rất nhiều.
Hiểu về kiến trúc Kubernetes
Kubernetes dựa trên kiến trúc master-worker. Control Plane đưa ra các quyết định toàn cục về cluster, trong khi các Node chạy các workload.
# Simplified Kubernetes Architecture
┌─────────────────────────────────────────────────────────────┐
│ CONTROL PLANE │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ API Server │ │ Scheduler │ │ Controller Manager │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ etcd ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ NODE 1 │ │ NODE 2 │ │ NODE 3 │
│ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │
│ │ kubelet │ │ │ │ kubelet │ │ │ │ kubelet │ │
│ ├───────────┤ │ │ ├───────────┤ │ │ ├───────────┤ │
│ │ kube-proxy│ │ │ │ kube-proxy│ │ │ │ kube-proxy│ │
│ ├───────────┤ │ │ ├───────────┤ │ │ ├───────────┤ │
│ │ Pods │ │ │ │ Pods │ │ │ │ Pods │ │
│ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘ └─────────────────┘API Server là điểm vào cho mọi lệnh. etcd lưu trữ trạng thái của cluster. Scheduler gán Pod cho các Node. Controller duy trì trạng thái mong muốn của hệ thống.
Thiết lập môi trường cục bộ
Có nhiều tùy chọn để thử nghiệm Kubernetes cục bộ: minikube, kind, k3d hoặc Docker Desktop. Minikube vẫn là giải pháp phổ biến nhất để học.
# terminal
# Install kubectl (Kubernetes client)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# Verify installation
kubectl version --client
# Client Version: v1.31.0
# Install minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# Start the local cluster
minikube start --driver=docker --cpus=2 --memory=4096
# Check status
minikube status
# minikube: Running
# cluster: Running
# kubectl: ConfiguredMinikube tạo một cluster Kubernetes một-node bên trong một máy ảo hoặc một container Docker. Tài nguyên được phân bổ (CPU, bộ nhớ) có thể được điều chỉnh theo nhu cầu.
# terminal
# Access the Kubernetes dashboard (web interface)
minikube dashboard
# Check cluster nodes
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# minikube Ready control-plane 5m v1.31.0
# Detailed cluster information
kubectl cluster-infoKind (Kubernetes in Docker) khởi động nhanh hơn và phù hợp hơn cho việc kiểm thử CI/CD. K3d sử dụng k3s, một bản phân phối Kubernetes nhẹ. Docker Desktop tích hợp Kubernetes trực tiếp nhưng tiêu thụ nhiều tài nguyên hơn.
Pods: đơn vị cơ bản
Pod là đơn vị nhỏ nhất có thể triển khai trong Kubernetes. Một Pod đóng gói một hoặc nhiều container chia sẻ cùng một mạng và bộ lưu trữ.
# pod-simple.yaml
apiVersion: v1
kind: Pod
metadata:
# Unique Pod name within the namespace
name: nginx-pod
# Labels for organization and selection
labels:
app: nginx
environment: development
spec:
containers:
# Main container definition
- name: nginx
# Docker image to use
image: nginx:1.25-alpine
# Ports exposed by the container
ports:
- containerPort: 80
# Container resource allocation
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"Manifest YAML này khai báo một Pod chứa một container nginx duy nhất. Các nhãn cho phép xác định và chọn các Pod. Tài nguyên xác định các đảm bảo tối thiểu (requests) và giới hạn tối đa (limits).
# terminal
# Create the Pod
kubectl apply -f pod-simple.yaml
# pod/nginx-pod created
# List Pods
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# nginx-pod 1/1 Running 0 30s
# Full Pod details
kubectl describe pod nginx-pod
# Container logs
kubectl logs nginx-pod
# Execute a command inside the Pod
kubectl exec -it nginx-pod -- /bin/sh
# Delete the Pod
kubectl delete pod nginx-podPod có bản chất là tạm thời. Trong trường hợp gặp sự cố hoặc bị xóa, Kubernetes không tự động tạo lại chúng. Deployment giải quyết hạn chế này.
Deployments: quản lý theo kiểu khai báo
Deployment xác định trạng thái mong muốn cho một tập hợp các Pod giống nhau. Kubernetes tự động duy trì trạng thái này bằng cách tạo, cập nhật hoặc xóa các Pod khi cần.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
# Deployment name
name: webapp-deployment
labels:
app: webapp
spec:
# Desired number of replicas
replicas: 3
# Selector to identify managed Pods
selector:
matchLabels:
app: webapp
# Template for Pod creation
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
# Liveness probe: restarts container on failure
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
# Readiness probe: removes Pod from Service on failure
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5Deployment tạo một ReplicaSet duy trì 3 Pod giống nhau. Các probe kiểm tra trạng thái của các container và cho phép Kubernetes phản ứng tự động với các sự cố.
# terminal
# Create the Deployment
kubectl apply -f deployment.yaml
# deployment.apps/webapp-deployment created
# Verify the Deployment
kubectl get deployments
# NAME READY UP-TO-DATE AVAILABLE AGE
# webapp-deployment 3/3 3 3 1m
# List Pods created by the Deployment
kubectl get pods -l app=webapp
# NAME READY STATUS RESTARTS AGE
# webapp-deployment-7d9f8b6c4-abc12 1/1 Running 0 1m
# webapp-deployment-7d9f8b6c4-def34 1/1 Running 0 1m
# webapp-deployment-7d9f8b6c4-ghi56 1/1 Running 0 1m
# Manual scaling
kubectl scale deployment webapp-deployment --replicas=5
# Deployment history
kubectl rollout history deployment webapp-deploymentXóa một Pod sẽ tự động kích hoạt việc tạo một Pod mới để duy trì số lượng bản sao mong muốn.
Sẵn sàng chinh phục phỏng vấn DevOps?
Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.
Services: phơi bày mạng
Các Pod có địa chỉ IP tạm thời. Services cung cấp một địa chỉ ổn định để truy cập một tập hợp các Pod, với cân bằng tải tích hợp.
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
# Service type: ClusterIP (internal), NodePort, LoadBalancer
type: ClusterIP
# Selector to identify target Pods
selector:
app: webapp
ports:
# Port exposed by the Service
- port: 80
# Target container port
targetPort: 80
# Protocol (TCP by default)
protocol: TCPService ClusterIP này chỉ có thể truy cập được từ bên trong cluster. Các yêu cầu đến webapp-service:80 được phân phối giữa các Pod có nhãn app: webapp.
# terminal
# Create the Service
kubectl apply -f service.yaml
# service/webapp-service created
# List Services
kubectl get services
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# webapp-service ClusterIP 10.96.123.456 <none> 80/TCP 30s
# Test from a temporary Pod
kubectl run curl-test --rm -it --image=curlimages/curl -- curl webapp-service
# Detailed Service description
kubectl describe service webapp-serviceĐể phơi bày ứng dụng ra ngoài cluster, cần loại NodePort hoặc LoadBalancer.
# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp-nodeport
spec:
type: NodePort
selector:
app: webapp
ports:
- port: 80
targetPort: 80
# Port on each Node (30000-32767)
nodePort: 30080Với minikube, lệnh minikube service webapp-nodeport tự động mở trình duyệt tại đúng URL.
ConfigMaps: cấu hình bên ngoài
ConfigMap tách cấu hình khỏi mã nguồn. Các giá trị được tiêm dưới dạng biến môi trường hoặc gắn dưới dạng tệp.
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: webapp-config
data:
# Simple key-value pairs
APP_ENV: "production"
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
# Multiline configuration (complete file)
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /health {
return 200 'OK';
add_header Content-Type text/plain;
}
}ConfigMap lưu trữ dữ liệu không nhạy cảm. Đối với các bí mật (mật khẩu, token), Secrets của Kubernetes phù hợp hơn.
# deployment-with-config.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-configured
spec:
replicas: 2
selector:
matchLabels:
app: webapp-configured
template:
metadata:
labels:
app: webapp-configured
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
# Inject environment variables
envFrom:
- configMapRef:
name: webapp-config
# Or individual variables
env:
- name: SPECIFIC_VAR
valueFrom:
configMapKeyRef:
name: webapp-config
key: LOG_LEVEL
# Mount configuration file
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: webapp-configCấu hình này tiêm các biến môi trường và gắn tệp nginx.conf vào bên trong container.
# terminal
# Apply resources
kubectl apply -f configmap.yaml
kubectl apply -f deployment-with-config.yaml
# Verify environment variables
kubectl exec deployment/webapp-configured -- printenv | grep APP_ENV
# APP_ENV=production
# Verify mounted file
kubectl exec deployment/webapp-configured -- cat /etc/nginx/conf.d/default.confViệc sửa đổi một ConfigMap không tự động khởi động lại các Pod. Để áp dụng thay đổi, cần khởi động lại thủ công: kubectl rollout restart deployment webapp-configured. Các công cụ như Reloader tự động hóa quy trình này.
Secrets: dữ liệu nhạy cảm
Secret lưu trữ thông tin nhạy cảm như mật khẩu, token hoặc khóa SSH. Mặc dù được mã hóa base64, chúng không được mã hóa mặc định khi ở trạng thái nghỉ.
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: webapp-secrets
type: Opaque
# Values must be base64-encoded
data:
# echo -n 'admin' | base64
username: YWRtaW4=
# echo -n 'supersecretpassword' | base64
password: c3VwZXJzZWNyZXRwYXNzd29yZA==
---
# Alternative: stringData accepts plain text values
apiVersion: v1
kind: Secret
metadata:
name: webapp-secrets-plain
type: Opaque
stringData:
username: admin
password: supersecretpasswordSecret được tiêm theo cùng cách như ConfigMap.
# deployment-with-secrets.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-secure
spec:
replicas: 1
selector:
matchLabels:
app: webapp-secure
template:
metadata:
labels:
app: webapp-secure
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: webapp-secrets
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: webapp-secrets
key: password# terminal
# Create the Secret
kubectl apply -f secret.yaml
# List Secrets (values are not displayed)
kubectl get secrets
# NAME TYPE DATA AGE
# webapp-secrets Opaque 2 10s
# Decode a value
kubectl get secret webapp-secrets -o jsonpath='{.data.password}' | base64 -d
# supersecretpasswordNamespaces: cô lập logic
Namespace phân chia một cluster thành các môi trường ảo cô lập. Sự phân chia này cho phép quản lý nhiều nhóm hoặc môi trường trên cùng một cluster.
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: development
labels:
environment: development
---
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
environment: stagingMỗi tài nguyên có thể được tạo trong một namespace cụ thể.
# terminal
# Create namespaces
kubectl apply -f namespace.yaml
# List namespaces
kubectl get namespaces
# NAME STATUS AGE
# default Active 1d
# development Active 10s
# staging Active 10s
# Create a resource in a specific namespace
kubectl apply -f deployment.yaml -n development
# List Pods in a namespace
kubectl get pods -n development
# Change default namespace
kubectl config set-context --current --namespace=developmentTài nguyên trong các namespace khác nhau được cô lập theo mặc định. Giao tiếp giữa các namespace được thực hiện thông qua DNS nội bộ: service-name.namespace.svc.cluster.local.
Ứng dụng hoàn chỉnh: lắp ráp các tài nguyên
Dưới đây là một ứng dụng hoàn chỉnh kết hợp tất cả các khái niệm đã trình bày.
# complete-app.yaml
---
# Dedicated Namespace
apiVersion: v1
kind: Namespace
metadata:
name: myapp
---
# ConfigMap for configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: myapp
data:
APP_NAME: "MyApp"
LOG_LEVEL: "info"
---
# Secret for sensitive data
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
namespace: myapp
type: Opaque
stringData:
api-key: "sk-1234567890abcdef"
---
# Deployment with 3 replicas
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: myapp-config
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: myapp-secrets
key: api-key
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
---
# Service for internal exposure
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: myapp
spec:
type: ClusterIP
selector:
app: myapp
ports:
- port: 80
targetPort: 80
---
# NodePort Service for external access (development)
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
namespace: myapp
spec:
type: NodePort
selector:
app: myapp
ports:
- port: 80
targetPort: 80
nodePort: 30100Một tệp duy nhất này triển khai một ứng dụng hoàn chỉnh với cấu hình bên ngoài, các bí mật, tính sẵn sàng cao và phơi bày mạng.
# terminal
# Deploy the complete application
kubectl apply -f complete-app.yaml
# Verify all resources
kubectl get all -n myapp
# NAME READY STATUS RESTARTS AGE
# pod/myapp-7d9f8b6c4-abc12 1/1 Running 0 30s
# pod/myapp-7d9f8b6c4-def34 1/1 Running 0 30s
# pod/myapp-7d9f8b6c4-ghi56 1/1 Running 0 30s
#
# NAME TYPE CLUSTER-IP PORT(S) AGE
# service/myapp-service ClusterIP 10.96.123.456 80/TCP 30s
# service/myapp-nodeport NodePort 10.96.123.789 80:30100/TCP 30s
#
# NAME READY UP-TO-DATE AVAILABLE AGE
# deployment.apps/myapp 3/3 3 3 30s
# Access the application with minikube
minikube service myapp-nodeport -n myappCập nhật và rollback
Kubernetes hỗ trợ các cập nhật tiến triển và rollback một cách dễ dàng.
# terminal
# Update the Deployment image
kubectl set image deployment/myapp myapp=nginx:1.26-alpine -n myapp
# Track deployment in real-time
kubectl rollout status deployment/myapp -n myapp
# Waiting for deployment "myapp" rollout to finish: 1 out of 3 new replicas updated
# Waiting for deployment "myapp" rollout to finish: 2 out of 3 new replicas updated
# deployment "myapp" successfully rolled out
# Revision history
kubectl rollout history deployment/myapp -n myapp
# REVISION CHANGE-CAUSE
# 1 <none>
# 2 <none>
# Rollback to previous revision
kubectl rollout undo deployment/myapp -n myapp
# Rollback to a specific revision
kubectl rollout undo deployment/myapp --to-revision=1 -n myappChiến lược cập nhật mặc định (RollingUpdate) thay thế dần các Pod cũ bằng các Pod mới, đảm bảo tính sẵn sàng liên tục.
Các lệnh kubectl thiết yếu
# terminal
# ========================================
# General Information
# ========================================
kubectl cluster-info # Cluster info
kubectl get nodes -o wide # Nodes with details
kubectl api-resources # List resource types
# ========================================
# Resource Management
# ========================================
kubectl get all # All namespace resources
kubectl get pods -A # Pods from all namespaces
kubectl get pods -o wide # Pods with IP and Node
kubectl get pods -w # Watch mode (real-time)
# ========================================
# Inspection and Debugging
# ========================================
kubectl describe pod <name> # Full details
kubectl logs <pod> -f # Streaming logs
kubectl logs <pod> -c <container> # Specific container logs
kubectl exec -it <pod> -- /bin/sh # Interactive shell
kubectl port-forward <pod> 8080:80 # Local tunnel to Pod
# ========================================
# Editing and Deletion
# ========================================
kubectl edit deployment <name> # Live editing (vi)
kubectl delete -f manifest.yaml # Delete via file
kubectl delete pod <name> --force # Force deletionKết luận
Kubernetes biến đổi việc quản lý các ứng dụng được container hóa bằng cách cung cấp một khuôn khổ khai báo, có khả năng phục hồi và mở rộng. Các khái niệm cơ bản được trình bày ở đây tạo nền tảng cho các triển khai sẵn sàng cho production.
Danh sách kiểm tra cho lần triển khai Kubernetes đầu tiên
- ✅ Cluster cục bộ hoạt động (minikube, kind hoặc k3d)
- ✅ kubectl đã cài đặt và cấu hình
- ✅ Deployment với các bản sao và health probes
- ✅ Service để phơi bày mạng
- ✅ ConfigMap cho cấu hình bên ngoài
- ✅ Secret cho dữ liệu nhạy cảm
- ✅ Namespace để cô lập
- ✅ Giới hạn tài nguyên đã được xác định (requests/limits)
- ✅ Nắm vững chiến lược cập nhật và rollback
Bắt đầu luyện tập!
Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.
Thành thạo Kubernetes mở ra cánh cửa tới các kiến trúc cloud-native có khả năng mở rộng. Các bước tiếp theo bao gồm khám phá Ingress Controllers cho định tuyến HTTP, PersistentVolumes cho lưu trữ và Helm cho quản lý gói. Kubernetes trở thành một tài sản quan trọng trong các cuộc phỏng vấn DevOps và SRE.
Thẻ
Chia sẻ
Bài viết liên quan

Câu hỏi Phỏng vấn DevOps Thiết yếu: Hướng dẫn Đầy đủ 2026
Chuẩn bị phỏng vấn DevOps với những câu hỏi bắt buộc về CI/CD, Kubernetes, Docker, Terraform và các thực tiễn SRE. Có câu trả lời chi tiết.

Docker: tu phat trien den san xuat
Huong dan Docker day du de container hoa ung dung. Dockerfile, Docker Compose, multi-stage build va trien khai san xuat voi cac vi du thuc te.

Phong van Kubernetes: Giai thich chi tiet Pods, Services va Deployments
Cac cau hoi phong van Kubernetes ve Pods, Services va Deployments — voi vi du YAML, co che networking noi bo va chien luoc scaling cho nam 2026.