AI-Chain

Kubernetes 不只是部署工具:用控制迴路把容器系統變成可自癒平台

從控制迴路、Deployment 與 Service,到健康檢查、滾動更新和 AI 推理服務,拆解 Kubernetes 如何把容器維運變成可觀察、可回復的工程系統。

分享:
Kubernetes 不只是部署工具:用控制迴路把容器系統變成可自癒平台

Kubernetes 不只是部署工具:用控制迴路把容器系統變成可自癒平台

很多團隊第一次接觸 Kubernetes,看到的是一串指令:建立 Deployment、暴露 Service、設定副本數,然後期待應用程式「自己運作」。但 Kubernetes 真正值得理解的地方,不是命令列有多少子命令,而是它把分散式系統的維運工作,整理成一組可持續執行的控制迴路。

你描述想要的狀態,Kubernetes 負責觀察目前狀態、計算差異,再透過控制器、Scheduler、kubelet 與網路元件逐步把系統拉回目標。容器意外停止時,它可以重新啟動;副本數不足時,它可以補齊;版本更新時,它可以依 Deployment 的策略逐步替換。這套模型讓「部署一次」轉成「持續維持」。

本文以 kubernetes/kubernetes 為主題,從原始碼專案的定位開始,拆解控制平面與工作負載的關係,接著用一個可在本機重現的範例,走過部署、服務發現、健康檢查、設定管理、滾動更新與回滾。重點不是背 YAML,而是理解每一個資源在控制迴路中扮演的角色。

先看專案:為什麼 Kubernetes 仍值得研究

截至 2026 年 8 月 10 日,GitHub API 顯示 kubernetes/kubernetes 約有 124,378 顆星,最近一次推送時間為 2026 年 8 月 9 日,授權為 Apache-2.0;同一個 API 回應也列出 v1.37.0-rc.0 於 2026 年 8 月 6 日發布。這些資料只用來確認專案活躍度與版本脈絡,不代表候選版本已經適合所有生產環境。

Kubernetes 官方 README 將它定位為管理多主機容器化應用程式的開源系統,提供部署、維護與擴展的基本機制。官方概念文件則進一步說明,它提供服務探索與負載平衡、自我修復、水平擴展、滾動更新、密鑰與設定管理等能力。

這個專案適合用來寫實作型文章,原因有三個:

  1. 它是一個真正可執行的控制平台。 不只是規範或資源清單,而是包含 API Server、Controller Manager、Scheduler、kubelet 與大量控制器的完整系統。
  2. 抽象層彼此可驗證。 你可以用 kubectl get 觀察資源,用 describe 追蹤事件,再把 YAML 的宣告和實際狀態對照起來。
  3. 同一套模型可延伸到 AI 服務。 API、工作負載、服務、資源限制與健康檢查,都是模型推理服務、資料處理工作與 Agent 後端會遇到的基礎問題。

核心不是 Pod,而是控制迴路

初學者常把 Kubernetes 等同於「啟動 Pod 的工具」,但 Pod 只是最小的可部署單位。實務上,應用程式通常由多個物件共同描述:Deployment 管理無狀態工作負載,ReplicaSet 維持副本數,Service 提供穩定的網路入口,ConfigMap 與 Secret 分離設定和敏感資料,Probe 則把應用程式健康狀態交給平台判斷。

可以把一次部署想成以下流程:

  1. 使用者將期望狀態送進 API Server,例如「要有三個 web Pod,映像版本是 v2」。
  2. Deployment Controller 讀取這個期望狀態,建立或更新 ReplicaSet。
  3. ReplicaSet Controller 觀察目前 Pod 數量,若少於三個,就建立新的 Pod 物件。
  4. Scheduler 為尚未綁定節點的 Pod 選擇合適 Node,考量資源請求、限制、親和性與其他排程條件。
  5. Node 上的 kubelet 透過容器執行環境啟動容器,並持續回報狀態。
  6. 若容器不符合 liveness 或 readiness 條件,平台依探針結果採取重啟或暫停流量分派等動作。

這裡最重要的觀念是「控制器不是腳本」。腳本執行完就結束;控制器會持續 watch 資源與事件,因此即使某個 Pod 被刪除,系統仍會發現差異並嘗試修復。這也是 Kubernetes 能處理節點故障、部署中斷與副本漂移的原因。

建立一個最小可觀察範例

以下範例採用 Minikube 作為本機學習環境。官方 Hello Minikube 教學涵蓋建立叢集、建立 Deployment、使用 Service 暴露應用程式、查看 Pod 與 Node,以及執行擴展和滾動更新。若你已經有其他 Kubernetes 叢集,也可以把 minikube 指令換成自己的叢集操作。

先確認環境

準備 Docker 或其他相容的容器執行環境,以及 kubectl 與 Minikube。先建立叢集並確認節點狀態:

minikube start
kubectl cluster-info
kubectl get nodes -o wide

如果 minikube start 失敗,先看容器執行環境是否啟動、目前使用的 driver 是否可用,以及本機是否有足夠 CPU、記憶體和磁碟。不要一開始就把問題歸咎於 YAML;叢集尚未 Ready 時,後續每一層都會連鎖失敗。

用 Deployment 描述工作負載

建立 web.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: nginx
          image: nginx:stable-alpine
          ports:
            - name: http
              containerPort: 80
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 256Mi
          readinessProbe:
            httpGet:
              path: /
              port: http
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /
              port: http
            initialDelaySeconds: 10
            periodSeconds: 10

套用並觀察:

kubectl apply -f web.yaml
kubectl get deployment,replicaset,pod -l app=web
kubectl describe deployment web
kubectl get events --sort-by=.lastTimestamp

這幾個指令提供不同層次的觀察:get 看摘要,describe 看控制器計算出的狀態與事件,events 則協助辨識排程、拉取映像或探針失敗。若 Pod 卡在 Pending,優先檢查資源與排程;若是 ImagePullBackOff,檢查映像名稱、標籤與 Registry;若是 CrashLoopBackOff,再查看容器日誌和啟動參數。

用 Service 固定網路入口

Pod 會被重新建立,IP 也可能改變,因此不應讓其他服務直接依賴 Pod IP。建立 web-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - name: http
      port: 80
      targetPort: http
  type: ClusterIP

執行:

kubectl apply -f web-service.yaml
kubectl get service web
kubectl get endpointslices -l kubernetes.io/service-name=web
minikube service web --url

Service 以 selector 找到符合條件的 Pod,提供穩定的服務抽象。這個細節很關鍵:Deployment 負責「有哪些副本」,Service 負責「流量送到哪些副本」。把兩者混在一起,排查問題時就很容易誤判。

三種健康檢查,不要只設定一種

官方文件將探針分成 liveness、readiness 與 startup 三類。它們解決的是不同問題:

  • livenessProbe:應用程式是否已經進入無法自行恢復的狀態。如果失敗,kubelet 可能重啟容器。
  • readinessProbe:應用程式目前能否接收流量。如果失敗,Pod 會暫時從 Service 的可用端點中移除,但不一定重啟容器。
  • startupProbe:應用程式是否完成啟動。啟動探針成功前,liveness 與 readiness 不會開始判斷,適合需要較長 warm-up 的服務。

這三者的分工能避免一個常見錯誤:把「尚未載入模型」誤判成「程式壞掉」。以 AI 推理服務為例,模型載入、GPU 初始化或快取建立可能需要幾十秒甚至更久。此時應用程式可能仍然活著,但還不適合接收流量;使用 startup 和 readiness 的組合,通常比單純把 liveness 的延遲調到很大更清楚。

探針也不是越多越好。HTTP endpoint 應該是低成本、可預測的檢查;不要讓健康檢查每次都觸發資料庫全表掃描、模型推理或昂貴的外部 API 呼叫。否則平台為了判斷健康,反而會製造新的負載。

設定、密鑰與映像版本要分離

把所有設定硬編碼在映像裡,會讓同一個映像難以跨環境重用。ConfigMap 適合非敏感設定,例如服務埠、功能開關與環境名稱;Secret 則用來傳遞密鑰、憑證或其他敏感資料。Secret 並不等於完整的密鑰管理系統,生產環境仍應評估加密儲存、RBAC、外部 Secret manager、輪替與稽核。

一個不含真實憑證的示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: web-config
data:
  LOG_LEVEL: info
  FEATURE_MODE: production
---
apiVersion: v1
kind: Secret
metadata:
  name: web-secret
type: Opaque
stringData:
  API_TOKEN: "[REDACTED]"

套用後,可以用 envFrom 或個別 env 將資料注入容器。檢查設定時要留意:kubectl describe、事件、Shell history 和 CI log 都可能造成敏感資料意外曝光。不要把 kubectl get secret -o yaml 的輸出貼到 issue 或聊天頻道。

滾動更新、擴展與回滾

Kubernetes 的價值不只在第一次部署,更在於變更之後仍能維持服務。修改 Deployment 的映像版本:

kubectl set image deployment/web nginx=nginx:1.27-alpine
kubectl rollout status deployment/web
kubectl rollout history deployment/web

如果新版本行為不符合預期,可以回滾:

kubectl rollout undo deployment/web
kubectl rollout status deployment/web

這些指令背後是 Deployment Controller 建立新 ReplicaSet、逐步調整新舊 ReplicaSet 副本數的過程。實際的可用性還取決於 maxUnavailablemaxSurge、PodDisruptionBudget、探針與應用程式是否能優雅關閉。看到 rollout 完成,不代表功能驗證完成;仍應搭配 smoke test、指標、日誌和錯誤率檢查。

水平擴展則是調整期望副本數:

kubectl scale deployment/web --replicas=4
kubectl get pods -l app=web -w

如果要依 CPU 或自訂指標自動擴展,還需要安裝並正確設定相對應的 metrics 元件,不能只建立一個 HPA 物件就假設它會工作。對模型推理服務而言,GPU、模型記憶體、併發請求和批次大小通常比 CPU 使用率更能反映容量;擴展策略要依服務特性設計。

從故障現象反推控制迴路

實作時,先建立一個固定的排查順序,比記住更多指令更有用。第一步看資源是否真的存在:kubectl get deployment webkubectl get pods -l app=webkubectl get svc web 可以確認物件是否被 API Server 接受。第二步看狀態是否收斂:Deployment 的 AVAILABLE、Pod 的 READY 與 Service 的 EndpointSlice 應該互相一致。第三步才深入事件和日誌:kubectl describe pod 能顯示排程、掛載、探針與映像拉取事件,kubectl logs 則用來辨識應用程式本身的啟動錯誤。

常見狀況可以這樣分層:Pod 是 Pending,通常先查 Node 資源、taint、親和性或 PVC;Pod 是 ContainerCreating,檢查映像、Volume、CNI 與 Secret;Pod 反覆重啟,查看上一個容器的日誌和退出碼;Deployment 有新 ReplicaSet 卻沒有可用副本,檢查 readinessProbe、資源限制和映像版本;Service 沒有端點,檢查 selector 是否與 Pod labels 完全相符。這套流程的目的,是把「服務不通」拆成 API、排程、啟動、健康與網路幾個可驗證的假設。

完成修改後,至少做一次正向和一次反向驗證:先確認正常版本能被 Service 存取,再故意部署一個不存在的映像或暫時調高副本數,觀察事件和 rollout 狀態,最後恢復設定並確認系統回到穩定狀態。這比只看到一行 deployment successfully configured 更能證明控制迴路真的按預期工作。

生產環境最容易被忽略的邊界

1. 資源請求不是裝飾

requests 影響排程,limits 影響容器可使用的資源上限。沒有合理的 requests,Scheduler 難以做出可靠決策;沒有觀測實際使用量,limits 可能造成 OOMKill 或 CPU throttling。先用指標建立基線,再調整,而不是複製別人的數字。

2. 命名空間與 RBAC 要一起設計

Namespace 可以協助分隔團隊、環境和配額,但它不是完整的安全邊界。ServiceAccount、Role、RoleBinding 與最小權限原則才是 API 存取控制的核心。工作負載不應預設拿到整個叢集的讀寫權限。

3. 觀測要對準控制迴路

除了應用程式 log,還要看 Pod 狀態、Deployment 可用副本、排程事件、探針失敗、節點壓力和 API Server 錯誤。遇到問題時,依序問「期望狀態是什麼、目前狀態是什麼、哪個控制器沒有把差異收斂」通常比盲目重啟更快找到根因。

4. YAML 可維護性會決定變更速度

小型測試可以用單一檔案;團隊協作則要建立版本控制、環境覆寫、驗證與審查流程。無論選用 Kustomize、Helm 或其他工具,都應讓最後送進 API Server 的資源可追蹤、可重現、可回滾。模板不是目的,能清楚回答「這次變更會影響哪些工作負載」才是目的。

AI Chain 實作視角:把模型服務當成平台的一部分

Kubernetes 不會替你解決模型品質、提示詞設計或資料治理,但它能承接 AI 應用進入生產後的工程問題:

  • 模型 API 可以由 Deployment 管理副本,由 Service 提供穩定入口。
  • 模型載入時間 可以用 startupProbe 描述,避免容器尚未準備好就被重啟或接收流量。
  • 版本切換 可以透過多個 Deployment、標籤與流量策略逐步執行,而不是一次替換所有實例。
  • GPU 工作負載 可以使用 Kubernetes 的資源與排程能力,但仍須搭配正確的裝置外掛、節點標籤、資源請求與監控。
  • 資料處理工作 可用 Job 或 CronJob 表達一次性與週期性任務,並將失敗重試、保留策略和輸出位置明確化。

這種拆法能讓 AI 系統從「一台機器上跑一個服務」逐步成為可觀測、可更新、可回復的工程系統。不過,叢集複雜度也是真實成本。若服務規模很小,Docker Compose 或平台代管服務可能更合適;選 Kubernetes 的理由應該是你確實需要它的控制迴路、擴展能力和生態系,而不是因為它很流行。

結語:先學會觀察差異,再學 YAML

Kubernetes 最值得帶走的不是某一個 kubectl 參數,而是「宣告期望狀態,讓控制迴路持續收斂」的工程思想。Deployment 管副本與版本,Service 管穩定入口,Probe 管健康判斷,ConfigMap 和 Secret 管設定邊界;每個物件都應該有清楚責任,並能用命令、事件和指標驗證。

建議用本文的最小範例開始:先建立兩個副本,確認 Service 能找到端點,再故意改錯映像觀察 rollout,最後回滾並檢查事件。當你能回答「哪個控制器看到了什麼差異、它做了什麼、下一步如何驗證」,就不再只是會套用 YAML,而是真的開始理解 Kubernetes。

查證來源

  • Kubernetes GitHub repository:<https://github.com/kubernetes/kubernetes>
  • Kubernetes README:<https://github.com/kubernetes/kubernetes/blob/master/README.md>
  • Kubernetes Overview:<https://kubernetes.io/docs/concepts/overview/>
  • Deployments:<https://kubernetes.io/docs/concepts/workloads/controllers/deployment/>
  • Service:<https://kubernetes.io/docs/concepts/services-networking/service/>
  • Secrets:<https://kubernetes.io/docs/concepts/configuration/secret/>
  • Liveness、Readiness、Startup Probes:<https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/>
  • kubectl Quick Reference:<https://kubernetes.io/docs/reference/kubectl/quick-reference/>
  • Hello Minikube:<https://kubernetes.io/docs/tutorials/hello-minikube/>