为 GKE 专用集群配置受限访问权限

本文档介绍了如何在 VPC Service Controls 服务边界中使用 Google Kubernetes Engine 专用集群时,配置 DNS 条目以使用受限虚拟 IP (VIP) 将请求路由到 pkg.devgcr.io 网域。

注册表网域通常解析为互联网上的公共 IP 地址。在 GKE 专用集群中,节点默认与互联网隔离。这意味着,如果您未将 DNS 路由配置为受限 VIP,则对注册表网域的请求将失败。

您的专用集群应始终使用受限 VIP 访问 Artifact Registry 或 Container Registry,以防止数据从受支持的服务渗漏到不受支持的服务。

当满足以下所有条件时,为 GKE 专用集群配置受限访问权限:

  • 您使用的是 GKE 专用集群。
  • 您尚未将 pkg.devgcr.io 注册表网域的路由配置为 restricted.googleapis.com

准备工作

在创建服务边界之前,请设置新的专用集群或标识要保护的现有专用集群。

此外,您必须允许通过端口 443 向 199.36.153.4/30 发送出站流量。通常,VPC 网络具有一条隐式规则允许将所有出站流量发送到任何目标。但是,如果您有拒绝此类流量的规则,则必须创建出站防火墙规则,以允许端口 443 上的 TCP 流量发送到 199.36.153.4/30。

配置 DNS

配置 DNS 服务器,以便将发送到注册表地址的请求解析为 restricted.googleapis.com(即受限 VIP)。您可以使用 Cloud DNS 专用 DNS 区域执行此操作。

  1. 创建专用代管区域。

    gcloud dns managed-zones create ZONE_NAME \
        --visibility=private \
        --networks=https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/NETWORK \
        --description=DESCRIPTION \
        --dns-name=REGISTRY_DOMAIN \
        --project=PROJECT_ID
    

    其中:

    • ZONE_NAME 是您要创建的区域的名称。例如,registry。此名称将在 以下每个步骤中使用。
    • PROJECT_ID 是托管 GKE 专用集群的项目的 ID。
    • NETWORK 是您要从中重定向请求的 集群网络名称的可选列表。
    • DESCRIPTION 是代管式可用区的直观易懂的说明 。
    • REGISTRY_DOMAIN 是注册表的网域:
      • pkg.dev(对于 Artifact Registry)
      • gcr.io(对于 Container Registry 或托管在 Artifact Registry 中的 gcr.io 代码库)
  2. 启动一项事务。

    gcloud dns record-sets transaction start \
      --zone=ZONE_NAME \
      --project=PROJECT_ID
    

    其中:

    • ZONE_NAME 是您在第一步中创建的区域的名称。

    • PROJECT_ID 是托管 GKE 专用集群的项目的 ID。

  3. 为注册表添加 CNAME 记录。

    gcloud dns record-sets transaction add \
      --name=*.REGISTRY_DOMAIN. \
      --type=CNAME REGISTRY_DOMAIN. \
      --zone=ZONE_NAME \
      --ttl=300 \
      --project=PROJECT_ID
    

    其中:

    • ZONE_NAME 是您在第一步中创建的区域的名称。
    • PROJECT_ID 是托管 GKE 专用集群的项目的 ID。
    • REGISTRY_DOMAIN 是注册表的网域:
      • pkg.dev(对于 Artifact Registry)
      • gcr.io(对于 Container Registry 或托管在 Artifact Registry 中的 gcr.io 代码库)
  4. 为受限 VIP 提供 A 记录。

    gcloud dns record-sets transaction add \
      --name=REGISTRY_DOMAIN. \
      --type=A 199.36.153.4 199.36.153.5 199.36.153.6 199.36.153.7 \
      --zone=ZONE_NAME \
      --ttl=300 \
      --project=PROJECT_ID
    

    其中:

    • ZONE_NAME 是您在第一步中创建的区域的名称。
    • PROJECT_ID 是托管 GKE 专用集群的项目的 ID。
    • REGISTRY_DOMAIN 是注册表的网域:
      • pkg.dev(对于 Artifact Registry)
      • gcr.io(对于 Container Registry 或托管在 Artifact Registry 中的 gcr.io 代码库)
  5. 执行事务。

    gcloud dns record-sets transaction execute \
      --zone=ZONE_NAME \
      --project=PROJECT_ID
    

    其中:

    • ZONE_NAME 是您在第一步中创建的区域的名称。

    • PROJECT_ID 是托管 GKE 专用集群的项目的 ID。

配置 DNS 路由后,请确保您的 GKE、注册表和其他必需服务位于 VPC Service Controls 服务边界内。如需配置服务边界,请参阅以下部分。

配置服务边界

配置 DNS 记录 后,请执行以下操作:

  1. 创建新的服务边界更新现有边界
  2. 将 Container Registry 或 Artifact Registry 服务添加到要使用服务边界保护的服务列表中 。
  3. 将存储库使用的其他受支持的服务(例如 Cloud Build、Artifact Analysis 和 Binary Authorization)添加到服务边界。
  4. 如果您需要访问 Container Registry,则还必须将 Cloud Storage 添加到服务边界。

验证边界是否有效

配置服务边界后,如果映像存储在服务边界内的项目中,则 GKE 专用集群中的节点可以访问 Artifact Registry 和 Container Registry 中的容器映像。

边界外的项目中的容器映像仍然无法访问,但 一些特定的只读公共代码库除外。

例如,如果 google-samples 项目不在您的服务边界内,则运行以下命令以从 hello-app 容器创建部署将失败:

pkg.dev 网域

kubectl create deployment hello-server --image=us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

gcr.io 网域

kubectl create deployment hello-server --image=gcr.io/google-samples/hello-app:1.0

使用以下命令检查 pod 的状态:

kubectl get pods

该命令会返回如下例所示的表。pod 状态 ErrImagePull 表示拉取失败。

NAME                            READY   STATUS         RESTARTS   AGE
hello-server-dbd86c8c4-h5wsf    1/1     ErrImagePull   0          45s

您可以使用 kubectl describe pod 命令查看有关部署的更多详细信息。对于上例中的 pod,命令如下:

kubectl describe pod hello-server-dbd86c8c4-h5wsf