本文档介绍如何将存储在 Secret Manager 中的 Secret 同步到 Google Kubernetes Engine (GKE) 集群中的 Kubernetes Secret。
通过同步过程,在 GKE 上运行的应用可以使用标准 Kubernetes 方法(例如环境变量或卷挂载)从 Secret Manager 访问 Secret。对于已设计为从 Kubernetes Secret 对象读取 Secret 的应用,此功能非常有用,因为这些应用无需更新即可直接访问 Secret Manager。
建议:Secret 同步功能是 Secret Manager 插件的替代方案, 该插件会将 Secret 作为内存文件直接挂载到您的 Pod 中。只要您的应用支持,就使用 Secret Manager 插件,因为这是在 GKE 中从 Secret Manager 访问 Secret 的更安全方法。
准备工作
在同步 Secret 之前,请完成以下前提条件:
-
启用 Secret Manager 和 Google Kubernetes Engine API。
启用 API 所需的角色
如需启用 API,您需要拥有 Service Usage Admin IAM 角色 (
roles/serviceusage.serviceUsageAdmin),该角色包含serviceusage.services.enable权限。了解如何授予 角色。 安装 gcloud CLI,然后进行初始化。如果您之前安装了 gcloud CLI,请通过运行
gcloud components update命令来获取最新版本。确保您拥有 GKE 集群并且它正在运行。此功能需要 GKE 1.33 及更高版本。
确保在 GKE 集群上启用了 Workload Identity Federation for GKE。 这是进行身份验证的必要条件。Autopilot 集群默认启用 Workload Identity Federation for GKE。
确保您拥有管理 GKE 集群和 Secret Manager 所需的 Identity and Access Management 权限。
在 GKE 集群上启用 Secret 同步
在创建新集群或更新现有集群时,启用 Secret 同步功能。此功能适用于标准集群和 Autopilot 集群。
在新集群上启用 Secret 同步
如需创建启用 Secret 同步的新集群,请使用以下 gcloud CLI 命令之一:
标准集群
要在命令行上使用 Secret Manager,请先 安装或升级到 Google Cloud CLI 版本 378.0.0 或更高版本。 在 Compute Engine 或 GKE 上,您必须 使用 cloud-platform 范围进行身份验证。
启用 Secret 同步,但不启用自动轮替。
gcloud container clusters create CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--workload-pool=PROJECT_ID.svc.id.goog \
--enable-secret-sync
启用 Secret 同步并启用自动轮替。默认时间间隔为 2 分钟。
gcloud container clusters create CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--workload-pool=PROJECT_ID.svc.id.goog \
--enable-secret-sync \
--enable-secret-sync-rotation
启用 Secret 同步并使用自定义轮替时间间隔。最短间隔时间为 1 分钟。
gcloud 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=60s
替换以下内容:
CLUSTER_NAME:您的 GKE 集群的名称CONTROL_PLANE_LOCATION:集群控制平面所在的区域或可用区,例如us-central1或us-east1-aPROJECT_ID:您的 Google Cloud 项目 ID
Autopilot 集群
要在命令行上使用 Secret Manager,请先 安装或升级到 Google Cloud CLI 版本 378.0.0 或更高版本。 在 Compute Engine 或 GKE 上,您必须 使用 cloud-platform 范围进行身份验证。
启用 Secret 同步,但不启用自动轮替。
gcloud container clusters create-auto CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--enable-secret-sync
启用 Secret 同步并启用自动轮替。默认时间间隔为 2 分钟。
gcloud container clusters create-auto CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--enable-secret-sync \
--enable-secret-sync-rotation
启用 Secret 同步并使用自定义轮替时间间隔。最短间隔时间为 1 分钟。
gcloud container clusters create-auto CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--enable-secret-sync \
--enable-secret-sync-rotation \
--secret-sync-rotation-interval=60s
替换以下内容:
CLUSTER_NAME:您的 GKE 集群的名称CONTROL_PLANE_LOCATION:集群控制平面所在的区域或可用区,例如us-central1或us-east1-a
在现有集群上启用 Secret 同步
如需更新现有集群以启用 Secret 同步,请使用以下 gcloud CLI 命令之一:
gcloud
要在命令行上使用 Secret Manager,请先 安装或升级到 Google Cloud CLI 版本 378.0.0 或更高版本。 在 Compute Engine 或 GKE 上,您必须 使用 cloud-platform 范围进行身份验证。
在现有集群上启用 Secret 同步
gcloud container clusters update CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--enable-secret-sync
启用轮替并使用自定义时间间隔
gcloud container clusters update CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--enable-secret-sync-rotation \
--secret-sync-rotation-interval=300s
停用轮替
gcloud container clusters update CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--no-enable-secret-sync-rotation
替换以下内容:
CLUSTER_NAME:您的 GKE 集群的名称CONTROL_PLANE_LOCATION:集群控制平面所在的区域或可用区,例如us-central1或us-east1-a
配置 Secret 同步
如需同步 Secret,请完成以下步骤:
使用以下命令创建 Kubernetes ServiceAccount :
kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
替换以下内容:
KSA_NAME:Kubernetes ServiceAccount 的名称NAMESPACE:您要在其中创建 ServiceAccount 的 Kubernetes 命名空间
创建引用新的 Kubernetes ServiceAccount 的 IAM 许可政策,并向 ServiceAccount 授予访问 Secret 的权限:
gcloud
要在命令行上使用 Secret Manager,请先 安装或升级到 Google Cloud CLI 版本 378.0.0 或更高版本。 在 Compute Engine 或 GKE 上,您必须 使用 cloud-platform 范围进行身份验证。
gcloud secrets add-iam-policy-binding SECRET_NAME \ --role=roles/secretmanager.secretAccessor \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME
替换以下内容:
SECRET_NAME:Secret Manager 中的 Secret 名称PROJECT_NUMBER:您的 Google Cloud 项目编号PROJECT_ID:您的 Google Cloud 项目 IDNAMESPACE:Kubernetes 命名空间KSA_NAME:Kubernetes ServiceAccount 的名称
使用 YAML 清单创建 SecretProviderClass 自定义资源。SecretProviderClass 资源定义要从 Secret Manager 检索的特定 Secret,包括其资源名称和路径。Secret Manager 插件还使用 SecretProviderClass 资源列出要挂载的 Secret 以及要将它们挂载为的文件名。
创建包含以下内容的
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_1/versions/SECRET_VERSION_1" path: "FILENAME.txt" - resourceName: "projects/SECRET_PROJECT_ID/secrets/SECRET_NAME_2/versions/SECRET_VERSION_2" path: "FILENAME1.txt"替换以下内容:
SECRET_PROVIDER_CLASS_NAME:SecretProviderClass 对象的名称。NAMESPACE:您要在其中创建此资源的 Kubernetes 命名空间。resourceName:Secret Manager 中 Secret 的完整资源标识符。此标识符必须包含项目 ID、Secret 名称和 版本,格式如下:projects/SECRET_PROJECT_ID/secrets/SECRET_NAME/versions/SECRET_VERSION.SECRET_PROJECT_ID:存储 Secret 的 Google Cloud 项目 的 ID。如果 Secret 与 GKE 集群存储在同一项目中,则此 ID 可以与 PROJECT_ID相同。SECRET_NAME:Secret 名称。SECRET_VERSION:Secret 版本。Secret 版本必须与集群位于同一区域。
path:Secret 值在 Kubernetes 环境中将显示为的本地文件名或别名。它是将特定 Secret Manager 版本链接到集群使用的本地表示形式的唯一标识符。当使用 SecretSync 资源将 Secret 同步到 Kubernetes Secret 时,sourcePath字段会引用此路径来查找要同步的 Secret 值。 您可以在同一 SecretProviderClass 中将多个 Secret(由resourceName定义)映射到不同的路径名称。
如需应用清单,请运行以下命令:
kubectl apply -f spc.yaml
使用 YAML 清单创建 SecretSync 自定义资源。此资源指示同步控制器根据 SecretProviderClass 中定义的内容创建或更新 Kubernetes Secret。
创建包含以下内容的
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:您要为 SecretSync 资源将创建的新 Kubernetes Secret 指定的名称。NAMESPACE:新资源创建所在的 Kubernetes 命名空间。它必须与 SecretProviderClass 位于同一命名空间。KSA_NAME:SecretSync 控制器用于创建和更新目标 Kubernetes Secret 的 Kubernetes ServiceAccount 的名称。 此 ServiceAccount 必须具有从 Secret Manager 访问外部 Secret 所需的权限。SECRET_PROVIDER_CLASS_NAME:您在上一步中创建的 SecretProviderClass 对象的名称。SecretSync 资源使用此名称查找 Secret 的正确配置。KUBERNETES_SECRET_TYPE:要创建的 Kubernetes Secret 的类型,例如Opaque、tls或docker-registry。这决定了 Kubernetes 如何处理 Secret 的数据。sourcePath:用于标识要检索的 Secret 数据的本地文件名或别名(SecretProviderClass 中path字段的值)。SecretSync 控制器使用此sourcePath请求特定的 Secret 内容,并将其转换为新的 Kubernetes Secret。targetKey:将在创建的新 Kubernetes Secret 的data部分中使用的键。这定义了如何命名使用sourcePath检索到的 Secret 内容,以及如何将其存储在最终的 Kubernetes Secret 对象中。通过在数据数组中使用多个条目,您可以在同一目标 Secret 中定义多个键值对。
如需应用清单,请运行以下命令:
kubectl apply -f secret-sync.yaml
同步控制器会在指定的命名空间中创建 Kubernetes Secret。此 Secret 包含从 Secret Manager 映射的数据。
验证 Kubernetes Secret 是否已创建:
kubectl get secret KUBERNETES_SECRET_NAME -n NAMESPACE -o yaml
替换以下内容:
KUBERNETES_SECRET_NAME:新 Kubernetes Secret 的名称NAMESPACE:新 Secret 创建所在的 Kubernetes 命名空间
如需排查同步问题,请使用以下命令:
kubectl describe secretSync KUBERNETES_SECRET_NAME -n NAMESPACE
替换以下内容:
KUBERNETES_SECRET_NAME:新 Kubernetes Secret 的名称NAMESPACE:新 Secret 应存在的 Kubernetes 命名空间
管理 Secret 轮替
如果您在集群上启用了 --enable-secret-sync-rotation 标志,则同步控制器会定期检查 Secret Manager 中是否有 SecretProviderClass 资源中指定的 Secret 的新版本。--secret-sync-rotation-interval 标志决定了控制器检查更新的频率。
如果控制器在 Secret Manager 中检测到新的 Secret 版本,则控制器会更新相应的 Kubernetes Secret。控制器会比较 Secret 内容的哈希值,以便仅在发生更改时更新 Secret。
使用这些 Secret 的应用必须检测 Kubernetes Secret 中的更新后的 Secret 值并重新加载这些值。应用的架构决定了如何处理此问题。
停用 Secret 同步
如需停用 Secret 同步,请运行以下 gcloud CLI 命令:
gcloud
要在命令行上使用 Secret Manager,请先 安装或升级到 Google Cloud CLI 版本 378.0.0 或更高版本。 在 Compute Engine 或 GKE 上,您必须 使用 cloud-platform 范围进行身份验证。
gcloud container clusters update CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--no-enable-secret-sync
替换以下内容:
CLUSTER_NAME:您的 GKE 集群的名称CONTROL_PLANE_LOCATION:集群控制平面所在的区域或可用区,例如us-central1或us-east1-a
此命令会停止同步控制器。它不会删除任何已创建的 Kubernetes Secret。如果您不再需要任何已同步的 Kubernetes Secret,则必须手动将其删除。
删除已同步的 Secret
如需删除已同步的 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 驱动程序 安装迁移,请按照以下步骤操作:
将 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"创建 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 在 Secret Manager 中处于静态加密和传输中加密状态。当您将 Secret 同步到 Kubernetes Secret 时,它们在集群中的安全性取决于 GKE 集群的配置。请考虑以下事项:
存储:Kubernetes Secret 存储在 etcd 中,这是 GKE 的主要数据存储区。默认情况下,GKE 会对静态数据进行加密。为了提高安全性, 请使用您在Cloud Key Management Service(Cloud KMS)中管理的密钥在应用层加密 Kubernetes Secret。 加密 Secret 可为敏感工作负载提供额外的安全保障。
访问权限控制:GKE 支持多种选项,以使用基于角色的访问控制 (RBAC) 管理对项目及其集群中的资源的访问权限。过于宽泛的 RBAC 权限可能会将 Secret 暴露给意外的工作负载或用户。请遵循最小权限原则授予访问权限,并定期审核对 Secret Manager 和 Kubernetes Secret 的访问权限。
环境变量:为了提高安全性,请将 Kubernetes Secret 作为 卷挂载,而不是将其用作环境变量。这样可以降低意外日志记录或暴露给其他进程的风险。