为容器配置可写入的 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 配置有保证的 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 中创建 shell 会话:

    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,则表示文件系统处于只读状态。

后续步骤