為容器設定可寫入的 cgroup

您可以使用 Linux cgroups API,讓 Google Kubernetes Engine (GKE) 工作負載管理子程序的資源,例如 CPU 和記憶體。本文說明如何為容器提供 cgroups API 的讀寫存取權,而不需以具備權限的模式執行這些容器。

使用可寫入的 cgroup 的時機

根據預設,Kubernetes 會在每個 Linux 容器中掛接 /sys/fs/cgroup 檔案系統,為所有 Linux 容器提供 cgroups API 的唯讀存取權。您可以選擇讓 GKE 在特定 Pod 中以讀寫模式掛接這個檔案系統,讓根程序管理及限制子程序的資源。

這些可寫入的 cgroup 有助於提升應用程式的可靠性,例如在同一個容器中執行系統程序和使用者程式碼的 Ray。透過寫入 /sys/fs/cgroup 檔案系統,Ray 可以為重要程序保留容器的部分資源。您可以使用可寫入的 cgroup,提升這些應用程式的可靠性,不必擔心容器使用具備權限模式時會發生安全性風險。

事前準備

開始之前,請務必先完成下列工作:

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文件中的指令。

為節點啟用可寫入的 cgroup

自訂 containerd 設定,在節點上啟用可寫入的 cgroup。

在 containerd 設定檔中新增 writableCgroups 區段,並將 enabled 欄位設為 true。詳情請參閱「在 GKE 節點中自訂 containerd 設定」。

writableCgroups:
  enabled: true

您可以透過下列任一支援路徑啟用可寫入的 cgroup:

  • 建立新叢集:建立新叢集時,使用 --containerd-config-from-file 旗標指定設定檔 (使用 gcloud container clusters create 或 gcloud container clusters create-auto 指令)。
  • 更新現有叢集:更新叢集層級的節點預設值時,請使用 --containerd-config-from-file 標記指定設定檔 (使用 gcloud container clusters update 指令)。更新叢集層級的節點預設值不會影響現有節點。在標準叢集中,您必須升級現有節點集區 (使用 gcloud container clusters upgrade 指令和 --node-pool 旗標),或重新建立節點集區,才能套用設定。
  • 建立新的節點集區:在標準叢集中,建立新的節點集區時,請使用 --containerd-config-from-file 旗標指定設定檔 (使用 gcloud container node-pools create 指令)。

在工作負載中使用可寫入的 cgroup

為叢集或節點集區啟用可寫入的 cgroup 後,請設定工作負載,確保符合下列所有需求:

  • 選取已啟用可寫入 cgroup 的節點。
  • 為 Pod 中的一或多個容器啟用可寫入的 cgroup。
  • 如要使用 服務品質 (QoS) 保證類別, 請符合下列其中一項條件:

    • 如果工作負載在 Pod 層級指定資源,請在 Pod 規格中,為 resources.requests 和 resources.limits 設定相同的值。
    • 如果工作負載為每個容器指定資源,請在 Pod 中每個容器 (包括 init 容器) 的規格中,為 resources.requests 和 resources.limits 設定相同的值。

如要設定這些需求條件,請按照下列步驟操作:

  1. 如要選取已啟用可寫入 cgroup 的節點,請將 node.gke.io/enable-writable-cgroups: "true" 標籤新增至 Pod 規格的 spec.nodeSelector 欄位:

    node.gke.io/enable-writable-cgroups: "true"
    
  2. 如要為工作負載啟用可寫入的 cgroup,請在 Pod 規格的 metadata.annotations 欄位中新增下列其中一個註解:

    • 為整個 Pod 啟用:

      node.gke.io/enable-writable-cgroups: "true"
      
    • 為 Pod 中的特定容器啟用:

      node.gke.io/enable-writable-cgroups.CONTAINER_NAME: "true"
      

      將 CONTAINER_NAME 替換為容器名稱。

  3. 如要為 Pod 設定 Guaranteed QoS 類別,請為 Pod 中或整個 Pod 的每個容器指定相同的 CPU 和記憶體要求與限制,如下列範例所示:

    resources:
      requests:
        cpu: "100m"
        memory: "100Mi"
      limits:
        cpu: "100m"
        memory: "100Mi"
    

    即使您只為 Pod 中的其中一個容器啟用可寫入的 cgroup,也必須為每個容器指定相同的要求和限制。

最終的 Pod 規格應類似下列範例。

  • 這個範例會為 Pod 中的所有容器啟用可寫入的 cgroup:

    apiVersion: v1
    kind: Pod
    metadata:
      name: writable-cgroups-pod
      annotations:
        node.gke.io/enable-writable-cgroups: "true"
    spec:
      nodeSelector:
        node.gke.io/enable-writable-cgroups: "true"
      containers:
      - name: container
        image: busybox:stable
        command: ["/bin/sh", "-c"]
        args:
        -   |
          trap 'echo "Caught SIGTERM, exiting..."; exit 0' TERM
          echo "Waiting for termination signal..."
          while true; do sleep 1; done
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
          limits:
            cpu: "100m"
            memory: "100Mi"
    
  • 這個範例會為多容器 Pod 中的特定容器啟用可寫入的 cgroup:

    apiVersion: v1
    kind: Pod
    metadata:
      name: writable-cgroups-per-container
      annotations:
        node.gke.io/enable-writable-cgroups.busybox-container: "true"
    spec:
      nodeSelector:
        node.gke.io/enable-writable-cgroups: "true"
      containers:
      - name: busybox-container
        image: busybox:stable
        command: ["/bin/sh", "-c"]
        args:
        -   |
          trap 'echo "Caught SIGTERM, exiting..."; exit 0' TERM
          echo "Waiting for termination signal..."
          while true; do sleep 1; done
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
          limits:
            cpu: "100m"
            memory: "100Mi"
      - name: container-disabled
        image: busybox:stable
        command: ["/bin/sh", "-c"]
        args:
        -   |
          trap 'echo "Caught SIGTERM, exiting..."; exit 0' TERM
          echo "Waiting for termination signal..."
          while true; do sleep 1; done
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
          limits:
            cpu: "100m"
            memory: "100Mi"
    

確認 cgroup 檔案系統可寫入

如要驗證 Pod 或容器的 /sys/fs/cgroup 檔案系統權限,請按照下列步驟操作:

  1. 找出要檢查的 Pod。您可以使用「在工作負載中使用可寫入的 cgroup」一節中的其中一個 Pod 範例。
  2. 在 Pod 中建立殼層工作階段:

    kubectl exec -it POD_NAME -- /bin/sh
    

    將 POD_NAME 替換為 Pod 名稱。

  3. 說明已掛接的 cgroup 檔案系統:

    mount | grep cgroup
    

    輸出結果會與下列內容相似:

    cgroup on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime)
    

    在此輸出內容中,rw 表示檔案系統可寫入。如果輸出內容顯示 ro,表示檔案系統為唯讀。

後續步驟