建立符合政策規定的 Google Cloud 資源


本教學課程說明平台管理員如何使用 Policy Controller 政策,控管如何使用 Config Connector 建立 Google Cloud 資源。

如果您是 IT 管理員和作業人員,希望確保雲端平台中執行的所有資源都符合機構的法規遵循規定,並提供及維護自動化功能來稽核或強制執行規定,以及管理基礎技術架構的生命週期,歡迎參閱這個頁面。如要進一步瞭解我們在Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE Enterprise 使用者角色和工作」。

本教學課程的指示假設您具備 KubernetesGoogle Kubernetes Engine (GKE) 的基本知識。在本教學課程中,您會定義一項政策,限制 Cloud Storage 值區的允許位置。

Policy Controller 會檢查、稽核 Kubernetes 叢集資源,並強制執行與安全性、法規或商業規則相關的政策,確保資源符合規定。Policy Controller 是以 OPA Gatekeeper 開放原始碼專案為基礎建構而成。

Config Connector 會將Google Cloud 資源描述為 Kubernetes 自訂資源,藉此建立及管理資源的生命週期。如要建立 Google Cloud 資源,請在 Config Connector 管理的命名空間中建立 Kubernetes 資源。以下範例說明如何使用 Config Connector 描述 Cloud Storage 值區:

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

使用 Config Connector 管理資源時,您可以在 Google Kubernetes Engine (GKE) Enterprise 版叢集中建立資源,並對這些資源套用 Policy Controller 政策。 Google Cloud 您可以透過這些政策,防止或回報以違反政策的方式建立或修改資源的動作。舉例來說,您可以強制執行政策,限制 Cloud Storage 值區的位置。

這個方法是以 Kubernetes 資源模型 (KRM) 為基礎,可讓您使用一致的工具和工作流程,管理 Kubernetes 和 Google Cloud 資源。本教學課程將示範如何完成下列工作:

  • 定義管理 Google Cloud 資源的政策。
  • 實作控管措施,禁止開發人員和管理員建立違反政策的 Google Cloud 資源。
  • 導入控制項,根據政策稽核現有 Google Cloud 資源,即使您是在 Config Connector 外部建立這些資源也沒問題。
  • 在開發人員和管理員建立及更新資源定義時,快速提供意見回饋。
  • 先根據政策驗證 Google Cloud 資源定義,再嘗試將定義套用至 Kubernetes 叢集。

目標

  • 建立包含 Config Connector 外掛程式的 Google Kubernetes Engine (GKE) Enterprise 版叢集。
  • 安裝 Policy Controller。
  • 建立政策,限制允許的 Cloud Storage 值區位置。
  • 確認政策可防止在未獲允許的位置建立 Cloud Storage 值區。
  • 在開發期間評估 Cloud Storage 值區定義的政策合規性。
  • 稽核現有的 Cloud Storage bucket,確保符合政策規定。

費用

在本文件中,您會使用 Google Cloud的下列計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

初次使用 Google Cloud 的使用者可能符合免費試用資格。

事前準備

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. In the Google Cloud console, activate Cloud Shell.

    Activate 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. 啟用 Policy Controller API:

    gcloud services enable anthospolicycontroller.googleapis.com
    
  7. 建立目錄來儲存本教學課程建立的檔案:

    mkdir -p ~/cnrm-gatekeeper-tutorial
    
  8. 前往您建立的目錄:

    cd ~/cnrm-gatekeeper-tutorial
    

建立 GKE 叢集

  1. 在 Cloud Shell 中,使用 Config Connector 外掛程式Workload Identity Federation for GKE 建立 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

    Config Connector 外掛程式會在 GKE 叢集中安裝自訂資源定義 (CRD),以供Google Cloud 資源使用。

  2. 選用:如果您在自己的環境中使用私人叢集,請新增防火牆規則,允許 GKE 叢集控制層連線至 Policy Controller Webhook:

    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 叢集中所有節點的標記。

    如果叢集使用私人節點,則必須設定這項選用的防火牆規則,Policy Controller Webhook 才能正常運作。

設定 Config Connector

Google Cloud 安裝設定連接器的專案稱為主專案。您使用 Config Connector 管理資源的專案稱為「受管理專案」。在本教學課程中,您會使用 Config Connector 在與 GKE 叢集相同的專案中建立Google Cloud 資源,因此主專案和代管專案是同一個專案。

  1. 在 Cloud Shell 中,為 Config Connector 建立 Google 服務帳戶

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

    請將 SERVICE_ACCOUNT_NAME 替換為想要用於這個服務帳戶的名稱,例如 cnrm-gatekeeper-tutorial。Config Connector 會使用這個 Google 服務帳戶,在受管理專案中建立資源。

  2. 儲存空間管理員角色授予 Google 服務帳戶:

    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 bucket。在您自己的環境中,授予管理要為「設定連接器」建立的 Google Cloud 資源所需的角色。如要進一步瞭解預先定義的角色,請參閱 IAM 說明文件中的「瞭解角色」。

  3. 為本教學課程中建立的 Config Connector 資源建立 Kubernetes 命名空間:

    kubectl create namespace NAMESPACE
    

    NAMESPACE 替換為您要在本教學課程中使用的 Kubernetes 命名空間,例如 tutorial

  4. 為命名空間加上註解,指定 Config Connector 應使用哪個專案建立 Google Cloud 資源 (受管理專案):

    kubectl annotate namespace NAMESPACE \
        cnrm.cloud.google.com/project-id=$GOOGLE_CLOUD_PROJECT
    
  5. 建立 ConfigConnectorContext 資源,為 Kubernetes 命名空間啟用 Config Connector,並將其與您建立的 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 資源時,Config Connector 會在 cnrm-system 命名空間中建立 Kubernetes 服務帳戶StatefulSet,以便管理命名空間中的 Config Connector 資源。

  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 政策繫結,將 Config Connector 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

請按照安裝說明安裝 Policy Controller。

使用 60 秒的稽核間隔。

使用 Config Connector 建立 Google Cloud 資源

  1. 在 Cloud Shell 中,建立代表 us-central1 區域中 Cloud Storage 值區的 Config Connector 資訊清單:

    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 bucket,請套用資訊清單:

    kubectl apply -f tutorial-storagebucket-us-central1.yaml
    
  3. 確認 Config Connector 已建立 Cloud Storage bucket:

    gcloud storage ls | grep tutorial
    

    輸出結果會與下列內容相似:

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

    這項輸出內容包含 PROJECT_ID,也就是您的 Google Cloud 專案 ID。

    如果沒有看到這項輸出內容,請稍後再重新執行上述步驟。

建立政策

Policy Controller 中的政策由限制範本限制組成。限制範本包含政策邏輯。限制條件會指定政策的適用位置,以及政策邏輯的輸入參數。

  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 bucket:

    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. 建立資訊清單,代表位於不允許位置的 Cloud Storage bucket (us-west1):

    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 bucket,請套用資訊清單:

    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 稽核記錄中查看拒絕要求的決定記錄。查詢專案的管理員活動記錄:

    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. 建立資訊清單,代表許可位置 (asia-southeast1) 中的 Cloud Storage bucket:

    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 bucket,請套用資訊清單:

    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. 確認 Config Connector 已建立 Cloud Storage bucket:

    gcloud storage ls | grep tutorial
    

    輸出結果會與下列內容相似:

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

    如果沒有看到這項輸出內容,請稍後再重新執行這個步驟。

稽核限制

Policy Controller 中的稽核控制器會定期評估資源是否符合限制。對於在限制條件之前建立的資源,以及在 Config Connector 外部建立的資源,控制器會偵測政策違規情形。

  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 bucket。

在開發期間驗證資源

在開發和持續整合建構期間,建議您先根據限制條件驗證資源,再將這些資源套用至 GKE 叢集。驗證功能可快速提供意見回饋,讓您及早發現資源和限制的問題。下列步驟說明如何使用 kpt 驗證資源。您可以使用 kpt 指令列工具管理及套用 Kubernetes 資源資訊清單。

  1. 在 Cloud Shell 中,使用 kpt 執行 gatekeeper KRM 函式

    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 在 Config Connector 外部建立的資源。匯出資源後,請使用下列任一選項,根據匯出的資源評估 Policy Controller 政策:

  • 使用 gatekeeper KRM 函式驗證資源。

  • 將資源匯入 Config Connector。

如要匯出資源,請使用 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 bucket,且這些 bucket 的位置違反限制,則先前建立的 bucket 會顯示在輸出內容中。

恭喜,您已成功設定政策,控管 Cloud Storage bucket 的允許位置。教學課程已完成。 現在可以繼續為其他 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

如果 Policy Controller 未正確強制執行政策,請使用下列指令查看控制器管理員的記錄:

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

如果 Policy Controller 未在限制物件的 status 欄位中回報違規事項,請使用下列指令查看稽核控制器記錄:

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

如果您在本教學課程中遇到其他問題,建議查看下列文件:

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程中所用資源的相關費用,請刪除含有該項資源的專案,或者保留專案但刪除個別資源。

刪除專案

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. If the project that you plan to delete is attached to an organization, expand the Organization list in the Name column.
  3. In the project list, select the project that you want to delete, and then click Delete.
  4. In the dialog, type the project ID, and then click Shut down to delete the project.

刪除資源

如要保留您在本教學課程中使用的 Google Cloud 專案,請刪除個別資源。

  1. 在 Cloud Shell 中,刪除 Cloud Storage bucket 位置限制:

    kubectl delete -f tutorial-storagebucket-location-constraint.yaml
    
  2. 在 Config Connector 管理的命名空間中,為所有 storagebucket 資源新增 cnrm.cloud.google.com/force-destroy 註解,並將字串值設為 true

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

    這個註解是指令,可讓 Config Connector 在您刪除 GKE 叢集中的對應 storagebucket 資源時,一併刪除 Cloud Storage 值區,即使值區含有物件也沒問題

  3. 刪除代表 Cloud Storage bucket 的 Config Connector 資源:

    kubectl delete --namespace NAMESPACE storagebucket --all
    
  4. 刪除 GKE 叢集:

    gcloud container clusters delete CLUSTER_NAME \
      --zone ZONE --async --quiet
    
  5. 在 IAM 中刪除工作負載身分政策繫結:

    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 管理員角色繫結:

    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. 刪除為 Config Connector 建立的 Google 服務帳戶:

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

後續步驟