Skip to main content
GCPDevOps & IaCintermediate

Cloud Deploy CI/CD Guide

Guide to Cloud Deploy covering delivery pipelines, targets, Skaffold rendering, canary deployments, approval gates, rollbacks, and integration with Cloud Build for end-to-end CI/CD.

CloudToolStack Team22 min readPublished Mar 14, 2026

Prerequisites

  • Experience with container deployment (GKE or Cloud Run)
  • Basic understanding of CI/CD pipeline concepts
  • Familiarity with Kubernetes manifests or Cloud Run service YAML

Introduction to Cloud Deploy

Google Cloud Deploy is a fully managed continuous delivery service that automates the deployment of applications to GKE, Cloud Run, and Anthos clusters. It provides an opinionated but flexible delivery pipeline that handles progressive rollouts, canary deployments, automated verification, approval gates, and instant rollbacks. Cloud Deploy integrates with Skaffold for rendering Kubernetes manifests, making it compatible with Helm, Kustomize, and plain YAML configurations.

Unlike general-purpose CI/CD tools like Jenkins or GitHub Actions, Cloud Deploy focuses exclusively on the delivery (CD) portion of the pipeline. It assumes you have already built and tested your artifacts (typically using Cloud Build or another CI system) and manages the promotion of those artifacts through a sequence of environments like dev, staging, and production. This separation of concerns makes deployment pipelines more reliable and auditable.

This guide covers creating delivery pipelines and targets, configuring Skaffold for manifest rendering, setting up canary and blue-green deployments, implementing approval gates, automated rollbacks, and integrating Cloud Deploy with Cloud Build for end-to-end CI/CD.

Cloud Deploy Pricing

Cloud Deploy charges $0.20 per active delivery pipeline per day and $0.02 per target per day. A typical three-target pipeline (dev, staging, prod) costs approximately $0.26/day or about $8/month. Rendering and deployment operations are free. This is significantly cheaper than maintaining a dedicated deployment tool like Spinnaker or ArgoCD on your own infrastructure.

Core Concepts

Cloud Deploy Architecture

ConceptDescriptionExample
Delivery PipelineDefines the sequence of targets for promotionmy-app-pipeline (dev → staging → prod)
TargetA deployment destination (GKE cluster, Cloud Run service)dev-cluster, prod-run-service
ReleaseA specific version of the application to deployrelease-v1.2.3
RolloutThe deployment of a release to a specific targetrollout-001 (release-v1.2.3 to prod)
Skaffold ConfigDefines how to render and deploy manifestsskaffold.yaml with Helm or Kustomize
AutomationRules for automatic promotion and rollbackAuto-promote to staging after dev succeeds

Setting Up Your First Pipeline

A Cloud Deploy pipeline requires three components: a delivery pipeline definition, target definitions, and a Skaffold configuration. Let us create a pipeline that deploys a containerized application to Cloud Run across three environments.

bash
# Enable the Cloud Deploy API
gcloud services enable clouddeploy.googleapis.com

# Grant the Cloud Deploy service account required roles
PROJECT_NUMBER=$(gcloud projects describe MY_PROJECT --format="value(projectNumber)")
gcloud projects add-iam-policy-binding MY_PROJECT \
  --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --role="roles/clouddeploy.jobRunner"
gcloud projects add-iam-policy-binding MY_PROJECT \
  --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --role="roles/run.developer"
clouddeploy.yaml
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  name: my-app-pipeline
description: "My application delivery pipeline"
serialPipeline:
  stages:
    - targetId: dev
      profiles: [dev]
    - targetId: staging
      profiles: [staging]
    - targetId: prod
      profiles: [prod]
      strategy:
        canary:
          runtimeConfig:
            cloudRun:
              automaticTrafficControl: true
          canaryDeployment:
            percentages: [25, 50, 75]
            verify: true
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: dev
description: "Development environment"
run:
  location: projects/MY_PROJECT/locations/us-central1
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: staging
description: "Staging environment"
run:
  location: projects/MY_PROJECT/locations/us-central1
requireApproval: false
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: prod
description: "Production environment"
run:
  location: projects/MY_PROJECT/locations/us-central1
requireApproval: true
bash
# Apply the pipeline and target definitions
gcloud deploy apply --file=clouddeploy.yaml --region=us-central1

# Verify the pipeline was created
gcloud deploy delivery-pipelines describe my-app-pipeline \
  --region=us-central1

# List all targets
gcloud deploy targets list --region=us-central1

Configuring Skaffold

Skaffold is the rendering engine that Cloud Deploy uses to transform your manifests for each target. Skaffold supports Helm charts, Kustomize overlays, and raw Kubernetes YAML. For Cloud Run deployments, Skaffold renders Cloud Run service YAML files.

skaffold.yaml
apiVersion: skaffold/v4beta11
kind: Config
metadata:
  name: my-app
manifests:
  rawYaml:
    - service.yaml
deploy:
  cloudrun: {}
profiles:
  - name: dev
    manifests:
      rawYaml:
        - service.yaml
    patches:
      - op: replace
        path: /deploy/cloudrun
        value:
          projectid: MY_PROJECT
          region: us-central1
  - name: staging
    manifests:
      rawYaml:
        - service.yaml
    patches:
      - op: replace
        path: /deploy/cloudrun
        value:
          projectid: MY_PROJECT
          region: us-central1
  - name: prod
    manifests:
      rawYaml:
        - service.yaml
    patches:
      - op: replace
        path: /deploy/cloudrun
        value:
          projectid: MY_PROJECT
          region: us-central1
service.yaml (Cloud Run manifest)
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: my-app
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: "1"
        autoscaling.knative.dev/maxScale: "10"
    spec:
      containerConcurrency: 80
      containers:
        - image: us-central1-docker.pkg.dev/MY_PROJECT/docker-repo/my-app
          ports:
            - containerPort: 8080
          resources:
            limits:
              cpu: "1"
              memory: "512Mi"
          env:
            - name: ENVIRONMENT
              value: "production"

Creating Releases and Promoting

bash
# Create a release (deploys to the first target automatically)
gcloud deploy releases create release-v1-0-0 \
  --delivery-pipeline=my-app-pipeline \
  --region=us-central1 \
  --images=my-app=us-central1-docker.pkg.dev/MY_PROJECT/docker-repo/my-app:v1.0.0

# Check release status
gcloud deploy releases describe release-v1-0-0 \
  --delivery-pipeline=my-app-pipeline \
  --region=us-central1

# List rollouts for the release
gcloud deploy rollouts list \
  --delivery-pipeline=my-app-pipeline \
  --release=release-v1-0-0 \
  --region=us-central1

# Promote the release to the next target (dev -> staging)
gcloud deploy releases promote \
  --release=release-v1-0-0 \
  --delivery-pipeline=my-app-pipeline \
  --region=us-central1

# Approve a rollout for a target that requires approval (prod)
gcloud deploy rollouts approve rollout-name \
  --delivery-pipeline=my-app-pipeline \
  --release=release-v1-0-0 \
  --region=us-central1

Automating Promotions

Cloud Deploy supports automation rules that automatically promote releases between targets. For example, you can configure automatic promotion from dev to staging when the dev rollout succeeds, while requiring manual approval for production. This balances automation speed with production safety.

Canary Deployments

Canary deployments gradually shift traffic to a new version, allowing you to detect issues before they affect all users. Cloud Deploy supports canary deployments for both GKE and Cloud Run targets. You define the percentage steps and optional verification steps that run automated tests at each stage.

Pipeline with canary strategy
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  name: my-app-pipeline
serialPipeline:
  stages:
    - targetId: dev
      profiles: [dev]
    - targetId: staging
      profiles: [staging]
    - targetId: prod
      profiles: [prod]
      strategy:
        canary:
          runtimeConfig:
            cloudRun:
              automaticTrafficControl: true
          canaryDeployment:
            percentages: [10, 25, 50, 75]
            verify: true
            predeploy:
              actions: ["pre-deploy-check"]
            postdeploy:
              actions: ["post-deploy-verify"]
bash
# During a canary rollout, advance to the next phase
gcloud deploy rollouts advance ROLLOUT_NAME \
  --delivery-pipeline=my-app-pipeline \
  --release=release-v1-1-0 \
  --region=us-central1

# Check canary phase status
gcloud deploy rollouts describe ROLLOUT_NAME \
  --delivery-pipeline=my-app-pipeline \
  --release=release-v1-1-0 \
  --region=us-central1 \
  --format="yaml(phases)"

# Rollback a canary (reverts all traffic to previous version)
gcloud deploy targets rollback prod \
  --delivery-pipeline=my-app-pipeline \
  --region=us-central1

Rollbacks

Cloud Deploy supports instant rollbacks by re-deploying a previous release or by creating a rollback rollout that restores the previous known-good state. For Cloud Run targets, rollbacks shift traffic back to the previous revision with zero downtime.

bash
# Rollback the production target to the previous release
gcloud deploy targets rollback prod \
  --delivery-pipeline=my-app-pipeline \
  --region=us-central1

# Alternatively, re-deploy a specific previous release
gcloud deploy releases promote \
  --release=release-v1-0-0 \
  --delivery-pipeline=my-app-pipeline \
  --region=us-central1 \
  --to-target=prod

# View rollout history for a target
gcloud deploy rollouts list \
  --delivery-pipeline=my-app-pipeline \
  --release=- \
  --region=us-central1 \
  --filter="targetId=prod" \
  --format="table(name,approvalState,state,deployEndTime)"

Integration with Cloud Build

The most common pattern is using Cloud Build for the CI portion (build, test, scan) and Cloud Deploy for the CD portion (deploy through environments). Cloud Build triggers create releases in Cloud Deploy after successful builds.

cloudbuild.yaml with Cloud Deploy integration
steps:
  # Build the Docker image
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'build'
      - '-t'
      - 'us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/my-app:$COMMIT_SHA'
      - '.'

  # Run tests
  - name: 'us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/my-app:$COMMIT_SHA'
    entrypoint: 'npm'
    args: ['test']

  # Push the image
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'push'
      - 'us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/my-app:$COMMIT_SHA'

  # Create a Cloud Deploy release
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - 'deploy'
      - 'releases'
      - 'create'
      - 'release-$SHORT_SHA-$BUILD_ID'
      - '--delivery-pipeline=my-app-pipeline'
      - '--region=us-central1'
      - '--images=my-app=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/my-app:$COMMIT_SHA'

images:
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/my-app:$COMMIT_SHA'

Skaffold Version Compatibility

Cloud Deploy uses a specific Skaffold version for rendering. Check the Cloud Deploy release notes for the currently supported Skaffold API version. Using an unsupported Skaffold version in your configuration will cause rendering failures. Pin theapiVersion in your skaffold.yaml and update it when upgrading your Cloud Deploy pipeline.

GKE Target Configuration

For GKE targets, Cloud Deploy can deploy Kubernetes manifests rendered through Helm or Kustomize. The Skaffold configuration specifies the rendering engine and the deploy section specifies the GKE cluster.

GKE target with Helm
# Target definition for GKE
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: gke-prod
description: "Production GKE cluster"
gke:
  cluster: projects/MY_PROJECT/locations/us-central1/clusters/prod-cluster
---
# Skaffold config for Helm deployment
apiVersion: skaffold/v4beta11
kind: Config
metadata:
  name: my-app-gke
manifests:
  helm:
    releases:
      - name: my-app
        chartPath: charts/my-app
        valuesFiles:
          - charts/my-app/values.yaml
        setValues:
          image.tag: "{{.IMAGE_TAG_my_app}}"
deploy:
  kubectl: {}

Monitoring and Observability

bash
# List all releases with their status
gcloud deploy releases list \
  --delivery-pipeline=my-app-pipeline \
  --region=us-central1 \
  --format="table(name,renderState,targetRenders)"

# View delivery pipeline metrics in Cloud Monitoring
# Navigate to: Cloud Deploy > Delivery pipelines > my-app-pipeline > Metrics

# Set up Pub/Sub notifications for deploy events
gcloud deploy delivery-pipelines add-iam-policy-binding my-app-pipeline \
  --region=us-central1 \
  --member="serviceAccount:deploy-notify@MY_PROJECT.iam.gserviceaccount.com" \
  --role="roles/clouddeploy.viewer"

Cleanup

bash
# Delete releases
gcloud deploy releases list \
  --delivery-pipeline=my-app-pipeline \
  --region=us-central1 \
  --format="value(name)" | while read release; do
  gcloud deploy releases delete "${release}" \
    --delivery-pipeline=my-app-pipeline \
    --region=us-central1 --quiet
done

# Delete the delivery pipeline
gcloud deploy delivery-pipelines delete my-app-pipeline \
  --region=us-central1 --force --quiet

# Delete targets
gcloud deploy targets delete dev --region=us-central1 --quiet
gcloud deploy targets delete staging --region=us-central1 --quiet
gcloud deploy targets delete prod --region=us-central1 --quiet
Cloud Build CI/CD GuideArtifact Registry GuideCloud Run for Production

Key Takeaways

  1. 1Cloud Deploy separates delivery (CD) from integration (CI), providing a focused deployment experience.
  2. 2A typical three-target pipeline (dev, staging, prod) costs approximately $8/month.
  3. 3Canary deployments gradually shift traffic at configurable percentages with optional verification at each stage.
  4. 4Approval gates require human approval before deploying to sensitive targets like production.
  5. 5Rollbacks instantly revert to the previous release with zero-downtime traffic shifting.
  6. 6Skaffold handles manifest rendering supporting Helm, Kustomize, and raw YAML configurations.

Frequently Asked Questions

How does Cloud Deploy differ from Cloud Build?
Cloud Build is a CI tool that builds, tests, and packages your code. Cloud Deploy is a CD tool that manages the promotion of built artifacts through environments (dev, staging, prod). They are complementary: Cloud Build creates releases in Cloud Deploy after successful builds.
Can Cloud Deploy handle blue-green deployments?
Yes. Cloud Deploy supports canary deployments for both GKE and Cloud Run targets. For Cloud Run, you can configure traffic splitting percentages (e.g., 10%, 25%, 50%, 75%, 100%). Blue-green is achieved by setting a single 100% traffic shift after verification.
What is Skaffold and why does Cloud Deploy use it?
Skaffold is an open-source tool for Kubernetes development that handles building, pushing, and deploying applications. Cloud Deploy uses Skaffold specifically for manifest rendering (transforming Helm charts, Kustomize overlays, or raw YAML for different environments). You don't need to know Skaffold deeply; Cloud Deploy manages it for you.

Written by CloudToolStack Team

Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.

Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.