日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Pod 的生命周期及探针

發布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Pod 的生命周期及探针 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

?

?

Pod 的生命周期

Pod 生命期

Pod 階段

容器狀態

Waiting?(等待)

Running(運行中)

Terminated(已終止)

容器重啟策略

Pod 狀況

Pod 就緒態

Pod 就緒態的狀態

容器探針

何時該使用存活態探針?

何時該使用就緒態探針?

何時該使用啟動探針?

Pod 的終止

強制終止 Pod

失效 Pod 的垃圾收集

配置存活、就緒和啟動探測器

準備開始

定義存活命令

定義一個存活態 HTTP 請求接口

定義 TCP 的存活探測

使用命名端口

使用啟動探測器保護慢啟動容器

定義就緒探測器

配置探測器

HTTP 探測

TCP 探測

探測器級別?terminationGracePeriodSeconds

總結


?

Pod 的生命周期

?Pod 遵循一個預定義的生命周期,起始于?Pending?階段,如果至少 其中有一個主要容器正常啟動,則進入?Running,之后取決于 Pod 中是否有容器以 失敗狀態結束而進入?Succeeded?或者?Failed?階段。

在 Pod 運行期間,kubelet?能夠重啟容器以處理一些失效場景。 在 Pod 內部,Kubernetes 跟蹤不同容器的狀態?并確定使 Pod 重新變得健康所需要采取的動作。

在 Kubernetes API 中,Pod 包含規約部分和實際狀態部分。 Pod 對象的狀態包含了一組?Pod 狀況(Conditions)。 如果應用需要的話,你也可以向其中注入自定義的就緒性信息。

Pod 在其生命周期中只會被調度一次。 一旦 Pod 被調度(分派)到某個節點,Pod 會一直在該節點運行,直到 Pod 停止或者 被終止。

Pod 生命期

和一個個獨立的應用容器一樣,Pod 也被認為是相對臨時性(而不是長期存在)的實體。 Pod 會被創建、賦予一個唯一的 ID(UID), 并被調度到節點,并在終止(根據重啟策略)或刪除之前一直運行在該節點。

如果一個節點死掉了,調度到該節點 的 Pod 也被計劃在給定超時期限結束后刪除。

Pod 自身不具有自愈能力。如果 Pod 被調度到某節點?而該節點之后失效,Pod 會被刪除;類似地,Pod 無法在因節點資源 耗盡或者節點維護而被驅逐期間繼續存活。Kubernetes 使用一種高級抽象 來管理這些相對而言可隨時丟棄的 Pod 實例,稱作?控制器。

任何給定的 Pod (由 UID 定義)從不會被“重新調度(rescheduled)”到不同的節點; 相反,這一 Pod 可以被一個新的、幾乎完全相同的 Pod 替換掉。 如果需要,新 Pod 的名字可以不變,但是其 UID 會不同。

如果某物聲稱其生命期與某 Pod 相同,例如存儲卷, 這就意味著該對象在此 Pod (UID 亦相同)存在期間也一直存在。 如果 Pod 因為任何原因被刪除,甚至某完全相同的替代 Pod 被創建時, 這個相關的對象(例如這里的卷)也會被刪除并重建。

Pod 階段

Pod 的?status?字段是一個?PodStatus?對象,其中包含一個?phase?字段。

下面是?phase?可能的值:

取值描述
Pending(懸決)Pod 已被 Kubernetes 系統接受,但有一個或者多個容器尚未創建亦未運行。此階段包括等待 Pod 被調度的時間和通過網絡下載鏡像的時間,
Running(運行中)Pod 已經綁定到了某個節點,Pod 中所有的容器都已被創建。至少有一個容器仍在運行,或者正處于啟動或重啟狀態。
Succeeded(成功)Pod 中的所有容器都已成功終止,并且不會再重啟。
Failed(失敗)Pod 中的所有容器都已終止,并且至少有一個容器是因為失敗終止。也就是說,容器以非 0 狀態退出或者被系統終止。
Unknown(未知)因為某些原因無法取得 Pod 的狀態。這種情況通常是因為與 Pod 所在主機通信失敗。

如果某節點死掉或者與集群中其他節點失聯,Kubernetes 會實施一種策略,將失去的節點上運行的所有 Pod 的?phase?設置為?Failed。

容器狀態

Kubernetes 會跟蹤 Pod 中每個容器的狀態,就像它跟蹤 Pod 總體上的階段一樣。 你可以使用容器生命周期回調?來在容器生命周期中的特定時間點觸發事件。

一旦調度器將 Pod 分派給某個節點,kubelet?就通過?容器運行時?開始為 Pod 創建容器。 容器的狀態有三種:Waiting(等待)、Running(運行中)和?Terminated(已終止)。

要檢查 Pod 中容器的狀態,你可以使用?kubectl describe pod <pod 名稱>。 其輸出中包含 Pod 中每個容器的狀態。

每種狀態都有特定的含義:

Waiting?(等待)

如果容器并不處在?Running?或?Terminated?狀態之一,它就處在?Waiting?狀態。 處于?Waiting?狀態的容器仍在運行它完成啟動所需要的操作:例如,從某個容器鏡像 倉庫拉取容器鏡像,或者向容器應用?Secret?數據等等。 當你使用?kubectl?來查詢包含?Waiting?狀態的容器的 Pod 時,你也會看到一個 Reason 字段,其中給出了容器處于等待狀態的原因。

Running(運行中)

Running?狀態表明容器正在執行狀態并且沒有問題發生。 如果配置了?postStart?回調,那么該回調已經執行且已完成。 如果你使用?kubectl?來查詢包含?Running?狀態的容器的 Pod 時,你也會看到 關于容器進入?Running?狀態的信息。

Terminated(已終止)

處于?Terminated?狀態的容器已經開始執行并且或者正常結束或者因為某些原因失敗。 如果你使用?kubectl?來查詢包含?Terminated?狀態的容器的 Pod 時,你會看到 容器進入此狀態的原因、退出代碼以及容器執行期間的起止時間。

如果容器配置了?preStop?回調,則該回調會在容器進入?Terminated?狀態之前執行。

容器重啟策略

Pod 的?spec?中包含一個?restartPolicy?字段,其可能取值包括 Always、OnFailure 和 Never。默認值是 Always。

restartPolicy?適用于 Pod 中的所有容器。restartPolicy?僅針對同一節點上?kubelet?的容器重啟動作。當 Pod 中的容器退出時,kubelet?會按指數回退 方式計算重啟的延遲(10s、20s、40s、...),其最長延遲為 5 分鐘。 一旦某容器執行了 10 分鐘并且沒有出現問題,kubelet?對該容器的重啟回退計時器執行 重置操作。

Pod 狀況

Pod 有一個 PodStatus 對象,其中包含一個?PodConditions?數組。Pod 可能通過也可能未通過其中的一些狀況測試。

  • PodScheduled:Pod 已經被調度到某節點;
  • ContainersReady:Pod 中所有容器都已就緒;
  • Initialized:所有的?Init 容器?都已成功啟動;
  • Ready:Pod 可以為請求提供服務,并且應該被添加到對應服務的負載均衡池中。
字段名稱描述
typePod 狀況的名稱
status表明該狀況是否適用,可能的取值有 "True", "False" 或 "Unknown"
lastProbeTime上次探測 Pod 狀況時的時間戳
lastTransitionTimePod 上次從一種狀態轉換到另一種狀態時的時間戳
reason機器可讀的、駝峰編碼(UpperCamelCase)的文字,表述上次狀況變化的原因
message人類可讀的消息,給出上次狀態轉換的詳細信息

Pod 就緒態

FEATURE STATE:?Kubernetes v1.14 [stable]

你的應用可以向 PodStatus 中注入額外的反饋或者信號:Pod Readiness(Pod 就緒態)。 要使用這一特性,可以設置 Pod 規約中的?readinessGates?列表,為 kubelet 提供一組額外的狀況供其評估 Pod 就緒態時使用。

就緒態門控基于 Pod 的?status.conditions?字段的當前值來做決定。 如果 Kubernetes 無法在?status.conditions?字段中找到某狀況,則該狀況的 狀態值默認為 "False"。

這里是一個例子:

kind: Pod ... spec:readinessGates:- conditionType: "www.example.com/feature-1" status:conditions:- type: Ready # 內置的 Pod 狀況status: "False"lastProbeTime: nulllastTransitionTime: 2018-01-01T00:00:00Z- type: "www.example.com/feature-1" # 額外的 Pod 狀況status: "False"lastProbeTime: nulllastTransitionTime: 2018-01-01T00:00:00ZcontainerStatuses:- containerID: docker://abcd...ready: true ...

你所添加的 Pod 狀況名稱必須滿足 Kubernetes?標簽鍵名格式。

Pod 就緒態的狀態

命令?kubectl patch?不支持修改對象的狀態。 如果需要設置 Pod 的?status.conditions,應用或者?Operators?需要使用?PATCH?操作。 你可以使用?Kubernetes 客戶端庫?之一來編寫代碼,針對 Pod 就緒態設置定制的 Pod 狀況。

對于使用定制狀況的 Pod 而言,只有當下面的陳述都適用時,該 Pod 才會被評估為就緒:

  • Pod 中所有容器都已就緒;
  • readinessGates?中的所有狀況都為?True?值。

當 Pod 的容器都已就緒,但至少一個定制狀況沒有取值或者取值為?False,?kubelet?將 Pod 的狀況設置為?ContainersReady。

容器探針

Probe?是由?kubelet?對容器執行的定期診斷。 要執行診斷,kubelet 調用由容器實現的?Handler?(處理程序)。有三種類型的處理程序:

  • ExecAction: 在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功。

  • TCPSocketAction: 對容器的 IP 地址上的指定端口執行 TCP 檢查。如果端口打開,則診斷被認為是成功的。

  • HTTPGetAction: 對容器的 IP 地址上指定端口和路徑執行 HTTP Get 請求。如果響應的狀態碼大于等于 200 且小于 400,則診斷被認為是成功的。

每次探測都將獲得以下三種結果之一:

  • Success(成功):容器通過了診斷。
  • Failure(失敗):容器未通過診斷。
  • Unknown(未知):診斷失敗,因此不會采取任何行動。

針對運行中的容器,kubelet?可以選擇是否執行以下三種探針,以及如何針對探測結果作出反應:

  • livenessProbe:指示容器是否正在運行。如果存活態探測失敗,則 kubelet 會殺死容器, 并且容器將根據其重啟策略決定未來。如果容器不提供存活探針, 則默認狀態為?Success。

  • readinessProbe:指示容器是否準備好為請求提供服務。如果就緒態探測失敗, 端點控制器將從與 Pod 匹配的所有服務的端點列表中刪除該 Pod 的 IP 地址。 初始延遲之前的就緒態的狀態值默認為?Failure。 如果容器不提供就緒態探針,則默認狀態為?Success。

  • startupProbe: 指示容器中的應用是否已經啟動。如果提供了啟動探針,則所有其他探針都會被 禁用,直到此探針成功為止。如果啟動探測失敗,kubelet?將殺死容器,而容器依其?重啟策略進行重啟。 如果容器沒有提供啟動探測,則默認狀態為?Success。

如欲了解如何設置存活態、就緒態和啟動探針的進一步細節,可以參閱?配置存活態、就緒態和啟動探針。

何時該使用存活態探針?

FEATURE STATE:?Kubernetes v1.0 [stable]

如果容器中的進程能夠在遇到問題或不健康的情況下自行崩潰,則不一定需要存活態探針;?kubelet?將根據 Pod 的restartPolicy?自動執行修復操作。

如果你希望容器在探測失敗時被殺死并重新啟動,那么請指定一個存活態探針, 并指定restartPolicy?為 "Always" 或 "OnFailure"。

何時該使用就緒態探針?

FEATURE STATE:?Kubernetes v1.0 [stable]

如果要僅在探測成功時才開始向 Pod 發送請求流量,請指定就緒態探針。 在這種情況下,就緒態探針可能與存活態探針相同,但是規約中的就緒態探針的存在意味著 Pod 將在啟動階段不接收任何數據,并且只有在探針探測成功后才開始接收數據。

如果你的容器需要加載大規模的數據、配置文件或者在啟動期間執行遷移操作,可以添加一個 就緒態探針。

如果你希望容器能夠自行進入維護狀態,也可以指定一個就緒態探針,檢查某個特定于 就緒態的因此不同于存活態探測的端點。

說明:

請注意,如果你只是想在 Pod 被刪除時能夠排空請求,則不一定需要使用就緒態探針; 在刪除 Pod 時,Pod 會自動將自身置于未就緒狀態,無論就緒態探針是否存在。 等待 Pod 中的容器停止期間,Pod 會一直處于未就緒狀態。

何時該使用啟動探針?

FEATURE STATE:?Kubernetes v1.18 [beta]

對于所包含的容器需要較長時間才能啟動就緒的 Pod 而言,啟動探針是有用的。 你不再需要配置一個較長的存活態探測時間間隔,只需要設置另一個獨立的配置選定, 對啟動期間的容器執行探測,從而允許使用遠遠超出存活態時間間隔所允許的時長。

如果你的容器啟動時間通常超出?initialDelaySeconds + failureThreshold × periodSeconds?總值,你應該設置一個啟動探測,對存活態探針所使用的同一端點執行檢查。?periodSeconds?的默認值是 10 秒。你應該將其?failureThreshold?設置得足夠高, 以便容器有充足的時間完成啟動,并且避免更改存活態探針所使用的默認值。 這一設置有助于減少死鎖狀況的發生。

Pod 的終止

由于 Pod 所代表的是在集群中節點上運行的進程,當不再需要這些進程時允許其體面地 終止是很重要的。一般不應武斷地使用?KILL?信號終止它們,導致這些進程沒有機會 完成清理操作。

設計的目標是令你能夠請求刪除進程,并且知道進程何時被終止,同時也能夠確保刪除 操作終將完成。當你請求刪除某個 Pod 時,集群會記錄并跟蹤 Pod 的體面終止周期, 而不是直接強制地殺死 Pod。在存在強制關閉設施的前提下,?kubelet?會嘗試體面地終止 Pod。

通常情況下,容器運行時會發送一個 TERM 信號到每個容器中的主進程。 很多容器運行時都能夠注意到容器鏡像中?STOPSIGNAL?的值,并發送該信號而不是 TERM。 一旦超出了體面終止限期,容器運行時會向所有剩余進程發送 KILL 信號,之后 Pod 就會被從?API 服務器?上移除。如果?kubelet?或者容器運行時的管理服務在等待進程終止期間被重啟, 集群會從頭開始重試,賦予 Pod 完整的體面終止限期。

下面是一個例子:

  • 你使用?kubectl?工具手動刪除某個特定的 Pod,而該 Pod 的體面終止限期是默認值(30 秒)。

  • API 服務器中的 Pod 對象被更新,記錄涵蓋體面終止限期在內 Pod 的最終死期,超出所計算時間點則認為 Pod 已死(dead)。 如果你使用?kubectl describe?來查驗你正在刪除的 Pod,該 Pod 會顯示為 "Terminating" (正在終止)。 在 Pod 運行所在的節點上:kubelet?一旦看到 Pod 被標記為正在終止(已經設置了體面終止限期),kubelet?即開始本地的 Pod 關閉過程。

  • 如果 Pod 中的容器之一定義了?preStop?回調,?kubelet?開始在容器內運行該回調邏輯。如果超出體面終止限期時,preStop?回調邏輯 仍在運行,kubelet?會請求給予該 Pod 的寬限期一次性增加 2 秒鐘。

    說明:?如果?preStop?回調所需要的時間長于默認的體面終止限期,你必須修改?terminationGracePeriodSeconds?屬性值來使其正常工作。

  • kubelet?接下來觸發容器運行時發送 TERM 信號給每個容器中的進程 1。

    說明:?Pod 中的容器會在不同時刻收到 TERM 信號,接收順序也是不確定的。 如果關閉的順序很重要,可以考慮使用?preStop?回調邏輯來協調。

  • 與此同時,kubelet?啟動體面關閉邏輯,控制面會將 Pod 從對應的端點列表(以及端點切片列表, 如果啟用了的話)中移除,過濾條件是 Pod 被對應的?服務以某?選擇算符選定。?ReplicaSets和其他工作負載資源 不再將關閉進程中的 Pod 視為合法的、能夠提供服務的副本。關閉動作很慢的 Pod 也無法繼續處理請求數據,因為負載均衡器(例如服務代理)已經在終止寬限期開始的時候 將其從端點列表中移除。
  • 超出終止寬限期限時,kubelet?會觸發強制關閉過程。容器運行時會向 Pod 中所有容器內 仍在運行的進程發送?SIGKILL?信號。?kubelet?也會清理隱藏的?pause?容器,如果容器運行時使用了這種容器的話。

  • kubelet?觸發強制從 API 服務器上刪除 Pod 對象的邏輯,并將體面終止限期設置為 0 (這意味著馬上刪除)。

  • API 服務器刪除 Pod 的 API 對象,從任何客戶端都無法再看到該對象。

  • 強制終止 Pod

    注意:?對于某些工作負載及其 Pod 而言,強制刪除很可能會帶來某種破壞。

    默認情況下,所有的刪除操作都會附有 30 秒鐘的寬限期限。?kubectl delete?命令支持?--grace-period=<seconds>?選項,允許你重載默認值, 設定自己希望的期限值。

    將寬限期限強制設置為?0?意味著立即從 API 服務器刪除 Pod。 如果 Pod 仍然運行于某節點上,強制刪除操作會觸發?kubelet?立即執行清理操作。

    說明:?你必須在設置?--grace-period=0?的同時額外設置?--force?參數才能發起強制刪除請求。

    執行強制刪除操作時,API 服務器不再等待來自?kubelet?的、關于 Pod 已經在原來運行的節點上終止執行的確認消息。 API 服務器直接刪除 Pod 對象,這樣新的與之同名的 Pod 即可以被創建。 在節點側,被設置為立即終止的 Pod 仍然會在被強行殺死之前獲得一點點的寬限時間。

    如果你需要強制刪除 StatefulSet 的 Pod,請參閱?從 StatefulSet 中刪除 Pod?的任務文檔。

    失效 Pod 的垃圾收集

    對于已失敗的 Pod 而言,對應的 API 對象仍然會保留在集群的 API 服務器上,直到 用戶或者控制器進程顯式地 將其刪除。

    控制面組件會在 Pod 個數超出所配置的閾值 (根據?kube-controller-manager?的?terminated-pod-gc-threshold?設置)時 刪除已終止的 Pod(階段值為?Succeeded?或?Failed)。 這一行為會避免隨著時間演進不斷創建和終止 Pod 而引起的資源泄露問題

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    配置存活、就緒和啟動探測器

    kubelet?使用存活探測器來知道什么時候要重啟容器。 例如,存活探測器可以捕捉到死鎖(應用程序在運行,但是無法繼續執行后面的步驟)。 這樣的情況下重啟容器有助于讓應用程序在有問題的情況下更可用。

    kubelet 使用就緒探測器可以知道容器什么時候準備好了并可以開始接受請求流量, 當一個 Pod 內的所有容器都準備好了,才能把這個 Pod 看作就緒了。 這種信號的一個用途就是控制哪個 Pod 作為 Service 的后端。 在 Pod 還沒有準備好的時候,會從 Service 的負載均衡器中被剔除的。

    kubelet 使用啟動探測器可以知道應用程序容器什么時候啟動了。 如果配置了這類探測器,就可以控制容器在啟動成功后再進行存活性和就緒檢查, 確保這些存活、就緒探測器不會影響應用程序的啟動。 這可以用于對慢啟動容器進行存活性檢測,避免它們在啟動運行之前就被殺掉。

    準備開始

    你必須擁有一個 Kubernetes 的集群,同時你的 Kubernetes 集群必須帶有 kubectl 命令行工具。 如果你還沒有集群,你可以通過?Minikube?構建一 個你自己的集群,或者你可以使用下面任意一個 Kubernetes 工具構建:

    • Katacoda
    • 玩轉 Kubernetes

    定義存活命令

    許多長時間運行的應用程序最終會過渡到斷開的狀態,除非重新啟動,否則無法恢復。 Kubernetes 提供了存活探測器來發現并補救這種情況。

    ?

    apiVersion: v1 kind: Pod metadata:labels:test: livenessname: liveness-exec spec:containers:- name: livenessimage: k8s.gcr.io/busyboxargs:- /bin/sh- -c- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600livenessProbe:exec:command:- cat- /tmp/healthyinitialDelaySeconds: 5periodSeconds: 5

    在這個配置文件中,可以看到 Pod 中只有一個容器。?periodSeconds?字段指定了 kubelet 應該每 5 秒執行一次存活探測。?initialDelaySeconds?字段告訴 kubelet 在執行第一次探測前應該等待 5 秒。 kubelet 在容器內執行命令?cat /tmp/healthy?來進行探測。 如果命令執行成功并且返回值為 0,kubelet 就會認為這個容器是健康存活的。 如果這個命令返回非 0 值,kubelet 會殺死這個容器并重新啟動它。

    當容器啟動時,執行如下的命令:

    /bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"

    這個容器生命的前 30 秒,?/tmp/healthy?文件是存在的。 所以在這最開始的 30 秒內,執行命令?cat /tmp/healthy?會返回成功代碼。 30 秒之后,執行命令?cat /tmp/healthy?就會返回失敗代碼。

    創建 Pod:

    kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml

    在 30 秒內,查看 Pod 的事件:

    kubectl describe pod liveness-exec

    輸出結果表明還沒有存活探測器失敗:

    FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 24s 24s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0 23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox" 23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox" 23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined] 23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e

    35 秒之后,再來看 Pod 的事件:

    kubectl describe pod liveness-exec

    在輸出結果的最下面,有信息顯示存活探測器失敗了,這個容器被殺死并且被重建了。

    FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 37s 37s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0 36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox" 36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox" 36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined] 36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e 2s 2s 1 {kubelet worker0} spec.containers{liveness} Warning Unhealthy Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

    再等另外 30 秒,檢查看這個容器被重啟了:

    kubectl get pod liveness-exec

    輸出結果顯示?RESTARTS?的值增加了 1。

    NAME READY STATUS RESTARTS AGE liveness-exec 1/1 Running 1 1m

    定義一個存活態 HTTP 請求接口

    另外一種類型的存活探測方式是使用 HTTP GET 請求。 下面是一個 Pod 的配置文件,其中運行一個基于?k8s.gcr.io/liveness?鏡像的容器。

    pods/probe/http-liveness.yaml?

    apiVersion: v1 kind: Pod metadata:labels:test: livenessname: liveness-http spec:containers:- name: livenessimage: k8s.gcr.io/livenessargs:- /serverlivenessProbe:httpGet:path: /healthzport: 8080httpHeaders:- name: Custom-Headervalue: AwesomeinitialDelaySeconds: 3periodSeconds: 3

    在這個配置文件中,可以看到 Pod 也只有一個容器。?periodSeconds?字段指定了 kubelet 每隔 3 秒執行一次存活探測。?initialDelaySeconds?字段告訴 kubelet 在執行第一次探測前應該等待 3 秒。 kubelet 會向容器內運行的服務(服務會監聽 8080 端口)發送一個 HTTP GET 請求來執行探測。 如果服務器上?/healthz?路徑下的處理程序返回成功代碼,則 kubelet 認為容器是健康存活的。 如果處理程序返回失敗代碼,則 kubelet 會殺死這個容器并且重新啟動它。

    任何大于或等于 200 并且小于 400 的返回代碼標示成功,其它返回代碼都標示失敗。

    可以在這里看服務的源碼?server.go。

    容器存活的最開始 10 秒中,/healthz?處理程序返回一個 200 的狀態碼。之后處理程序返回 500 的狀態碼。

    http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {duration := time.Now().Sub(started)if duration.Seconds() > 10 {w.WriteHeader(500)w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))} else {w.WriteHeader(200)w.Write([]byte("ok"))} })

    kubelet 在容器啟動之后 3 秒開始執行健康檢測。所以前幾次健康檢查都是成功的。 但是 10 秒之后,健康檢查會失敗,并且 kubelet 會殺死容器再重新啟動容器。

    創建一個 Pod 來測試 HTTP 的存活檢測:

    kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml

    10 秒之后,通過看 Pod 事件來檢測存活探測器已經失敗了并且容器被重新啟動了。

    kubectl describe pod liveness-http

    在 1.13(包括 1.13版本)之前的版本中,如果在 Pod 運行的節點上設置了環境變量?http_proxy(或者?HTTP_PROXY),HTTP 的存活探測會使用這個代理。 在 1.13 之后的版本中,設置本地的 HTTP 代理環境變量不會影響 HTTP 的存活探測。

    定義 TCP 的存活探測

    第三種類型的存活探測是使用 TCP 套接字。 通過配置,kubelet 會嘗試在指定端口和容器建立套接字鏈接。 如果能建立連接,這個容器就被看作是健康的,如果不能則這個容器就被看作是有問題的。

    apiVersion: v1 kind: Pod metadata:name: goproxylabels:app: goproxy spec:containers:- name: goproxyimage: k8s.gcr.io/goproxy:0.1ports:- containerPort: 8080readinessProbe:tcpSocket:port: 8080initialDelaySeconds: 5periodSeconds: 10livenessProbe:tcpSocket:port: 8080initialDelaySeconds: 15periodSeconds: 20

    如你所見,TCP 檢測的配置和 HTTP 檢測非常相似。 下面這個例子同時使用就緒和存活探測器。kubelet 會在容器啟動 5 秒后發送第一個就緒探測。 這會嘗試連接?goproxy?容器的 8080 端口。 如果探測成功,這個 Pod 會被標記為就緒狀態,kubelet 將繼續每隔 10 秒運行一次檢測。

    除了就緒探測,這個配置包括了一個存活探測。 kubelet 會在容器啟動 15 秒后進行第一次存活探測。 與就緒探測類似,會嘗試連接?goproxy?容器的 8080 端口。 如果存活探測失敗,這個容器會被重新啟動。

    kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml

    15 秒之后,通過看 Pod 事件來檢測存活探測器:

    kubectl describe pod goproxy

    使用命名端口

    對于 HTTP 或者 TCP 存活檢測可以使用命名的?ContainerPort。

    ports: - name: liveness-portcontainerPort: 8080hostPort: 8080livenessProbe:httpGet:path: /healthzport: liveness-port

    使用啟動探測器保護慢啟動容器

    有時候,會有一些現有的應用程序在啟動時需要較多的初始化時間。 要不影響對引起探測死鎖的快速響應,這種情況下,設置存活探測參數是要技巧的。 技巧就是使用一個命令來設置啟動探測,針對HTTP 或者 TCP 檢測,可以通過設置?failureThreshold * periodSeconds?參數來保證有足夠長的時間應對糟糕情況下的啟動時間。

    所以,前面的例子就變成了:

    ports: - name: liveness-portcontainerPort: 8080hostPort: 8080livenessProbe:httpGet:path: /healthzport: liveness-portfailureThreshold: 1periodSeconds: 10startupProbe:httpGet:path: /healthzport: liveness-portfailureThreshold: 30periodSeconds: 10

    幸虧有啟動探測,應用程序將會有最多 5 分鐘(30 * 10 = 300s) 的時間來完成它的啟動。 一旦啟動探測成功一次,存活探測任務就會接管對容器的探測,對容器死鎖可以快速響應。 如果啟動探測一直沒有成功,容器會在 300 秒后被殺死,并且根據?restartPolicy?來設置 Pod 狀態。

    定義就緒探測器

    有時候,應用程序會暫時性的不能提供通信服務。 例如,應用程序在啟動時可能需要加載很大的數據或配置文件,或是啟動后要依賴等待外部服務。 在這種情況下,既不想殺死應用程序,也不想給它發送請求。 Kubernetes 提供了就緒探測器來發現并緩解這些情況。 容器所在 Pod 上報還未就緒的信息,并且不接受通過 Kubernetes Service 的流量。

    說明:?就緒探測器在容器的整個生命周期中保持運行狀態。

    注意:?活躍性探測器?不等待?就緒性探測器成功。 如果要在執行活躍性探測器之前等待,應該使用 initialDelaySeconds 或 startupProbe。

    就緒探測器的配置和存活探測器的配置相似。 唯一區別就是要使用?readinessProbe?字段,而不是?livenessProbe?字段。

    readinessProbe:exec:command:- cat- /tmp/healthyinitialDelaySeconds: 5periodSeconds: 5

    HTTP 和 TCP 的就緒探測器配置也和存活探測器的配置一樣的。

    就緒和存活探測可以在同一個容器上并行使用。 兩者都用可以確保流量不會發給還沒有準備好的容器,并且容器會在它們失敗的時候被重新啟動。

    配置探測器

    Probe?有很多配置字段,可以使用這些字段精確的控制存活和就緒檢測的行為:

    • initialDelaySeconds:容器啟動后要等待多少秒后存活和就緒探測器才被初始化,默認是 0 秒,最小值是 0。
    • periodSeconds:執行探測的時間間隔(單位是秒)。默認是 10 秒。最小值是 1。
    • timeoutSeconds:探測的超時后等待多少秒。默認值是 1 秒。最小值是 1。
    • successThreshold:探測器在失敗后,被視為成功的最小連續成功數。默認值是 1。 存活和啟動探測的這個值必須是 1。最小值是 1。
    • failureThreshold:當探測失敗時,Kubernetes 的重試次數。 存活探測情況下的放棄就意味著重新啟動容器。 就緒探測情況下的放棄 Pod 會被打上未就緒的標簽。默認值是 3。最小值是 1。

    ?

    說明:

    在 Kubernetes 1.20 版本之前,exec 探針會忽略?timeoutSeconds:探針會無限期地 持續運行,甚至可能超過所配置的限期,直到返回結果為止。

    這一缺陷在 Kubernetes v1.20 版本中得到修復。你可能一直依賴于之前錯誤的探測行為, 甚至你都沒有覺察到這一問題的存在,因為默認的超時值是 1 秒鐘。 作為集群管理員,你可以在所有的 kubelet 上禁用?ExecProbeTimeout?特性門控?(將其設置為?false),從而恢復之前版本中的運行行為,之后當集群中所有的 exec 探針都設置了?timeoutSeconds?參數后,移除此標志重載。 如果你有 Pods 受到此默認 1 秒鐘超時值的影響,你應該更新 Pod 對應的探針的 超時值,這樣才能為最終去除該特性門控做好準備。

    當此缺陷被修復之后,在使用?dockershim?容器運行時的 Kubernetes?1.20+?版本中,對于 exec 探針而言,容器中的進程可能會因為超時值的設置保持持續運行, 即使探針返回了失敗狀態。

    注意:

    如果就緒態探針的實現不正確,可能會導致容器中進程的數量不斷上升。 如果不對其采取措施,很可能導致資源枯竭的狀況。

    HTTP 探測

    HTTP Probes?可以在?httpGet?上配置額外的字段:

    • host:連接使用的主機名,默認是 Pod 的 IP。也可以在 HTTP 頭中設置 “Host” 來代替。
    • scheme?:用于設置連接主機的方式(HTTP 還是 HTTPS)。默認是 HTTP。
    • path:訪問 HTTP 服務的路徑。默認值為 "/"。
    • httpHeaders:請求中自定義的 HTTP 頭。HTTP 頭字段允許重復。
    • port:訪問容器的端口號或者端口名。如果數字必須在 1 ~ 65535 之間。

    對于 HTTP 探測,kubelet 發送一個 HTTP 請求到指定的路徑和端口來執行檢測。 除非?httpGet?中的?host?字段設置了,否則 kubelet 默認是給 Pod 的 IP 地址發送探測。 如果?scheme?字段設置為了?HTTPS,kubelet 會跳過證書驗證發送 HTTPS 請求。 大多數情況下,不需要設置host?字段。 這里有個需要設置?host?字段的場景,假設容器監聽 127.0.0.1,并且 Pod 的?hostNetwork?字段設置為了?true。那么?httpGet?中的?host?字段應該設置為 127.0.0.1。 可能更常見的情況是如果 Pod 依賴虛擬主機,你不應該設置?host?字段,而是應該在?httpHeaders?中設置?Host。

    針對 HTTP 探針,kubelet 除了必需的?Host?頭部之外還發送兩個請求頭部字段:?User-Agent?和?Accept。這些頭部的默認值分別是?kube-probe/{{ skew latestVersion >}}?(其中?1.21?是 kubelet 的版本號)和?*/*。

    你可以通過為探測設置?.httpHeaders?來重載默認的頭部字段值;例如:

    livenessProbe:httpGet:httpHeaders:- name: Acceptvalue: application/jsonstartupProbe:httpGet:httpHeaders:- name: User-Agentvalue: MyUserAgent

    你也可以通過將這些頭部字段定義為空值,從請求中去掉這些頭部字段。

    livenessProbe:httpGet:httpHeaders:- name: Acceptvalue: ""startupProbe:httpGet:httpHeaders:- name: User-Agentvalue: ""

    TCP 探測

    對于一次 TCP 探測,kubelet 在節點上(不是在 Pod 里面)建立探測連接, 這意味著你不能在?host?參數上配置服務名稱,因為 kubelet 不能解析服務名稱。

    探測器級別?terminationGracePeriodSeconds

    FEATURE STATE:?Kubernetes v1.21 [alpha]

    在 1.21 版之前,pod 級別的?terminationGracePeriodSeconds?被用來終止 未能成功處理活躍性探測或啟動探測的容器。 這種耦合是意料之外的,可能會導致在設置了 pod 級別的?terminationGracePeriodSeconds?后, 需要很長的時間來重新啟動失敗的容器。

    在1.21中,啟用特性標志?ProbeTerminationGracePeriod?后, 用戶可以指定一個探測器級別的?terminationGracePeriodSeconds?作為探測器規格的一部分。 當該特性標志被啟用時,若同時設置了 Pod 級別和探測器級別的?terminationGracePeriodSeconds, kubelet 將使用探測器級的值。

    例如,

    spec:terminationGracePeriodSeconds: 3600 # pod-levelcontainers:- name: testimage: ...ports:- name: liveness-portcontainerPort: 8080hostPort: 8080livenessProbe:httpGet:path: /healthzport: liveness-portfailureThreshold: 1periodSeconds: 60# Override pod-level terminationGracePeriodSeconds #terminationGracePeriodSeconds: 60

    探測器級別的?terminationGracePeriodSeconds?不能用于設置就緒態探針。 它將被 API 服務器拒絕。

    ?

    ?

    ?

    ?

    ?

    總結

    StartupProbe:k8s 1.16版本后新加的探測方式,用于判斷容器內應用程序是否已經啟動。如果配置了startupProbe,就會先禁止其他的探測,直到它成功為止,成功后將不再進行探測。比較適用于容器啟動時間長的場景。
    LivenessProbe:用于探測容器是否運行,如果探測失敗,kubelet會根據配置的重啟策略進行相應的處理。若沒有配置該探針,默認就是success。
    ReadinessProbe:一般用于探測容器內的程序是否健康,它的返回值如果為success,那么久代表這個容器已經完成啟動,并且程序已經是可以接受流量的狀態。

    ?

    #???startupProbe: # 可選,檢測容器內進程是否完成啟動 #??????httpGet:??????# httpGet檢測方式,生產環境建議使用httpGet實現接口級健康檢查,健康檢查由應用程序提供。 #????????????path: /api/successStart # 檢查路徑 #????????????port: 80readinessProbe: # 可選,健康檢查httpGet:??????# httpGet檢測方式,生產環境建議使用httpGet實現接口級健康檢查,健康檢查由應用程序提供。path: / # 檢查路徑port: 80????????# 監控端口livenessProbe:??# 可選,健康檢查#exec:????????# 執行容器命令檢測方式#command:?#- cat#- /health#httpGet:???????# httpGet檢測方式#???path: /_health # 檢查路徑#???port: 8080#???httpHeaders: # 檢查的請求頭#???- name: end-user#?????value: Jason?


    二、Pod探針的檢測方式
    注意:三種檢查方式同時只能使用一種。

    ExecAction:在容器內執行一個命令,如果返回值為0,則認為容器健康。
    TCPSocketAction:通過TCP連接檢查容器內的端口是否通的,如果是通的就認為容器健康。
    HTTPGetAction:通過應用程序暴露的API地址檢查程序是否正常,如果狀態碼為200~400之間,則認為容器健康。(常用)

    三、探針檢查參數配置

    # ?????initialDelaySeconds: 60 ??????# 初始化時間 # ?????timeoutSeconds: 2 ????# 超時時間 # ?????periodSeconds: 5 ?????# 檢測間隔 # ?????successThreshold: 1 # 檢查成功為1次表示就緒 # ?????failureThreshold: 2 # 檢測失敗2次表示未就緒

    ?

    ?

    ?

    ?

    ?

    ?

    總結

    以上是生活随笔為你收集整理的Pod 的生命周期及探针的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。