保护集群元数据


Google Kubernetes Engine (GKE) 使用实例元数据配置节点虚拟机 (VM),但此元数据的一部分可能比较敏感,应该受到保护,以免受到集群上运行的工作负载的影响

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。

配置节点服务账号

每个节点的服务账号凭据将继续向工作负载公开。默认情况下,您的节点使用 Compute Engine 默认服务账号。您应该配置具有最低权限的服务账号,供节点而不是 Compute Engine 默认服务账号使用。然后,将此服务账号附加到节点,这样攻击者就无法通过使用 Compute Engine API 直接访问底层虚拟机实例来绕开 GKE 的元数据保护。

如需了解详情,请参阅使用最小权限节点服务账号

如需创建最小权限节点服务账号,请执行以下步骤:

  1. 创建新的 Identity and Access Management (IAM) 服务账号并将电子邮件地址保存在环境变量中:

    gcloud iam service-accounts create NODE_SA_NAME \
        --display-name="DISPLAY_NAME"
    export NODE_SA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \
        --filter='displayName:DISPLAY_NAME')
    

    替换以下内容:

    • NODE_SA_NAME:新节点服务账号的名称。
    • DISPLAY_NAME:新服务账号的显示名称。

    节点服务账号电子邮件地址的格式为 NODE_SA_NAME@PROJECT_ID.iam.gserviceaccount.com

  2. 为您的服务账号配置运行 GKE 节点所需的最小角色和权限:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:$NODE_SA_EMAIL \
        --role=roles/monitoring.metricWriter
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:$NODE_SA_EMAIL \
        --role=roles/monitoring.viewer
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:$NODE_SA_EMAIL \
        --role=roles/logging.logWriter
    

    PROJECT_ID 替换为您的 Google Cloud 项目 ID。

    此外,如果您的集群从 Artifact Registry 中拉取私有映像,请添加 roles/artifactregistry.reader 角色:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:$NODE_SA_EMAIL \
        --role=roles/artifactregistry.reader
    

元数据隐藏

GKE 元数据隐藏可保护一些潜在的敏感系统元数据免受集群上运行的用户工作负载的影响。

您可以启用元数据隐藏,以防止用户 Pod 访问集群节点中的某些虚拟机元数据,例如 kubelet 凭据和虚拟机实例信息。具体而言,元数据隐藏可为 kube-env(包含 Kubelet 凭据)和虚拟机的实例身份令牌提供访问保护。

元数据隐藏使用防火墙阻隔从用户 Pod(未在 HostNetwork 上运行的 Pod)到集群元数据服务器的流量,仅允许安全查询。防火墙阻止用户 Pod 使用 kubelet 凭据进行提升权限攻击,或使用虚拟机身份进行实例升级攻击。

您只能在创建新集群或在向现有集群添加新节点池时启用元数据隐藏。

限制

  • 元数据隐藏只能为 kube-env 和节点的实例身份令牌提供访问保护。
  • 元数据隐藏不限制对节点服务账号的访问。
  • 元数据隐藏不限制对其他相关实例元数据的访问。
  • 元数据隐藏不限制对其他旧版元数据 API 的访问。
  • 元数据隐藏不限制来自主机网络(Pod 规范中的 hostNetwork: true)上运行的 Pod 的流量。

创建带元数据隐藏的新集群或节点池

创建服务账号后,您可以使用 Google Cloud CLI 创建新的集群或节点池,并启用元数据隐藏。

创建新集群

如需在创建集群的同时启用元数据隐藏,请运行以下命令:

gcloud beta container clusters create CLUSTER_NAME \
  --workload-metadata-from-node=SECURE \
  --service-account=$NODE_SA_EMAIL

CLUSTER_NAME 替换为新集群的名称。

--workload-metadata-from-node 标志采用以下值:

  • SECURE:启用元数据隐藏。
  • EXPOSEDUNSPECIFIED:停用元数据隐藏。

创建新的节点池

如需创建启用元数据隐藏的节点池,请运行以下命令:

gcloud beta container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --workload-metadata-from-node=SECURE \
  --service-account=$NODE_SA_EMAIL

NODE_POOL_NAME 替换为新节点池的名称。

验证集群工作负载中已隐藏身份令牌元数据

元数据隐藏后,应该无法通过节点的实例身份令牌请求签名。如需验证请求是否会将隐藏的元数据明确告知用户,请执行以下操作:

  1. 在新 Pod 中打开一个 shell 会话:

    kubectl run metadata-concealment -it --image=google/cloud-sdk:slim -- /bin/bash
    
  2. 在此 Pod 中,尝试获取隐藏的端点:

    curl -H "Metadata-Flavor: Google" \
    'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://www.example.com'
    

    输出内容类似如下:

    This metadata endpoint is concealed.
    

停用旧版元数据 API 并从其转换到新版

v0.1v1beta1 Compute Engine 元数据服务器端点已被弃用,并已于 2020 年 9 月 30 日关停。

如需了解关停时间表,请参阅 v0.1v1beta1 元数据服务器端点弃用

后续步骤