iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Kubernetes

從零開始的 Kubernetes 基礎觀念與實作系列 第 29 篇

# 從零開始的 Kubernetes 基礎觀念與實作 DAY29

  • 分享至 

  • xImage
  •  

Kubernetes 綜合實作(三):健康檢查與故障排查

前兩篇已經建立了一個簡單的 Web API,並整合 Deployment、Service、ConfigMap、Secret、PVC 和 Ingress。

目前應用程式已經能夠接收 HTTP 請求,也能夠將資料保存到持久化儲存空間。

不過,當應用程式發生問題時,Kubernetes 要如何判斷容器是否正常?又該如何限制容器使用的資源?

這篇將延續前面的專案,加入 Probe 和資源限制,最後透過故障模擬觀察 Kubernetes 的處理方式。

加入健康檢查 API

首先修改 DAY28 的 app.py,在原本程式中新增兩個 API:

@app.route("/health")
def health():
    return jsonify({
        "status": "healthy"
    })

@app.route("/ready")
def ready():
    try:
        if not os.path.isdir(DATA_DIR):
            raise RuntimeError("Data directory not found")

        if not os.access(DATA_DIR, os.R_OK | os.W_OK):
            raise RuntimeError("Data directory not accessible")

        load_messages()

        return jsonify({
            "status": "ready"
        })

    except (OSError, ValueError, RuntimeError):
        return jsonify({
            "status": "not ready"
        }), 503

這兩個 API 的用途不同:

  • /health:確認應用程式的 HTTP 服務仍然能夠回應。
  • /ready:檢查應用程式是否具備基本的資料目錄存取能力,以及資料檔案是否能正常讀取。

這裡的健康檢查只是一個簡化範例,並不能涵蓋所有應用程式故障。

其中 /ready 也沒有實際測試寫入,因此不能保證儲存空間一定可以成功寫入資料。

重新建立 Docker 映像檔

由於修改了應用程式,需要重新建立映像檔:

docker build -t k8s-final-demo:3.0 .

接著載入 Minikube:

minikube image load k8s-final-demo:3.0

這次使用新的 Tag,避免和前面建立的映像檔混淆。

修改 Deployment

接下來修改 k8s/deployment.yaml,加入 Probe 與資源限制。

完整設定如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: final-demo
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: final-demo
  template:
    metadata:
      labels:
        app: final-demo
    spec:
      containers:
        - name: web
          image: k8s-final-demo:3.0
          imagePullPolicy: Never
          ports:
            - containerPort: 5000

          envFrom:
            - configMapRef:
                name: final-demo-config
            - secretRef:
                name: final-demo-secret

          volumeMounts:
            - name: app-data
              mountPath: /data

          resources:
            requests:
              cpu: "100m"
              memory: "64Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"

          startupProbe:
            httpGet:
              path: /health
              port: 5000
            periodSeconds: 5
            failureThreshold: 12

          livenessProbe:
            httpGet:
              path: /health
              port: 5000
            periodSeconds: 10
            failureThreshold: 3

          readinessProbe:
            httpGet:
              path: /ready
              port: 5000
            periodSeconds: 5
            failureThreshold: 3

      volumes:
        - name: app-data
          persistentVolumeClaim:
            claimName: final-demo-pvc

這份 YAML 延續 DAY28 的 PVC 設定,並新增三種 Probe 和 CPU、Memory 限制。

Probe 的用途

DAY15 已介紹過 Kubernetes 的健康檢查機制,這裡直接將它整合到實際應用程式。

Startup Probe

Startup Probe 用來判斷應用程式是否已完成啟動。

startupProbe:
  httpGet:
    path: /health
    port: 5000
  periodSeconds: 5
  failureThreshold: 12

在 Startup Probe 成功前,Kubernetes 不會執行 Liveness Probe 和 Readiness Probe。

這個範例大約提供最多 60 秒的啟動檢查時間。

Liveness Probe

Liveness Probe 用來判斷容器是否需要重新啟動。

livenessProbe:
  httpGet:
    path: /health
    port: 5000
  periodSeconds: 10
  failureThreshold: 3

如果健康檢查連續失敗達到設定門檻,kubelet 會重新啟動容器。

Readiness Probe

Readiness Probe 用來判斷 Pod 是否準備好接收流量。

readinessProbe:
  httpGet:
    path: /ready
    port: 5000
  periodSeconds: 5
  failureThreshold: 3

如果 Readiness Probe 失敗,Pod 會被標記為 NotReady,Service 不會再將一般流量轉送到這個未就緒的 Pod。

但 Readiness Probe 失敗本身不會導致容器重新啟動。

CPU 與 Memory 資源限制

除了 Probe,這次也加入資源限制:

resources:
  requests:
    cpu: "100m"
    memory: "64Mi"
  limits:
    cpu: "500m"
    memory: "256Mi"

其中:

  • requests.cpu:排程時要求至少配置 100m CPU。
  • requests.memory:排程時要求 64Mi Memory。
  • limits.cpu:限制容器可使用的 CPU 資源。
  • limits.memory:設定容器的 Memory 使用上限。

當容器持續使用超過 CPU Limit 的運算資源時,可能受到 CPU Throttling 限制。

如果容器記憶體使用量超過限制,則可能發生 OOM Kill。

這裡的資源數值只是示範,實際環境應根據應用程式的使用情況調整。

更新應用程式

完成 YAML 後,執行:

kubectl apply -f k8s/deployment.yaml

等待 Pod 重新建立:

kubectl rollout status deployment/final-demo

查看 Pod:

kubectl get pods

正常情況下,Pod 應該進入 Running,並且顯示 Ready。

也可以查看詳細資訊:

kubectl describe pod <pod-name>

在 Containers 區塊中,可以找到 Liveness、Readiness、Startup Probe,以及 Requests、Limits 的設定。

故障模擬:Readiness Probe 失敗

接下來故意修改 Readiness Probe,讓 Kubernetes 無法通過健康檢查。

將 Deployment 中的:

readinessProbe:
  httpGet:
    path: /ready
    port: 5000

暫時修改成:

readinessProbe:
  httpGet:
    path: /wrong-path
    port: 5000

由於應用程式沒有 /wrong-path 這個 API,因此 HTTP 請求會回傳 404。

重新套用 Deployment:

kubectl apply -f k8s/deployment.yaml

接著查看 Pod:

kubectl get pods -w

由於 Readiness Probe 無法通過,Pod 會顯示:

image

這裡可以觀察到:

Pod 處於 Running,並不代表它已經準備好接收流量。

接著查看 Pod 事件:

kubectl describe pod <pod-name>

可能會看到類似:

image

這表示 Kubernetes 已經偵測到 Readiness Probe 失敗。

不過,因為 Liveness Probe 仍然正常,容器不會只因為 Readiness Probe 失敗就重新啟動。

觀察 Service Endpoint

接著查看 Service 對應的 EndpointSlice:

kubectl get endpointslices -l kubernetes.io/service-name=final-demo-service

也可以查看詳細內容:

kubectl describe endpointslice <endpointslice-name>

當 Pod 的 Readiness Probe 失敗時,對應端點的 Ready 狀態會變成 false。

Service 一般不會將新的連線轉送到未就緒的端點。

由於目前只有一個 Pod,因此當它無法通過 Readiness Probe 時,Service 可能沒有可用的後端。

這也說明 Readiness Probe 的重要性:避免應用程式尚未準備好時就接收請求。

恢復 Readiness Probe

完成觀察後,將路徑改回:

readinessProbe:
  httpGet:
    path: /ready
    port: 5000

重新套用:

kubectl apply -f k8s/deployment.yaml

等待 Deployment 更新完成:

kubectl rollout status deployment/final-demo

再次查看 Pod:

kubectl get pods

正常情況下,Pod 應該恢復 Ready 狀態。

故障模擬:Liveness Probe 失敗

接下來測試 Liveness Probe。

將 Deployment 中的 Liveness Probe 修改成:

livenessProbe:
  httpGet:
    path: /wrong-health
    port: 5000
  periodSeconds: 10
  failureThreshold: 3

由於 /wrong-health 不存在,Liveness Probe 會持續收到 HTTP 404。

重新部署:

kubectl apply -f k8s/deployment.yaml

接著觀察:

kubectl get pods -w

當 Liveness Probe 連續失敗達到設定門檻後,kubelet 會重新啟動容器。

這時可以觀察 Pod 的 RESTARTS 欄位。

也可以透過:

kubectl describe pod <pod-name>

查看相關事件。

可能會看到:

image

與 Readiness Probe 不同,Liveness Probe 失敗會觸發容器重新啟動。

如果問題持續存在,容器就可能不斷重新啟動。

查看容器日誌

當容器重新啟動後,可以使用:

kubectl logs <pod-name> --previous

查看上一個已終止容器實例的日誌。

如果容器仍在正常執行,也可以使用:

kubectl logs <pod-name>

查看目前的日誌。

這些指令在 DAY24 已經介紹過,這裡可以實際搭配 Probe 故障使用。

如果容器尚未重新啟動,或上一個容器實例的日誌已經無法取得,--previous 可能會出現錯誤。

恢復應用程式

完成測試後,將 Liveness Probe 改回:

livenessProbe:
  httpGet:
    path: /health
    port: 5000
  periodSeconds: 10
  failureThreshold: 3

重新部署:

kubectl apply -f k8s/deployment.yaml

等待 Deployment 恢復:

kubectl rollout status deployment/final-demo

查看狀態:

kubectl get pods

最後可以再次測試 API,確認應用程式已經恢復正常。

總結

這篇延續前兩篇建立的 Kubernetes 應用程式,整合了 Probe、資源限制與故障排查。

透過實際修改健康檢查路徑,可以觀察到:

  • Startup Probe:判斷應用程式是否完成啟動。
  • Readiness Probe:判斷 Pod 是否準備好接收流量。
  • Liveness Probe:判斷容器是否需要重新啟動。
  • Requests 和 Limits:控制資源需求與使用上限。
  • kubectl describe:查看資源狀態與相關事件。
  • kubectl logs:查看容器執行時產生的日誌。

到這裡,已經完成一個簡單的 Kubernetes 應用程式部署,並且整合了設定管理、資料持久化、網路存取、健康檢查與基本維運。

雖然這個範例距離正式的生產環境還有不少差距,例如高可用性、備份、監控與安全管理,但已經涵蓋了 Kubernetes 的多項核心功能。

下一篇 DAY30 將回顧整個系列學過的內容,並整理後續可以繼續學習的方向,為這次的 30 天 Kubernetes 入門系列畫下句點。


上一篇
# 從零開始的 Kubernetes 基礎觀念與實作 DAY28
下一篇
從零開始的 Kubernetes 基礎觀念與實作 DAY30
系列文
從零開始的 Kubernetes 基礎觀念與實作 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言