Kubernetes 入門與生產部署實戰 2026 | 容器編排完全指南

Kubernetes(K8s)是容器編排的事實標準。當 Docker Compose 無法滿足大規模容器管理需求時,K8s 提供了自動擴縮容、自愈、服務發現等強大能力。本文將從核心概念到生產部署,系統講解 K8s 實戰。
一、Kubernetes 核心概念
1.1 架構概覽
┌─────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌──────────────────────┐ ┌──────────────────────────┐ │
│ │ Control Plane │ │ Worker Nodes │ │
│ │ (Master) │ │ │ │
│ │ │ │ ┌─────────────────────┐ │ │
│ │ • API Server │◄──►│ │ kubelet │ │ │
│ │ • etcd │ │ │ kube-proxy │ │ │
│ │ • Scheduler │ │ │ Container Runtime │ │ │
│ │ • Controller Manager │ │ │ (containerd) │ │ │
│ │ • Cloud Controller │ │ │ │ │ │
│ └──────────────────────┘ │ │ Pod → Pod → Pod │ │ │
│ │ └─────────────────────┘ │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘1.2 核心對象
| 對象 | 說明 | 類比 |
|---|---|---|
| Pod | 最小調度單位,包含一個或多個容器 | 一間辦公室 |
| Deployment | 管理 Pod 的副本和更新 | 辦公室管理層 |
| Service | 為 Pod 提供穩定的網絡訪問 | 前臺總機 |
| ConfigMap | 配置數據 | 配置文件 |
| Secret | 敏感數據 | 保險箱 |
| Ingress | HTTP 路由 | 大門口指引 |
| Volume | 存儲卷 | 文件櫃 |
| Namespace | 資源隔離 | 樓層 |
二、本地環境搭建
2.1 Minikube(推薦入門)
bash
# 安裝 Minikube(macOS)
brew install minikube
# 啟動集群
minikube start --driver=docker --kubernetes-version=v1.30.0
# 驗證
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# minikube Ready control-plane 1m v1.30.0
# 啟動 Dashboard
minikube dashboard2.2 kubectl 命令行工具
bash
# 安裝
brew install kubectl
# 常用命令
kubectl get pods # 查看 Pod
kubectl get deployments # 查看 Deployment
kubectl get services # 查看 Service
kubectl get nodes # 查看節點
kubectl describe pod <pod-name> # 查看詳情
kubectl logs <pod-name> # 查看日誌
kubectl exec -it <pod-name> -- sh # 進入容器
kubectl apply -f <file.yaml> # 應用配置
kubectl delete -f <file.yaml> # 刪除資源
kubectl scale deployment <name> --replicas=3 # 擴縮容三、Pod 與 Deployment
3.1 Pod 基本定義
yaml
# pod-simple.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 3
periodSeconds: 5
restartPolicy: Always3.2 Deployment 部署
yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
namespace: production
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: my-registry/web-app:v1.0.0
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5bash
# 部署
kubectl apply -f deployment.yaml
# 查看部署狀態
kubectl rollout status deployment/web-app
# 查看副本
kubectl get pods -l app=web
# 滾動更新(更新鏡像版本)
kubectl set image deployment/web-app web=my-registry/web-app:v1.1.0
# 回滾
kubectl rollout undo deployment/web-app
kubectl rollout undo deployment/web-app --to-revision=2
# 查看歷史
kubectl rollout history deployment/web-app3.3 多容器 Pod(Sidecar 模式)
yaml
# sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
# 主容器:Web 應用
- name: web
image: my-app:v1
ports:
- containerPort: 3000
volumeMounts:
- name: logs
mountPath: /var/log/app
# Sidecar:日誌收集
- name: log-collector
image: fluent-bit:3.0
volumeMounts:
- name: logs
mountPath: /var/log/app
readOnly: true
volumes:
- name: logs
emptyDir: {}四、Service 與網絡
4.1 Service 類型
yaml
# 1. ClusterIP(默認,集群內部訪問)
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
type: ClusterIP
selector:
app: web
ports:
- port: 80
targetPort: 3000
---
# 2. NodePort(暴露到節點端口)
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 3000
nodePort: 30080
---
# 3. LoadBalancer(雲負載均衡器)
apiVersion: v1
kind: Service
metadata:
name: web-lb
spec:
type: LoadBalancer
selector:
app: web
ports:
- port: 80
targetPort: 30004.2 Headless Service(用於 StatefulSet)
yaml
apiVersion: v1
kind: Service
metadata:
name: database
spec:
clusterIP: None # Headless
selector:
app: postgres
ports:
- port: 54324.3 Ingress 路由
yaml
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
cert-manager.io/cluster-issuer: "letsencrypt"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
- app.example.com
secretName: tls-secret
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80五、配置管理
5.1 ConfigMap
yaml
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
# 簡單鍵值
LOG_LEVEL: "info"
API_TIMEOUT: "5000"
CACHE_TTL: "3600"
# 配置文件
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://backend:3000;
}
}yaml
# 在 Deployment 中使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
template:
spec:
containers:
- name: app
image: my-app:v1
envFrom:
- configMapRef:
name: app-config
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
volumes:
- name: config-volume
configMap:
name: app-config
items:
- key: nginx.conf
path: default.conf5.2 Secret
bash
# 創建 Secret
kubectl create secret generic app-secrets \
--from-literal=database-url="postgresql://user:pass@db:5432/myapp" \
--from-literal=api-key="sk-xxxxxxxxxxxx" \
--from-literal=jwt-secret="my-jwt-secret"yaml
# secret.yaml(Base64 編碼)
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
database-url: cG9zdGdyZXNxbDovL3VzZXI6cGFzc0BkYjo1NDMyL215YXBw
api-key: c2steHh4eHh4eHh4eHh4eHg=
jwt-secret: bXktand0LXNlY3JldA==yaml
# 在 Pod 中使用
spec:
containers:
- name: app
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
- name: API_KEY
valueFrom:
secretKeyRef:
name: app-secrets
key: api-key六、存儲管理
6.1 PersistentVolume 與 PVC
yaml
# pv.yaml — 持久卷
apiVersion: v1
kind: PersistentVolume
metadata:
name: data-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
hostPath:
path: /mnt/data
---
# pvc.yaml — 持久卷聲明
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard
resources:
requests:
storage: 5Giyaml
# 在 Pod 中使用
spec:
containers:
- name: database
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc6.2 StorageClass(動態 provisioning)
yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
fsType: ext4
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer七、Helm 包管理
7.1 安裝 Helm
bash
# 安裝
brew install helm
# 添加倉庫
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# 搜索
helm search repo redis7.2 使用 Helm Chart
bash
# 安裝 Redis
helm install my-redis bitnami/redis \
--namespace database \
--create-namespace \
--set auth.password="my-password" \
--set replica.replicaCount=3
# 查看已安裝的 Chart
helm list -n database
# 升級
helm upgrade my-redis bitnami/redis \
--set replica.replicaCount=5
# 卸載
helm uninstall my-redis -n database7.3 創建自定義 Chart
bash
# 創建 Chart 骨架
helm create my-appmy-app/
├── Chart.yaml # Chart 元數據
├── values.yaml # 默認配置值
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ └── _helpers.tpl # 模板輔助函數
└── charts/ # 依賴的子 Chartyaml
# values.yaml
replicaCount: 3
image:
repository: my-app
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: true
host: app.example.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Miyaml
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ include "my-app.name" . }}
template:
metadata:
labels:
app: {{ include "my-app.name" . }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: {{ .Values.service.port }}
resources:
{{- toYaml .Values.resources | nindent 12 }}bash
# 模板渲染(預覽)
helm template my-app ./my-app
# 安裝
helm install my-app ./my-app -n production
# 打包
helm package ./my-app八、生產環境最佳實踐
8.1 健康檢查
yaml
spec:
containers:
- name: app
# 存活探針:失敗會重啟容器
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 3
# 就緒探針:失敗會從 Service 摘除
readinessProbe:
httpGet:
path: /readyz
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
# 啟動探針:應用啟動慢時使用
startupProbe:
httpGet:
path: /startup
port: 3000
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30 # 最多等 150 秒啟動8.2 資源管理
yaml
spec:
containers:
- name: app
resources:
# 請求:調度依據
requests:
cpu: 250m # 0.25 核
memory: 256Mi
# 限制:硬上限
limits:
cpu: 500m # 0.5 核
memory: 512Mi8.3 安全加固
yaml
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
# Pod Security Standards
# restricted / baseline / privileged8.4 HPA 自動擴縮容
yaml
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 608.5 PodDisruptionBudget
yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb
spec:
minAvailable: 2 # 至少保持 2 個可用
selector:
matchLabels:
app: web九、CI/CD 集成
9.1 GitHub Actions 部署到 K8s
yaml
# .github/workflows/deploy-k8s.yml
name: Deploy to K8s
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Login to ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/web-app:$IMAGE_TAG .
docker push $ECR_REGISTRY/web-app:$IMAGE_TAG
- name: Configure kubectl
run: |
aws eks update-kubeconfig --name my-cluster --region ap-northeast-1
- name: Deploy
run: |
kubectl set image deployment/web-app \
web=$ECR_REGISTRY/web-app:${{ github.sha }} \
-n production
kubectl rollout status deployment/web-app -n production十、總結
- ✅ K8s 架構與核心概念(Pod、Deployment、Service)
- ✅ 本地開發環境搭建(Minikube + kubectl)
- ✅ Pod 與 Deployment 部署(滾動更新、回滾、Sidecar)
- ✅ Service 與 Ingress 網絡路由
- ✅ 配置管理(ConfigMap、Secret)
- ✅ 存儲管理(PV、PVC、StorageClass)
- ✅ Helm 包管理(安裝 Chart、自定義 Chart)
- ✅ 生產最佳實踐(健康檢查、資源管理、安全加固、HPA、PDB)
- ✅ CI/CD 集成(GitHub Actions 自動部署)
Kubernetes 是雲原生時代的基礎設施,掌握它意味著具備了構建大規模容器化應用的能力。
相關閱讀: