如何基于Google Cloud Build和Kubernetes处理多环境部署?
Great question! You’ve already got a solid foundation with your single-production pipeline, so expanding to staging, dev, or other environments just needs a few structured adjustments. Let’s tackle your questions one by one:
Do I need separate kubernetes.yaml files for each environment?
You have two practical approaches here—pick the one that fits your team’s workflow:
Separate per-environment files: This is straightforward for small teams or simple setups. Organize files in a directory structure like:
k8s/ staging/ deployment.yaml service.yaml production/ deployment.yaml service.yamlEach file holds environment-specific values (e.g., replica counts, resource limits, config references). The downside is duplicated common configs, which can lead to drift if you don’t keep them in sync.
Template + parameterization (recommended for scaling): Use tools like Kustomize or Helm to manage shared base configs and overlay environment-specific changes. For example with Kustomize:
k8s/ base/ deployment.yaml # Shared config (image placeholder, ports, labels) service.yaml overlays/ staging/ kustomization.yaml # Overrides: replica count=2, resource limits=512Mi patch-deployment.yaml production/ kustomization.yaml # Overrides: replica count=5, resource limits=1Gi patch-deployment.yamlThis keeps your config DRY (Don’t Repeat Yourself) and makes it easy to roll out cross-environment changes while preserving unique settings.
How to handle Kubernetes namespaces?
Use dedicated namespaces for each environment—this is a best practice for isolation and security:
- Create namespaces upfront (or automate this in your pipeline):
kubectl create namespace staging kubectl create namespace production - When deploying, target the specific namespace with
kubectl apply -n <environment> ...or configure it in your Kustomize/Helm setup (Kustomize lets you set the namespace directly in itskustomization.yaml). - Pair namespaces with RBAC: Restrict access so only authorized teams can modify production resources, while developers can freely iterate in staging/dev. For example, grant a "staging-editor" role that only has permissions in the
stagingnamespace.
How to implement staging (and other) environment deployments with Cloud Build?
Here’s a step-by-step workflow to integrate multi-environment deployments into your pipeline:
Trigger deployments by branch/tag:
- Set up Cloud Build triggers: e.g., pushes to the
developbranch trigger staging deployment, pushes tomainorv*tags trigger production deployment. - Use Cloud Build substitutions to pass environment context (e.g.,
_TARGET_ENV=stagingor_TARGET_ENV=production) to your build steps.
- Set up Cloud Build triggers: e.g., pushes to the
Build and tag images consistently:
- Tag your container images with a unique identifier (like the Git commit hash or build ID) so you can trace exactly which version runs in each environment:
gcloud builds submit --tag gcr.io/[PROJECT_ID]/my-app:$COMMIT_SHA
- Tag your container images with a unique identifier (like the Git commit hash or build ID) so you can trace exactly which version runs in each environment:
Inject environment-specific configs during deployment:
- If using Kustomize, update your overlay’s
kustomization.yamlto reference the new image tag, then build and apply:kustomize edit set image gcr.io/[PROJECT_ID]/my-app:$COMMIT_SHA kustomize build k8s/overlays/${_TARGET_ENV} | kubectl apply -n ${_TARGET_ENV} -f - - If using separate YAML files, use
sedor a template tool to replace placeholders (like{{IMAGE_TAG}}) with the build-specific tag before applying.
- If using Kustomize, update your overlay’s
Add gates for production deployments:
- For production, add a manual approval step in Cloud Build (via the
manualApprovalbuild step) to prevent accidental deployments. Or run automated integration tests against staging first—only proceed to production if tests pass.
- For production, add a manual approval step in Cloud Build (via the
Example Cloud Build config snippet:
steps: # Build the image - name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/$PROJECT_ID/my-app:$COMMIT_SHA', '.'] # Push the image - name: 'gcr.io/cloud-builders/docker' args: ['push', 'gcr.io/$PROJECT_ID/my-app:$COMMIT_SHA'] # Deploy to staging (triggered by develop branch) - name: 'gcr.io/cloud-builders/kubectl' args: ['apply', '-n', 'staging', '-f', 'k8s/staging/'] env: - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a' - 'CLOUDSDK_CONTAINER_CLUSTER=my-cluster' if: '$BRANCH_NAME == "develop"' # Deploy to production (triggered by main branch, with approval) - name: 'gcr.io/cloud-builders/gcloud' args: ['builds', 'approve'] id: 'approve-prod' if: '$BRANCH_NAME == "main"' - name: 'gcr.io/cloud-builders/kubectl' args: ['apply', '-n', 'production', '-f', 'k8s/production/'] env: - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a' - 'CLOUDSDK_CONTAINER_CLUSTER=my-cluster' waitFor: ['approve-prod'] if: '$BRANCH_NAME == "main"'
内容的提问来源于stack exchange,提问作者Neko

