Kubernetes v1.34:更精細地控制容器重啟

隨著 Kubernetes 1.34 的釋出,引入了一個新的 Alpha 功能,使你能夠更精細地控制 Pod 內的容器重啟。此功能名為 容器重啟策略與規則(Container Restart Policy and Rules),允許你為每個容器單獨指定重啟策略,從而覆蓋 Pod 的全域性重啟策略。此外,它還允許你根據容器的退出碼有條件地重啟單個容器。此功能在 Alpha 特性門控 ContainerRestartRules 之後可用。

這是一個被長期請求的功能。讓我們深入瞭解它的工作原理以及如何使用它。

單一重啟策略的問題

在此功能之前,restartPolicy 是在 Pod 級別設定的。這意味著 Pod 中的所有容器共享相同的重啟策略(AlwaysOnFailureNever)。雖然這適用於許多用例,但在其他情況下可能會受到限制。

例如,考慮一個包含主應用容器和一個執行某些初始設定的 Init 容器的 Pod。你可能希望主容器在失敗時總是重啟,但 Init 容器應該只執行一次並且永不重啟。使用單一的 Pod 級重啟策略,這是不可能的。

引入按容器重啟策略

透過新的 ContainerRestartRules 特性門控,你現在可以為 Pod 規約中的每個容器指定一個 restartPolicy。你還可以定義 restartPolicyRules 以根據退出碼控制重啟。這為你提供了處理複雜場景所需的精細控制。

使用場景

讓我們看一些現實生活中的使用場景,在這些場景中,按容器重啟策略可能是有益的。

訓練作業的就地重啟

在機器學習研究中,編排大量長期執行的 AI/ML 訓練工作負載是很常見的。在這些場景中,工作負載故障是不可避免的。當工作負載因可重試的退出碼而失敗時,你希望容器能夠快速重啟,而無需重新排程整個 Pod,這會消耗大量的時間和資源。對失敗的容器進行“就地”重啟對於更好地利用計算資源至關重要。容器只應在因可重試錯誤失敗時才“就地”重啟;否則,容器和 Pod 應終止並可能被重新排程。

現在,這可以透過容器級的 restartPolicyRules 來實現。工作負載可以以不同的程式碼退出,以表示可重試和不可重試的錯誤。有了 restartPolicyRules,工作負載可以快速就地重啟,但僅限於錯誤是可重試的情況。

一次性嘗試的 Init 容器

Init 容器通常用於為主容器執行初始化工作,例如設定環境和憑據。有時,你希望主容器總是被重啟,但如果初始化失敗,你不想重試。

透過容器級的 restartPolicy,這現在成為可能。Init 容器可以只執行一次,其失敗將被視為 Pod 失敗。如果初始化成功,主容器可以總是被重啟。

具有多個容器的 Pod

對於執行多個容器的 Pod,你可能對每個容器有不同的重啟要求。一些容器可能有明確的成功定義,並且只應在失敗時重啟。其他容器可能需要總是被重啟。

現在,透過容器級的 restartPolicy,這成為可能,允許單個容器具有不同的重啟策略。

如何使用它

要使用此新功能,你需要在執行 Kubernetes 1.34+ 的 Kubernetes 叢集控制平面和工作節點上啟用 ContainerRestartRules 特性門控。啟用後,你可以在容器定義中指定 restartPolicyrestartPolicyRules 欄位。

以下是一些示例

示例 1:根據特定退出碼重啟

在此示例中,僅當容器因可重試錯誤(由退出碼 42 表示)而失敗時,容器才應重啟。

為實現此目的,該容器的 restartPolicyNever,並有一條重啟策略規則,告訴 Kubernetes 如果容器以退出碼 42 退出,則就地重啟該容器。

apiVersion: v1
kind: Pod
metadata:
  name: restart-on-exit-codes
  annotations:
    kubernetes.io/description: "This Pod only restart the container only when it exits with code 42."
spec:
  restartPolicy: Never
  containers:
  - name: restart-on-exit-codes
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'sleep 60 && exit 0']
    restartPolicy: Never     # Container restart policy must be specified if rules are specified
    restartPolicyRules:      # Only restart the container if it exits with code 42
    - action: Restart
      exitCodes:
        operator: In
        values: [42]

示例 2:一個只嘗試一次的 Init 容器

在此示例中,一個 Pod 在初始化成功後應該總是被重啟。但是,初始化應該只嘗試一次。

為實現此目的,Pod 的重啟策略為 Alwaysinit-once 這個 Init 容器將只嘗試一次。如果它失敗,Pod 將會失敗。這使得 Pod 在初始化失敗時會失敗,但在初始化成功後也能保持執行。

apiVersion: v1
kind: Pod
metadata:
  name: fail-pod-if-init-fails
  annotations:
    kubernetes.io/description: "This Pod has an init container that runs only once. After initialization succeeds, the main container will always be restarted."
spec:
  restartPolicy: Always
  initContainers:
  - name: init-once      # This init container will only try once. If it fails, the Pod will fail.
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'echo "Failing initialization" && sleep 10 && exit 1']
    restartPolicy: Never
  containers:
  - name: main-container # This container will always be restarted once initialization succeeds.
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'sleep 1800 && exit 0']

示例 3:具有不同重啟策略的容器

在此示例中,有兩個具有不同重啟要求的容器。一個應該總是被重啟,而另一個只應在失敗時重啟。

這是透過在兩個容器上使用不同的容器級 restartPolicy 來實現的。

apiVersion: v1
kind: Pod
metadata:
  name: on-failure-pod
  annotations:
    kubernetes.io/description: "This Pod has two containers with different restart policies."
spec:
  containers:
  - name: restart-on-failure
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'echo "Not restarting after success" && sleep 10 && exit 0']
    restartPolicy: OnFailure
  - name: restart-always
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'echo "Always restarting" && sleep 1800 && exit 0']
    restartPolicy: Always

瞭解更多

路線圖

更多用於重啟 Pod 和容器的動作和訊號即將到來!值得注意的是,有計劃增加對重啟整個 Pod 的支援。關於這些功能的規劃和討論正在進行中。歡迎與 SIG Node 社群分享反饋或請求!

歡迎你的反饋!

這是一個 Alpha 功能,Kubernetes 專案希望聽到你的反饋。請試用它。此功能由 SIG Node 推動。如果你有興趣幫助開發此功能、分享反饋或參與任何其他正在進行的 SIG Node 專案,請與 SIG Node 社群聯絡!

你可以透過多種方式聯絡 SIG Node