Kubernetes 容器的最佳實務:健康檢查

Kubernetes 容器的最佳實務:健康檢查

TL博士

  • 要實現容器和微服務的高可觀察性,日誌和主要指標是不夠的。
  • 為了更快地恢復並提高彈性,應用程式應應用高可觀測性原則 (HOP)。
  • 在應用程式級別,NOP 需要:正確的日誌記錄、密切監控、健全性檢查和效能/轉換追蹤。
  • 使用檢查作為 NOR 的元素 準備狀態探測 и 活性探針 Kubernetes。

什麼是健康檢查模板?

在設計關鍵任務和高可用性應用程式時,考慮容錯等方面非常重要。 如果應用程式能夠從故障中快速恢復,則該應用程式被認為具有容錯能力。 典型的雲端應用程式使用微服務架構 - 每個元件都放置在單獨的容器中。 並且為了確保在設計叢集時k8s上的應用程式是高可用的,需要遵循一定的模式。 其中包括健康檢查模板。 它定義了應用程式如何向 k8s 傳達其運作狀況良好的訊息。 這不僅是有關 pod 是否正在運行的信息,還包括有關它如何接收和回應請求的資訊。 Kubernetes 對 Pod 健康狀況了解越多,它在流量路由和負載平衡方面做出的決策就越明智。 因此,高可觀察性原則允許應用程式及時回應請求。

高可觀測原則(HOP)

高可觀測原理是其中之一 設計容器化應用程式的原則。 在微服務架構中,服務並不關心它們的請求是如何處理的(這是正確的),但重要的是它們如何從接收服務接收回應。 例如,為了驗證用戶身份,一個容器向另一個容器發送 HTTP 請求,並期望得到某種格式的回應 - 僅此而已。 PythonJS 也可以處理請求,Python Flask 可以回應。 容器就像黑盒子,彼此隱藏著內容。 然而,NOP 原則要求每個服務公開多個 API 端點,以指示其健康狀況以及其準備和容錯狀態。 Kubernetes 請求這些指標是為了考慮路由和負載平衡的後續步驟。

精心設計的雲端應用程式使用標準 I/O 流 STDERR 和 STDOUT 記錄其主要事件。 接下來是輔助服務,例如 filebeat、logstash 或 Fluentd,將日誌傳送到集中監控系統(例如 Prometheus)和日誌收集系統(ELK 軟體套件)。 下圖顯示了雲端應用程式如何根據健康測試模式和高可觀測性原則來運作。

Kubernetes 容器的最佳實務:健康檢查

如何在 Kubernetes 中應用健康檢查模式?

k8s 開箱即用,使用其中一個控制器(部署, 副本集, 守護程式集, 有狀態集 等等)。 控制器發現 Pod 由於某種原因掉落後,會嘗試重新啟動它或將其移動到另一個節點。 然而,pod 可能會報告它已啟動並正在運行,但它本身卻無法運行。 讓我們舉個例子:您的應用程式使用 Apache 作為 Web 伺服器,您將該元件安裝在叢集的多個 pod 上。 由於庫配置不正確,所有對應用程式的請求都會回應代碼 500(內部伺服器錯誤)。 在檢查交付時,檢查 Pod 的狀態會給出成功的結果,但客戶的想法不同。 我們將這種不良情況描述如下:

Kubernetes 容器的最佳實務:健康檢查

在我們的範例中,k8s 確實 功能檢查。 在這種類型的驗證中,kubelet 不斷檢查容器中進程的狀態。 一旦他了解到該過程已停止,他將重新啟動它。 如果只需重新啟動應用程式即可解決該錯誤,並且該程式設計為在出現任何錯誤時關閉,那麼您只需遵循 NOP 和運行狀況測試模式進行進程運行狀況檢查即可。 唯一遺憾的是,並不是所有的錯誤都可以透過重啟來消除。 在這種情況下,k8s 提供了 2 種更深層的方法來識別 pod 的問題: 活性探針 и 準備狀態探測.

活性探針

在這期間 活性探針 kubelet 執行 3 種類型的檢查:不僅確定 pod 是否正在運行,還確定它是否準備好接收並充分回應請求:

  • 設定對 pod 的 HTTP 請求。 回應必須包含 200 到 399 範圍內的 HTTP 回應代碼。因此,代碼 5xx 和 4xx 表示 Pod 有問題,即使進程正在執行也是如此。
  • 若要使用非 HTTP 服務(例如 Postfix 郵件伺服器)測試 pod,您需要建立 TCP 連線。
  • 對 Pod(內部)執行任意指令。 如果指令完成碼為 0,則認為檢查成功。

這是如何工作的一個例子。 下一個 pod 定義包含一個 NodeJS 應用程序,它會在 HTTP 請求上拋出 500 錯誤。為了確保容器在收到此類錯誤時重新啟動,我們使用 livenessProbe 參數:

apiVersion: v1
kind: Pod
metadata:
 name: node500
spec:
 containers:
   - image: magalix/node500
     name: node500
     ports:
       - containerPort: 3000
         protocol: TCP
     livenessProbe:
       httpGet:
         path: /
         port: 3000
       initialDelaySeconds: 5

這與任何其他 pod 定義沒有什麼不同,但我們添加了一個對象 .spec.containers.livenessProbe。 範圍 httpGet 接受 HTTP GET 請求傳送到的路徑(在我們的範例中是 /,但是在戰鬥場景中可能會出現類似的情況 /api/v1/status)。 另一個 livenessProbe 接受一個參數 initialDelaySeconds,指示驗證操作等待指定的秒數。 之所以需要延遲,是因為容器需要時間來啟動,重新啟動後會在一段時間內無法使用。

若要將此設定套用至集群,請使用:

kubectl apply -f pod.yaml

幾秒鐘後,您可以使用以下命令檢查 pod 的內容:

kubectl describe pods node500

在輸出的最後,找到 就是這樣.

如您所看到的,livenessProbe 發起了一個 HTTP GET 請求,容器產生了錯誤 500(這是它被編程要做的事情),而 kubelet 重新啟動了它。

如果您想知道 NideJS 應用程式是如何編程的,這裡是使用的 app.js 和 Dockerfile:

應用程序.js

var http = require('http');

var server = http.createServer(function(req, res) {
    res.writeHead(500, { "Content-type": "text/plain" });
    res.end("We have run into an errorn");
});

server.listen(3000, function() {
    console.log('Server is running at 3000')
})

Dockerfile

FROM node
COPY app.js /
EXPOSE 3000
ENTRYPOINT [ "node","/app.js" ]

需要注意的是:livenessProbe 僅在失敗時才會重新啟動容器。 如果重新啟動無法修正阻止容器運行的錯誤,kubelet 將無法採取措施修正問題。

準備狀態探測

readinessProbe 的運作方式與 livenessProbe 類似(GET 請求、TCP 通訊和命令執行),但故障排除操作除外。 偵測到故障的容器不會重新啟動,但會與傳入流量隔離。 想像一下,其中一個容器正在執行大量計算或負載很重,導致回應時間增加。 對於 livenessProbe,會觸發回應可用性檢查(透過 timeoutSeconds 檢查參數),之後 kubelet 會重新啟動容器。 啟動後,容器開始執行資源密集型任務並再次重新啟動。 這對於需要響應速度的應用程式至關重要。 例如,一輛汽車在路上等待伺服器的回應,回應被延遲 - 並且汽車發生事故。

我們來編寫一個 redinessProbe 定義,將 GET 請求回應時間設定為不超過兩秒,應用程式將在 5 秒後回應 GET 請求。 pod.yaml 檔案應如下所示:

apiVersion: v1
kind: Pod
metadata:
 name: nodedelayed
spec:
 containers:
   - image: afakharany/node_delayed
     name: nodedelayed
     ports:
       - containerPort: 3000
         protocol: TCP
     readinessProbe:
       httpGet:
         path: /
         port: 3000
       timeoutSeconds: 2

讓我們用 kubectl 部署一個 pod:

kubectl apply -f pod.yaml

讓我們等幾秒鐘,然後看看 readinessProbe 是如何運作的:

kubectl describe pods nodedelayed

在輸出的末尾,您可以看到一些事件是相似的 這個.

可以看到,當檢查時間超過2秒時,kubectl並沒有重新啟動pod。 相反,他取消了請求。 傳入的通訊被重定向到其他正在工作的 Pod。

請注意,現在 Pod 已卸載,kubectl 會再次將請求路由到它:對 GET 請求的回應不再延遲。

為了進行比較,以下是修改後的 app.js 檔案:

var http = require('http');

var server = http.createServer(function(req, res) {
   const sleep = (milliseconds) => {
       return new Promise(resolve => setTimeout(resolve, milliseconds))
   }
   sleep(5000).then(() => {
       res.writeHead(200, { "Content-type": "text/plain" });
       res.end("Hellon");
   })
});

server.listen(3000, function() {
   console.log('Server is running at 3000')
})

TL博士
在雲端應用程式出現之前,日誌是監控和檢查應用程式運作狀況的主要手段。 然而,沒有辦法採取任何糾正措施。 日誌在今天仍然有用;需要收集它們並將其發送到日誌收集系統以分析緊急情況並做出決策。 [例如,所有這些都可以在不使用 monit 的雲端應用程式的情況下完成,但使用 k8s 就變得容易多了:) – 編者註。 ]

如今,必須幾乎即時進行更正,因此應用程式不再必須是黑盒子。 不,它們應該顯示允許監控系統查詢和收集有關流程狀態的有價值資料的端點,以便它們可以在必要時立即回應。 這稱為效能測試設計模式,它遵循高可觀察性原則(HOP)。

Kubernetes 預設提供 2 種類型的健康檢查:readinessProbe 和 livenessProbe。 兩者都使用相同類型的檢查(HTTP GET 請求、TCP 通訊和命令執行)。 他們針對 Pod 中的問題所做的決策有所不同。 livenessProbe 重新啟動容器,希望錯誤不再發生,而 readinessProbe 將 pod 與傳入流量隔離,直到問題原因解決。

正確的應用程式設計應該包括這兩種類型的檢查,並確保它們收集足夠的數據,特別是在引發異常時。 它還應該顯示必要的 API 端點,為監控系統(Prometheus)提供重要的健康指標。

來源: www.habr.com

添加評論