Kubernetes 存活、就緒探針
在設計關鍵任務、高可用應用程序時,彈性是要考慮的最重要因素之一。
當應用程序可以快速從故障中恢復時,它便具有彈性。
云原生應用程序通常設計為使用微服務架構,其中每個組件都位于容器中。為了確保Kubernetes托管的應用程序高可用,在設計集群時需要遵循一些特定的模式,其中有“健康探測模式”。應用 高可觀察性原則 (HOP)可確保您的應用程序收到的每個請求都能及時找到響應。
The High Observability Principle (HOP)
高可觀察性原則是基于容器的應用程序設計原則之一。微服務體系要求每個服務不關心(也不應該關心)被調用方如何處理請求。
HOP原則要求每個服務必須公開幾個API端點,其意義在于揭示服務健康狀態,Kubernetes調用這些端點,決定下一步的路由和負載平衡。
設計良好的云原生程序應將日志事件記錄到STDERR和STDOUT,由logstash、Fluent等日志攝取服務將這些日志運送到集中式監控(例如Prometheus)和日志聚合系統(例如ELK)。下圖說明了云原生應用程序如何遵守健康狀況探測模式和高可觀察性原則。

How to Apply Health Probe Pattern in Kubernetes?
我之前寫過ASP.NetCore + Docker健康檢查的原創:[web程序暴露http健康檢查端點,平臺輪詢探測], Kubernetes針對不同場合細化了探針,更為強大的是給出對應決策。
Liveness Probes
使用[存活探針]判斷什么時候重啟容器。
使用存活探針檢查容器本身是否無響應、死鎖, 有時候重啟容器常常能解決此類問題。
我們以kubernetes官方demo為例:
- apiVersion: v1
- kind: Pod
- metadata:
- labels:
- test: liveness
- name: liveness-exec
- spec:
- containers:
- - name: liveness
- image: busybox
- args:
- - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
- livenessProbe:
- exec:
- command:
- - cat
- - /tmp/healthy
- initialDelaySeconds: 5 # 指示kubectl等待5s才執行首次探測
- periodSeconds: 5 # 間隔5秒輪詢
- 在第5秒kubectl開始首次liveness探測
- 在30秒進行的每次探測均成功
- 30s之后容器內文件被刪除,之后間隔5s的探測會失敗,根據liveness默認配置連續3次失敗就會放棄探測,放棄探測意味著重啟容器,故容器會在第45s重啟
- 重啟之后又開始以上流程, 故可以看到此探針以重啟的決策嘗試修復應用問題。
這個探針會體現到 kubectl get pod 的 RESTARTS 列

Readiness Probes
使用[就緒探針]判斷容器是否就緒,是否可以接受流量。
Pod內所有容器ready,則該Pod被認為ready,當pod沒有ready,將會從服務負載均衡中移除。
有些時候,應用程序臨時不可用(加載大量數據或者依賴外部服務),這個時候,重啟這個Pod無濟于事,同時你也不希望請求被發送到該Pod
下面的應用強依賴mongodb,我們針對這些依賴項設置了readiness探針
- services.AddHealthChecks()
- .AddCheck<MongoHealthCheck>(nameof(MongoHealthCheck), tags: new[] { "readyz" });
- // ----------------------
- app.UseHealthChecks("/readyz", new HealthCheckOptions
- {
- Predicate = (check) => check.Tags.Contains("readyz")
- });
以下是探測Mongodb的連通性
- sealed class MongoHealthCheck : IHealthCheck
- { private readonly IMongoDatabase _defaultMongoDatabase;
- public MongoHealthCheck(IDefaultMongoDatabaseProvider defaultMongoDatabaseProvider)
- { _defaultMongoDatabase = defaultMongoDatabaseProvider.GetDatabase(); } public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
- { var doc = await _defaultMongoDatabase.RunCommandAsync(
- new BsonDocumentCommand<BsonDocument>(
- new BsonDocument() {
- { "ping", "1" }
- }), cancellationToken: cancellationToken); var ok = doc["ok"].ToBoolean();
- if (ok)
- { return HealthCheckResult.Healthy("OK");
- } return HealthCheckResult.Unhealthy("NotOK");
- } }
對于依賴項的探測,探測周期和超時時間可以設置的稍長一點
- readinessProbe:
- httpGet:
- path: /readyz
- port: 80
- initialDelaySeconds: 5
- periodSeconds: 60 # 60s探測一次
- timeoutSeconds: 30 # 每次探測30s超時,與應用建立與依賴項的連接超時時間一致
- failureThreshold: 3 # 連續3次探測失敗,該Pod會被標記為`Unready`
Startup Probes
使用[啟動探針]判斷容器應用是否已經啟動。如果配置了這個探針,則該探針成功之前將會禁用存活和就緒探針。
配置探針
- initialDelaySeconds:容器啟動,探針延后工作,默認是0s
- periodSeconds 探針探測周期,默認10s
- timeoutSeconds: 探針工作的超時時間,默認1s
- successThreshold: 連續幾次探測成功,該探針被認為是成功的,默認1次
- failureThreshold: 連續幾次探測失敗,該探針被認為最終失敗,對于livenes探針最終失敗意味著重啟,對于readiness探針意味著該pod Unready, 默認3次。
強烈建議根據應用結構合理設置探針參數,避免不切實際的認定失敗導致的頻繁重啟或 Unready。
結論:
- Kubernetes生態這么龐大,為啥單獨拎出k8s探針, 是因為k8s探針是與應用程序結構密切相關的機制。
就使用方式看:
- 存活探針:用于快速判斷應用進程是否無響應,嘗試重啟修復;
- 就緒探針:判斷應用及依賴項是否就緒,是否可以分配流量,如果不能就標記Unready,從負載均衡器中移除該Pod
Kubernetes存活、就緒探針可以極大地提高服務的健壯性和彈性,并提供出色的最終用戶體驗。