11.2 Cloud Build Workers and Step Dependencies
Key Takeaways
waitFor omitted means all preceding steps; waitFor with a dash starts without dependencies.
Fan-in steps must reference every required independent predecessor.
A private pool alone does not bridge a second service peering to a private GKE control plane.
Continuous Integration Pipelines with Cloud Build
Modern cloud-native software delivery requires automated, repeatable, and scalable continuous integration (CI) pipelines. Cloud Build is Google Cloud's serverless continuous integration and continuous delivery (CI/CD) platform that executes build steps natively inside container environments. It scales elastically to handle high-concurrency build spikes without requiring developers to provision, patch, or maintain build servers.
For the Google Cloud Professional Cloud Developer exam, you must master Cloud Build architecture, pipeline syntax (cloudbuild.yaml), parallel execution and dependency modeling (waitFor), worker pool networking, variable substitutions, trigger automations, and service account security boundaries.
Cloud Build Architecture & Worker Pools
At its core, Cloud Build treats every operation in your pipeline as a container execution. A build consists of a sequence of build steps, where each step is invoked inside a dedicated container image. Cloud Build mounts a shared workspace directory across all steps at /workspace, enabling subsequent steps to inspect, modify, and consume artifacts generated by earlier steps.
Default Public Worker Pools vs. Private Worker Pools
When a build is initiated, Cloud Build routes execution to a Worker Pool. Google Cloud provides two fundamentally different worker pool architectures:
| Architectural Dimension | Default Public Worker Pool | Private Worker Pools |
|---|---|---|
| Hosting Model | Multi-tenant Google-managed environment | Single-tenant dedicated worker instances |
| Network Placement | Google-owned VPC with direct public internet egress | Peered to customer Virtual Private Cloud (VPC) via Private Service Access (PSA) |
| Private Network Access | Cannot access RFC 1918 internal IPs or private VPC services | Configured private routes; other service peerings are not transitively reachable |
| VPC Service Controls | Not compliant with strict VPC Service Controls perimeters | Fully supported within VPC Service Controls (VPC-SC) perimeters |
| Static Egress IPs | Dynamic public IP addresses; cannot be whitelisted | Static egress needs the documented private-pool network/NAT architecture; simple peering alone does not make Cloud NAT transitive |
| Compute Sizing | Standard machine types (e2-standard-2 through e2-standard-32) | Custom machine types, custom disk sizes (up to 4,000 GB), and customizable concurrency |
| Billing Model | Billed per build-minute consumed | Usage-based build-time pricing by selected machine resources; not a permanently allocated idle VM fleet |
Private Worker Pools in Enterprise Topologies
In secure enterprise architectures, workloads such as private Google Kubernetes Engine (GKE) control planes, private Cloud SQL instances, or internal artifact repositories disable public IP access entirely. If a pipeline running on the default public worker pool attempts to run kubectl apply against a private GKE cluster control plane (172.16.0.2), the operation fails with a network timeout.
To resolve this, developers configure a Private Worker Pool:
- A dedicated Service Networking connection (VPC Network Peering) is established between the customer VPC and the Google Services VPC.
- The Private Worker Pool is allocated a reserved internal IP range (
/24CIDR block) within the customer network. - Cloud Build workers spin up inside this isolated network slice, with access limited to routes and DNS deliberately made reachable. VPC peering is non-transitive: a private GKE control plane or Cloud SQL reached through another service peering may require the documented VPN/proxy or other supported connectivity design.
## Creating a Private Worker Pool peered to a custom VPC network
gcloud builds worker-pools create enterprise-pool \
--project=my-project-id \
--region=us-central1 \
--peered-network=projects/my-project-id/global/networks/production-vpc \
--worker-machine-type=e2-standard-8 \
--worker-disk-size=200GB \
--no-external-ip-address
Anatomy of cloudbuild.yaml
A Cloud Build configuration file is written in YAML or JSON and defines the exact state machine of your pipeline. The primary building blocks include:
steps: An ordered list of containerized actions to execute.name: The container image used to execute the step (the "builder").args: Arguments passed directly to the container entrypoint.entrypoint: Overrides the defaultENTRYPOINTdefined in the builder container image.env: Environment variables injected into the step container.dir: Working directory inside the container, relative to/workspace.id: An optional unique string identifier for the step, used for dependency tracking.waitFor: Controls step execution order and parallelization.timeout: Maximum execution time for an individual step or the overall build.secretEnv: Secret environment variables extracted securely from Secret Manager.
Directed Acyclic Graphs (DAGs) and Parallel Execution
By default, Cloud Build executes steps serially in the order they are listed in the YAML file. However, modern CI pipelines must run unit tests, security linters, static code analysis, and asset minification concurrently to minimize build duration.
Cloud Build supports arbitrary Directed Acyclic Graph (DAG) orchestration through the waitFor field:
- Sequential Default: If
waitForis omitted, the step waits for all preceding steps to complete successfully. - Parallel Start (
waitFor: ['-']): SettingwaitFor: ['-']instructs Cloud Build that this step has no dependencies and should begin execution immediately upon build start, concurrently with any other zero-dependency steps. - Explicit Fan-In (
waitFor: ['step-a', 'step-b']): A step will pause execution until all referenced step IDs have finished successfully.
Concrete Example: Parallel CI/CD Pipeline
steps:
# Step 1: Run unit tests immediately in parallel
- name: 'golang:1.26-bookworm'
id: 'run-unit-tests'
entrypoint: 'go'
args: ['test', '-v', '-race', './...']
waitFor: ['-']
# Step 2: Run security linter immediately in parallel
- name: 'securego/gosec:v2.22.0'
id: 'run-security-linter'
args: ['-exclude-dir=vendor', './...']
waitFor: ['-']
# Step 3: Build container image only after tests and lint pass
- name: 'gcr.io/cloud-builders/docker'
id: 'build-image'
args:
- 'build'
- '-t'
- 'us-central1-docker.pkg.dev/$PROJECT_ID/app-repo/payment-service:$SHORT_SHA'
- '-t'
- 'us-central1-docker.pkg.dev/$PROJECT_ID/app-repo/payment-service:latest'
- '.'
waitFor: ['run-unit-tests', 'run-security-linter']
# Step 4: Push the tagged image to Artifact Registry
- name: 'gcr.io/cloud-builders/docker'
id: 'push-image'
args:
- 'push'
- '--all-tags'
- 'us-central1-docker.pkg.dev/$PROJECT_ID/app-repo/payment-service'
waitFor: ['build-image']
# Step 5: Deploy to Cloud Run using Secret Manager credential
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
id: 'deploy-cloud-run'
entrypoint: 'gcloud'
args:
- 'run'
- 'deploy'
- 'payment-service'
- '--image=us-central1-docker.pkg.dev/$PROJECT_ID/app-repo/payment-service:$SHORT_SHA'
- '--region=us-central1'
- '--platform=managed'
- '--set-env-vars=ENVIRONMENT=$_ENVIRONMENT'
waitFor: ['push-image']
substitutions:
_ENVIRONMENT: 'staging'
options:
substitutionOption: 'ALLOW_LOOSE'
logging: 'CLOUD_LOGGING_ONLY'
timeout: '1200s'
Official references checked October 18, 2026: Google Cloud 1, Google Cloud 2.
A development team is configuring a Cloud Build pipeline to deploy application manifests to a Google Kubernetes Engine (GKE) cluster. The cluster was created as a private cluster with private endpoint enabled and public master endpoint access disabled. When the pipeline runs 'kubectl apply', the build step fails with a connection timeout error. What architectural change resolves this issue while maintaining the cluster's private security posture?
Use a private pool and the documented private-GKE connectivity design (including VPN/routing where peering would otherwise be transitive), then run the build there
Grant the default Cloud Build service account the roles/container.admin IAM role in the host project
Configure 'waitFor: ['-']' on the kubectl build step to bypass public routing queues during execution
Add the substitutionOption: 'ALLOW_LOOSE' setting to cloudbuild.yaml to permit private IP address resolution
A developer needs to optimize a Cloud Build pipeline that currently runs sequentially: code checkout, backend unit tests, frontend unit tests, container image build, and deployment. The backend and frontend unit tests are completely independent of each other. How should the developer configure 'waitFor' in cloudbuild.yaml to run both test suites concurrently immediately upon build launch?
Combine both test commands into a single build step using a composite bash command with a single ampersand background operator
Set 'waitFor: ['-']' on both the backend test step and frontend test step, and set the container build step to wait for both test step IDs
Set 'parallelExecution: true' at the root level of cloudbuild.yaml and omit the 'id' field from all test steps
Define a custom substitution variable '_CONCURRENCY: 2' in the Cloud Build trigger configuration settings
Sections you finish are checked off in the contents.