為容器設定可寫入的 cgroup

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

使用可寫入的 cgroup 的時機

根據預設,Kubernetes 會在每個容器中掛接 /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。您可以將這項設定套用至整個叢集,或 Standard 叢集中的特定節點集區。

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

writableCgroups:
  enabled: true

建立或更新叢集或節點集區時,請指定更新後的設定檔。

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

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

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

    • 對於在 Pod 層級指定資源的工作負載,請在 Pod 規格中為 resources.requestsresources.limits 設定相同的值。
    • 如果工作負載為每個容器指定資源,請在 Pod 中每個容器 (包括 init 容器) 的規格中,為 resources.requestsresources.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,表示檔案系統為唯讀。

後續步驟