監控、日誌與自動伸縮

應用部署上線只是第一步。真正的挑戰在於:如何確保應用持續穩定運行?

當你的應用開始有用戶使用後,你可能會遇到以下問題:

  • 半夜 3 點應用突然變得超慢,但你完全不知道
  • 某個容器 crash 了,但 K8s 沒有正確重新啟動
  • 因為某個行銷活動,流量暴增 10 倍,伺服器直接被打掛
  • 工程師花了 3 天才找到問題根源,因為日誌散落在不同的 Pod 中

這一章,我們將學習如何建立完整的監控、日誌與自動伸縮體系

建立監控系統:Prometheus + Grafana

在 Kubernetes 生態系中,最主流的監控組合是 Prometheus(監控資料收集) + Grafana(視覺化儀表板)

使用 kube-prometheus-stack 一鍵安裝

我們可以使用 Helm Chart kube-prometheus-stack 來一次安裝 Prometheus、Grafana 和 AlertManager:

# 新增 Helm Repository
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# 安裝監控堆疊(命名空間 monitoring)
helm install monitoring prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace

安裝完成後,檢查所有元件是否正常運行:

kubectl get pods -n monitoring

# 輸出範例
NAME                                                     READY   STATUS
monitoring-prometheus-operator-7d8b9c7d9-abcde            2/2     Running
monitoring-grafana-6d6b8c8b9-xyzab                        3/3     Running
monitoring-kube-state-metrics-5c6d7e8f9-qwert             1/1     Running
prometheus-monitoring-kube-prometheus-prometheus-0        2/2     Running
alertmanager-monitoring-kube-prometheus-alertmanager-0    2/2     Running

存取 Grafana 儀表板

# 將 Grafana 服務轉發到本機
kubectl port-forward -n monitoring service/monitoring-grafana 3000:80

開啟瀏覽器連到 http://localhost:3000,預設帳號密碼為:

  • Username: admin
  • Password: prom-operator

Grafana 已經預設內建了 Kubernetes 叢集的監控儀表板!你可以直接看到:

  • 叢集資源使用率:CPU、記憶體、磁碟、網路
  • Pod 狀態分布:Running / Pending / CrashLoopBackOff
  • API 伺服器延遲:kube-apiserver 的回應時間
  • 節點 (Node) 健康狀態:哪些節點負載過高

自訂重要監控指標

除了內建的儀表板之外,你還應該關注以下關鍵指標:

1. Pod 重啟次數 如果某個 Pod 頻繁重啟,代表應用可能有記憶體洩漏或崩潰:

rate(kube_pod_container_status_restarts_total[5m]) > 0

2. 應用 HTTP 錯誤率 如果你的應用有匯出 Prometheus metrics(透過 /metrics 端點),可以監控 5xx 錯誤率:

sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.01

3. 磁碟空間使用率 叢集的磁碟空間不足會導致 Pod 無法排程:

(1 - (node_filesystem_avail_bytes{fstype!=""} / node_filesystem_size_bytes{fstype!=""})) * 100 > 80

集中日誌管理:Loki + Promtail

K8s 的 Pod 是動態的,當 Pod 被刪除或重新排程,舊的日誌也隨之消失。我們需要一個集中式日誌系統來收集所有 Pod 的日誌。

安裝 Loki 日誌堆疊

# 新增 Grafana Helm Repository(如果還沒加過)
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update

# 安裝 Loki(日誌儲存引擎)
helm install loki grafana/loki-stack \
  --namespace monitoring \
  --set promtail.enabled=true \
  --set loki.persistence.enabled=true \
  --set loki.persistence.size=10Gi

在 Grafana 中查詢日誌

  1. 進入 Grafana → 左側選單 → Explore
  2. 在資料來源中選擇 Loki
  3. 輸入查詢語法來搜尋日誌:
# 查看某個應用的所有日誌
{app="backend"}

# 查看包含 "error" 的日誌(不分大小寫)
{app="backend"} |= "error"

# 排除 heartbeat 日誌,只看真正的錯誤
{app="backend"} |= "error" != "heartbeat"

有了集中式日誌,你再也不需要 kubectl logs 一個一個 Pod 去看了。直接在 Grafana 上搜尋所有 Pod 的日誌!

設定自動伸縮:HorizontalPodAutoscaler (HPA)

自動伸縮是 Kubernetes 最強大的功能之一。設定 HPA 後,K8s 會根據 CPU 或記憶體使用量,自動增減 Pod 的數量。

建立 HPA

# hpa-backend.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: backend-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: backend
  minReplicas: 2          # 最少 2 個副本
  maxReplicas: 10         # 最多 10 個副本
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70   # 當 CPU 使用率超過 70% 時觸發擴展
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80   # 當記憶體使用率超過 80% 時觸發擴展
# 部署 HPA
kubectl apply -f hpa-backend.yaml

# 查看 HPA 狀態
kubectl get hpa -w

# 輸出範例
NAME           REFERENCE             TARGETS                MINPODS   MAXPODS   REPLICAS
backend-hpa    Deployment/backend    cpu: 45%/70%, mem: 60%/80%   2         10        2

模擬流量測試

為了測試 HPA 是否正常運作,我們可以用一個簡單的工具來模擬流量:

# 啟動一個測試 Pod
kubectl run -it load-generator --image=busybox -- /bin/sh

# 在 Pod 內部連續發送請求
while true; do wget -q -O- http://backend:8000; done

當 CPU 使用率超過 70% 時,K8s 會自動增加 Pod 數量:

kubectl get hpa -w
# 你會看到 replicas 從 2 → 4 → 6 → 8(取決於流量大小)

停止測試後,當 CPU 使用率下降,K8s 會逐步減少 Pod 數量(冷卻時間約 5 分鐘)。

設定預算:PodDisruptionBudget (PDB)

當你進行節點維護或滾動更新時,如果一次關閉太多 Pod,可能會導致服務中斷。PodDisruptionBudget (PDB) 可以確保在自願中斷(如節點維護)時,最少保持一定數量的 Pod 正常運行:

# pdb-backend.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: backend-pdb
spec:
  minAvailable: 2    # 至少 2 個 Pod 必須保持可用
  selector:
    matchLabels:
      app: backend
kubectl apply -f pdb-backend.yaml

建立預算警報:AlertManager Rules

當某個指標異常時,AlertManager 會自動發送通知。以下是幾個必設的警報規則:

# 在 Prometheus 的 values.yaml 中設定
alertmanager:
  config:
    global:
      slack_api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
    route:
      receiver: 'slack-notifications'
    receivers:
      - name: 'slack-notifications'
        slack_configs:
          - channel: '#alerts'
            send_resolved: true

建議的警報規則:

| 警報名稱 | 條件 | 嚴重程度 | |---------|------|---------| | Pod 頻繁重啟 | 5 分鐘內重啟超過 3 次 | Critical 🔴 | | Pod 處於 Pending 狀態 | 超過 5 分鐘 | Warning 🟡 | | 節點磁碟空間不足 | 使用率 > 85% | Warning 🟡 | | HPA 最大副本 | 達到 maxReplicas 且仍持續成長 | Warning 🟡 | | API 延遲過高 | 延遲 > 1 秒持續 5 分鐘 | Critical 🔴 |

本日總結

在本章中,你學到了:

  1. Prometheus + Grafana:監控 K8s 叢集的 CPU、記憶體、網路與 Pod 狀態
  2. Loki + Promtail:集中式日誌管理,不再需要一個 Pod 一個 Pod 看日誌
  3. HorizontalPodAutoscaler (HPA):根據 CPU/記憶體自動伸縮 Pod 數量
  4. PodDisruptionBudget (PDB):確保維護期間服務不中斷
  5. AlertManager:設定自動警報通知到 Slack 或 Email

下一章,我們將串聯 CI/CD 自動化流水線,實現從程式碼提交到自動部署的完整流程!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!