Kubernetes 中的活躍度探測可能很危險

筆記。 翻譯。:Zalando 的首席工程師 Henning Jacobs 多次注意到 Kubernetes 使用者在理解活性(和就緒)探針的目的及其正確使用方面存在問題。 因此,他將自己的想法集中在這篇大篇幅的筆記中,最終將成為 K8s 文件的一部分。

Kubernetes 中的活躍度探測可能很危險

健康檢查,在 Kubernetes 中稱為 活性探針 (即,字面意思是“生存能力測試”-大約翻譯。),可能非常危險。 我建議盡可能避免使用它們:唯一的例外是當它們確實有必要並且您完全了解其使用的具體情況和後果時。 本出版物將討論活性和就緒性檢查,也將告訴您在什麼情況下 成本 你不應該使用它們。

我的同事 Sandor 最近在 Twitter 上分享了他遇到的最常見錯誤,包括與使用就緒/活躍探針相關的錯誤:

Kubernetes 中的活躍度探測可能很危險

配置不正確 livenessProbe 可能會加劇高負載情況(滾雪球式關閉+可能較長的容器/應用程式啟動時間)並導致其他負面後果,例如依賴性下降 (也可以看看 我最近的文章 關於限制K3s+ACME組合中的請求數量)。 當活性探針與健康檢查(外部資料庫)結合使用時,情況會更糟: 單一資料庫故障將重新啟動所有容器!

一般資訊 “不要使用活性探針” 在這種情況下它沒有多大幫助,所以讓我們看看就緒性和活性檢查的用途。

注意:下面的大部分測試最初包含在 Zalando 的內部開發人員文件中。

準備情況和活性檢查

Kubernetes 提供了兩種重要的機制,稱為 活性探針和就緒探針。 它們會定期執行某些操作(例如發送 HTTP 請求、開啟 TCP 連線或在容器中執行命令)以確認應用程式是否按預期運作。

Kubernetes 使用 就緒探針了解容器何時準備好接受流量。 如果 Pod 的所有容器都準備就緒,則認為該 Pod 已準備好使用。 此機制的用途之一是控制哪些 Pod 作為 Kubernetes 服務(尤其是 Ingress)的後端。

活性探針 幫助 Kubernetes 了解何時需要重新啟動容器。 例如,這樣的檢查允許您在應用程式卡在一個地方時攔截死鎖。 儘管出現錯誤,但在此狀態下重新啟動容器有助於應用程式啟動,但也可能導致級聯故障(請參閱下文)。

如果您嘗試部署未通過活動/就緒檢查的應用程式更新,則其部署將因 Kubernetes 等待狀態而停止 Ready 來自所有 pod。

例子

這是檢查路徑的就緒探針的範例 /health 透過 HTTP 使用預設設定 (間隔:10秒, 超時: 1秒, 成功門檻:1, 失敗閾值:3):

# часть общего описания deployment'а/стека
podTemplate:
  spec:
    containers:
    - name: my-container
      # ...
      readinessProbe:
        httpGet:
          path: /health
          port: 8080

建議

  1. 對於具有 HTTP 端點(REST 等)的微服務 始終定義就緒探針,它檢查應用程式 (pod) 是否準備好接受流量。
  2. 確保就緒探針 涵蓋實際 Web 伺服器連接埠的可用性:
    • 將連接埠用於管理目的,稱為“admin”或“management”(例如,9090),例如 readinessProbe,確保端點僅在主 HTTP 連接埠(如 8080)準備好接受流量*時才傳回 OK;

      *據我所知,Zalando 至少有一個案例沒有發生這種情況,即 readinessProbe 我檢查了“管理”端口,但由於加載快取的問題,伺服器本身沒有開始工作。

    • 將就緒探針附加到單獨的連接埠可能會導致主連接埠的過載不會反映在健康檢查中(即伺服器上的執行緒池已滿,但健康檢查仍然顯示一切正常) )。
  3. 確保 就緒探針支援資料庫初始化/遷移;
    • 實現此目的的最簡單方法是僅在初始化完成後才聯繫 HTTP 伺服器(例如,從 飛道 等等。); 也就是說,在資料庫遷移完成之前不要啟動 Web 伺服器,而不是更改運行狀況檢查狀態*。

      * 您也可以從 pod 外部的 init 容器執行資料庫遷移。 我仍然喜歡獨立應用程序,即應用程式容器知道如何在無需外部協調的情況下使資料庫進入所需狀態的應用程式。

  4. 使用 httpGet 透過典型的運轉狀況檢查端點(例如, /health).
  5. 了解預設檢查參數 (interval: 10s, timeout: 1s, successThreshold: 1, failureThreshold: 3):
    • 預設選項意味著 pod 將變成 沒有準備好 約 30 秒後(3 次健全性檢查失敗)。
  6. 如果技術堆疊(例如 Java/Spring)允許,請使用單獨的「admin」或「management」端口,將運行狀況和指標管理與常規流量分開:
    • 但不要忘記第 2 點。
  7. 如有必要,就緒探針可用於預熱/載入快取並返回 503 狀態代碼,直到容器預熱:

注意事項

  1. 不要依賴外部依賴 (例如資料倉儲)執行就緒性/活躍性測試時 - 這可能會導致級聯故障:
    • 舉個例子,我們以一個有10 個Pod 的有狀態REST 服務為例,該服務依賴於一個Postgres 資料庫:當檢查依賴與資料庫的工作連接時,如果網路/資料庫端存在延遲,則所有10 個Pod 都可能會失敗- 通常是這樣一切的結局都比它可能的更糟;
    • 請注意,Spring Data 預設檢查資料庫連線*;

      * 這是 Spring Data Redis 的預設行為(至少是我上次檢查的時候),這導致了「災難性」故障:當 Redis 短時間不可用時,所有 pod 都「崩潰」了。

    • 從這個意義上說,「外部」也可以指同一應用程式的其他 pod,也就是說,理想情況下,檢查不應依賴同一叢集的其他 pod 的狀態,以防止級聯崩潰:
      • 對於具有分散式狀態的應用程式(例如,pod 中的記憶體快取),結果可能會有所不同。
  2. 不要使用活性探針 對於 pod(例外情況是確實有必要並且您完全了解其使用的具體情況和後果):
    • 活性探針可以幫助恢復掛起的容器,但由於您可以完全控制應用程序,因此理想情況下不應發生掛起進程和死鎖之類的情況:最好的替代方案是故意使應用程式崩潰並將其恢復到先前的穩定狀態;
    • 失敗的活性探測將導致容器重新啟動,從而可能加劇加載相關錯誤的後果:重新啟動容器將導致停機(至少在應用程式啟動期間,例如 30 多秒),從而導致新的錯誤、增加其他貨櫃的負載並增加其故障的可能性等;
    • 活性檢查與外部依賴項結合是最糟糕的組合,可能會導致級聯故障:資料庫端的輕微延遲將導致所有容器重新啟動!
  3. 活性和就緒檢查參數 一定是不同的:
    • 您可以使用具有相同運行狀況檢查但響應閾值更高的活性探針(failureThreshold),例如,分配狀態 沒有準備好 3次嘗試後,10次嘗試後認為活性探測失敗;
  4. 不要使用執行檢查,因為它們與導致殭屍進程出現的已知問題相關:

總結

  • 使用就緒偵測來確定 Pod 何時準備好接收流量。
  • 僅在真正需要時才使用活性探針。
  • 就緒/活躍探針使用不當可能會導致可用性降低和級聯故障。

Kubernetes 中的活躍度探測可能很危險

有關該主題的其他資料

1-2019-09 更新第 29 號

關於用於資料庫遷移的 init 容器:添加了腳註。

EJ提醒我了 關於 PDB:活性檢查的問題之一是 pod 之間缺乏協調。 庫伯內特斯有 Pod 中斷預算 (PDB) 限制應用程式可能遇到的並發故障數量,但是檢查不考慮 PDB。 理想情況下,我們可以告訴 K8s“如果測試失敗,則重新啟動一個 Pod,但不要重新啟動所有 Pod,以免事情變得更糟。”

布萊恩說得很完美:「當您確切知道什麼時,請使用活性探測 最好的方法就是終止該應用程式「(再次強調,不要得意忘形)。

Kubernetes 中的活躍度探測可能很危險

2-2019-09 更新第 29 號

關於使用前閱讀文檔:我創建了相應的請求(功能要求)添加有關活性探針的文件。

譯者PS

另請閱讀我們的博客:

來源: www.habr.com

添加評論