You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过GCP Secret Manager结合Cloud Build/Cloud Deploy为K8s Pod提供密钥

为Kubernetes Pod提供密钥并结合GCP Cloud Build与Cloud Deploy的最优方案

需求背景

需要在GCP Cloud Build构建容器镜像、Cloud Deploy部署到Kubernetes的流程中,安全地为Pod提供敏感密钥(如示例中的MONGO_URI),同时避免密钥泄露风险。


现有配置问题分析

  1. 构建时传递密钥的风险:原Cloud Build配置通过--build-arg传递MONGO_URI,该参数会被记录在镜像构建历史中,存在敏感信息泄露风险。
  2. Deployment配置错误:autoscaling字段被错误放置在容器spec下,不符合Kubernetes API规范。
  3. 未实现运行时密钥注入:当前Deployment未配置从安全存储中注入密钥到Pod,无法满足运行时获取敏感信息的需求。

最优方案推荐

方案一:运行时注入密钥(首选)

核心思路是不在构建阶段嵌入密钥,而是在K8s Pod运行时通过安全渠道注入,确保密钥不会出现在镜像中。

1. 调整Cloud Build配置(移除构建阶段密钥传递)

# cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '.', '-t', 'gcr.io/$PROJECT_ID/test-clouddeploy-image:${COMMIT_SHA}', '-f', 'Dockerfile.app']
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'gcr.io/$PROJECT_ID/test-clouddeploy-image:${COMMIT_SHA}']
- name: gcr.io/google.com/cloudsdktool/cloud-sdk
  entrypoint: gcloud
  args:
    [
      "deploy", "releases", "create", "release-${SHORT_SHA}",
      "--delivery-pipeline", "test-backend",
      "--region", "us-west1",
      "--annotations", "commitId=${REVISION_ID}",
      "--images", "test-clouddeploy-image=gcr.io/$PROJECT_ID/test-clouddeploy-image:${COMMIT_SHA}"
    ]

2. 选择运行时密钥注入方式

方式A:K8s Secret + Cloud Deploy
  • 在目标集群创建Secret(从GCP Secret Manager拉取密钥):
    kubectl create secret generic mongo-secret --from-literal=MONGO_URI=$(gcloud secrets versions access latest --secret=MONGO_URI)
    
  • 修改Deployment.yaml,将Secret注入为环境变量:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: clouddeploy-deployment
      labels:
        app: project-test
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: project-test
      # 修正autoscaling位置
      autoscaling:
        enabled: true
        minReplicas: 1
        maxReplicas: 2
        targetCPUUtilizationPercentage: 80
      template:
        metadata:
          labels:
            app: project-test
        spec:
          containers:
          - name: project-test
            image: test-clouddeploy-image
            resources:
              limits:
                cpu: 2
                memory: 3Gi
              requests:
                cpu: 1
                memory: 512Mi
            # 注入Secret为环境变量
            env:
            - name: MONGO_URI
              valueFrom:
                secretKeyRef:
                  name: mongo-secret
                  key: MONGO_URI
            ports:
              - name: http
                containerPort: 8000
                protocol: TCP
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: clouddeploy-service
    spec:
      selector:
        app: project-test
      ports:
        - port: 80
          targetPort: 8000
      type: LoadBalancer
    
方式B:直接集成GCP Secret Manager到K8s(推荐)

通过Secret Store CSI Driver让K8s直接从Secret Manager拉取密钥,无需手动维护集群内Secret:

  1. 在集群安装CSI Driver和GCP Provider:
    kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/secrets-store-csi-driver/v1.3.0/deploy/secrets-store-csi-driver.yaml
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/secrets-store-csi-driver-provider-gcp/main/deploy/provider-gcp-plugin.yaml
    
  2. 给K8s服务账号授权访问Secret Manager:
    kubectl create serviceaccount gcp-secret-manager-sa
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:$(kubectl get serviceaccount gcp-secret-manager-sa -o jsonpath='{.metadata.annotations[iam\.gke\.io/gcp-service-account]}')" \
      --role="roles/secretmanager.secretAccessor"
    
  3. 创建SecretProviderClass:
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: mongo-secret-provider
    spec:
      provider: gcp
      parameters:
        secrets: |
          - resourceName: "projects/$PROJECT_ID/secrets/MONGO_URI/versions/latest"
            path: "MONGO_URI"
      secretObjects:
      - secretName: mongo-secret
        type: Opaque
        data:
        - key: MONGO_URI
          objectName: MONGO_URI
    
  4. 修改Deployment.yaml挂载CSI卷:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: clouddeploy-deployment
      labels:
        app: project-test
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: project-test
      autoscaling:
        enabled: true
        minReplicas: 1
        maxReplicas: 2
        targetCPUUtilizationPercentage: 80
      template:
        metadata:
          labels:
            app: project-test
        spec:
          serviceAccountName: gcp-secret-manager-sa
          volumes:
          - name: secrets-store-inline
            csi:
              driver: secrets-store.csi.k8s.io
              readOnly: true
              volumeAttributes:
                secretProviderClass: "mongo-secret-provider"
          containers:
          - name: project-test
            image: test-clouddeploy-image
            resources:
              limits:
                cpu: 2
                memory: 3Gi
              requests:
                cpu: 1
                memory: 512Mi
            env:
            - name: MONGO_URI
              valueFrom:
                secretKeyRef:
                  name: mongo-secret
                  key: MONGO_URI
            volumeMounts:
            - name: secrets-store-inline
              mountPath: "/mnt/secrets-store"
              readOnly: true
            ports:
              - name: http
                containerPort: 8000
                protocol: TCP
    ---
    # Service配置保持不变
    apiVersion: v1
    kind: Service
    metadata:
      name: clouddeploy-service
    spec:
      selector:
        app: project-test
      ports:
        - port: 80
          targetPort: 8000
      type: LoadBalancer
    

方案二:构建时必须使用密钥的场景(仅特殊情况使用)

如果构建过程依赖密钥(如安装私有依赖),可通过Cloud Build安全传递,但需确保密钥不留在镜像中:

1. 修改Cloud Build配置

# cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/docker'
  entrypoint: 'bash'
  args: 
    - -c
    - |
        echo "$$MONGO_URI" > .env
        docker build -t gcr.io/$PROJECT_ID/test-clouddeploy-image:${COMMIT_SHA} -f Dockerfile.app .
        rm .env
  secretEnv: ['MONGO_URI']
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'gcr.io/$PROJECT_ID/test-clouddeploy-image:${COMMIT_SHA}']
- name: gcr.io/google.com/cloudsdktool/cloud-sdk
  entrypoint: gcloud
  args:
    [
      "deploy", "releases", "create", "release-${SHORT_SHA}",
      "--delivery-pipeline", "test-backend",
      "--region", "us-west1",
      "--annotations", "commitId=${REVISION_ID}",
      "--images", "test-clouddeploy-image=gcr.io/$PROJECT_ID/test-clouddeploy-image:${COMMIT_SHA}"
    ]

availableSecrets:
  secretManager:
  - versionName: projects/$PROJECT_ID/secrets/MONGO_URI/versions/latest
    env: 'MONGO_URI'

2. 多阶段构建Dockerfile

# Dockerfile.app
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
COPY .env ./
RUN npm install

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
RUN rm .env
CMD ["node", "app.js"]

额外优化建议

  1. 使用Artifact Registry:替换Container Registry存储镜像,GCP推荐Artifact Registry,功能更完善。
  2. 权限最小化:确保Cloud Build服务账号仅拥有clouddeploy.releaser等必要角色,目标集群节点拥有镜像仓库访问权限。
  3. Skaffold配置简化:当前Skaffold配置无需修改,可继续用于本地调试和Cloud Deploy的manifest管理。

内容的提问来源于stack exchange,提问作者Ayush Chordia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 11:05:54