Kubernetes 叢集的監控和日誌管理對於維護系統穩定性和應用程式效能至關重要。本文將探討如何利用 Grafana 監控 USE 方法指標,並使用 Loki-Stack 建立日誌收集系統。同時,我們也將探討如何設定警示以及如何使用 ConfigMaps 和 Secrets 管理應用程式組態。透過整合這些工具和技術,可以建立一個穩固的監控和日誌管理系統,有效地提升 Kubernetes 叢集的可靠性和可觀測性。此係統能協助開發團隊快速診斷和解決問題,並最佳化應用程式效能。
使用Grafana監控Kubernetes叢集
在前面的章節中,我們討論瞭如何使用USE方法來監控Kubernetes叢集。現在,我們將進一步探討如何使用kube-prometheus-stack來收集節點的CPU利用率和飽和度等指標。kube-prometheus-stack提供了預先建置的Grafana儀錶板,可以用來視覺化這些重要的USE方法指標。
連線到Grafana例項
首先,我們需要建立一個隧道來連線到kube-prometheus-stack中包含的Grafana例項。這樣,我們就可以從本地機器連線到Grafana:
kubectl port-forward -n monitoring svc/prometheus-grafana 3000:80
接下來,開啟網頁瀏覽器,存取http://localhost:3000,並使用以下憑據登入:
- 使用者名稱:admin
- 密碼:prom-operator
在Grafana儀錶板中,您將找到一個名為"Kubernetes / USE Method / Cluster"的儀錶板。這個儀錶板提供了Kubernetes叢集的利用率和飽和度的概覽,這是USE方法的核心。圖3-2展示了一個範例儀錶板。
圖示說明:Grafana儀錶板範例
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Kubernetes叢集監控與日誌管理實踐
package "Kubernetes Cluster" {
package "Control Plane" {
component [API Server] as api
component [Controller Manager] as cm
component [Scheduler] as sched
database [etcd] as etcd
}
package "Worker Nodes" {
component [Kubelet] as kubelet
component [Kube-proxy] as proxy
package "Pods" {
component [Container 1] as c1
component [Container 2] as c2
}
}
}
api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2
note right of api
核心 API 入口
所有操作經由此處
end note
@enduml此圖示展示瞭如何使用Grafana儀錶板來監控Kubernetes叢集的效能。
日誌記錄概述
到目前為止,我們已經討論了很多關於指標和Kubernetes的內容。但是,要全面瞭解您的環境,您還需要收集和集中來自Kubernetes叢集和佈署到叢集中的應用程式的日誌。日誌記錄看似簡單,但實際上有兩個問題:
- 日誌太多,難以快速找到問題。
- 日誌會消耗大量資源,並帶來高昂的成本。
沒有明確的答案來決定應該記錄什麼,因為除錯日誌是必要的。隨著時間的推移,您將開始更好地瞭解您的環境,並學會如何從日誌系統中過濾掉噪音。此外,為了應對日益增長的日誌儲存需求,您需要實施保留和歸檔策略。從終端使用者經驗的角度來看,保留30到45天的歷史日誌是合適的。這樣可以在調查長時間內出現的問題的同時減少儲存日誌所需的資源。如果出於合規性需要更長期的儲存,您可以將日誌歸檔到更具成本效益的資源中。
Kubernetes叢集中的日誌收集
在Kubernetes叢集中,有多個元件需要收集日誌。以下是一些需要收集日誌的元件:
- 節點日誌
- Kubernetes控制平面日誌
- API伺服器
- 控制器管理器
- 排程器
- Kubernetes稽核日誌
- 應用程式容器日誌
節點日誌收集
節點日誌記錄了節點上發生的事件,例如Docker守護程式的日誌。收集這些日誌可以幫助您診斷與Docker守護程式相關的問題。
Kubernetes控制平面日誌收集
Kubernetes控制平面由多個元件組成,需要收集日誌以深入瞭解其內部問題。控制平面是叢集健康的核心,您需要聚合儲存在主機上的日誌,例如/var/log/kube-APIserver.log、var/log/kube-scheduler.log和/var/log/kube-controller-manager.log。
Kubernetes稽核日誌
Kubernetes稽核日誌提供了對系統內部發生事件的洞察,可以視為安全監控。這些日誌可能會非常嘈雜,因此需要根據您的環境進行調整。
應用程式容器日誌
應用程式容器日誌提供了應用程式發出的日誌。您可以透過多種方式將這些日誌轉發到中央儲存函式庫。建議的方法是將所有應用程式日誌傳送到STDOUT,這樣可以提供統一的應用程式日誌記錄方式,並且監控守護程式可以直接從Docker守護程式收集日誌。
日誌管理工具
與收集指標一樣,有許多工具可用於從Kubernetes和叢集中執行的應用程式收集日誌。您可能已經擁有用於此目地的工具,但需要注意該工具如何實作日誌記錄。該工具應該能夠以Kubernetes DaemonSet的形式執行,並且具有作為應用程式旁車執行的解決方案。使用現有工具的好處是您已經具備了對該工具的操作知識。
程式碼範例:使用Fluentd收集日誌
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-logging
template:
metadata:
labels:
name: fluentd-logging
spec:
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log
內容解密:
- 此YAML檔案定義了一個名為
fluentd-logging的DaemonSet,用於在每個節點上執行Fluentd。 spec.selector.matchLabels指定了DaemonSet所管理的Pod標籤。spec.template.metadata.labels為Pod設定了標籤,用於與DaemonSet的選擇器比對。spec.template.spec.containers定義了容器列表,這裡使用的是Fluentd官方提供的映像。volumeMounts將主機上的/var/log目錄掛載到容器內的/var/log,以便Fluentd可以讀取主機上的日誌檔案。volumes定義了要掛載的卷,這裡使用的是hostPath卷,直接掛載主機上的/var/log目錄。
這段程式碼展示瞭如何使用Fluentd作為DaemonSet來收集節點上的日誌。
在 Kubernetes 中實作監控與日誌記錄
使用 Loki-Stack 進行日誌記錄
在眾多的 Kubernetes 整合工具中,一些流行的選擇包括:
- Loki
- Elastic Stack
- Datadog
- Sumo Logic
- Sysdig
- 雲端服務供應商的服務(GCP Stackdriver、Azure Monitor for containers 和 Amazon CloudWatch)
選擇日誌集中工具時,託管解決方案可以提供極大的價值,因為它們能夠降低維運成本。自建日誌解決方案在初期看似理想,但隨著環境的擴充套件,維護成本會顯著增加。
對於本文的目的,我們採用 Loki-Stack 結合 prom-tail 來進行叢集日誌記錄。雖然 Loki-Stack 是個良好的起點,但隨著時間的推移,您可能會質疑是否值得自行管理日誌平台。通常,自建方案在初期表現良好,但隨著環境擴充套件,維運複雜度會急劇增加。因此,評估業務需求是否需要自建解決方案至關重要。Grafana 提供了託管的 Loki 解決方案,因此在需要時可以輕鬆轉換。
佈署 Loki-Stack
我們將使用以下元件來構建日誌記錄堆積疊:
- Loki
- prom-tail
- Grafana
透過 Helm 將 Loki-Stack 佈署到 Kubernetes 叢集的步驟如下:
新增 Loki-Stack Helm 倉函式庫
helm repo add grafana https://grafana.github.io/helm-charts
更新 Helm 倉函式庫
helm repo update
安裝或升級 Loki-Stack
helm upgrade --install loki --namespace=monitoring grafana/loki-stack
#### 內容解密:
上述命令用於將 Loki-Stack 佈署到 Kubernetes 叢集中。首先,我們新增 Grafana 的 Helm 倉函式庫並更新本地倉函式庫列表。接著,使用 helm upgrade --install 命令安裝或升級 Loki-Stack 至 monitoring 名稱空間中。這將佈署 Loki 和 prom-tail,使我們能夠將日誌轉發至 Loki 並透過 Grafana 進行視覺化。
佈署完成後,您可以透過以下命令檢查相關 Pod 的狀態:
kubectl get pods -n monitoring
示例輸出:
NAME READY STATUS RESTARTS AGE
loki-0 1/1 Running 0 93s
loki-promtail-x7nw8 1/1 Running 0 93s
#### 內容解密:
這段輸出顯示了 monitoring 名稱空間中的 Pod 狀態。loki-0 和 loki-promtail-x7nw8 都處於執行狀態,表示 Loki 和 prom-tail 已成功佈署。
接下來,透過埠轉發將 Grafana 服務暴露至本地:
kubectl port-forward -n monitoring svc/prometheus-grafana 3000:80
#### 內容解密:
此命令將 prometheus-grafana 服務的 80 埠轉發至本地的 3000 埠,使得我們能夠透過 http://localhost:3000 存取 Grafana。
在 Grafana 中,使用預設憑證(使用者名稱:admin,密碼:prom-operator)登入。然後,在資料來源組態中新增 Loki 作為資料來源,並將 URL 設定為 http://loki:3100。
使用 Grafana 探索日誌
在 Grafana 中,您可以對日誌進行即席查詢,並構建儀錶板以概覽環境狀態。使用「Explore」功能,您可以對已收集的日誌執行查詢。例如,使用 namespace = kube-system 的標籤篩選器來檢視特定名稱空間的日誌。
警示管理
警示管理是一把雙刃劍,需要在警示內容和監控內容之間取得平衡。過多的警示會導致警示疲勞,使重要的事件淹沒在噪音中。有效的警示策略應該聚焦於影響服務水平目標(SLO)的事件,例如前端服務的回應時間超過預期閾值。
在 Kubernetes 環境中,警示需要關注終端使用者經驗,而不是傳統的監控指標(如 CPU 使用率或記憶體使用率)。對於不需要立即處理的警示,可以透過自動化修復措施來處理,例如自動刪除日誌以釋放磁碟空間,或利用 Kubernetes 的 liveness probes 自動重啟無回應的容器。
在設定警示閾值時,應避免過短的閾值以減少誤報。通常建議設定至少五分鐘的閾值,並遵循特定的模式(如 5 分鐘、10 分鐘、30 分鐘等)來定義標準化的閾值。在警示通知中,提供相關資訊(如故障排除的連結)至關重要,以協助快速解決問題。
Kubernetes 中的監控、紀錄與警示最佳實踐
在 Kubernetes 環境中,監控、紀錄和警示是確保系統穩定性和應用程式效能的關鍵要素。正確地實施這些實踐,可以幫助團隊快速識別和解決問題,從而提升整體系統的可靠性。
監控的最佳實踐
監控是瞭解系統目前狀態的重要手段。以下是一些監控的最佳實踐:
- 監控節點和所有 Kubernetes 元件的使用率、飽和度和錯誤率,以及應用程式的請求率、錯誤率和持續時間。
- 使用封閉式監控來監測系統的症狀,而不是預測系統的健康狀態。
- 使用開放式監控來檢查系統及其內部狀態,透過儀表化來實作。
- 實施根據時間序列的指標,以獲得高精確度的指標,並深入瞭解應用程式的行為。
- 使用像 Prometheus 這樣的監控系統,它提供關鍵標籤以實作高維度監控,從而更好地識別影響問題的症狀。
- 使用平均指標來視覺化小計和根據事實資料的指標。
- 使用總和指標來視覺化特定指標的分佈情況。
紀錄的最佳實踐
紀錄提供了系統執行時的詳細資訊,與監控相輔相成。以下是一些紀錄的最佳實踐:
- 結合紀錄和指標監控,以全面瞭解環境的執行狀況。
- 謹慎儲存超過 30 到 45 天的紀錄,如有需要,可使用較便宜的資源進行長期存檔。
- 限制在 sidecar 模式下使用日誌轉發器,因為它們會佔用大量資源。建議使用 DaemonSet 來執行日誌轉發器,並將日誌傳送到 STDOUT。
警示的最佳實踐
警示機制能夠在系統出現問題時及時通知相關人員。以下是一些警示的最佳實踐:
- 謹防警示疲勞,因為它可能導致人員和流程出現不良行為。
- 不斷改進警示機制,並接受它永遠不會完美的事實。
- 對影響服務水準目標(SLO)和客戶的症狀發出警示,而不是針對不需要立即人工關注的暫時性問題。
設定、機密資訊和 RBAC
Kubernetes 的可組合性使得我們可以在執行時將設定資料注入容器中。這使得應用程式的功能與其執行的環境解耦。透過容器執行時允許的慣例,可以在執行時將環境變數或外部磁碟區掛載到容器中,從而有效地改變應用程式的設定。
設定管理
Kubernetes 提供了 ConfigMaps 和 Secrets 來原生地為應用程式提供設定資訊。兩者之間的主要區別在於 Pod 儲存接收資訊的方式,以及資料在 etcd 資料儲存中的儲存方式。
RBAC(根據角色的存取控制)
RBAC 是 Kubernetes 中最常用的安全方法,用於實作對 API 的細粒度許可權結構。正確地實施 RBAC 可以確保只有授權的使用者或群組才能對 API 執行特定的操作。
程式碼範例:使用 Prometheus 監控 Kubernetes
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: example-prometheus
spec:
replicas: 2
serviceAccountName: prometheus-service-account
serviceMonitorSelector:
matchLabels:
team: frontend
resources:
requests:
memory: 400Mi
內容解密:
apiVersion和kind定義了這個 YAML 檔案所代表的 Kubernetes 物件型別,在此例中是 Prometheus 物件。metadata部分包含了物件的中繼資料,如名稱。spec部分定義了 Prometheus 物件的規格,包括副本數量、服務帳戶名稱和 ServiceMonitor 的選擇器。serviceMonitorSelector用於選擇符合特定標籤的 ServiceMonitor 物件,這裡選擇了標籤team: frontend的 ServiceMonitor。resources部分定義了 Prometheus Pod 的資源請求,在此例中請求了 400Mi 的記憶體。
這個 YAML 檔案定義了一個 Prometheus 物件,用於監控 Kubernetes 環境中的前端團隊相關的服務。透過適當的設定,Prometheus 可以收集這些服務的指標,並提供給使用者查詢。
Kubernetes 組態管理:ConfigMaps 與 Secrets 深度解析
在現代化的應用程式開發中,組態資訊的管理對於確保應用程式的可移植性和安全性至關重要。Kubernetes 提供了兩種重要的資源:ConfigMaps 和 Secrets,用於管理和注入組態資訊到應用程式中。本文將探討這兩種資源的使用方法、最佳實踐以及相關的安全考量。
ConfigMaps:組態資訊的管理
ConfigMaps 允許開發者將組態資訊與應用程式分離,從而實作真正的應用程式可移植性。它們可以用於提供鍵值對或複雜的批次資料,如 JSON、XML 或專有的組態資料。
使用 ConfigMaps 的優勢
- 將組態資訊與應用程式分離,提高可移植性
- 可提供鍵值對或複雜的批次資料
- 可用於提供組態資訊給 Pod、控制器、CRD、運算元等系統服務
ConfigMaps 的使用方法
ConfigMaps 可以透過多種方式建立,例如從檔案、目錄或字串文字建立。建立後,可以將 ConfigMaps 掛載到 Pod 中作為檔案或環境變數。
kubectl create configmap myconfig --from-file=config.properties
Secrets:敏感資訊的管理
Secrets 用於管理敏感資訊,如密碼、OAuth token 和 ssh 金鑰。與 ConfigMaps 類別似,Secrets 也可以被掛載到 Pod 中或作為環境變數注入。
使用 Secrets 的優勢
- 安全地儲存和管理敏感資訊
- 可被掛載到 Pod 中或作為環境變數注入
- 支援多種型別的 Secrets,如 generic、docker-registry 和 tls
Secrets 的使用方法
Secrets 可以透過 kubectl create secret 命令建立。例如,建立一個 generic Secret:
kubectl create secret generic mysecret --from-literal=key1=$3cr3t1 --from-literal=key2=@3cr3t2
建立一個 docker-registry Secret:
kubectl create secret docker-registry registryKey --docker-server myreg.azurecr.io --docker-username myreg --docker-password $up3r$3cr3tP@ssw0rd --docker-email ignore@dummy.com
建立一個 tls Secret:
kubectl create secret tls www-tls --key=./path_to_key/wwwtls.key --cert=./path_to_crt/wwwtls.crt
ConfigMaps 和 Secrets 的最佳實踐
在使用 ConfigMaps 和 Secrets 時,需要注意以下最佳實踐:
- 將 ConfigMaps 和 Secrets 掛載為檔案,並使用檔案監控器檢測檔案變更
- 避免直接更新 ConfigMaps 和 Secrets 中的資料,而是重新建立新的資源
- 使用加密儲存 Secrets,並確保 etcd 環境的安全
範例:將 ConfigMap 和 Secret 掛載到 Pod 中
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-http-config
namespace: myapp-prod
data:
config: |
http {
server {
location / {
root /data/html;
}
location /images/ {
root /data;
}
}
}
apiVersion: v1
kind: Secret
metadata:
name: myapp-api-key
type: Opaque
data:
myapikey: YWRtd5thSaW4=
apiVersion: apps/v1
kind: Deployment
metadata:
name: mywebapp
namespace: myapp-prod
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /etc/nginx
name: nginx-config
- mountPath: /usr/var/nginx/html/keys
name: api-key
volumes:
- name: nginx-config
configMap:
name: nginx-http-config
items:
- key: config
path: nginx.conf
- name: api-key
secret:
name: myapp-api-key
secretName: myapikey
內容解密:
此範例展示瞭如何將 ConfigMap 和 Secret 掛載到 Pod 中。首先,建立了一個名為 nginx-http-config 的 ConfigMap,用於儲存 Nginx 的組態資訊。然後,建立了一個名為 myapp-api-key 的 Secret,用於儲存 API 金鑰。最後,在 Deployment 中,將 ConfigMap 和 Secret 掛載到 Nginx 容器中,分別作為 /etc/nginx/nginx.conf 和 /usr/var/nginx/html/keys/myapikey。