排查部署特权 Autopilot 工作负载的问题

Google Kubernetes Engine (GKE) Autopilot 集群中的特权工作负载必须正确配置,以避免出现问题。配置错误可能会导致与许可清单的同步失败,或导致工作负载被拒绝。这些问题可能会导致必要的代理或服务无法以所需的权限运行。

您可以使用本文档排查在 Autopilot 上部署特权工作负载时遇到的问题。查找有关如何解决许可清单同步错误的指导,并诊断特权工作负载可能遭拒的原因。

对于在 Autopilot 集群上部署具有提升权限的工作负载的平台管理员和运维人员以及安全团队来说,此信息非常重要。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务

许可名单同步问题

当您部署 AllowlistSynchronizer 时,GKE 会尝试安装并同步您指定的许可名单文件。如果此同步失败,AllowlistSynchronizerstatus 字段会报告错误。

获取 AllowlistSynchronizer 对象的状态:

kubectl get allowlistsynchronizer ALLOWLIST_SYNCHRONIZER_NAME -o yaml

输出类似于以下内容:

...
status:
  conditions:
  - type: Ready
    status: "False"
    reason: "SyncError"
    message: "some allowlists failed to sync: example-allowlist-1.yaml"
    lastTransitionTime: "2024-10-12T10:00:00Z"
    observedGeneration: 2
  managedAllowlistStatus:
    - filePath: "gs://path/to/allowlist1.yaml"
      generation: 1
      phase: Installed
      lastSuccessfulSync: "2024-10-10T10:00:00Z"
    - filePath: "gs://path/to/allowlist2.yaml"
      phase: Failed
      lastError: "Initial install failed: invalid contents"
      lastSuccessfulSync: "2024-10-08T10:00:00Z"

conditions.message 字段和 managedAllowlistStatus.lastError 字段会提供有关错误的详细信息。请使用此信息来解决问题。

多个 AllowlistSynchronizer

在版本低于 1.33.4-gke.1035000 的 GKE 集群中,如果存在多个 AllowlistSynchronizerWorkloadAllowlists 可能无法安装。

如需解决此问题,请仅使用包含多个 allowlistPaths 的单个 AllowlistSynchronizer

或者,您也可以将集群升级到较新版本。

工作负载容器排序

在版本低于 1.34.0-gke.0000000 的 GKE 集群中,如果一个或多个工作负载容器映像与集群内 WorkloadAllowlist 中指定的容器映像匹配,则工作负载容器可能会以反向字母顺序进行创建和排序。

如需解决此问题,请尝试以下选项:

  • 将集群升级到 1.34.0-gke.0000000 版或更高版本。
  • 重命名工作负载的容器,以便它们按正确的顺序排序。

特权工作负载部署问题

成功安装许可名单后,您可以在集群中部署相应的特权工作负载。在某些情况下,GKE 可能会拒绝工作负载。

请尝试以下解决方案:

  • 确保集群的 GKE 版本符合工作负载的版本要求。
  • 确保您要部署的工作负载是许可名单文件所应用的工作负载。

如需了解特权工作负载遭拒的原因,请向 GKE 请求有关许可名单违规行为的详细信息:

  1. 获取集群中已安装的许可名单列表:

    kubectl get workloadallowlist
    

    找到应该应用于特权工作负载的许可名单的名称。

  2. 在文本编辑器中打开特权工作负载的 YAML 清单。如果您无法访问 YAML 清单,例如,如果工作负载部署流程使用其他工具,请与工作负载提供商联系以提交问题。跳过其余步骤。

  3. 将以下标签添加到特权工作负载 Pod 规范的 spec.metadata.labels 部分:

    labels:
      cloud.google.com/matching-allowlist: ALLOWLIST_NAME
    

    ALLOWLIST_NAME 替换为您在上一步中获得的许可名单名称。使用 kubectl get workloadallowlist 命令输出中的名称,而不是许可名单文件的路径。

  4. 保存清单并将工作负载应用于集群:

    kubectl apply -f WORKLOAD_MANIFEST_FILE
    

    WORKLOAD_MANIFEST_FILE 替换为清单文件的路径。

    输出会详细说明工作负载中的哪些字段与指定的许可名单不匹配,如下例所示:

    Error from server (GKE Warden constraints violations): error when creating "STDIN": admission webhook "warden-validating.common-webhooks.networking.gke.io" denied the request:
    
    ===========================================================================
    Workload Mismatches Found for Allowlist (example-allowlist-1):
    ===========================================================================
    HostNetwork Mismatch: Workload=true, Allowlist=false
    HostPID Mismatch: Workload=true, Allowlist=false
    Volume[0]: data
             - data not found in allowlist. Verify volume with matching name exists in allowlist.
    Container[0]:
    - Envs Mismatch:
            - env[0]: 'ENV_VAR1' has no matching string or regex pattern in allowlist.
            - env[1]: 'ENV_VAR2' has no matching string or regex pattern in allowlist.
    - Image Mismatch: Workload=k8s.gcr.io/diff/image, Allowlist=k8s.gcr.io/pause2. Verify that image string or regex match.
    - SecurityContext:
            - Capabilities.Add Mismatch: the following added capabilities are not permitted by the allowlist: [SYS_ADMIN SYS_PTRACE]
    - VolumeMount[0]: data
            - data not found in allowlist. Verify volumeMount with matching name exists in allowlist.
    

    在此示例中,存在以下违规行为:

    • 工作负载指定了 hostNetwork: true,但许可名单未指定 hostNetwork: true
    • 工作负载指定了 hostPID: true,但许可名单未指定 hostPID: true
    • 工作负载指定了一个名为 data 的卷,但许可名单未指定名为 data 的卷。
    • 容器指定了名为 ENV_VAR1ENV_VAR2 的环境变量,但许可名单未指定这些环境变量。
    • 容器指定了映像 k8s.gcr.io/diff/image,但许可名单指定了 k8s.gcr.io/pause2
    • 容器添加了 SYS_ADMINSYS_PTRACE 功能,但许可名单不允许添加这些功能。
    • 容器指定了名为 data 的卷装载,但许可名单未指定名为 data 的卷装载。

如果您要部署由第三方提供商提供的工作负载,请向该提供商提交问题以解决违规问题。提供上一步中问题的输出。

Webhook 干扰许可清单上的工作负载

在某些情况下,即使工作负载已正确配置,符合许可清单,GKE 仍可能会拒绝该工作负载。如果在工作负载控制器创建的 Pod 得到许可清单的许可后,集群中的另一个准入控制器 (webhook) 修改了该 Pod,则可能会出现这种情况。这些修改可能会导致 Pod 规范不再与许可清单匹配,从而导致被 GKE Warden 准入 webhook 拒绝。

此问题在将边车容器或环境变量注入到 Pod 中的第三方监控和安全代理中很常见。

症状

最常见的症状是,虽然工作负载控制器(例如 DaemonSet 或 Deployment)已成功创建,但它未能创建任何 Pod。当您检查控制器的事件时,会看到指明 Pod 被准入 webhook 拒绝的消息。

诊断

  1. 按照特权工作负载部署问题部分中的步骤,将 cloud.google.com/matching-allowlist 标签添加到您的工作负载。
  2. 从工作负载的 YAML 清单中复制 spec.template
  3. 创建新的 Pod 清单,并将复制的规范粘贴到 spec 字段中。
  4. 在 Pod 清单中设置 apiVersionkindmetadata.name 字段:

    apiVersion: v1
    kind: Pod
    metadata:
      name: POD_NAME
      labels:
        cloud.google.com/matching-allowlist: ALLOWLIST_NAME
    spec:
      # Paste the content of spec.template here
    

    替换以下内容:

    • POD_NAME:测试 Pod 的名称。
    • ALLOWLIST_NAME:许可清单的名称。
  5. 应用 Pod 清单:

    kubectl apply -f YOUR_POD_MANIFEST_FILE
    

    YOUR_POD_MANIFEST_FILE 替换为 Pod 清单文件的路径。

  6. 检查上一步的输出。如果您在“工作负载不匹配”部分中看到意外的字段,例如额外的环境变量(如 DD_AGENT_HOST)、容器或卷,这强烈表明另一个 webhook 正在修改您的 Pod。

解决方法

如需解决此问题,您需要配置冲突的 webhook,以将其排除,使其无法修改已列入许可清单的工作负载的 Pod。具体操作通常是向工作负载或其命名空间添加标签或注解,以向 webhook 告知它应不介入变更。例如,使用 Datadog 时,您需要向工作负载的命名空间添加 admission.datadoghq.com/enabled: "false" 标签。

请参阅您所用特定第三方软件的相关文档,了解如何从其准入控制器中排除工作负载。

通过阻止其他 webhook 修改 Pod,您可以帮助确保这些 Pod 继续符合许可清单,并成功部署到 Autopilot 集群中。

关于特权工作负载和许可清单的 bug 和功能请求

合作伙伴负责创建、开发和维护其特权工作负载和许可名单。如果您遇到 bug 或想要提出关于特权工作负载或许可名单的功能请求,请与相应的合作伙伴联系。

后续步骤