將密鑰同步至 Kubernetes Secret

本文說明如何將 Secret Manager 中儲存的密鑰,同步至 Google Kubernetes Engine (GKE) 叢集內的 Kubernetes Secret。

透過同步程序,在 GKE 上執行的應用程式就能使用標準 Kubernetes 方法 (例如環境變數或磁碟區掛接) 存取 Secret Manager 中的密鑰。如果應用程式已設計為從 Kubernetes Secret 物件讀取密鑰,而非必須更新才能直接存取 Secret Manager,這項功能就非常實用。

建議:密鑰同步功能是 Secret Manager 外掛程式的替代方案,可將密鑰以記憶體內檔案的形式直接掛接至 Pod。只要應用程式支援,請一律使用 Secret Manager 外掛程式,因為這是從 GKE 的 Secret Manager 存取密鑰時,更安全的方法。

事前準備

同步處理密鑰前,請先完成下列先決條件:

  • Enable the Secret Manager and Google Kubernetes Engine APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  • 安裝初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令來取得最新版本。

  • 確認您已啟動 GKE 叢集。這項功能需要 GKE 1.34 以上版本。

  • 確認 GKE 叢集已啟用 Workload Identity Federation for GKE。 這是驗證程序所需步驟。Autopilot 叢集預設會啟用 Workload Identity Federation for GKE。

  • 確認您具備管理 GKE 叢集和 Secret Manager 的必要 Identity and Access Management 權限。

在 GKE 叢集上啟用密鑰同步功能

建立新叢集或更新現有叢集時,請啟用密鑰同步功能。這項功能適用於 Standard 和 Autopilot 叢集。

在新叢集上啟用密鑰同步

如要建立啟用密鑰同步功能的新叢集,請使用下列其中一個 gcloud CLI 指令:

Standard 叢集

如要在指令列上使用 Secret Manager,請先安裝或升級至 Google Cloud CLI 378.0.0 以上版本。在 Compute Engine 或 GKE 上,您必須使用 cloud-platform 範圍進行驗證

啟用密鑰同步功能,但不啟用自動輪替。

gcloud beta container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --workload-pool=PROJECT_ID.svc.id.goog \
    --enable-secret-sync

啟用密碼自動輪替功能,並同步密碼。預設間隔為 2 分鐘。

gcloud beta container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --workload-pool=PROJECT_ID.svc.id.goog \
    --enable-secret-sync \
    --enable-secret-sync-rotation

啟用密鑰同步功能,並設定自訂輪替間隔。間隔下限為 1 分鐘。

gcloud beta container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --workload-pool=PROJECT_ID.svc.id.goog \
    --enable-secret-sync \
    --enable-secret-sync-rotation \
    --secret-sync-rotation-interval=1m

更改下列內容:

  • CLUSTER_NAME:GKE 叢集名稱
  • CONTROL_PLANE_LOCATION:叢集控制平面的區域或可用區,例如 us-central1us-east1-a
  • PROJECT_ID:您的 Google Cloud 專案 ID

Autopilot 叢集

如要在指令列上使用 Secret Manager,請先安裝或升級至 Google Cloud CLI 378.0.0 以上版本。在 Compute Engine 或 GKE 上,您必須使用 cloud-platform 範圍進行驗證

啟用密鑰同步功能,但不啟用自動輪替。

gcloud beta container clusters create-auto CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync

啟用密碼自動輪替功能,並同步密碼。預設間隔為 2 分鐘。

gcloud beta container clusters create-auto CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync \
    --enable-secret-sync-rotation

啟用密鑰同步功能,並設定自訂輪替間隔。間隔下限為 1 分鐘。

gcloud beta container clusters create-auto CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync \
    --enable-secret-sync-rotation \
    --secret-sync-rotation-interval=1m

更改下列內容:

  • CLUSTER_NAME:GKE 叢集名稱
  • CONTROL_PLANE_LOCATION:叢集控制平面的區域或可用區,例如 us-central1us-east1-a

在現有叢集上啟用密鑰同步

如要更新現有叢集以進行密鑰同步,請使用下列其中一個 gcloud CLI 指令:

gcloud

如要在指令列上使用 Secret Manager,請先安裝或升級至 Google Cloud CLI 378.0.0 以上版本。在 Compute Engine 或 GKE 上,您必須使用 cloud-platform 範圍進行驗證

在現有叢集上啟用密鑰同步

gcloud beta container clusters update CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync

以自訂間隔啟用輪播功能

gcloud beta container clusters update CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --enable-secret-sync-rotation \
    --secret-sync-rotation-interval=5m

停用輪播

gcloud beta container clusters update CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --no-enable-secret-sync-rotation

更改下列內容:

  • CLUSTER_NAME:GKE 叢集名稱
  • CONTROL_PLANE_LOCATION:叢集控制平面的區域或可用區,例如 us-central1us-east1-a

設定密鑰同步

如要同步處理密鑰,請完成下列步驟:

  1. 使用下列指令建立 Kubernetes ServiceAccount

    kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
    

    更改下列內容:

    • KSA_NAME:Kubernetes ServiceAccount 的名稱
    • NAMESPACE:要建立 ServiceAccount 的 Kubernetes 命名空間
  2. 建立 IAM 允許政策,參照新的 Kubernetes ServiceAccount,並授予 ServiceAccount 存取密碼的權限:

    gcloud

    如要在指令列上使用 Secret Manager,請先安裝或升級至 Google Cloud CLI 378.0.0 以上版本。在 Compute Engine 或 GKE 上,您必須使用 cloud-platform 範圍進行驗證

    gcloud secrets add-iam-policy-binding SECRET_PROJECT_ID \
       --role=roles/secretmanager.secretAccessor \
       --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_IDsvc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME
    

    更改下列內容:

    • SECRET_PROJECT_ID:儲存密鑰的專案 ID。如果密鑰與 GKE 叢集儲存在同一個專案中,這項設定可以與 PROJECT_ID 相同。
    • PROJECT_NUMBER:您的 Google Cloud 專案編號
    • PROJECT_ID:您的 Google Cloud 專案 ID
    • NAMESPACE:Kubernetes 命名空間
    • KSA_NAME:Kubernetes ServiceAccount 的名稱
  3. 使用 YAML 資訊清單建立 SecretProviderClass 自訂資源。SecretProviderClass 資源會定義要從 Secret Manager 擷取的特定密鑰,包括資源名稱和路徑。Secret Manager 外掛程式也會使用 SecretProviderClass 資源,列出要掛接的密鑰和掛接檔案名稱。

    建立 spc.yaml 檔案,並加入以下內容:

    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: SECRET_PROVIDER_CLASS_NAME
      namespace: NAMESPACE
    spec:
      provider: gke
      parameters:
        secrets: |
          -   resourceName: "projects/SECRET_PROJECT_ID/secrets/SECRET_NAME/versions/SECRET_VERSION"
              path: "FILENAME.txt"
          -   resourceName: "projects/SECRET_PROJECT_ID/secrets/SECRET_NAME/versions/SECRET_VERSION"
              path: "FILENAME1.txt"
    

    更改下列內容:

    • SECRET_PROVIDER_CLASS_NAME:SecretProviderClass 物件的名稱。
    • NAMESPACE:您要建立這個資源的 Kubernetes 命名空間。
    • resourceName:Secret Manager 中密碼的完整資源 ID。這必須包含專案 ID、密鑰名稱和版本,格式如下:projects/SECRET_PROJECT_ID/secrets/SECRET_NAME/versions/SECRET_VERSION
      • SECRET_PROJECT_ID:儲存密鑰的 Google Cloud 專案 ID。如果密鑰與 GKE 叢集儲存在同一個專案中,這項設定可以與 PROJECT_ID 相同。
      • SECRET_NAME:密鑰名稱。
      • SECRET_VERSION:密鑰版本。密碼版本必須與叢集位於相同區域。
    • path:Secret 值在 Kubernetes 環境中公開時的本機檔案名稱或別名。這是專屬 ID,可將特定 Secret Manager 版本連結至叢集使用的本機表示法。使用 SecretSync 資源將密鑰同步至 Kubernetes Secret 時,sourcePath 欄位會參照這個路徑,找出要同步的密鑰值。您可以在同一個 SecretProviderClass 中,將多個密鑰 (由 resourceName 定義) 對應至不同的路徑名稱。
  4. 如要套用資訊清單,請執行下列指令:

    kubectl apply -f spc.yaml
    
  5. 使用 YAML 資訊清單建立 SecretSync 自訂資源。這項資源會指示同步控制器,根據 SecretProviderClass 中定義的內容建立或更新 Kubernetes 密鑰。

    建立 secret-sync.yaml 檔案,並加入以下內容:

    apiVersion: secret-sync.gke.io/v1
    kind: SecretSync
    metadata:
      name: KUBERNETES_SECRET_NAME
      namespace: NAMESPACE
    spec:
      serviceAccountName: KSA_NAME
      secretProviderClassName: SECRET_PROVIDER_CLASS_NAME
      secretObject:
        type: KUBERNETES_SECRET_TYPE
        data:
          -   sourcePath: "FILENAME.txt"
              targetKey: "TARGET_KEY1"
          -   sourcePath: "FILENAME1.txt"
              targetKey: "TARGET_KEY2"
    

    更改下列內容:

    • KUBERNETES_SECRET_NAME:您要授予新 Kubernetes Secret 的名稱,該 Secret 會由 SecretSync 資源建立。
    • NAMESPACE:建立新資源的 Kubernetes 命名空間。必須與 SecretProviderClass 位於相同命名空間。
    • KSA_NAME:SecretSync 控制器用來建立及更新目標 Kubernetes Secret 的 Kubernetes ServiceAccount 名稱。這個 ServiceAccount 必須具備必要權限,才能從 Secret Manager 存取外部密鑰。
    • SECRET_PROVIDER_CLASS_NAME:您在上一步建立的 SecretProviderClass 物件名稱。SecretSync 資源會使用這項資訊,找出密鑰的正確設定。
    • KUBERNETES_SECRET_TYPE:要建立的 Kubernetes Secret 類型,例如 Opaquetlsdocker-registry。這會決定 Kubernetes 如何處理密鑰資料。
    • sourcePath:本機檔案名稱或別名 (SecretProviderClass 中 path 欄位的值),用於識別要擷取的密鑰資料。SecretSync 控制器會使用這個 sourcePath 要求特定密鑰內容,並將其轉換為新的 Kubernetes 密鑰。
    • targetKey:將用於建立新 Kubernetes Secret 的 data 區段。這會定義使用 sourcePath 擷取的密鑰內容,在最終 Kubernetes Secret 物件中的命名和儲存方式。在資料陣列中使用多個項目,即可在同一個目標 Secret 中定義多個鍵/值組合。
  6. 如要套用資訊清單,請執行下列指令:

    kubectl apply -f secret-sync.yaml
    

    同步控制器會在指定命名空間中建立 Kubernetes Secret。這個密鑰包含從 Secret Manager 對應的資料。

  7. 確認 Kubernetes Secret 是否已建立:

    kubectl get secret KUBERNETES_SECRET_NAME -n NAMESPACE -o yaml
    

    更改下列內容:

    • KUBERNETES_SECRET_NAME:新 Kubernetes Secret 的名稱
    • NAMESPACE:建立新 Secret 的 Kubernetes 命名空間
  8. 如要排解同步問題,請使用下列指令:

    kubectl describe secretSync KUBERNETES_SECRET_NAME -n NAMESPACE
    

    更改下列內容:

    • KUBERNETES_SECRET_NAME:新 Kubernetes Secret 的名稱
    • NAMESPACE:新 Secret 應存在的 Kubernetes 命名空間

管理密鑰輪替

如果在叢集上--enable-secret-sync-rotation啟用旗標,同步控制器會定期檢查 Secret Manager,確認 SecretProviderClass 資源中指定的密鑰是否有新版本。--secret-sync-rotation-interval 旗標會決定控制器檢查更新的頻率。

如果控制器在 Secret Manager 中偵測到新的密鑰版本,就會更新對應的 Kubernetes 密鑰。控制器會比較密鑰內容的雜湊,只有在發生變更時才會更新密鑰。

使用這些密鑰的應用程式必須偵測 Kubernetes Secret 中的更新密鑰值,並重新載入。應用程式的設計決定了處理方式。

停用密鑰同步

如要停用 Secret 同步功能,請執行下列 gcloud CLI 指令:

gcloud

如要在指令列上使用 Secret Manager,請先安裝或升級至 Google Cloud CLI 378.0.0 以上版本。在 Compute Engine 或 GKE 上,您必須使用 cloud-platform 範圍進行驗證

gcloud beta container clusters update CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --no-enable-secret-sync

更改下列內容:

  • CLUSTER_NAME:GKE 叢集名稱
  • CONTROL_PLANE_LOCATION:叢集控制平面的區域或可用區,例如 us-central1us-east1-a

這項指令會停止同步控制器。不會刪除任何已建立的 Kubernetes Secret。如不再需要任何已同步的 Kubernetes 密鑰,請手動刪除。

刪除已同步處理的密碼

如要刪除已同步的 Kubernetes Secret,請使用下列指令刪除 SecretSync 資源:

    kubectl delete secretsync KUBERNETES_SECRET_NAME --namespace NAMESPACE

更改下列內容:

  • KUBERNETES_SECRET_NAME:Kubernetes Secret 的名稱
  • NAMESPACE:Secret 所在的 Kubernetes 命名空間

從現有 Secrets Store CSI 驅動程式遷移

如要從現有的 Secrets Store CSI 驅動程式安裝遷移,請按照下列步驟操作:

  1. 將 SecretProviderClass 中的 provider 欄位從 gcp 更新為 gke。 以下範例說明如何更新 provider 欄位:

    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: app-secrets-gke
    spec:
      provider: gke
      parameters:
        secrets: |
          -   resourceName: "projects/87654321/secrets/api-key-secret/versions/2"
              path: "good1.txt"
    
  2. 建立 SecretSync 資源。請使用下列範例設定:

    apiVersion: secret-sync.gke.io/v1
    kind: SecretSync
    metadata:
      name: my-kube-secret
      namespace: NAMESPACE
    spec:
      serviceAccountName: KSA_NAME
      secretProviderClassName: my-app-secrets
      secretObject:
        type: Opaque # Or other Kubernetes Secret types
        data:
          -   sourcePath: "my-secret.txt"
              targetKey: "USERNAME"
          -   sourcePath: "another-secret.txt"
              targetKey: "PASSWORD"
    

安全性考量

Secret Manager 提供多種安全性功能,例如透過 IAM 控管存取權客戶管理的加密金鑰 (CMEK),以及稽核記錄。Secret Manager 會加密儲存的密鑰,以及傳輸中的密鑰。將密鑰同步至 Kubernetes 密鑰時,密鑰在叢集內的安全性取決於 GKE 叢集的設定。請考量下列事項:

  • 儲存:Kubernetes Secret 會儲存在 etcd 中,這是 GKE 的主要資料存放區。根據預設,GKE 會加密靜態資料。為提升安全性,請使用您在 Cloud Key Management Service(Cloud KMS) 中管理的金鑰,在應用程式層加密 Kubernetes 密鑰。加密 Secret 可為機密工作負載提供額外一層安全防護。

  • 存取權控管:GKE 支援多種選項,可讓您使用角色型存取權控管 (RBAC),管理專案及其叢集內資源的存取權。過於寬鬆的 RBAC 權限可能會將密鑰暴露給非預期的工作負載或使用者。請遵循最低權限原則授予存取權,並定期稽核 Secret Manager 和 Kubernetes 密鑰的存取權。

  • 環境變數:為提升安全性,請將 Kubernetes 密鑰掛接為磁碟區,而非做為環境變數。這樣做可降低意外記錄或暴露於其他程序的風險。

後續步驟