
Kubernetes 入門:管理整個港口的系統
如果 Docker 是一個集裝箱,Kubernetes 就是管理整個港口的系統。
在 Container Runtime 和 Docker Compose 實戰模板 裡,我們用 Docker Compose 把多個容器組合在一起,一台機器上就能跑起完整的服務。這對小團隊、少量服務的場景完全夠用。但當你開始面對這些問題——「服務掛了能不能自動重啟?」「流量變大怎麼自動擴展?」「怎麼在不中斷服務的情況下更新版本?」「多台機器怎麼協調?」——Docker Compose 就力不從心了。Kubernetes(簡稱 K8s)就是來解決這些問題的。
為什麼需要 K8s?
單機 Docker(即使搭配 Compose)在生產環境會遇到幾個根本性的瓶頸:
flowchart LR subgraph SingleHost["單機 Docker 的瓶頸"] P1["手動 Scaling<br/>流量大了只能手動加容器"] P2["No Self-healing<br/>容器掛了要人工介入"] P3["No Rolling Update<br/>更新必須停機"] P4["單點故障<br/>Host 掛了全部服務掛"] end subgraph K8sSolves["K8s 解決方案"] S1["Horizontal Pod Autoscaler<br/>根據 CPU/Memory 自動擴縮"] S2["自動重啟 + 自動遷移<br/>Pod 掛了自動在其他 Node 重建"] S3["Rolling Update<br/>逐步替換 Pod,零停機"] S4["多 Node 叢集<br/>任一 Node 掛了,服務自動遷移"] end P1 --> S1 P2 --> S2 P3 --> S3 P4 --> S4 style SingleHost fill:#fce4ec,stroke:#c62828 style K8sSolves fill:#e8f5e9,stroke:#388e3c
Docker Compose 的 restart: unless-stopped 只能在同一台機器上重啟容器。如果那台機器本身掛了呢?如果你需要根據流量自動從 2 個實例擴展到 10 個呢?如果你要在不中斷任何一個請求的情況下從 v1.2 更新到 v1.3 呢?這些都超出了 Docker Compose 的設計範圍。
核心概念
K8s 的概念可以從外到內、從大到小來理解:
flowchart TD subgraph Cluster["Cluster(叢集)"] subgraph CP["Control Plane"] API[API Server] Sched[Scheduler] CM[Controller Manager] Etcd[(etcd)] end subgraph Node1["Node 1 (Worker)"] subgraph NS1["Namespace: production"] subgraph Deploy1["Deployment: api"] Pod1A["Pod (api-v2-abc)"] Pod1B["Pod (api-v2-def)"] end Svc1["Service: api-svc<br/>ClusterIP"] end Kubelet1[kubelet] end subgraph Node2["Node 2 (Worker)"] subgraph NS2["Namespace: production"] subgraph Deploy2["Deployment: worker"] Pod2A["Pod (worker-xyz)"] end end Kubelet2[kubelet] end Ingress["Ingress Controller<br/>外部流量入口"] --> Svc1 Svc1 --> Pod1A Svc1 --> Pod1B end API --> Kubelet1 API --> Kubelet2 style CP fill:#e3f2fd,stroke:#1976d2 style NS1 fill:#fff3e0,stroke:#f57c00 style NS2 fill:#fff3e0,stroke:#f57c00 style Deploy1 fill:#e8f5e9,stroke:#388e3c style Deploy2 fill:#e8f5e9,stroke:#388e3c
核心元件解說:
- Cluster:整個 K8s 環境,由一組 Node 組成。
- Node:叢集中的一台機器(虛擬機或實體機)。分為 Control Plane(管理層)和 Worker Node(工作層)。
- Pod:K8s 最小的部署單位。一個 Pod 裡通常跑一個容器(少數情況會有 sidecar 容器)。Pod 是短暫的,隨時可能被銷毀和重建,不要把它當成 VM 來用。
- Deployment:宣告「我要跑幾個 Pod、用什麼映像檔、怎麼更新」。Deployment 管理 Pod 的生命週期,處理 rolling update 和 rollback。
- Service:為一組 Pod 提供穩定的網路入口。Pod 的 IP 會變,但 Service 的 ClusterIP 和 DNS 名稱不會變。
- Ingress:管理外部 HTTP/HTTPS 流量如何路由到內部 Service。類似 Nginx 反向代理,但由 K8s 統一管理。
- ConfigMap / Secret:存放設定檔和敏感資料,注入到 Pod 裡。對應 Secrets & Config 的概念。
- Namespace:邏輯隔離。把不同環境(dev / staging / production)或不同團隊的資源分開。
從 Docker Compose 到 K8s 的對照表
如果你已經熟悉 Docker Compose,這張表幫助你快速對應 K8s 的概念:
| Docker Compose | Kubernetes | 用途 |
|---|---|---|
docker-compose.yml | Deployment + Service | 定義服務和網路 |
services.app.image | Deployment.spec.containers.image | 指定容器映像 |
ports: "8080:80" | Service(NodePort / LoadBalancer) | 暴露端口 |
volumes | PersistentVolumeClaim(PVC) | 持久存儲 |
environment | ConfigMap / Secret | 環境變數 |
depends_on | 無直接對應(用 initContainers) | 啟動順序 |
restart: unless-stopped | Pod restartPolicy + Deployment | 自動重啟 |
deploy.replicas | Deployment.spec.replicas | 副本數量 |
networks | NetworkPolicy | 網路隔離 |
logging | 由 Node 層級的 log agent 處理 | 日誌收集 |
最關鍵的心智模型轉變:Docker Compose 是「命令式」——你告訴 Docker 要跑什麼、怎麼跑。K8s 是「宣告式」——你描述你想要的狀態(desired state),K8s 自己想辦法達成並持續維持。
基本 K8s 清單範本
以下用一個簡單的 Web API 為例,展示最常用的 K8s 資源清單。
Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
labels:
app: api
version: v1.2.3
spec:
replicas: 3
selector:
matchLabels:
app: api
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 更新時最多多出 1 個 Pod
maxUnavailable: 0 # 更新時不允許有 Pod 不可用
template:
metadata:
labels:
app: api
version: v1.2.3
spec:
containers:
- name: api
image: registry.example.com/myapp/api:v1.2.3
ports:
- containerPort: 8000
envFrom:
- configMapRef:
name: api-config
- secretRef:
name: api-secrets
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10注意 readinessProbe 和 livenessProbe 的差別:readiness 決定 Pod 是否接收流量(不 ready 就從 Service 移除),liveness 決定 Pod 是否存活(不 live 就重啟)。這比 Docker 的單一 health check 更細緻。
Service
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: api-svc
namespace: production
spec:
selector:
app: api
ports:
- protocol: TCP
port: 80 # Service 對外的 port
targetPort: 8000 # 轉發到 Pod 的 port
type: ClusterIP # 只在叢集內部可存取Service 透過 selector 找到所有 label 為 app: api 的 Pod,自動做負載均衡。Pod 被替換了,Service 自動更新後端清單。
Ingress
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls-cert
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 80Ingress 處理 TLS 終結和路由,對應 Reverse Proxy + TLS 的角色。搭配 cert-manager 可以自動管理 Let’s Encrypt 憑證(參考 Secrets 管理與憑證生命週期)。
ConfigMap
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: production
data:
APP_ENV: production
LOG_LEVEL: info
DATABASE_HOST: postgres-svc
REDIS_HOST: redis-svc敏感資料(密碼、API Key)用 Secret,非敏感設定用 ConfigMap。修改 ConfigMap 後,需要重啟 Pod 才能吃到新值(除非應用程式有 watch config 的機制)。
K8s 生態工具
K8s 本身只是核心平台,真正發揮威力需要搭配生態工具:
flowchart TD subgraph Core["K8s Core"] K8s[Kubernetes API] end subgraph PackageMgmt["套件管理"] Helm["Helm<br/>K8s 的 apt/yum<br/>用 Chart 打包部署"] Kustomize["Kustomize<br/>用 overlay 管理多環境"] end subgraph GitOps["GitOps 部署"] Argo["ArgoCD<br/>Git repo 自動同步到叢集"] Flux["Flux<br/>另一個 GitOps 方案"] end subgraph GUI["GUI 管理"] Lens["Lens<br/>桌面端 K8s IDE"] K9s["k9s<br/>終端機 UI"] Dashboard["K8s Dashboard<br/>官方 Web UI"] end subgraph Monitoring["監控"] PromOp["Prometheus Operator<br/>一鍵部署監控 Stack"] end K8s --> PackageMgmt K8s --> GitOps K8s --> GUI K8s --> Monitoring style Core fill:#e3f2fd,stroke:#1976d2 style PackageMgmt fill:#e8f5e9,stroke:#388e3c style GitOps fill:#fff3e0,stroke:#f57c00 style GUI fill:#fce4ec,stroke:#c62828 style Monitoring fill:#f3e5f5,stroke:#7b1fa2
- Helm:K8s 的套件管理工具。把一組相關的 K8s 清單(Deployment、Service、ConfigMap 等)打包成 Chart,可以用一行命令安裝。社群有大量現成的 Chart(PostgreSQL、Redis、Prometheus、Grafana),不需要自己寫 YAML。Helm 也支援 values.yaml 做參數化,同一套 Chart 可以部署到不同環境。
- ArgoCD:GitOps 工具。把 K8s 清單放在 Git repo 裡,ArgoCD 監聽 repo 變更,自動同步到叢集。「Git 就是唯一的事實來源(single source of truth)」。搭配 CD 和 IaC 的理念,所有變更都有版本紀錄和 code review。
- Lens / k9s:K8s 的管理工具。Lens 是桌面 GUI,k9s 是終端機 UI,都能查看 Pod 狀態、即時日誌、exec 進容器、管理資源。比
kubectl直接打指令效率高很多,特別是在排查問題時。
什麼時候該上 K8s?什麼時候不該?
這是最重要的一節。K8s 是強大的工具,但它的複雜度也是真實的。不要因為「大家都在用」就上 K8s。
flowchart TD Start["你的場景"] --> Q1{"服務數量?"} Q1 -->|"1-5 個"| Q2{"需要 auto-scaling?"} Q1 -->|"10+ 個"| K8s["考慮 K8s"] Q2 -->|"不需要"| Q3{"需要 HA?"} Q2 -->|"需要"| K8s Q3 -->|"不需要"| Compose["Docker Compose<br/>+ Portainer 就夠了"] Q3 -->|"需要"| Q4{"團隊有 K8s 經驗?"} Q4 -->|"有"| K8s Q4 -->|"沒有"| Managed["用 Managed K8s<br/>GKE / EKS / AKS"] style Compose fill:#e8f5e9,stroke:#388e3c style K8s fill:#e3f2fd,stroke:#1976d2 style Managed fill:#fff3e0,stroke:#f57c00
適合 Docker Compose + Portainer 的場景:
- 小團隊(1-5 人),少量服務(1-5 個)
- 流量穩定,不需要自動擴展
- 單機或少量機器就能扛住
- 沒有專職的 DevOps/SRE
- 個人專案、Side project
適合考慮 K8s 的場景:
- 微服務架構,10 個以上的服務
- 需要根據流量自動擴縮(auto-scaling)
- 需要高可用(HA),任何單點故障都不能影響服務
- 需要零停機部署(rolling update / canary / blue-green)
- 有專職的 DevOps/SRE 或願意投入學習成本
- 多團隊共用叢集,需要資源隔離和配額管理
折衷方案:
- 如果需要 K8s 但團隊沒有經驗,用雲端的 Managed K8s(GKE、EKS、AKS)。Control Plane 由雲端廠商管理,你只管 Worker Node 和應用部署。省去了維護 etcd、API Server 等核心元件的負擔。
- Docker Swarm 是另一個選項——比 K8s 簡單很多,支援多機部署和基本的 service discovery。但社群活躍度和生態遠不如 K8s,不建議在新專案中採用。
一個誠實的建議:如果你需要花 30 分鐘以上的時間解釋為什麼需要 K8s,那你大概不需要 K8s。Docker Compose + 良好的 CI/CD + 監控,已經能搞定大部分中小型團隊的需求。K8s 的價值在規模化之後才真正顯現。
延伸閱讀
- Container Runtime:Docker Engine 基座設定,K8s 的底層容器執行環境
- Docker Compose 實戰模板:在還不需要 K8s 的階段,用標準化的 Compose 模板管理服務
- CD:CI pipeline 配合 K8s 部署的流程整合
- Infrastructure as Code:用 Terraform 管理 K8s 叢集本身的基礎設施