在雲端原生技術架構的演進歷程中,Kubernetes 已經成為容器編排領域的核心平台,其強大的自動化能力與豐富的生態系統為企業提供了前所未有的靈活性與擴展性。然而,隨著叢集規模的擴大與應用複雜度的提升,如何有效地測試應用程式、快速定位與排除故障,以及建立完善的監控體系,已經成為維運團隊與開發團隊面臨的核心挑戰。在動態且短暫的容器環境中,傳統的測試與監控方法往往力不從心,需要全新的思維模式與工具鏈來應對這些挑戰。
Kubernetes 提供了豐富的原生工具與 API 來支援測試與偵錯工作,其中 kubectl 命令列工具是開發者與叢集互動的主要介面。透過 kubectl 的各種子命令,開發者能夠檢視容器日誌、執行除錯命令、轉發網路連接埠,甚至直接進入容器內部進行即時診斷。然而,純粹依賴命令列操作在處理複雜問題時效率有限,特別是需要同時檢視多個資源狀態或進行多層次追蹤時。因此,將 Kubernetes 工具整合到現代化的整合開發環境(IDE)中,透過視覺化介面與智慧提示來提升開發效率,已經成為業界的主流做法。
在開發環境的設計方面,如何平衡資源利用效率與開發者自主性是一個需要深思的問題。採用單一大型叢集配合命名空間隔離與資源配額管理,相較於為每個開發者建立獨立叢集,通常能夠更有效地利用資源並簡化維運複雜度。然而,這種共享模式需要完善的權限控制與資源清理機制,確保開發者之間不會互相干擾,同時避免資源浪費。
監控系統的建立是確保叢集穩定運作的關鍵基礎設施。在 Kubernetes 的動態環境中,容器隨時可能被創建、遷移或銷毀,傳統的基於主機的監控方法已經無法滿足需求。現代化的監控體系需要結合指標收集、日誌聚合與分散式追蹤三個維度,建立完整的可觀測性(Observability)體系。指標提供了系統狀態的量化視圖,日誌記錄了事件的詳細脈絡,而分散式追蹤則揭示了請求在微服務架構中的完整路徑。這三者相輔相成,共同支撐起故障診斷與效能優化的工作。
Prometheus 作為雲端原生計算基金會(CNCF)的畢業專案,已經成為 Kubernetes 監控領域的事實標準。其拉取式(Pull)的指標收集模型、多維度的時間序列資料庫,以及強大的查詢語言 PromQL,為監控系統提供了堅實的技術基礎。配合 Grafana 的視覺化能力與 Alertmanager 的警示管理功能,能夠建立起完整的監控、告警與視覺化解決方案。
本文將系統化地探討 Kubernetes 測試、偵錯與監控的完整實踐體系。從 kubectl 工具的進階應用技巧,到 IDE 整合開發環境的配置方法;從開發叢集的架構設計原則,到監控系統的理論基礎與實作細節。透過深入剖析黑箱監控與白箱監控的技術差異,詳解 USE 方法與 RED 方法的監控理論,並提供 Prometheus 與 Grafana 的完整部署方案,協助讀者建立從開發環境到生產環境的全方位測試、偵錯與監控能力。
Kubernetes 測試與偵錯的核心理念
在 Kubernetes 環境中進行應用程式測試與偵錯,需要理解容器化應用與傳統單體應用在本質上的差異。在傳統的開發模式中,應用程式通常直接部署在物理機或虛擬機上,開發者可以直接登入主機、檢視檔案系統、查看程序狀態。然而在 Kubernetes 的世界裡,容器是短暫且不可變的(Immutable),它們可能隨時被重新調度到不同的節點上,甚至在執行期間被替換為新版本。這種特性雖然帶來了極大的靈活性與可靠性,但也為測試與偵錯工作帶來了新的挑戰。
測試策略在 Kubernetes 環境中需要涵蓋多個層次。在單元測試層面,開發者需要確保應用程式的各個元件能夠正確運作,這通常在開發者的本地環境進行,不需要完整的 Kubernetes 叢集。整合測試則需要驗證不同服務之間的互動是否符合預期,這時候可能需要在本地啟動輕量級的 Kubernetes 環境(如 Minikube 或 kind),或是連接到遠端的開發叢集。端對端測試(E2E Testing)則需要在盡可能接近生產環境的配置下進行,驗證整個系統的行為是否正確。
偵錯工作在 Kubernetes 中通常比傳統環境更具挑戰性。當應用程式出現問題時,開發者需要快速定位問題是發生在應用程式代碼層面、容器配置層面、Kubernetes 資源配置層面,還是底層基礎設施層面。這需要對 Kubernetes 的運作機制有深入的理解,同時也需要掌握相應的工具與技巧。例如,一個 Pod 無法啟動可能是因為映像拉取失敗、資源配額不足、節點標籤不匹配、健康檢查配置錯誤等多種原因,開發者需要系統化地排查這些可能性。
容器的不可變特性也改變了偵錯的方式。在傳統環境中,當程式出現問題時,開發者可能會直接在執行環境中安裝除錯工具、修改配置檔案,甚至直接修改代碼來驗證假設。但在容器環境中,這種做法不僅違背了不可變基礎設施的原則,而且這些修改會在容器重啟後消失。因此,Kubernetes 環境中的偵錯更強調使用非侵入式的方法,例如透過日誌收集系統查看應用程式輸出、使用分散式追蹤系統追蹤請求路徑、透過指標監控系統觀察資源使用情況,或是使用臨時的除錯容器來輔助診斷。
開發效率的提升不僅依賴於工具的選擇,更重要的是建立良好的開發工作流程。一個理想的開發工作流程應該讓開發者能夠快速地建置、部署與測試他們的代碼變更,並在出現問題時能夠迅速定位與修復。這需要在開發環境中建立完善的自動化流程,包括持續整合(CI)管道、自動化測試套件、快速的映像建置與推送流程,以及便捷的部署更新機制。同時,開發環境也需要提供與生產環境相似的配置,避免因為環境差異導致的「在我的機器上可以運作」問題。
kubectl 命令列工具的深度應用實踐
kubectl 作為與 Kubernetes 叢集互動的主要命令列工具,提供了豐富且強大的功能集合,是每個 Kubernetes 開發者與維運人員必須精通的核心工具。雖然現代化的 IDE 與 GUI 工具提供了更友善的使用者介面,但深入理解 kubectl 的各種指令與選項,對於高效地進行測試、偵錯與故障排除仍然至關重要。
在日誌檢視方面,kubectl logs 指令是最常用的偵錯工具之一。當容器出現異常行為時,檢視其輸出的日誌通常是第一步診斷工作。kubectl logs 不僅能夠顯示容器的標準輸出與標準錯誤,還支援多種進階選項來滿足不同的偵錯需求。例如,使用 --follow 或 -f 選項可以即時追蹤日誌輸出,這在觀察應用程式的即時行為時特別有用。當 Pod 包含多個容器時,需要使用 --container 或 -c 選項來指定要檢視哪個容器的日誌。
# 檢視指定 Pod 的日誌輸出
# 這是最基本的日誌查看方式
kubectl logs my-pod -n production
# 參數說明:
# my-pod: Pod 的名稱
# -n production: 指定命名空間為 production
#
# 輸出將顯示該 Pod 主容器的所有日誌內容
# 即時追蹤日誌輸出
# 適用於需要觀察應用程式即時行為的場景
kubectl logs -f my-pod -n production
# 參數說明:
# -f 或 --follow: 持續輸出新產生的日誌,類似 tail -f
# 使用 Ctrl+C 可以中斷追蹤
# 檢視包含多個容器的 Pod 中特定容器的日誌
# 當 Pod 包含 sidecar 容器時經常需要使用
kubectl logs my-pod -c app-container -n production
# 參數說明:
# -c app-container: 指定要檢視的容器名稱
# 如果不指定容器名稱且 Pod 包含多個容器,指令會失敗並提示選擇容器
# 檢視前一個容器實例的日誌
# 當容器崩潰重啟時,這個選項非常有用
kubectl logs my-pod --previous -n production
# 參數說明:
# --previous: 顯示前一個終止的容器實例的日誌
# 這對於診斷容器崩潰原因特別有幫助
# 如果容器從未重啟過,這個指令會失敗
# 限制日誌輸出的時間範圍
# 適用於日誌量很大時,只關注最近的輸出
kubectl logs my-pod --since=1h -n production
# 參數說明:
# --since=1h: 只顯示最近 1 小時內的日誌
# 可以使用的時間單位: s(秒)、m(分)、h(時)
# 這可以大幅減少需要處理的日誌量
# 限制日誌輸出的行數
# 快速查看最新的日誌內容
kubectl logs my-pod --tail=100 -n production
# 參數說明:
# --tail=100: 只顯示最後 100 行日誌
# 預設會顯示所有日誌,在日誌量大時可能需要等待較長時間
# 檢視所有具有特定標籤的 Pod 的日誌
# 適用於檢視一組相關 Pod 的日誌
kubectl logs -l app=myapp -n production
# 參數說明:
# -l app=myapp: 使用標籤選擇器選擇 Pod
# 這會顯示所有匹配標籤的 Pod 的日誌
# --prefix 選項可以在每行前加上 Pod 名稱以區分來源
在容器內執行指令是另一個重要的偵錯技巧。kubectl exec 指令允許開發者在執行中的容器內執行任意指令,這在需要檢查容器內部狀態、驗證網路連線或執行臨時診斷指令時非常有用。最常見的用法是開啟一個互動式的 shell,讓開發者能夠像登入傳統伺服器一樣探索容器環境。
# 在容器中執行單一指令
# 適用於快速檢查特定資訊
kubectl exec my-pod -n production -- ls -la /app
# 參數說明:
# --: 這個分隔符號很重要,它將 kubectl 的選項與要在容器內執行的指令分開
# ls -la /app: 列出 /app 目錄的詳細內容
# 指令的輸出會直接顯示在終端
# 開啟互動式 shell
# 這是最常用的除錯方式,讓你能夠在容器內自由操作
kubectl exec -it my-pod -n production -- /bin/bash
# 參數說明:
# -i 或 --stdin: 保持標準輸入開啟
# -t 或 --tty: 分配一個偽終端(TTY)
# 兩者結合使用才能獲得完整的互動式體驗
# /bin/bash: 要執行的 shell 程式
# 如果容器中沒有 bash,可以嘗試 /bin/sh
# 在多容器 Pod 中的特定容器內執行指令
kubectl exec my-pod -c sidecar -n production -- ps aux
# 參數說明:
# -c sidecar: 指定要執行指令的容器
# ps aux: 列出該容器內所有執行中的程序
# 這可以幫助理解容器內的程序結構
# 檢查網路連線
# 驗證容器能否連接到其他服務
kubectl exec my-pod -n production -- curl -v http://other-service:8080/health
# 參數說明:
# curl -v: 以詳細模式執行 HTTP 請求
# 這可以幫助診斷服務間的網路連接問題
# 注意: 容器內需要安裝 curl 工具
# 檢查環境變數
# 驗證容器的環境變數配置是否正確
kubectl exec my-pod -n production -- env
# 參數說明:
# env: 列出所有環境變數
# 這可以幫助確認 ConfigMap 或 Secret 是否正確注入
# 檢視容器內的檔案內容
# 適用於驗證配置檔案是否正確掛載
kubectl exec my-pod -n production -- cat /etc/config/app.conf
# 參數說明:
# cat: 顯示檔案內容
# 這可以確認配置檔案的內容是否符合預期
連接埠轉發功能允許開發者將叢集內服務的連接埠映射到本地機器,這在開發與測試階段特別有用。透過連接埠轉發,開發者可以直接從本地瀏覽器或工具存取叢集內的服務,而不需要透過 LoadBalancer 或 Ingress 等外部暴露機制。
# 將 Pod 的連接埠轉發到本地
# 這是最直接的連接埠轉發方式
kubectl port-forward my-pod 8080:80 -n production
# 參數說明:
# 8080:80 表示將 Pod 的 80 連接埠映射到本地的 8080 連接埠
# 之後可以透過 http://localhost:8080 存取該 Pod 的服務
# 按 Ctrl+C 可以終止轉發
#
# 注意事項:
# 1. 連接埠轉發只在 kubectl 指令執行期間有效
# 2. 只有執行該指令的本地機器可以存取
# 3. 適用於開發與除錯,不建議在生產環境長期使用
# 將 Service 的連接埠轉發到本地
# 自動選擇一個健康的 Pod 進行轉發
kubectl port-forward service/my-service 8080:80 -n production
# 參數說明:
# service/my-service: 指定要轉發的 Service
# Kubernetes 會自動選擇該 Service 後端的一個 Pod
# 如果 Pod 失敗,轉發會中斷,需要重新執行指令
# 監聽所有網路介面
# 允許同一網路內的其他機器也能存取
kubectl port-forward --address 0.0.0.0 my-pod 8080:80 -n production
# 參數說明:
# --address 0.0.0.0: 監聽所有網路介面
# 預設只監聽 localhost (127.0.0.1)
# 使用此選項時需要注意安全性,確保網路環境是受信任的
# 轉發多個連接埠
# 當服務使用多個連接埠時很有用
kubectl port-forward my-pod 8080:80 8443:443 -n production
# 參數說明:
# 8080:80 和 8443:443: 同時轉發兩個連接埠
# 第一個數字是本地連接埠,第二個是 Pod 的連接埠
# 可以根據需要轉發任意數量的連接埠
除了這些基本的偵錯指令外,kubectl 還提供了許多其他有用的功能。例如,kubectl describe 指令可以顯示資源的詳細資訊與事件歷史,這在診斷 Pod 無法啟動或服務配置錯誤時特別有幫助。kubectl get events 可以查看叢集中最近發生的事件,幫助理解系統的整體狀態。kubectl top 指令可以顯示節點或 Pod 的資源使用情況,這對於診斷效能問題很有價值。
IDE 整合開發環境的 Kubernetes 工具配置
雖然 kubectl 命令列工具功能強大,但在日常開發工作中,純粹依賴命令列操作可能會降低效率。現代化的整合開發環境(IDE)透過提供視覺化介面、智慧提示與快捷操作,能夠大幅簡化與 Kubernetes 叢集的互動過程。市面上有多種支援 Kubernetes 的 IDE 擴充套件與外掛,其中 Visual Studio Code 的 Kubernetes 擴充套件因其功能完整性與易用性而廣受歡迎。
Visual Studio Code 的 Kubernetes 擴充套件提供了完整的叢集管理功能。安裝擴充套件後,它會自動讀取本地的 kubeconfig 檔案(通常位於 ~/.kube/config),並在側邊欄中顯示可用的叢集清單。開發者可以輕鬆地在不同的叢集與命名空間之間切換,無需記憶複雜的 kubectl context 切換指令。擴充套件還提供了樹狀結構的資源瀏覽器,讓開發者能夠直觀地查看叢集中的各種資源,包括 Deployments、Services、Pods、ConfigMaps、Secrets 等。
在資源操作方面,擴充套件提供了豐富的右鍵選單功能。對 Pod 點擊右鍵,可以直接選擇查看日誌、描述資源詳情、開啟終端機、設定連接埠轉發等操作,這些功能在背後都是呼叫相應的 kubectl 指令,但透過圖形介面操作更加直觀與便捷。例如,設定連接埠轉發時,擴充套件會彈出對話框讓開發者輸入本地連接埠與目標連接埠,而不需要記憶 kubectl port-forward 的參數格式。
YAML 檔案的編輯是 Kubernetes 開發中的常見任務。Visual Studio Code 配合 Kubernetes 擴充套件能夠提供智慧的 YAML 編輯體驗,包括語法高亮、自動完成、即時驗證與錯誤提示。當編輯 Deployment 或 Service 的 YAML 檔案時,擴充套件會根據 Kubernetes API 規範提供欄位建議,並在輸入錯誤的欄位名稱或值時給予警告。這大幅降低了因為 YAML 語法錯誤或欄位拼寫錯誤導致的部署失敗。
除了 Visual Studio Code 外,其他流行的 IDE 如 IntelliJ IDEA、GoLand、PyCharm 等 JetBrains 系列產品也都提供了 Kubernetes 整合外掛。這些外掛的功能大同小異,都是圍繞著簡化叢集互動、提升開發效率的目標設計。選擇哪個 IDE 主要取決於開發者的個人偏好與所使用的程式語言生態系統。
在配置 IDE 整合時,有幾個最佳實踐值得注意。首先,建議為不同的環境(開發、測試、生產)配置不同的 kubeconfig context,並透過 IDE 的叢集切換功能明確地選擇當前要操作的環境,避免誤操作生產環境。其次,對於團隊協作場景,可以將常用的 Kubernetes 資源清單檔案與配置腳本納入版本控制系統,確保團隊成員使用一致的開發環境配置。最後,善用 IDE 的快捷鍵與自訂命令功能,將常用的 kubectl 操作綁定到快捷鍵上,進一步提升操作效率。
開發叢集的架構設計與資源管理策略
在企業環境中,為開發團隊提供合適的 Kubernetes 開發環境是一個需要仔細規劃的任務。開發環境的設計需要在資源利用效率、開發者自主性、安全隔離與維運複雜度之間取得平衡。業界主要有兩種常見的開發叢集架構模式:為每個開發者提供獨立的小型叢集,或是建立一個大型共享叢集並透過命名空間(Namespace)進行隔離。
為每個開發者提供獨立叢集的方案提供了最大程度的隔離性與自主性。每個開發者擁有完整的叢集控制權,可以隨意實驗各種配置、安裝任何需要的工具,而不用擔心影響其他人。這種方案的缺點是資源利用效率較低,因為每個叢集都需要執行自己的控制平面(Control Plane)元件,包括 API Server、Controller Manager、Scheduler 等,這些元件即使在閒置時也會消耗相當的資源。此外,維運團隊需要管理大量的叢集實例,增加了維護的複雜度與成本。
相比之下,單一大型共享叢集配合命名空間隔離的方案在大多數情況下是更好的選擇。這種架構透過 Kubernetes 原生的命名空間機制為每個開發者或團隊提供邏輯隔離的工作空間。透過適當的 RBAC(角色基礎存取控制)配置,可以確保開發者只能存取自己的命名空間,無法查看或修改其他人的資源。配合 ResourceQuota 與 LimitRange 等資源管理機制,可以限制每個命名空間可以使用的資源上限,防止單一開發者佔用過多的叢集資源。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "開發叢集架構" {
package "控制平面" as ControlPlane {
component "API Server" as API
component "Controller Manager" as CM
component "Scheduler" as Sched
component "etcd" as ETCD
}
package "開發者命名空間隔離" as Namespaces {
package "Namespace: dev-alice" as NS1 {
component "Deployment A" as DepA
component "Service A" as SvcA
component "ConfigMap" as CMA
}
note right of DepA
資源配額:
CPU: 4 核心
Memory: 8 GB
Pods: 20
end note
package "Namespace: dev-bob" as NS2 {
component "Deployment B" as DepB
component "Service B" as SvcB
component "Secret" as SecB
}
note right of DepB
資源配額:
CPU: 4 核心
Memory: 8 GB
Pods: 20
end note
package "Namespace: shared-services" as NS3 {
component "Monitoring" as Mon
component "Logging" as Log
component "Registry" as Reg
}
note right of Mon
共享服務:
- Prometheus
- Grafana
- Fluentd
- Harbor
end note
}
package "節點池" as NodePool {
component "Worker Node 1" as WN1
component "Worker Node 2" as WN2
component "Worker Node 3" as WN3
}
}
API --> ETCD
API --> CM
API --> Sched
Sched --> WN1
Sched --> WN2
Sched --> WN3
DepA --> WN1
DepB --> WN2
Mon --> WN3
@enduml在共享叢集的架構中,資源配額(ResourceQuota)的設定是關鍵環節。ResourceQuota 允許管理員為每個命名空間設定可以使用的資源上限,包括 CPU、記憶體、持久化儲存空間、Pod 數量、Service 數量等。這確保了即使某個開發者的應用程式出現資源洩漏或無限迴圈等問題,也不會耗盡整個叢集的資源而影響其他開發者。以下是一個典型的 ResourceQuota 配置範例:
# 為開發者命名空間設定資源配額
# 這個配置限制了命名空間可以使用的最大資源量
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev-alice
labels:
environment: development
managed-by: platform-team
spec:
hard:
# CPU 資源限制
# requests.cpu: 命名空間內所有 Pod 的 CPU 請求總和上限
# limits.cpu: 命名空間內所有 Pod 的 CPU 限制總和上限
requests.cpu: "4"
limits.cpu: "8"
# 記憶體資源限制
# requests.memory: 命名空間內所有 Pod 的記憶體請求總和上限
# limits.memory: 命名空間內所有 Pod 的記憶體限制總和上限
requests.memory: 8Gi
limits.memory: 16Gi
# 持久化儲存限制
# 限制命名空間可以請求的持久化儲存總量
requests.storage: 100Gi
persistentvolumeclaims: "10"
# 物件數量限制
# 防止建立過多的資源物件
pods: "20"
services: "10"
configmaps: "20"
secrets: "20"
# 可選:設定資源配額的作用域
# 例如只限制特定優先順序類別的 Pod
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["low-priority", "medium-priority"]
---
# 設定 LimitRange 以提供預設值並限制單一 Pod 的資源
# LimitRange 與 ResourceQuota 配合使用,提供更精細的控制
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limits
namespace: dev-alice
spec:
limits:
# 對 Pod 的限制
- type: Pod
max:
cpu: "4"
memory: 8Gi
min:
cpu: "100m"
memory: 128Mi
# 對 Container 的限制
- type: Container
# 單一容器可以使用的最大資源
max:
cpu: "2"
memory: 4Gi
# 單一容器必須請求的最小資源
min:
cpu: "100m"
memory: 128Mi
# 如果容器沒有指定資源請求或限制,使用這些預設值
default:
cpu: "500m"
memory: 512Mi
defaultRequest:
cpu: "200m"
memory: 256Mi
# 對持久化儲存卷的限制
- type: PersistentVolumeClaim
max:
storage: 50Gi
min:
storage: 1Gi
除了資源配額外,自動化的資源清理機制也很重要。開發者在測試完成後可能忘記刪除不再需要的資源,導致叢集資源被浪費。可以透過設定自動清理策略來解決這個問題,例如使用 Kubernetes 的 TTL Controller 為資源設定存活時間,或是使用 CronJob 定期掃描並清理閒置的資源。
在身份認證與授權方面,建議為每個開發者建立獨立的使用者帳號,而不是共用單一的叢集管理員帳號。這不僅能夠追蹤每個操作的來源,也能夠根據每個開發者的職責與需求授予適當的權限。對於命名空間層級的操作,可以使用 RoleBinding 將 Role 綁定到特定開發者,讓他們擁有自己命名空間的完整控制權,但無法存取其他命名空間或叢集層級的資源。
叢集層級的共享服務是提升開發效率的另一個重要面向。在共享叢集中,可以部署一些所有開發者都可以使用的公共服務,例如統一的日誌收集系統(如 Fluentd 或 Loki)、監控系統(如 Prometheus)、容器映像倉庫(如 Harbor)、持續整合系統等。這些服務由平台團隊統一維護,開發者無需自行搭建,可以專注於應用程式的開發工作。
監控系統的理論基礎:黑箱與白箱監控
在深入探討 Kubernetes 監控的具體實作之前,理解監控系統的理論基礎與設計理念至關重要。監控系統的核心目標是提供系統狀態的可見性,讓維運團隊能夠及時發現問題、診斷原因並採取修復措施。在監控方法論中,黑箱監控(Black-box Monitoring)與白箱監控(White-box Monitoring)代表了兩種不同但互補的視角。
黑箱監控關注於從外部觀察系統的行為,就像一個黑盒子,我們只關心輸入與輸出,而不深入了解內部的運作機制。這種監控方式模擬真實使用者的體驗,透過傳送探測請求(Probe)或健康檢查(Health Check)來驗證服務是否正常運作。例如,定期向一個 HTTP 端點傳送 GET 請求,如果回應時間超過閾值或回應狀態碼不是 200,就觸發警示。黑箱監控的優勢在於它關注最終使用者實際體驗到的服務品質,能夠快速發現服務不可用的問題。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
actor "外部監控探針" as Probe
participant "負載平衡器" as LB
participant "Kubernetes\nService" as Svc
participant "Pod 1" as Pod1
participant "Pod 2" as Pod2
database "監控系統" as Monitor
== 黑箱監控流程 ==
Probe -> LB : HTTP GET /health
activate LB
note right of Probe
定期傳送探測請求
不關心內部實作
只驗證回應結果
end note
LB -> Svc : 轉發請求
activate Svc
Svc -> Pod1 : 路由到健康的 Pod
activate Pod1
Pod1 --> Svc : 200 OK\n{"status":"healthy"}
deactivate Pod1
Svc --> LB : 回傳回應
deactivate Svc
LB --> Probe : 200 OK\n回應時間: 50ms
deactivate LB
Probe -> Monitor : 記錄指標\n- 可用性: 100%\n- 回應時間: 50ms
activate Monitor
note right of Monitor
黑箱監控指標:
- 服務可用性
- 回應時間
- 錯誤率
end note
deactivate Monitor
@enduml然而,黑箱監控也有其局限性。當黑箱監控發現服務異常時,它無法提供足夠的資訊來診斷問題的根本原因。例如,一個 HTTP 端點回應時間過長,可能是因為資料庫查詢效能低落、記憶體不足觸發了頻繁的垃圾回收、網路延遲增加,或是上游服務出現問題等多種原因。黑箱監控無法區分這些不同的情況,這時候就需要白箱監控來提供更深入的洞察。
白箱監控深入到系統內部,收集應用程式與基礎設施層面的詳細指標。這包括應用程式層級的指標(如 HTTP 請求總數、請求延遲分布、錯誤類型統計、資料庫查詢次數)、執行期指標(如垃圾回收次數、執行緒數量、堆積記憶體使用)、以及基礎設施指標(如 CPU 使用率、記憶體使用量、網路流量、磁碟 I/O)。透過白箱監控,維運團隊可以理解系統狀態的背後原因,從而更有效地診斷與解決問題。
白箱監控需要應用程式主動暴露(Expose)指標。在現代的雲端原生應用中,最常見的做法是使用 Prometheus 格式的指標端點,讓監控系統可以定期抓取(Scrape)這些指標。應用程式通常會使用相應程式語言的 Prometheus 客戶端函式庫來建立與更新指標,並透過 HTTP 端點暴露出來。
# Python 應用程式暴露 Prometheus 指標的範例
# 這個範例展示如何在 Flask 應用程式中整合 Prometheus 指標收集
from flask import Flask, request
from prometheus_client import Counter, Histogram, Gauge, generate_latest, REGISTRY
import time
# 建立 Flask 應用程式實例
app = Flask(__name__)
# 定義各種類型的 Prometheus 指標
# Counter: 計數器,只能增加的指標
# 適用於記錄累積的事件數量,如請求總數、錯誤總數等
http_requests_total = Counter(
'http_requests_total',
'HTTP 請求總數',
['method', 'endpoint', 'status_code']
)
# Histogram: 直方圖,記錄數值的分布情況
# 適用於記錄請求延遲、回應大小等
http_request_duration_seconds = Histogram(
'http_request_duration_seconds',
'HTTP 請求處理時間(秒)',
['method', 'endpoint']
)
# Gauge: 儀表,可增可減的指標
# 適用於記錄當前狀態,如當前連線數、佇列長度等
active_connections = Gauge(
'active_connections',
'當前活躍連線數'
)
# 中介軟體:自動記錄每個請求的指標
@app.before_request
def before_request():
# 記錄請求開始時間
request.start_time = time.time()
# 增加活躍連線計數
active_connections.inc()
@app.after_request
def after_request(response):
# 計算請求處理時間
request_duration = time.time() - request.start_time
# 記錄請求計數
# labels 用於區分不同類型的請求
http_requests_total.labels(
method=request.method,
endpoint=request.endpoint or 'unknown',
status_code=response.status_code
).inc()
# 記錄請求處理時間
http_request_duration_seconds.labels(
method=request.method,
endpoint=request.endpoint or 'unknown'
).observe(request_duration)
# 減少活躍連線計數
active_connections.dec()
return response
# 業務邏輯端點
@app.route('/api/data')
def get_data():
# 這裡是實際的業務邏輯
# 所有的指標記錄都由中介軟體自動處理
return {'data': 'example'}
# Prometheus 指標端點
# 這個端點會被 Prometheus 定期抓取
@app.route('/metrics')
def metrics():
# generate_latest() 會生成所有已註冊指標的當前值
# 格式為 Prometheus 可以解析的文字格式
return generate_latest(REGISTRY)
# 啟動應用程式
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
# 指標輸出範例:
# # HELP http_requests_total HTTP 請求總數
# # TYPE http_requests_total counter
# http_requests_total{method="GET",endpoint="get_data",status_code="200"} 1523.0
# http_requests_total{method="POST",endpoint="create_item",status_code="201"} 342.0
# http_requests_total{method="GET",endpoint="get_data",status_code="500"} 12.0
#
# # HELP http_request_duration_seconds HTTP 請求處理時間(秒)
# # TYPE http_request_duration_seconds histogram
# http_request_duration_seconds_bucket{method="GET",endpoint="get_data",le="0.005"} 1234.0
# http_request_duration_seconds_bucket{method="GET",endpoint="get_data",le="0.01"} 1456.0
# http_request_duration_seconds_bucket{method="GET",endpoint="get_data",le="0.025"} 1489.0
# http_request_duration_seconds_sum{method="GET",endpoint="get_data"} 15.234
# http_request_duration_seconds_count{method="GET",endpoint="get_data"} 1523.0
#
# # HELP active_connections 當前活躍連線數
# # TYPE active_connections gauge
# active_connections 23.0
在實務中,黑箱監控與白箱監控應該相互配合使用。黑箱監控作為第一道防線,快速發現服務不可用或效能下降的問題,並觸發警示。白箱監控則提供詳細的內部指標,協助維運團隊診斷問題的根本原因。理想的監控體系應該包含多個層次,從最外層的使用者體驗監控,到中層的應用程式指標監控,再到底層的基礎設施監控,形成一個完整的可觀測性體系。
USE 與 RED 監控方法論的深度解析
在建立監控系統時,收集哪些指標、如何組織這些指標,以及如何從指標中提取有價值的洞察,是需要系統化思考的問題。業界發展出了多種監控方法論來指導監控系統的設計,其中 USE 方法與 RED 方法是最廣為採用的兩種框架。
USE 方法:基礎設施資源監控
USE 方法由效能工程領域的專家 Brendan Gregg 提出,主要用於基礎設施層面的資源監控。USE 是三個英文單字的縮寫,分別代表 Utilization(利用率)、Saturation(飽和度)與 Errors(錯誤率)。這個方法提供了一個系統化的框架,協助維運團隊識別資源瓶頸與效能問題。
利用率(Utilization)衡量資源在一段時間內被使用的平均百分比。例如,如果一個 CPU 核心在過去一分鐘內有 75% 的時間處於忙碌狀態,其利用率就是 75%。高利用率通常意味著資源接近滿載,可能成為效能瓶頸。然而,利用率本身並不總是問題的指標,某些資源(如批次處理系統的 CPU)在設計上就是要保持高利用率以最大化吞吐量。
飽和度(Saturation)衡量資源無法滿足需求的程度,通常表現為工作佇列的長度或等待時間。當資源的利用率達到 100% 時,新的請求無法立即被處理,會被放入等待佇列中。飽和度指標可以提前預警資源不足的問題,即使利用率還沒有達到極限,持續增長的佇列長度也表明系統正在接近其容量上限。
錯誤率(Errors)記錄資源在處理請求時發生錯誤的頻率。這些錯誤可能是硬體故障、軟體缺陷或配置錯誤導致的。即使在利用率與飽和度看起來正常的情況下,高錯誤率也表明系統存在問題,需要立即關注。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "USE 方法監控框架" {
component "CPU 資源" as CPU {
rectangle "Utilization\n利用率" as CPU_U
rectangle "Saturation\n飽和度" as CPU_S
rectangle "Errors\n錯誤率" as CPU_E
}
note right of CPU_U
測量指標:
- CPU 使用率 (%)
- idle 時間百分比
正常範圍:
- 一般: 30-70%
- 高負載: 70-90%
- 警示: > 90%
end note
note right of CPU_S
測量指標:
- Run queue 長度
- Load average
- Context switch 頻率
警示條件:
- Load > CPU 核心數
- 長時間等待排程
end note
note right of CPU_E
測量指標:
- CPU 硬體錯誤
- 過熱降頻事件
- 異常中斷
end note
component "記憶體資源" as MEM {
rectangle "Utilization\n利用率" as MEM_U
rectangle "Saturation\n飽和度" as MEM_S
rectangle "Errors\n錯誤率" as MEM_E
}
note right of MEM_U
測量指標:
- 已用記憶體百分比
- Cache/Buffer 使用量
- Swap 使用量
警示條件:
- 可用記憶體 < 10%
- Swap 使用 > 0
end note
note right of MEM_S
測量指標:
- Page fault 頻率
- Swap in/out 速率
- OOM kill 次數
警示條件:
- 頻繁 swap 活動
- 發生 OOM kill
end note
note right of MEM_E
測量指標:
- ECC 錯誤
- 記憶體硬體故障
end note
component "網路資源" as NET {
rectangle "Utilization\n利用率" as NET_U
rectangle "Saturation\n飽和度" as NET_S
rectangle "Errors\n錯誤率" as NET_E
}
note right of NET_U
測量指標:
- 頻寬使用率
- 封包傳輸率
警示條件:
- 頻寬使用 > 80%
end note
note right of NET_S
測量指標:
- 傳輸佇列長度
- Drop 封包數
- Retransmit 比率
end note
note right of NET_E
測量指標:
- CRC 錯誤
- Frame 錯誤
- Collision 次數
end note
}
CPU_U -[hidden]down-> CPU_S
CPU_S -[hidden]down-> CPU_E
MEM_U -[hidden]down-> MEM_S
MEM_S -[hidden]down-> MEM_E
NET_U -[hidden]down-> NET_S
NET_S -[hidden]down-> NET_E
@enduml在 Kubernetes 環境中應用 USE 方法時,需要在多個層次收集指標。在節點層次,監控實體或虛擬機的 CPU、記憶體、網路與磁碟資源。在 Pod 層次,監控容器的資源使用情況與限制。透過比較資源請求(Request)、資源限制(Limit)與實際使用量,可以識別資源配置是否合理,以及是否存在資源爭用的問題。
RED 方法:服務層級監控
RED 方法由 Tom Wilkie 提出,源自 Google 的 Four Golden Signals 理論,主要用於監控面向使用者的服務。RED 同樣是三個英文單字的縮寫,分別代表 Rate(請求率)、Errors(錯誤率)與 Duration(請求延遲)。這個方法關注於服務對外提供的 API 或端點,從使用者體驗的角度評估服務品質。
請求率(Rate)衡量服務每秒處理的請求數量。這個指標反映了服務的負載水平與流量趨勢。透過追蹤請求率的變化,可以識別流量尖峰、異常的流量模式,或是服務使用量的增長趨勢。請求率的突然下降可能表示上游服務出現問題或網路連接中斷,而不是服務本身的問題。
錯誤率(Errors)衡量請求失敗的比例。這個指標直接反映了服務的可靠性。錯誤可以是明確的失敗回應(如 HTTP 5xx 狀態碼),也可以是邏輯錯誤(如回應內容不符合預期)。高錯誤率表明服務存在嚴重問題,需要立即介入處理。即使只有少數請求失敗,如果這些失敗影響了關鍵業務流程,也應該觸發警示。
請求延遲(Duration)衡量服務處理請求所需的時間。這個指標直接影響使用者體驗,過長的延遲會導致使用者感到不耐煩或放棄操作。延遲指標通常使用直方圖或百分位數來表示,因為平均值可能會掩蓋異常值的影響。常用的百分位數包括 P50(中位數)、P95、P99 與 P99.9,分別表示 50%、95%、99% 與 99.9% 的請求延遲低於該值。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "RED 方法監控框架" {
actor "使用者" as User
component "前端服務" as Frontend {
rectangle "Rate\n請求率" as F_R {
note right
測量指標:
- 每秒請求數 (RPS)
- 每分鐘請求數 (RPM)
- 依端點分類的請求數
分析重點:
- 流量趨勢
- 異常尖峰
- 流量突降
end note
}
rectangle "Errors\n錯誤率" as F_E {
note right
測量指標:
- 4xx 錯誤率 (客戶端錯誤)
- 5xx 錯誤率 (伺服器錯誤)
- 逾時率
警示條件:
- 錯誤率 > 1%
- 5xx 錯誤 > 0.1%
end note
}
rectangle "Duration\n請求延遲" as F_D {
note right
測量指標:
- P50 延遲 (中位數)
- P95 延遲
- P99 延遲
- P99.9 延遲
目標值範例:
- P50 < 100ms
- P95 < 500ms
- P99 < 1s
end note
}
}
component "API 服務" as API {
rectangle "Rate\n請求率" as A_R
rectangle "Errors\n錯誤率" as A_E
rectangle "Duration\n請求延遲" as A_D
}
component "資料庫服務" as DB {
rectangle "Rate\n查詢率" as D_R
rectangle "Errors\n錯誤率" as D_E
rectangle "Duration\n查詢延遲" as D_D
}
User -> Frontend : HTTP 請求
Frontend -> API : 內部 API 呼叫
API -> DB : 資料庫查詢
}
F_R -[hidden]down-> F_E
F_E -[hidden]down-> F_D
A_R -[hidden]down-> A_E
A_E -[hidden]down-> A_D
D_R -[hidden]down-> D_E
D_E -[hidden]down-> D_D
@enduml在微服務架構中,RED 方法特別有價值。每個微服務都應該暴露其 RED 指標,讓監控系統能夠追蹤請求在服務網格中的流動。當使用者報告服務緩慢時,透過比較各個服務的 RED 指標,可以快速定位哪個服務是瓶頸。例如,如果前端服務的 P99 延遲很高,但其自身的處理時間很短,問題很可能出在其呼叫的後端服務上。
USE 方法與 RED 方法相輔相成,共同構成了完整的監控框架。USE 方法關注資源層面,協助識別基礎設施的瓶頸與故障。RED 方法關注服務層面,協助評估使用者體驗與服務品質。在實務中,應該同時應用這兩種方法,從不同角度監控系統的健康狀態。當服務出現效能問題時,可以先透過 RED 指標定位問題發生在哪個服務,再透過 USE 指標診斷該服務是否遇到資源瓶頸。
Prometheus 監控系統的架構與部署實踐
Prometheus 是雲端原生計算基金會(CNCF)的畢業專案,已經成為 Kubernetes 生態系統中監控領域的標準選擇。其設計理念與 Kubernetes 高度契合,提供了原生的服務發現、標籤系統整合,以及動態的目標配置能力。深入理解 Prometheus 的架構與運作原理,對於建立可靠的監控系統至關重要。
Prometheus 的核心架構元件
Prometheus 採用拉取式(Pull-based)的指標收集模型,這與傳統的推送式(Push-based)監控系統有本質上的差異。在拉取模式中,Prometheus Server 主動向目標端點傳送 HTTP 請求來抓取指標,而不是被動接收目標推送的指標。這種設計有多個優勢:首先,Prometheus Server 完全控制抓取的時機與頻率,可以根據自身的負載動態調整。其次,目標服務不需要知道監控系統的位置,只需要暴露一個 HTTP 端點即可,簡化了配置。最後,Prometheus Server 可以透過健康檢查來驗證目標是否可達,自動處理目標的上下線。
Prometheus Server 是系統的核心元件,負責指標的抓取、儲存與查詢。它內建了一個時間序列資料庫(TSDB),採用特殊設計的儲存格式來高效地儲存與壓縮大量的時間序列資料。時間序列資料的特點是資料點按時間順序排列,且大多數查詢都是基於時間範圍的。Prometheus 的 TSDB 針對這些特性進行了最佳化,能夠在有限的硬體資源下處理數百萬個時間序列。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "Prometheus 監控架構" {
component "Prometheus Server" as PS {
rectangle "抓取引擎\n(Scrape Engine)" as SE
rectangle "時間序列資料庫\n(TSDB)" as TSDB
rectangle "查詢引擎\n(PromQL)" as QE
rectangle "警示管理器\n(Rule Engine)" as RE
}
component "服務發現" as SD {
rectangle "Kubernetes SD" as K8S_SD
rectangle "靜態配置" as Static
rectangle "檔案 SD" as File_SD
}
component "目標端點" as Targets {
rectangle "應用程式\n/metrics" as App
rectangle "Node Exporter" as NE
rectangle "kube-state-metrics" as KSM
rectangle "cAdvisor" as CA
}
component "Alertmanager" as AM {
rectangle "警示路由" as Route
rectangle "警示聚合" as Group
rectangle "通知發送" as Notify
}
component "視覺化工具" as Visual {
rectangle "Grafana" as GF
rectangle "Prometheus UI" as PUI
}
component "長期儲存" as LTS {
rectangle "Thanos" as Thanos
rectangle "Cortex" as Cortex
}
}
SD --> SE : 提供目標清單
SE --> Targets : HTTP GET /metrics\n(每 15s 抓取一次)
Targets --> SE : 回傳指標資料
SE --> TSDB : 儲存時間序列
TSDB --> QE : 查詢資料
RE --> TSDB : 評估警示規則
RE --> AM : 觸發警示
AM --> Route : 路由警示
Route --> Group : 聚合警示
Group --> Notify : 發送通知\n(Email, Slack, PagerDuty)
QE --> Visual : 提供查詢 API
TSDB --> LTS : 遠端寫入\n(長期保存)
note right of SE
抓取配置:
- 抓取間隔: 15s
- 抓取逾時: 10s
- 重試次數: 3
end note
note right of TSDB
儲存特性:
- 本地儲存
- 預設保留 15 天
- 壓縮率高
- 快速查詢
end note
note right of AM
警示處理:
- 去重
- 分組
- 靜音
- 抑制
- 路由
end note
@endumlAlertmanager 是 Prometheus 生態系統中負責警示管理的獨立元件。當 Prometheus Server 根據警示規則檢測到問題時,會將警示傳送給 Alertmanager。Alertmanager 負責對警示進行去重、分組、抑制與路由,然後透過各種通知管道(如 Email、Slack、PagerDuty、Webhook)傳送警示通知。這種設計分離了指標收集與警示通知的職責,讓系統更加模組化與可擴展。
Exporter 是 Prometheus 生態系統中的重要概念。許多系統與應用程式並沒有原生支援 Prometheus 格式的指標暴露,這時候就需要使用 Exporter 來轉換。Exporter 是一個獨立的程序,它從目標系統讀取指標(可能透過特定的 API 或協定),然後將這些指標轉換為 Prometheus 格式並透過 HTTP 端點暴露出來。常見的 Exporter 包括 Node Exporter(匯出 Linux 系統指標)、MySQL Exporter(匯出 MySQL 資料庫指標)、Redis Exporter(匯出 Redis 指標)等。
在 Kubernetes 環境中,有幾個特別重要的指標來源。cAdvisor 內建於 kubelet 中,負責收集容器層級的資源使用指標,包括 CPU、記憶體、網路與磁碟 I/O。kube-state-metrics 是一個獨立的服務,負責收集 Kubernetes API 物件的狀態指標,例如 Deployment 的副本數、Pod 的狀態、PersistentVolumeClaim 的使用情況等。這些指標對於監控叢集的整體健康狀態與資源利用率至關重要。
使用 Prometheus Operator 簡化部署
雖然可以透過傳統的 Deployment 與 ConfigMap 來部署 Prometheus,但在 Kubernetes 環境中,Prometheus Operator 提供了更加雲端原生的部署與管理方式。Prometheus Operator 透過自訂資源定義(CRD)來宣告式地管理 Prometheus 實例、警示規則、ServiceMonitor 與其他相關資源。這種方式將 Prometheus 的配置變成 Kubernetes 原生的資源物件,可以使用 kubectl 進行管理,並整合到 GitOps 工作流程中。
kube-prometheus-stack 是一個 Helm Chart,它整合了 Prometheus Operator、Prometheus、Alertmanager、Grafana、kube-state-metrics、Node Exporter 等完整的監控堆疊。使用這個 Helm Chart 可以快速部署一個生產就緒的監控系統。以下是完整的部署步驟與說明:
# 步驟 1: 建立專用的命名空間
# 將所有監控相關的資源隔離在獨立的命名空間中
kubectl create namespace monitoring
# 參數說明:
# monitoring: 命名空間名稱,可以根據需要自訂
# 建立獨立命名空間的好處:
# 1. 邏輯隔離,便於管理
# 2. 可以設定專用的資源配額
# 3. 可以設定專用的網路策略
# 4. 便於日誌與監控的過濾
# 步驟 2: 新增 Prometheus Community Helm Chart 倉庫
# Helm Chart 倉庫類似於套件管理器的軟體源
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
# 參數說明:
# prometheus-community: 倉庫的本地別名
# https://prometheus-community...: 倉庫的實際 URL
#
# 這個倉庫包含了 Prometheus 相關的各種 Chart:
# - kube-prometheus-stack: 完整的監控堆疊
# - prometheus: 獨立的 Prometheus Server
# - alertmanager: 獨立的 Alertmanager
# - pushgateway: Prometheus Pushgateway
# 步驟 3: 新增 Helm Stable Chart 倉庫
# 某些相依套件可能在這個倉庫中
helm repo add stable https://charts.helm.sh/stable
# 注意:
# stable 倉庫已經被棄用,但某些舊的 Chart 可能仍有相依性
# 新的專案應該避免依賴 stable 倉庫
# 步驟 4: 更新本地的 Chart 倉庫索引
# 確保能夠獲取最新版本的 Chart
helm repo update
# 參數說明:
# 這個指令會從所有已新增的倉庫下載最新的 Chart 清單
# 類似於 apt-get update 或 yum update
# 步驟 5: 安裝 kube-prometheus-stack Chart
# 這會部署完整的監控堆疊
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace
# 參數詳細說明:
# install: Helm 子命令,用於安裝 Chart
# prometheus: Release 名稱,這個名稱會作為所有資源的前綴
# prometheus-community/kube-prometheus-stack: Chart 的完整名稱
# --namespace monitoring: 指定安裝到 monitoring 命名空間
# --create-namespace: 如果命名空間不存在則自動建立
#
# 這個 Chart 會建立以下資源:
# - Prometheus Operator: 管理 Prometheus 實例的 Operator
# - Prometheus Server: 指標收集與儲存
# - Alertmanager: 警示管理
# - Grafana: 視覺化儀表板
# - kube-state-metrics: Kubernetes 物件狀態指標
# - Node Exporter: 節點層級的系統指標
# - 預設的 ServiceMonitor: 自動發現與抓取目標
# - 預設的 PrometheusRule: 常見的警示規則
# 可選:使用自訂的 values.yaml 檔案
# 如果需要自訂配置,可以準備一個 values.yaml 檔案
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--values custom-values.yaml
# custom-values.yaml 範例:
# prometheus:
# prometheusSpec:
# retention: 30d # 指標保留時間
# storageSpec:
# volumeClaimTemplate:
# spec:
# storageClassName: fast-ssd
# resources:
# requests:
# storage: 100Gi
# grafana:
# adminPassword: "secure-password"
# persistence:
# enabled: true
# size: 10Gi
# 步驟 6: 驗證部署狀態
# 檢查所有 Pod 是否正常執行
kubectl get pods -n monitoring
# 預期輸出範例:
# NAME READY STATUS RESTARTS AGE
# alertmanager-prometheus-kube-prometheus-alertmanager-0 2/2 Running 0 2m
# prometheus-grafana-6f7cf9b968-xtnzj 3/3 Running 0 2m
# prometheus-kube-prometheus-operator-7bdb94567b-q8k9z 1/1 Running 0 2m
# prometheus-kube-state-metrics-6bdd65d76-s5r5j 1/1 Running 0 2m
# prometheus-prometheus-kube-prometheus-prometheus-0 2/2 Running 0 2m
# prometheus-prometheus-node-exporter-dgrlf 1/1 Running 0 2m
#
# 狀態說明:
# READY 2/2 或 3/3: 表示 Pod 內的所有容器都已就緒
# STATUS Running: Pod 正在正常執行
# RESTARTS 0: Pod 沒有重啟過,表示穩定
#
# 如果某個 Pod 的狀態不是 Running,可以使用以下指令診斷:
# kubectl describe pod <pod-name> -n monitoring
# kubectl logs <pod-name> -n monitoring
# 步驟 7: 檢視所有相關的資源
kubectl get all -n monitoring
# 這會列出命名空間內的所有資源:
# - Pods
# - Services
# - Deployments
# - StatefulSets
# - DaemonSets
# - ReplicaSets
# 步驟 8: 存取 Grafana 儀表板
# 使用連接埠轉發將 Grafana 服務暴露到本地
kubectl port-forward -n monitoring \
svc/prometheus-grafana 3000:80
# 參數說明:
# svc/prometheus-grafana: 要轉發的 Service
# 3000:80: 本地連接埠 3000 對應 Service 的連接埠 80
#
# 執行後,可以在瀏覽器中開啟 http://localhost:3000
# 預設登入憑證:
# 使用者名稱: admin
# 密碼: prom-operator (除非在 values.yaml 中自訂)
#
# 建議在生產環境中:
# 1. 修改預設密碼
# 2. 配置 Ingress 而不是使用 port-forward
# 3. 啟用 HTTPS
# 4. 整合 OAuth 或 LDAP 認證
# 步驟 9: 存取 Prometheus UI
# 使用連接埠轉發存取 Prometheus 的 Web UI
kubectl port-forward -n monitoring \
svc/prometheus-kube-prometheus-prometheus 9090:9090
# 存取 http://localhost:9090 可以:
# 1. 執行 PromQL 查詢
# 2. 檢視所有的抓取目標
# 3. 檢視警示規則的狀態
# 4. 瀏覽所有可用的指標
# 步驟 10: 檢視 Prometheus 的配置
# Prometheus 的配置儲存在 Secret 中
kubectl get secret -n monitoring \
prometheus-prometheus-kube-prometheus-prometheus \
-o jsonpath='{.data.prometheus\.yaml\.gz}' | \
base64 -d | gunzip
# 這會顯示 Prometheus 的完整配置,包括:
# - 抓取配置(scrape_configs)
# - 警示規則檔案(rule_files)
# - 警示管理器端點(alerting)
# - 遠端寫入配置(remote_write,如果有)
部署完成後,Prometheus Operator 會自動配置 ServiceMonitor 資源來發現叢集中的監控目標。ServiceMonitor 是一個自訂資源,用於宣告式地定義哪些 Service 應該被 Prometheus 抓取。Operator 會監聽 ServiceMonitor 的變化,並自動更新 Prometheus 的抓取配置,無需手動編輯 ConfigMap 或重啟 Prometheus。
配置自訂的監控目標
雖然 kube-prometheus-stack 提供了許多預設的監控目標,但通常還需要為自己的應用程式配置監控。這可以透過建立 ServiceMonitor 資源來實現。以下是一個完整的範例,展示如何為自訂應用程式配置監控:
# 步驟 1: 確保應用程式暴露了 Prometheus 指標端點
# 應用程式應該在某個路徑(通常是 /metrics)提供指標
# 這個端點需要回傳 Prometheus 文字格式的指標
# 步驟 2: 建立 Service 來暴露應用程式的指標端點
apiVersion: v1
kind: Service
metadata:
name: my-app-metrics
namespace: default
labels:
app: my-app
# 這個標籤很重要,ServiceMonitor 會使用它來選擇 Service
monitoring: "true"
spec:
selector:
app: my-app
ports:
- name: metrics
# 連接埠名稱對於 ServiceMonitor 很重要
# ServiceMonitor 會透過名稱來識別指標端點
port: 8080
targetPort: 8080
protocol: TCP
type: ClusterIP
---
# 步驟 3: 建立 ServiceMonitor 資源
# ServiceMonitor 告訴 Prometheus Operator 應該監控哪些 Service
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my-app-monitor
namespace: default
labels:
# 這個標籤必須與 Prometheus 的 serviceMonitorSelector 匹配
# kube-prometheus-stack 預設的 selector 是 release: prometheus
release: prometheus
spec:
# 選擇要監控的 Service
# 這個 selector 會匹配具有 app=my-app 與 monitoring=true 標籤的 Service
selector:
matchLabels:
app: my-app
monitoring: "true"
# 可選:限制在特定的命名空間中查找 Service
# 如果不設定,會在 ServiceMonitor 所在的命名空間中查找
namespaceSelector:
matchNames:
- default
- production
# 定義如何抓取指標
endpoints:
- port: metrics
# 連接埠名稱,必須與 Service 中定義的名稱匹配
interval: 30s
# 抓取間隔,預設是 30 秒
# 更短的間隔提供更高的時間解析度,但會增加 Prometheus 的負載
path: /metrics
# 指標端點的路徑,預設是 /metrics
scheme: http
# 使用的協定,可以是 http 或 https
# 可選:如果使用 HTTPS,可以配置 TLS
# tlsConfig:
# insecureSkipVerify: true
# ca:
# secret:
# name: my-app-ca-cert
# key: ca.crt
# 可選:添加額外的標籤到抓取的指標
# 這些標籤可以用於在 PromQL 查詢中進行過濾
relabelings:
- sourceLabels: [__meta_kubernetes_namespace]
targetLabel: kubernetes_namespace
- sourceLabels: [__meta_kubernetes_service_name]
targetLabel: kubernetes_service_name
# 可選:指標重新標籤
# 可以用來過濾或修改指標
# metricRelabelings:
# - sourceLabels: [__name__]
# regex: 'go_.*'
# action: drop # 丟棄所有以 go_ 開頭的指標
---
# 步驟 4: 驗證 ServiceMonitor 是否被 Prometheus 發現
# 可以透過 Prometheus UI 檢查
# 1. 開啟 http://localhost:9090/targets
# 2. 應該能看到 my-app-monitor 相關的目標
# 3. 檢查目標的狀態是否為 UP
# 步驟 5: 驗證指標是否被成功抓取
# 在 Prometheus UI 中執行查詢
# 例如:my_app_requests_total
# 應該能看到來自應用程式的指標
除了 ServiceMonitor 外,Prometheus Operator 還支援 PodMonitor 資源,用於直接監控 Pod 而不是透過 Service。這在某些場景下很有用,例如監控 DaemonSet 或 StatefulSet 中的每個 Pod。PrometheusRule 資源用於定義警示規則與記錄規則,讓警示配置也變成 Kubernetes 原生的資源物件,可以透過 kubectl 管理並納入版本控制。
Grafana 儀表板與警示系統的配置實踐
Prometheus 提供了強大的指標收集與儲存能力,但其內建的 Web UI 功能相對簡單,不適合作為日常監控的主要介面。Grafana 作為業界領先的開源視覺化平台,與 Prometheus 完美整合,提供了豐富的圖表類型、靈活的儀表板配置,以及強大的警示功能。透過 Grafana,可以將 Prometheus 收集的原始指標轉化為直觀易懂的視覺化圖表,大幅提升監控系統的可用性。
kube-prometheus-stack 已經預先配置了 Grafana 與多個常用的儀表板,包括 Kubernetes 叢集概覽、節點資源使用、Pod 資源使用、Persistent Volume 使用情況等。這些預設儀表板提供了良好的起點,但通常還需要根據特定的業務需求建立自訂儀表板。在生產環境中,建議將儀表板配置匯出為 JSON 檔案並納入版本控制,確保配置的可追溯性與可復原性。同時,可以透過 Grafana 的 Provisioning 機制自動部署儀表板,避免手動配置的繁瑣與錯誤。
警示系統是監控體系的重要組成部分。Prometheus 支援定義警示規則,當指標滿足特定條件時觸發警示。警示規則使用 PromQL 來定義觸發條件,並可以指定警示的嚴重程度、摘要與詳細描述。觸發的警示會被傳送到 Alertmanager,由其負責後續的處理,包括去重、分組、抑制、靜音與通知路由。
一個設計良好的警示系統應該平衡靈敏度與雜訊。過於靈敏的警示會產生大量的誤報,導致警示疲勞,最終使團隊忽視真正的問題。過於遲鈍的警示則可能在問題已經嚴重影響服務時才觸發,失去了提前預警的價值。建議採用多級警示策略,根據問題的嚴重程度與緊急程度設定不同的通知管道與通知頻率。
總結與企業級監控體系建議
本文全面探討了 Kubernetes 環境中測試、偵錯與監控的完整實踐體系。從 kubectl 命令列工具的深度應用,到 IDE 整合開發環境的配置優化;從開發叢集的架構設計與資源管理策略,到監控系統的理論基礎與實作細節;從 USE 與 RED 監控方法論的深度解析,到 Prometheus 與 Grafana 的企業級部署方案。這些知識與技能共同構成了在 Kubernetes 環境中高效開發與可靠維運的基礎。
建立完善的測試與偵錯流程是提升開發效率的關鍵。熟練掌握 kubectl 的各種指令與選項,能夠在遇到問題時快速定位與診斷。整合 Kubernetes 工具到 IDE 中,透過視覺化介面與智慧提示簡化日常操作。在開發環境的設計上,採用單一大型叢集配合命名空間隔離的架構,配合適當的資源配額與自動清理機制,能夠在資源利用效率與開發者自主性之間取得良好的平衡。
監控系統的建立需要系統化的思考與規劃。理解黑箱監控與白箱監控的差異與適用場景,掌握 USE 方法與 RED 方法的監控理論,能夠建立全面且有重點的監控框架。Prometheus 作為雲端原生監控的標準選擇,其拉取式的指標收集模型、多維度的時間序列資料庫,以及豐富的生態系統,為監控系統提供了堅實的技術基礎。透過 Prometheus Operator 簡化部署與管理,配合 Grafana 的視覺化能力,能夠快速建立起生產就緒的監控平台。
持續改進與最佳化是維護監控系統的長期承諾。隨著應用的演進與業務的發展,監控需求也會不斷變化。定期回顧警示規則的有效性,根據實際的告警情況調整閾值與通知策略。關注 Prometheus 與 Grafana 社群的最新發展,學習新的查詢技巧與視覺化方法。建立監控即程式碼(Monitoring as Code)的文化,將所有的監控配置納入版本控制,透過自動化流程部署與更新。透過這些實踐,能夠建立起可靠、高效且持續演進的監控體系,為 Kubernetes 應用的穩定運作提供堅實保障。