创建遵从政策的 Google Cloud 资源


本教程介绍了平台管理员如何使用 Policy Controller 政策来控制如何使用 Config Connector 创建 Google Cloud 资源。

本教程中的说明假定您具备 KubernetesGoogle Kubernetes Engine (GKE) 的基础知识。在本教程中,您将定义一个政策,该政策限制 Cloud Storage 存储桶允许的位置。

政策控制器利用与安全、法规或业务规则相关的政策来检查、审核并强制执行 Kubernetes 集群资源合规性。政策控制器是从 OPA Gatekeeper 开源项目构建的。

Config Connector 通过将 Google Cloud 资源描述为 Kubernetes 自定义资源来创建并管理其生命周期。如需创建 Google Cloud 资源,您需要在配置连接器管理的命名空间中创建 Kubernetes 资源。以下示例展示了如何使用配置连接器来描述 Cloud Storage 存储桶:

apiVersion: storage.cnrm.cloud.google.com/v1beta1
kind: StorageBucket
metadata:
  name: my-bucket
spec:
  location: us-east1

通过使用 Config Connector 管理 Google Cloud 资源,您可以在 Google Kubernetes Engine (GKE) Enterprise 版本集群中创建这些资源时,将 Policy Controller 政策应用于这些资源。这些政策可让您阻止或举报以违反政策的方式创建或修改资源的操作。例如,您可以强制执行限制 Cloud Storage 存储桶位置的政策。

此方法基于 Kubernetes 资源模型 (KRM),可让您使用一组一致的工具和工作流来管理 Kubernetes 和 Google Cloud 资源。本教程演示了如何完成以下任务:

  • 定义用于管理 Google Cloud 资源的政策。
  • 实施控制措施,用于防止开发者和管理员创建违反政策的 Google Cloud 资源。
  • 实施控制措施,用于审核现有 Google Cloud 资源是否违反政策,即使您在配置连接器之外创建了这些资源,也是如此。
  • 在开发者和管理员创建和更新资源定义时,为其提供快速反馈。
  • 在尝试将定义应用于 Kubernetes 集群之前,根据政策验证 Google Cloud 资源定义。

目标

  • 创建包含 Config Connector 插件的 Google Kubernetes Engine (GKE) Enterprise 版本集群。
  • 安装政策控制器。
  • 创建政策以限制允许的 Cloud Storage 存储桶位置。
  • 验证政策是否会阻止在不允许的位置创建 Cloud Storage 存储桶。
  • 在开发过程中评估 Cloud Storage 存储桶定义的政策合规性。
  • 审核现有 Cloud Storage 存储桶,以满足政策合规性要求。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

准备工作

  1. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  2. 确保您的 Google Cloud 项目已启用结算功能

  3. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

  4. 在 Cloud Shell 中,设置要用于本教程的 Google Cloud 项目:

    gcloud config set project PROJECT_ID
    

    PROJECT_ID 替换为您的项目的 Google Cloud 项目 ID。运行此命令时,Cloud Shell 会创建一个名为 GOOGLE_CLOUD_PROJECT 的已导出环境变量,其中包含您的项目 ID。如果您不使用 Cloud Shell,可使用以下命令创建环境变量:

    export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value core/project)
    
  5. 启用 GKE API:

    gcloud services enable container.googleapis.com
    
  6. 创建一个目录,用于存储为本教程创建的文件:

    mkdir -p ~/cnrm-gatekeeper-tutorial
    
  7. 转到您创建的目录:

    cd ~/cnrm-gatekeeper-tutorial
    

创建 GKE 集群

  1. 在 Cloud Shell 中,使用配置连接器插件Workload Identity 创建 GKE 集群:

    gcloud container clusters create CLUSTER_NAME \
      --addons ConfigConnector \
      --enable-ip-alias \
      --num-nodes 4 \
      --release-channel regular \
      --scopes cloud-platform \
      --workload-pool $GOOGLE_CLOUD_PROJECT.svc.id.goog \
      --zone ZONE
    

    替换以下内容:

    • CLUSTER_NAME:您要用于此项目的集群的名称,例如 cnrm-gatekeeper-tutorial
    • ZONE:靠近您所在位置的 Compute Engine 可用区,例如 asia-southeast1-b

    配置连接器插件可为 GKE 集群中的 Google Cloud 资源安装自定义资源定义 (CRD)

  2. 可选:如果您在自己的环境中使用专用集群,请添加允许 GKE 集群控制平面连接到政策控制器网络钩子的防火墙规则:

    gcloud compute firewall-rules create allow-cluster-control-plane-tcp-8443 \
      --allow tcp:8443 \
      --network default \
      --source-ranges CONTROL_PLANE_CIDR \
      --target-tags NODE_TAG
    

    替换以下内容:

    • CONTROL_PLANE_CIDR:GKE 集群控制层面的 IP 地址范围,例如 172.16.0.16/28
    • NODE_TAG:应用于 GKE 集群中所有节点的标记。

    在集群使用专用节点时,政策控制器网络钩子需要此可选的防火墙规则。

设置 Config Connector

安装配置连接器的 Google Cloud 项目被称为宿主项目。使用 Config Connector 管理资源的项目称为托管项目。在本教程中,您将使用 Config Connector 在 GKE 集群所属的项目中创建 Google Cloud 资源,以便宿主项目和托管项目为同一项目。

  1. 在 Cloud Shell 中,为配置连接器创建 Google 服务账号

    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
      --display-name "Config Connector Gatekeeper tutorial"
    

    SERVICE_ACCOUNT_NAME 替换为您要用于此服务账号的名称,例如 cnrm-gatekeeper-tutorial。配置连接器使用此 Google 服务账号在您的代管式项目中创建资源。

  2. 向 Google 服务账号授予 Storage Admin 角色

    gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
      --member "serviceAccount:SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
      --role roles/storage.admin
    

    在本教程中,您将使用 Storage Admin 角色,因为您使用 Config Connector 创建 Cloud Storage 存储桶。在您自己的环境中,授予管理为 Config Connector 创建的 Google Cloud 资源所需的角色。如需详细了解预定义角色,请参阅 IAM 文档中的了解角色

  3. 为在本教程中创建的配置连接器资源创建 Kubernetes 命名空间:

    kubectl create namespace NAMESPACE
    

    NAMESPACE 替换为您要在本教程中使用的 Kubernetes 命名空间,例如 tutorial

  4. 为命名空间添加注释,以指定应使用哪个项目配置连接器来创建 Google Cloud 资源(代管式项目):

    kubectl annotate namespace NAMESPACE \
        cnrm.cloud.google.com/project-id=$GOOGLE_CLOUD_PROJECT
    
  5. 创建一个 ConfigConnectorContext 资源,用于为 Kubernetes 命名空间启用配置连接器,并将其与您创建的 Google 服务账号相关联:

    cat << EOF | kubectl apply -f -
    apiVersion: core.cnrm.cloud.google.com/v1beta1
    kind: ConfigConnectorContext
    metadata:
      name: configconnectorcontext.core.cnrm.cloud.google.com
      namespace: NAMESPACE
    spec:
      googleServiceAccount: SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    EOF
    

    创建 ConfigConnectorContext 资源时,配置连接器会在 cnrm-system 命名空间中创建 Kubernetes 服务账号StatefulSet,以管理命名空间中的配置连接器资源。

  6. 等待命名空间的 Config Connector 控制器 Pod:

    kubectl wait --namespace cnrm-system --for=condition=Ready pod \
      -l cnrm.cloud.google.com/component=cnrm-controller-manager,cnrm.cloud.google.com/scoped-namespace=NAMESPACE
    

    Pod 准备就绪后,系统会显示 Cloud Shell 提示符。 如果您收到 error: no matching resources found 消息,请稍等一下再重试。

  7. 通过创建 IAM 政策绑定,将您的配置连接器 Kubernetes 服务账号绑定到您的 Google 服务账号:

    gcloud iam service-accounts add-iam-policy-binding \
      SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
      --member "serviceAccount:$GOOGLE_CLOUD_PROJECT.svc.id.goog[cnrm-system/cnrm-controller-manager-NAMESPACE]" \
      --role roles/iam.workloadIdentityUser
    

    此绑定允许 cnrm-system 命名空间中的 cnrm-controller-manager-NAMESPACE Kubernetes 服务账号充当您创建的 Google 服务账号。

安装政策控制器

按照安装说明安装 Policy Controller。

使用 60 秒的审核间隔。

使用 Config Connector 创建 Google Cloud 资源

  1. 在 Cloud Shell 中,创建代表 us-central1 区域中的 Cloud Storage 存储桶的配置连接器清单:

    cat << EOF > tutorial-storagebucket-us-central1.yaml
    apiVersion: storage.cnrm.cloud.google.com/v1beta1
    kind: StorageBucket
    metadata:
      name: tutorial-us-central1-$GOOGLE_CLOUD_PROJECT
      namespace: NAMESPACE
    spec:
      location: us-central1
      uniformBucketLevelAccess: true
    EOF
    
  2. 如需创建 Cloud Storage 存储桶,请应用清单:

    kubectl apply -f tutorial-storagebucket-us-central1.yaml
    
  3. 验证配置连接器是否创建了 Cloud Storage 存储桶:

    gsutil ls | grep tutorial
    

    输出类似于以下内容:

    gs://tutorial-us-central1-PROJECT_ID/
    

    此输出包含 PROJECT_ID,即您的 Google Cloud 项目 ID。

    如果您没有看到此输出,请等待一分钟,然后重新执行步骤。

创建政策

政策控制器中的政策由限制条件模板限制条件组成。限制条件模板包含政策逻辑。该限制指定了政策适用的位置以及政策逻辑的输入参数。

  1. 在 Cloud Shell 中,创建限制 Cloud Storage 存储桶位置的限制条件模板:

    cat << EOF > tutorial-storagebucket-location-template.yaml
    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: gcpstoragelocationconstraintv1
    spec:
      crd:
        spec:
          names:
            kind: GCPStorageLocationConstraintV1
          validation:
            openAPIV3Schema:
              properties:
                locations:
                  type: array
                  items:
                    type: string
                exemptions:
                  type: array
                  items:
                    type: string
      targets:
      - target: admission.k8s.gatekeeper.sh
        rego: |
          package gcpstoragelocationconstraintv1
    
          allowedLocation(reviewLocation) {
              locations := input.parameters.locations
              satisfied := [ good | location = locations[_]
                                    good = lower(location) == lower(reviewLocation)]
              any(satisfied)
          }
    
          exempt(reviewName) {
              input.parameters.exemptions[_] == reviewName
          }
    
          violation[{"msg": msg}] {
              bucketName := input.review.object.metadata.name
              bucketLocation := input.review.object.spec.location
              not allowedLocation(bucketLocation)
              not exempt(bucketName)
              msg := sprintf("Cloud Storage bucket <%v> uses a disallowed location <%v>, allowed locations are %v", [bucketName, bucketLocation, input.parameters.locations])
          }
    
          violation[{"msg": msg}] {
              not input.parameters.locations
              bucketName := input.review.object.metadata.name
              msg := sprintf("No permitted locations provided in constraint for Cloud Storage bucket <%v>", [bucketName])
          }
    EOF
    
  2. 应用模板以创建 Cloud Storage 存储桶:

    kubectl apply -f tutorial-storagebucket-location-template.yaml
    
  3. 创建仅允许位于新加坡和雅加达区域的存储桶(asia-southeast1asia-southeast2)。该限制条件适用于您之前创建的命名空间。它会豁免 Cloud Build 的默认 Cloud Storage 存储桶。

    cat << EOF > tutorial-storagebucket-location-constraint.yaml
    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: GCPStorageLocationConstraintV1
    metadata:
      name: singapore-and-jakarta-only
    spec:
      enforcementAction: deny
      match:
        kinds:
        - apiGroups:
          - storage.cnrm.cloud.google.com
          kinds:
          - StorageBucket
        namespaces:
        - NAMESPACE
      parameters:
        locations:
        - asia-southeast1
        - asia-southeast2
        exemptions:
        - ${GOOGLE_CLOUD_PROJECT}_cloudbuild
    EOF
    
  4. 如需限制可以存在存储桶的可用区,请应用限制条件:

    kubectl apply -f tutorial-storagebucket-location-constraint.yaml
    

验证政策

  1. 在不允许的位置 (us-west1) 创建一个表示 Cloud Storage 存储桶的清单:

    cat << EOF > tutorial-storagebucket-us-west1.yaml
    apiVersion: storage.cnrm.cloud.google.com/v1beta1
    kind: StorageBucket
    metadata:
      name: tutorial-us-west1-$GOOGLE_CLOUD_PROJECT
      namespace: NAMESPACE
    spec:
      location: us-west1
      uniformBucketLevelAccess: true
    EOF
    
  2. 如需创建 Cloud Storage 存储桶,请应用清单:

    kubectl apply -f tutorial-storagebucket-us-west1.yaml
    

    输出类似于以下内容:

    Error from server ([singapore-and-jakarta-only] Cloud Storage bucket
    <tutorial-us-west1-PROJECT_ID> uses a disallowed location
    <us-west1>, allowed locations are ["asia-southeast1",
    "asia-southeast2"]): error when creating
    "tutorial-storagebucket-us-west1.yaml": admission webhook
    "validation.gatekeeper.sh" denied the request: [singapore-and-jakarta-only]
    Cloud Storage bucket <tutorial-us-west1-PROJECT_ID> uses a
    disallowed location <us-west1>, allowed locations are
    ["asia-southeast1", "asia-southeast2"]
    
  3. 可选:您可以在 Cloud Audit Logs 中查看拒绝请求的记录。查询项目的管理员活动日志:

    gcloud logging read --limit=1 \
        "logName=\"projects/$GOOGLE_CLOUD_PROJECT/logs/cloudaudit.googleapis.com%2Factivity\""'
        resource.type="k8s_cluster"
        resource.labels.cluster_name="CLUSTER_NAME"
        resource.labels.location="ZONE"
        protoPayload.authenticationInfo.principalEmail!~"system:serviceaccount:cnrm-system:.*"
        protoPayload.methodName:"com.google.cloud.cnrm."
        protoPayload.status.code=7'
    

    输出类似于以下内容:

    insertId: 3c6940bb-de14-4d18-ac4d-9a6becc70828
    labels:
      authorization.k8s.io/decision: allow
      authorization.k8s.io/reason: ''
      mutation.webhook.admission.k8s.io/round_0_index_0: '{"configuration":"mutating-webhook.cnrm.cloud.google.com","webhook":"container-annotation-handler.cnrm.cloud.google.com","mutated":true}'
      mutation.webhook.admission.k8s.io/round_0_index_1: '{"configuration":"mutating-webhook.cnrm.cloud.google.com","webhook":"management-conflict-annotation-defaulter.cnrm.cloud.google.com","mutated":true}'
    logName: projects/PROJECT_ID/logs/cloudaudit.googleapis.com%2Factivity
    operation:
      first: true
      id: 3c6940bb-de14-4d18-ac4d-9a6becc70828
      last: true
      producer: k8s.io
    protoPayload:
      '@type': type.googleapis.com/google.cloud.audit.AuditLog
      authenticationInfo:
        principalEmail: user@example.com
      authorizationInfo:
      - permission: com.google.cloud.cnrm.storage.v1beta1.storagebuckets.create
        resource: storage.cnrm.cloud.google.com/v1beta1/namespaces/NAMESPACE/storagebuckets/tutorial-us-west1-PROJECT_ID
      methodName: com.google.cloud.cnrm.storage.v1beta1.storagebuckets.create
      requestMetadata:
        callerIp: 203.0.113.1
        callerSuppliedUserAgent: kubectl/v1.21.1 (linux/amd64) kubernetes/5e58841
      resourceName: storage.cnrm.cloud.google.com/v1beta1/namespaces/NAMESPACE/storagebuckets/tutorial-us-west1-PROJECT_ID
      serviceName: k8s.io
      status:
        code: 7
        message: Forbidden
    receiveTimestamp: '2021-05-21T06:56:24.940264678Z'
    resource:
      labels:
        cluster_name: CLUSTER_NAME
        location: CLUSTER_ZONE
        project_id: PROJECT_ID
      type: k8s_cluster
    timestamp: '2021-05-21T06:56:09.060635Z'
    

    methodName 字段显示尝试执行的操作,resourceName 显示 Config Connector 资源的完整名称,status 部分显示请求失败,错误代码7,消息为 Forbidden

  4. 在允许的位置创建一个表示 Cloud Storage 存储桶的清单 (asia-southeast1):

    cat << EOF > tutorial-storagebucket-asia-southeast1.yaml
    apiVersion: storage.cnrm.cloud.google.com/v1beta1
    kind: StorageBucket
    metadata:
      name: tutorial-asia-southeast1-$GOOGLE_CLOUD_PROJECT
      namespace: NAMESPACE
    spec:
      location: asia-southeast1
      uniformBucketLevelAccess: true
    EOF
    
  5. 如需创建 Cloud Storage 存储桶,请应用清单:

    kubectl apply -f tutorial-storagebucket-asia-southeast1.yaml
    

    输出类似于以下内容:

    storagebucket.storage.cnrm.cloud.google.com/tutorial-asia-southeast1-PROJECT_ID created
    

    此输出包含 PROJECT_ID,即您的 Google Cloud 项目 ID。

  6. 检查配置连接器是否创建了 Cloud Storage 存储桶:

    gsutil ls | grep tutorial
    

    输出类似于以下内容:

    gs://tutorial-asia-southeast1-PROJECT_ID/
    gs://tutorial-us-central1-PROJECT_ID/
    

    如果您没有看到此输出,请等待一分钟,然后重新执行此步骤。

审核限制条件

政策控制器中的审核控制器会根据资源的限制条件定期评估资源。控制器会检测在限制条件之前创建的资源以及在配置连接器外部创建的资源违反政策的情况。

  1. 在 Cloud Shell 中,查看使用 GCPStorageLocationConstraintV1 限制条件模板的所有限制条件的违反情况:

    kubectl get gcpstoragelocationconstraintv1 -o json \
      | jq '.items[].status.violations'
    

    输出类似于以下内容:

    [
      {
        "enforcementAction": "deny",
        "kind": "StorageBucket",
        "message": "Cloud Storage bucket <tutorial-us-central1-PROJECT_ID>
        uses a disallowed location <us-central1>, allowed locations are
        \"asia-southeast1\", \"asia-southeast2\"",
        "name": "tutorial-us-central1-PROJECT_ID",
        "namespace": "NAMESPACE"
      }
    ]
    

    您会看到自己在创建限制条件之前在 us-central1 中创建的 Cloud Storage 存储桶。

在开发期间验证资源

在开发和持续集成 build 中,您可以先针对资源验证资源,然后再将这些资源应用于您的 GKE 集群。通过验证功能,您可以快速提供反馈,并尽早发现资源和限制条件的问题。这些步骤介绍了如何使用 kpt 验证资源。kpt 命令行工具允许您管理和应用 Kubernetes 资源清单。

  1. 在 Cloud Shell 中,使用 kpt 运行 gatekeeperKRM 函数

    kpt fn eval . --image=gcr.io/kpt-fn/gatekeeper:v0.2 --truncate-output=false
    

    KRM 函数是一个程序,可以更改或验证存储在本地文件系统上的 Kubernetes 资源,并将其存储为 YAML 文件。gatekeeper KRM 函数根据 Gatekeeper 政策验证 Config Connector Cloud Storage 存储桶资源。gatekeeper KRM 函数打包为 Artifact Registry 中提供的容器映像。

    该函数报告 us-central1us-west1 区域中 Cloud Storage 存储桶的清单文件违反了限制条件。

    输出类似于以下内容:

    [RUNNING] "gcr.io/kpt-fn/gatekeeper:v0.2"
    [FAIL] "gcr.io/kpt-fn/gatekeeper:v0.2"
      Results:
        [ERROR] Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are ["asia-southeast1", "asia-southeast2"] violatedConstraint: singapore-and-jakarta-only in object "storage.cnrm.cloud.google.com/v1beta1/StorageBucket/tutorial/tutorial-us-central1-GOOGLE_CLOUD_PROJECT" in file "tutorial-storagebucket-us-central1.yaml"
        [ERROR] Cloud Storage bucket <tutorial-us-west1-PROJECT_ID> uses a disallowed location <us-west1>, allowed locations are ["asia-southeast1", "asia-southeast2"] violatedConstraint: singapore-and-jakarta-only in object "storage.cnrm.cloud.google.com/v1beta1/StorageBucket/tutorial/tutorial-us-west1-GOOGLE_CLOUD_PROJECT" in file "tutorial-storagebucket-us-west1.yaml"
      Stderr:
        "[error] storage.cnrm.cloud.google.com/v1beta1/StorageBucket/test/tutorial-us-central1-PROJECT_ID : Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are [\"asia-southeast1\", \"asia-southeast2\"]"
        "violatedConstraint: singapore-and-jakarta-only"
        ""
        "[error] storage.cnrm.cloud.google.com/v1beta1/StorageBucket/test/tutorial-us-west1-PROJECT_IDT : Cloud Storage bucket <tutorial-us-west1-PROJECT_IDgt; uses a disallowed location <us-west1>, allowed locations are [\"asia-southeast1\", \"asia-southeast2\"]"
        "violatedConstraint: singapore-and-jakarta-only"
        ""
      Exit code: 1
    

验证在 Config Connector 外部创建的资源

您可以通过导出资源来验证在配置连接器外部创建的 Google Cloud 资源。导出资源后,您可以使用以下任一选项,根据导出的资源评估政策控制器政策:

  • 使用 gatekeeper KRM 函数验证资源。

  • 将资源导入配置连接器。

如需导出资源,请使用 Cloud Asset Inventory

  1. 在 Cloud Shell 中,启用 Cloud Asset API:

    gcloud services enable cloudasset.googleapis.com
    
  2. 删除 us-central1us-west1 中 Cloud Storage 存储桶的 Kubernetes 资源清单文件:

    rm tutorial-storagebucket-us-*.yaml
    
  3. 导出当前项目中的所有 Cloud Storage 资源,并将输出存储在名为 export.yaml 的文件中:

    gcloud beta resource-config bulk-export \
      --project $GOOGLE_CLOUD_PROJECT \
      --resource-format krm \
      --resource-types StorageBucket > export.yaml
    

    输出类似于以下内容:

    Exporting resource configurations to stdout...
    
    Export complete.
    
  4. 通过将 KRM 函数链接在一起创建 kpt 流水线。此流水线根据 Cloud Storage 存储桶位置政策验证当前目录中的资源:

    kpt fn source . \
      | kpt fn eval - --image=gcr.io/kpt-fn/set-namespace:v0.1 -- namespace=NAMESPACE \
      | kpt fn eval - --image=gcr.io/kpt-fn/gatekeeper:v0.2 --truncate-output=false
    

    导出的资源没有 namespace 属性的值。此流水线使用名为 set-namespace 的 KRM 函数来设置所有资源的 namespace 值。

    输出内容类似如下,并且会显示您导出的资源存在的违规问题:

    [RUNNING] "gcr.io/kpt-fn/set-namespace:v0.1"
    [PASS] "gcr.io/kpt-fn/set-namespace:v0.1"
    [RUNNING] "gcr.io/kpt-fn/gatekeeper:v0.2"
    [FAIL] "gcr.io/kpt-fn/gatekeeper:v0.2"
      Results:
        [ERROR] Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are ["asia-southeast1", "asia-southeast2"] violatedConstraint: singapore-and-jakarta-only in object "storage.cnrm.cloud.google.com/v1beta1/StorageBucket/tutorial/tutorial-us-central1-GOOGLE_CLOUD_PROJECT" in file "export.yaml"
      Stderr:
        "[error] storage.cnrm.cloud.google.com/v1beta1/StorageBucket/test/tutorial-us-central1-PROJECT_ID : Cloud Storage bucket <tutorial-us-central1-PROJECT_ID> uses a disallowed location <us-central1>, allowed locations are [\"asia-southeast1\", \"asia-southeast2\"]"
        "violatedConstraint: singapore-and-jakarta-only"
        ""
      Exit code: 1
    

    如果 Google Cloud 项目包含您在学习本教程之前创建的 Cloud Storage 存储桶,并且其位置违反了限制条件,则输出中会显示之前创建的存储桶。

恭喜,您已成功设置一项政策来规定 Cloud Storage 存储桶允许的位置。本教程已完成。您现在可以继续为其他 Google Cloud 资源添加您自己的政策。

问题排查

如果 Config Connector 未创建预期的 Google Cloud 资源,请在 Cloud Shell 中使用以下命令来查看 Config Connector 的控制器管理器的日志:

kubectl logs --namespace cnrm-system --container manager \
  --selector cnrm.cloud.google.com/component=cnrm-controller-manager,cnrm.cloud.google.com/scoped-namespace=NAMESPACE

如果政策控制器无法正确强制执行政策,请使用以下命令查看控制器管理器的日志:

kubectl logs deployment/gatekeeper-controller-manager \
  --namespace gatekeeper-system

如果政策控制器未在限制条件对象的 status 字段中报告违规行为,请使用以下命令查看审核控制器的日志:

kubectl logs deployment/gatekeeper-audit --namespace gatekeeper-system

如果您在使用本教程时遇到其他问题,我们建议您查看以下文档:

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

  1. 在 Google Cloud 控制台中,进入管理资源页面。

    转到“管理资源”

  2. 如果您打算删除的项目已附加到某个组织,请展开名称列中的组织列表。
  3. 在项目列表中,选择要删除的项目,然后点击删除
  4. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除资源

如果您希望保留在本教程中使用的 Google Cloud 项目,请删除单个资源。

  1. 在 Cloud Shell 中,删除 Cloud Storage 存储桶位置限制条件:

    kubectl delete -f tutorial-storagebucket-location-constraint.yaml
    
  2. 将字符串值为 truecnrm.cloud.google.com/force-destroy 注解添加到由配置连接器管理的命名空间中的所有 storagebucket 资源:

    kubectl annotate storagebucket --all --namespace NAMESPACE \
      cnrm.cloud.google.com/force-destroy=true
    

    该注解是一条指令,可让配置连接器在您删除 GKE 集群中的相应 storagebucket 资源时删除 Cloud Storage 存储桶,即使该存储桶包含对象也是如此

  3. 删除代表 Cloud Storage 存储桶的 Config Connector 资源:

    kubectl delete --namespace NAMESPACE storagebucket --all
    
  4. 删除 GKE 集群:

    gcloud container clusters delete CLUSTER_NAME \
      --zone ZONE --async --quiet
    
  5. 删除 IAM 中的 Workload Identity 政策绑定:

    gcloud iam service-accounts remove-iam-policy-binding \
      SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
      --member "serviceAccount:$GOOGLE_CLOUD_PROJECT.svc.id.goog[cnrm-system/cnrm-controller-manager-NAMESPACE]" \
      --role roles/iam.workloadIdentityUser
    
  6. 删除 Google 服务账号的 Cloud Storage Admin 角色绑定:

    gcloud projects remove-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
      --member "serviceAccount:SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" \
      --role roles/storage.admin
    
  7. 删除您为配置连接器创建的 Google 服务账号:

    gcloud iam service-accounts delete --quiet \
      SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    

后续步骤