Kubernetes 入門:Pod、Service、Deployment
當你的應用只是一個簡單的 Docker 容器時,用 Docker Compose 來管理就已經足夠了。但當你的系統擴展到以下規模時,Docker Compose 就會開始顯得力不從心:
- 你的應用需要自動伸縮(流量高時自動增加副本,流量低時減少)
- 某個容器 crash 了,需要自動重新啟動
- 你需要在不中斷服務的情況下更新版本(滾動更新)
- 你需要將多個容器平均分配到不同的伺服器上(負載平衡)
- 你的服務散落在多台雲端主機上,需要統一管理
這時候,我們就需要 Kubernetes (K8s) 登場了。
什麼是 Kubernetes?
Kubernetes 是一個容器編排平台 (Container Orchestration Platform),由 Google 基於其內部使用多年的 Borg 系統開源而來,現在由 Cloud Native Computing Foundation (CNCF) 維護。
簡單來說,Kubernetes 就是你整個應用的「作業系統」:
- Docker 容器就像是「應用程式」
- Kubernetes 就像是「作業系統」,負責管理這些應用程式的啟動、監控、資源分配與溝通
Kubernetes 的優勢
| 功能 | 說明 | |------|------| | 自動修復 | 當某個容器 crash,K8s 自動重新啟動 | | 自動伸縮 | 根據 CPU 或記憶體使用量,自動增減容器數量 | | 滾動更新 | 更新版本時逐步替換,不中斷服務 | | 服務發現 | 自動為每個服務分配 DNS 名稱,容器間可直接透過名稱溝通 | | 負載平衡 | 自動將流量分配到多個容器副本 | | 儲存編排 | 自動掛載雲端硬碟、本地儲存等 | | 自我修復 | 如果某個節點 (Node) 掛了,自動在其他節點重新排程 |
Kubernetes 的三大核心物件
在 Kubernetes 中,一切都是「物件 (Object)」。你透過撰寫 YAML 或 JSON 來宣告你想要的狀態,然後 K8s 會努力讓現實狀態符合你的宣告。
1. Pod(最小的部署單元)
Pod 是 Kubernetes 中最小的可部署單元。一個 Pod 裡面可以包含一個或多個容器(通常是一個)。
你可以把 Pod 想像成「一艘太空船」:
- 太空船裡面可以有一個或多個太空人(容器)
- 每個太空人各自執行不同的任務
- 他們共享太空船的生命週期與資源
- 太空船被摧毀時,所有太空人同時消失
Pod 的 YAML 範例:
apiVersion: v1
kind: Pod
metadata:
name: my-app-pod
labels:
app: my-app
version: v1
spec:
containers:
- name: my-app
image: my-app:latest
ports:
- containerPort: 3000
resources:
requests:
cpu: "250m" # 最少保證 0.25 核心
memory: "256Mi" # 最少保證 256 MB
limits:
cpu: "500m" # 最多使用 0.5 核心
memory: "512Mi" # 最多使用 512 MB
但 Pod 有一個重要的特性:Pod 是臨時性的 (Ephemeral)。如果你刪除了一個 Pod,它不會自動重現。這就是為什麼我們通常不會直接建立 Pod,而是透過更高層的抽象來管理它們。
2. Deployment(宣告期望狀態)
Deployment 是 Kubernetes 中最常用的控制器。它定義了你期望的「副本數量」與「更新策略」,K8s 會自動確保實際運行的 Pod 數量符合你的期望。
Deployment 的 YAML 範例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 3 # 期望 3 個副本
selector:
matchLabels:
app: my-app
template: # Pod 模板
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:v2
ports:
- containerPort: 3000
livenessProbe: # 存活檢查:如果失敗則重新啟動
httpGet:
path: /api/health
port: 3000
initialDelaySeconds: 10
periodSeconds: 15
readinessProbe: # 就緒檢查:如果失敗則不導入流量
httpGet:
path: /api/ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
Deployment 的關鍵能力:
滾動更新 (Rolling Update)
當你將 Image 版本從 v1 更新到 v2 時,K8s 會逐步替換 Pod:
- 建立一個 v2 的 Pod
- 等待 v2 的 Pod 通過 Readiness Probe(就緒檢查)
- 刪除一個 v1 的 Pod
- 重複直到所有 Pod 都被替換
這確保了更新過程中服務完全不會中斷。
自動復原 (Rollback) 如果 v2 版本出了問題(例如 Liveness Probe 失敗),K8s 會自動停止滾動,保留 v1 版本:
# 查看 Deployment 的更新歷史
kubectl rollout history deployment/my-app-deployment
# 回滾到上一個版本
kubectl rollout undo deployment/my-app-deployment
3. Service(穩定的存取入口)
Pod 是動態的,它可能因為節點故障而被重新排程到不同的伺服器,IP 位址也會隨之改變。如果我們直接使用 Pod 的 IP 來連線,只要 Pod 重啟或漂移,連線就會中斷。
Service 提供了一個穩定的虛擬 IP (ClusterIP) 與 DNS 名稱,作為後端 Pod 的存取入口。
Service 的 YAML 範例:
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app # 選擇所有 label 為 app: my-app 的 Pod
ports:
- protocol: TCP
port: 80 # Service 對外開放的埠
targetPort: 3000 # 轉發到 Pod 的 3000 埠
type: ClusterIP # 只在叢集內部可存取
Service 的四種類型:
| 類型 | 說明 | 使用場景 | |------|------|---------| | ClusterIP | 只在叢集內部可存取,分配一個虛擬 IP | 內部服務(資料庫、API) | | NodePort | 在所有節點上開啟一個隨機埠,外部可透過節點 IP 存取 | 開發測試 | | LoadBalancer | 自動建立雲端負載平衡器,分配外部 IP | 正式環境(搭配雲端服務商) | | Ingress | 七層 HTTP 路由,根據域名或路徑轉發到不同 Service | 生產環境的對外入口 |
在本機建立 Kubernetes 測試叢集
在正式購買雲端 K8s 叢集之前,我們可以用 kind (Kubernetes in Docker) 來在本機建立一個測試用的 K8s 環境。
安裝 kind
# macOS (Homebrew)
brew install kind
# 驗證安裝
kind version
建立一個叢集
kind create cluster --name my-test-cluster
輸出範例:
Creating cluster "my-test-cluster" ...
✓ Ensuring node image (kindest/node:v1.28.0) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-my-test-cluster"
You can now use your cluster with:
kubectl cluster-info --context kind-my-test-cluster
驗證叢集狀態
# 檢視節點
kubectl get nodes
# 檢視系統 Pod
kubectl get pods -n kube-system
# 取得叢集資訊
kubectl cluster-info
部署你的第一個應用
現在,讓我們用剛才學到的 Deployment 與 Service,將我們之前 Docker 化的應用部署到 K8s 上:
# 部署應用(建立 Deployment)
kubectl apply -f deployment.yaml
# 暴露服務(建立 Service)
kubectl apply -f service.yaml
# 查看 Pod 狀態
kubectl get pods -w
# 查看 Service
kubectl get svc
[!TIP] 在 kind 中,由於不是雲端環境,LoadBalancer 類型的 Service 不會自動分配外部 IP。你可以使用
kubectl port-forward來將叢集內的服務轉發到本機:kubectl port-forward service/my-app-service 3000:80
本日總結
在本章中,你學到了:
- ✅ Kubernetes 是什麼:一個容器編排平台,管理容器叢集的生命週期
- ✅ Pod:最小的部署單元,運行一個或多個容器
- ✅ Deployment:宣告期望狀態,管理 Pod 的滾動更新與伸縮
- ✅ Service:提供穩定的存取入口,支援 ClusterIP/NodePort/LoadBalancer/Ingress
- ✅ kind 本地叢集:在本機用 Docker 建立 K8s 測試環境
- ✅ kubectl 基本操作:get、apply、port-forward、rollout
下一章,我們將真正把一個完整的應用部署到雲端 Kubernetes 叢集上!