下面我把 **Kubernetes Deployment** 的概念、常用欄位、範例 YAML、常見操作指令、進階設定(滾動更新、probe、HPA、PDB、回滾)和最佳實務整理成一個實用手冊,帶註解與範例,方便你直接複製貼上、實作與調整。
# 1) Deployment 簡介(一句話)
Deployment 是 Kubernetes 用來 **管理一組 Pod(通常是無狀態應用)與其 ReplicaSet** 的控制器,讓你以「聲明式(declarative)」方式指定期望狀態,且支援受控更新(rolling updates)、回滾等功能。([Kubernetes][1])
---
# 2) 最重要的欄位(高階說明)
* `apiVersion: apps/v1` / `kind: Deployment` / `metadata`:基本識別。
* `spec.replicas`:期望的 Pod 數量。
* `spec.selector`:**必填**且(在 apps/v1)**建立後不可變**,必須和 `spec.template.metadata.labels` 相符(否則 API 會拒絕)。這個 selector 決定哪些 Pod 屬於這個 Deployment。([Kubernetes][2])
* `spec.template`:描述 Pod 模板(容器、ports、env、probes、resources…)。
* `spec.strategy`:部署策略,常見有 `RollingUpdate`(預設)與 `Recreate`;`RollingUpdate` 有 `maxSurge`、`maxUnavailable` 用來調整更新時的速度/可用性。從 Kubernetes 1.16 起,`maxSurge` / `maxUnavailable` 的預設值已改為 `25%`(可用整數或百分比)。([Kubernetes][3])
---
# 3) Annotated 範例 YAML(最常見的 minimal + production-oriented fields)
```yaml
apiVersion: apps/v1 # Deployment 所屬的 API 版本(固定為 apps/v1)
kind: Deployment # 資源種類:Deployment(控制器,用於管理 Pod 與 ReplicaSet)
metadata:
name: myapp-deployment # Deployment 的名稱(唯一識別)
labels: # 自定義標籤,可用於篩選或分類
app: myapp # 標籤名稱與值(與 selector 及 Pod labels 對應)
spec: # Deployment 的規格(宣告期望狀態)
replicas: 3 # 期望同時執行的 Pod 副本數(副本控制)
selector: # Deployment 如何挑選它要管理的 Pod(非常重要!)
matchLabels: # matchLabels 必須與下方 template.metadata.labels 一致
app: myapp # 若不一致,K8s 會拒絕建立 Deployment
strategy: # 定義更新策略(Deployment 如何滾動更新 Pod)
type: RollingUpdate # 預設為 RollingUpdate(逐步替換舊 Pod)
rollingUpdate: # 滾動更新的參數設定
maxSurge: 25% # 允許暫時多出最多 25% 的 Pod(相對於 replicas 數)
maxUnavailable: 25% # 更新期間最多可有 25% 的 Pod 不可用
minReadySeconds: 5 # Pod 成功啟動並通過 ReadinessProbe 後,必須維持 Ready 狀態至少 5 秒才算穩定
revisionHistoryLimit: 10 # 保留最多 10 個舊版 ReplicaSet,以支援回滾(預設 10)
template: # 定義 Pod 的模板(Pod 會依這裡建立)
metadata:
labels:
app: myapp # Pod 的標籤(必須與 selector.matchLabels 對應)
spec: # Pod 的詳細規格(與單獨的 Pod manifest 類似)
containers: # 定義容器列表(Pod 內可有多個容器)
- name: myapp-container # 容器名稱(在同一 Pod 內唯一)
image: myregistry/myapp:1.2.3 # 使用的映像檔(建議用固定版本號,不用 latest)
imagePullPolicy: IfNotPresent # (可選)若本地無映像才拉取,可改成 Always 強制更新
ports:
- containerPort: 8080 # 容器內部服務的 port(對應程式監聽的埠)
env: # (可選)環境變數設定
- name: ENVIRONMENT
value: production
resources: # 設定 CPU / Memory 資源限制(非常建議)
requests: # Scheduler 會依 requests 判斷要放在哪個節點
cpu: "100m" # 要求最少 0.1 顆 CPU
memory: "128Mi" # 要求最少 128MB 記憶體
limits: # 容器最大可用資源(超過會被限制或 OOMKilled)
cpu: "500m" # 最多 0.5 顆 CPU
memory: "512Mi" # 最多 512MB 記憶體
readinessProbe: # 檢查應用程式是否「已準備好」接收流量
httpGet: # 以 HTTP GET 方式檢查
path: /healthz # 檢查的路徑
port: 8080 # 檢查的埠號(對應 containerPort)
initialDelaySeconds: 5 # 容器啟動後等待幾秒才開始檢查
periodSeconds: 10 # 每 10 秒檢查一次
timeoutSeconds: 2 # (可選)每次檢查的逾時時間(預設 1 秒)
failureThreshold: 3 # (可選)連續失敗幾次才算不 Ready
successThreshold: 1 # (可選)成功一次即恢復 Ready 狀態
livenessProbe: # 檢查容器是否「活著」(避免程式卡死)
httpGet:
path: /live # 用另一個健康檢查端點
port: 8080
initialDelaySeconds: 30 # 延遲 30 秒才開始檢查(確保應用啟動完成)
periodSeconds: 10 # 每 10 秒檢查一次
timeoutSeconds: 2
failureThreshold: 3 # 若連續 3 次檢查失敗則重啟容器
startupProbe: # (可選)應用啟動很慢時使用(先用 startupProbe,成功後才啟動其他 probe)
httpGet:
path: /startup
port: 8080
failureThreshold: 30 # 最多允許 30 次失敗
periodSeconds: 10 # 每 10 秒檢查一次 → 最多容忍 5 分鐘啟動時間
volumeMounts: # (可選)掛載外部 volume 到容器內
- name: app-config
mountPath: /etc/myapp
volumes: # 定義可被 Pod 內容器共用的 volume
- name: app-config
configMap: # 來源是 ConfigMap
name: myapp-config # ConfigMap 名稱(需事先建立)
imagePullSecrets: # 若要拉 private registry 的映像
- name: my-registry-secret # 指向已建立的 Secret(type=kubernetes.io/dockerconfigjson)
securityContext: # Pod 層級的安全性設定
runAsNonRoot: true # 強制容器以非 root 身份執行
fsGroup: 2000 # 設定檔案系統群組 ID(有助於卷權限)
restartPolicy: Always # Pod 的重啟策略(Deployment 一定是 Always)
```
(上面是常見組合,可以依照你的應用調整 probes、resources、image tag 等)
---
# 4) 常用 kubectl 工作流(快速 Cheat-sheet)
* 建立/套用:`kubectl apply -f deployment.yaml`
* 看資源:`kubectl get deployments` / `kubectl describe deployment myapp-deployment`
* 檢查 rollout 狀態:`kubectl rollout status deployment/myapp-deployment`。`kubectl rollout` 可管理 rollout(查看歷史、回滾等)。([Kubernetes][4])
* 查看 rollout 歷史:`kubectl rollout history deployment/myapp-deployment`
* 回滾(到上一版):`kubectl rollout undo deployment/myapp-deployment`
* 更新容器映像(無 downtime 的方式):`kubectl set image deployment/myapp-deployment myapp-container=myregistry/myapp:1.2.4`(會觸發 rolling update)
* 強制重啟(讓 Pod 逐一重建):`kubectl rollout restart deployment/myapp-deployment`(等同觸發一個新的 rollout)。([Kubernetes][5])
* 縮放:`kubectl scale deployment/myapp-deployment --replicas=5`
* 快速自動縮放(建立 HPA):`kubectl autoscale deployment myapp-deployment --min=2 --max=10 --cpu-percent=60`(會建立 HorizontalPodAutoscaler)([Kubernetes][6])
---
# 5) 健康檢查 (liveness vs readiness vs startup)
* **Liveness probe**:決定 container 是否「死掉」需要重啟(避免 hung)。([Kubernetes][7])
* **Readiness probe**:決定 Pod 是否「已就緒」能接受流量(影響 Service 的 endpoint)。
* **Startup probe**:app 啟動很慢時先用 startupProbe 延後 liveness 判斷,避免啟動期間被重啟。
> 設定正確的 readinessProbe 很重要,因為 rolling update 會等到 new Pod 被標示為 Ready 才會把舊 Pod 刪掉(依 `maxSurge`/`maxUnavailable` 規則)。([Kubernetes][8])
---
# 6) Rolling update 與策略要點
* `RollingUpdate`(預設):用 `maxSurge`(可臨時多出的 Pod 數)與 `maxUnavailable`(更新期間最多不可用的 Pod)平衡速度與可用性。預設常為 `25%`(詳細行為與版本有差異,請留意 Kubernetes 版本)— 若想零 downtime,可考慮 `maxUnavailable: 0` 並把 `maxSurge` 設為 `1`(或更高)。([Kubernetes][3])
* `Recreate`:先把舊 Pod 全下線再建立新 Pod(會有 downtime),適用於無法同時跑舊/新版的場景。
* 注意:`spec.selector` 一旦建立後不可變(如果要改 selector,通常要刪掉再重建 Deployment)。因此建立時 selector 與 template labels 要小心規劃。([Kubernetes][2])
---
# 7) 進階:自動擴縮、流量分流與無停機部署
* **HPA(Horizontal Pod Autoscaler)**:根據 CPU/memory 或自訂 metrics 自動調整 Deployment replicas(需要 metrics server / API 支援)。用 `kubectl autoscale` 快速建立,或以 HPA 資源 manifest 管理。([Kubernetes][6])
* **Canary / Blue-Green**:Deployment 本身支援基本滾動更新;更進階的 canary/blue-green 通常需搭配 Service/Ingress 修改流量、或使用更專門的 delivery 工具(Argo Rollouts、Flagger、Istio/Service Mesh 等)。([Codefresh][9])
* **PodDisruptionBudget (PDB)**:控制自願性中斷(例如 node drain、cluster upgrade)期間最少要保留多少 Pod,以避免在維護時造成過大影響。([Kubernetes][10])
---
# 8) 常見問題與陷阱(小心會踩雷)
* **selector 不匹配 template labels → 會被 API 拒絕或造成控制器行為不正確**(建立時特別小心)。([Kubernetes][11])
* **用 `:latest` 標籤在 production 不安全**:因為 image tag 不可辨識版本,建議在 CI/CD 中使用 immutable tags(如 git hash、semver)。
* **忘了 readiness probe**:會導致 Service 把尚未可用的 Pod 當作可用而分流流量,造成錯誤或 502。([Kubernetes][7])
* **resource requests/limits 未設定**:scheduler 無法正確放置 Pod,或在節點壓力下遭到 OOMKill。
* **認知 `maxSurge` / `maxUnavailable` 為百分比時會向上取整**(1 個 replica 時 25% 會向上成為 1),可能導致你看到超過預期的 Pod 數量。([Kubernetes][3])
---
# 9) 範例操作流程(CI/CD 常見)
1. CI 建出新的 image 並打上版本號(例如 `v2025-10-09-abc123`)。
2. CI 更新 `image:` 字段或 patch deployment(`kubectl set image` 或 更新 manifest 並 `kubectl apply`)。
3. 觀察 rollout:`kubectl rollout status deployment/myapp-deployment`。若有問題,`kubectl rollout undo` 回滾。([Kubernetes][4])
---
# 10) 推薦閱讀(官方 / 深入)
* Deployment 概念與用法(官方 docs)。([Kubernetes][1])
* kubectl rollout / restart 文件(命令與用法)。([Kubernetes][4])
* Liveness / Readiness / Startup probes(設定細節與範例)。([Kubernetes][8])
* Horizontal Pod Autoscaler(HPA):自動擴縮說明與 walkthrough。([Kubernetes][6])
---
[1]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/?utm_source=chatgpt.com "Deployments"
[2]: https://kubernetes.io/docs/reference/using-api/deprecation-guide/?utm_source=chatgpt.com "Deprecated API Migration Guide"
[3]: https://kubernetes.io/blog/2018/04/30/zero-downtime-deployment-kubernetes-jenkins/?utm_source=chatgpt.com "Zero-downtime Deployment in Kubernetes with Jenkins"
[4]: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_rollout/?utm_source=chatgpt.com "kubectl rollout"
[5]: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_restart/?utm_source=chatgpt.com "kubectl rollout restart"
[6]: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/?utm_source=chatgpt.com "Horizontal Pod Autoscaling"
[7]: https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/?utm_source=chatgpt.com "Liveness, Readiness, and Startup Probes"
[8]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/?utm_source=chatgpt.com "Configure Liveness, Readiness and Startup Probes"
[9]: https://codefresh.io/learn/kubernetes-deployment/?utm_source=chatgpt.com "Kubernetes Deployment Strategies: The Definitive Guide"
[10]: https://kubernetes.io/docs/tasks/run-application/configure-pdb/?utm_source=chatgpt.com "Specifying a Disruption Budget for your Application"
[11]: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/?utm_source=chatgpt.com "ReplicaSet"