Google Cloud Build Private Pools: Separate IAM, VPC Reachability, and Egress
Route builds through Cloud Build private pools while keeping worker selection, caller IAM, build identity, VPC peering, and public egress separate.
A Cloud Build private pool is a managed set of build workers with configurable capacity and a path to resources in a customer VPC. It is not a VM group that your team patches, and the words “private pool” do not mean every build automatically has private-network reachability. A reliable design keeps three separate questions visible: which pool runs the build, which principal may use that pool, and what the build’s own service account may access after the worker starts.
Treat pool selection, pool permission, and runtime identity separately
Cloud Build runs each build on an isolated worker. A private pool adds dedicated worker configuration and can scale down to zero; Google manages the worker infrastructure. A private pool belongs to a project and region, while a build can originate in another project if the cross-project permissions are granted. The resource name therefore identifies both the pool’s owning project and its location:
projects/POOL_PROJECT/locations/REGION/workerPools/POOL_ID
For a build submitted through the CLI or API, the principal requesting that build needs roles/cloudbuild.workerPoolUser on the project that owns the pool. That permission answers “may this caller select this pool?” It does not grant the running build access to source repositories, Artifact Registry, Secret Manager, or deployment targets. Those permissions belong to the build’s configured service account and should be granted independently. Creating and managing pools is a separate administrative capability: roles/cloudbuild.workerPoolOwner grants broad pool control, including create, delete, get, list, and update permissions. If an operator only needs pool creation, define a narrower custom role instead of assuming the predefined owner role is create-only.
For a CLI submission, bind the same principal that authenticates the gcloud builds submit request, then select the pool by its full resource name. Set POOL_USER_MEMBER to that principal’s IAM member string (for example, user:[email protected] or serviceAccount:[email protected]). Trigger permissions are conditional: Google documents that a trigger in the same project as its worker pool needs no additional workerPoolUser grant; a cross-project trigger needs the role on the pool project for the service account configured on that trigger. Do not assume that service account is the person who created the trigger.
gcloud projects add-iam-policy-binding "$POOL_PROJECT" \
--member="$POOL_USER_MEMBER" \
--role="roles/cloudbuild.workerPoolUser"
gcloud builds submit . \
--project="$BUILD_PROJECT" \
--region="$REGION" \
--config=cloudbuild.yaml \
--worker-pool="projects/$POOL_PROJECT/locations/$REGION/workerPools/$POOL_ID"
Apply the binding only after confirming the pool project, the build-origin project, and the principal that will request the build. The same worker-pool resource can instead be selected in the build configuration’s options.pool.name; avoid maintaining two conflicting sources of pool selection.
A private pool is a network peer, not a subnet inside your VPC
Private pools run in a Google-managed service-producer VPC. To reach private resources in a customer VPC, configure the documented private connection between that VPC and the pool’s network. This gives the worker a direct path to resources reachable on that peered network; it does not make the worker part of the customer subnet or inherit every route in the organization.
VPC peering is not transitive. If the customer VPC is itself peered with another VPC that hosts a managed service, a private pool connected to the first VPC does not automatically gain a route through that second peering. This is a common reason a worker can reach an internal VM but not a private GKE endpoint or another peered managed service. Use the product-specific Google Cloud guidance for those layouts; where the architecture requires it, the documented alternatives include a VPN or Cloud Interconnect connection in place of one peering hop, or a supported proxy path.
Also decide explicitly whether workers need public internet access. The default network configuration supports public internet access. Setting the pool’s egress option to NO_PUBLIC_EGRESS prevents direct public-IP egress; public destinations remain reachable only through a configured proxy path. It is not a generic “more private” toggle that preserves package downloads. Enumerate source, package, image, and deployment endpoints first, and configure an approved proxy or private mirror where needed. A worker with no valid route to a package registry may fail before the build reaches its private deployment step.
This article follows the classic service-producer-VPC peering path. The current WorkerPool REST resource also exposes Private Service Connect network-attachment fields, including privateServiceConnect.networkAttachment, publicIpAddressDisabled, and routeAllTraffic. Treat PSC as a distinct supported topology and follow its API contract; do not combine its fields with peering assumptions without checking which configuration the target pool and region support. CLI maturity is a separate question: at the time of writing, --network-attachment appears in the beta/alpha worker-pool creation references, not the stable gcloud builds worker-pools create reference. REST schema support therefore does not by itself establish that the corresponding CLI flag is generally available; check the target SDK channel and release before scripting pool creation.
Diagnose the boundary where the build stopped
When a build fails, inspect evidence in this order:
- Pool selection: confirm the build’s location and the full worker-pool resource name in the build request or configuration. A pool in a different region is not interchangeable just because it is in the same project.
- Caller permission: for cross-project submission, confirm the invoking user or trigger service account has
roles/cloudbuild.workerPoolUseron the pool project. Do not try to solve this by granting the build service account more runtime permissions. - Runtime identity: once the build starts, identify the service account actually attached to it and test the narrow resource permission it needs. Pool use and build-time resource access are different IAM checks.
- Route and policy: confirm the private connection is active, the destination is on a directly reachable network, firewall and DNS configuration allow the flow, and the build’s egress mode matches the intended endpoint.
Use a small diagnostic build with no secrets to test name resolution and reachability to an approved internal endpoint. Keep that test in the same region and pool as the real build. Inspect the Cloud Build resource or submitted configuration to identify the selected pool through options.pool.name (or the deprecated workerPool field where applicable); use the build logs to diagnose step execution. VPC firewall or flow telemetry can help distinguish a missing route from a denied packet. A passing connectivity probe proves only that particular source, destination, port, and identity path, not the reachability of every service.
Private pools are useful when builds need controlled worker configuration or private resource access, but the network and IAM boundaries remain explicit. Record the pool project and region, worker-pool resource, caller principal, build service account, direct peering path, and public-egress decision as separate deployment inputs. That small inventory makes cross-project failures much easier to explain without broadening IAM or opening egress as a guess.
Related:
- Google Artifact Registry: Repository Modes, IAM, Cleanup, and Deployment Integration
- Google Kubernetes Engine: Autopilot, Standard, Cluster Architecture, and Operations
Sources:
- Private pools overview - Google Cloud Build
- Run builds in a private pool - Google Cloud Build
- gcloud builds submit reference - Google Cloud CLI
- Using Cloud Build in a private network - Google Cloud Build
- Create and manage private pools - Google Cloud Build
- Cloud Build IAM roles and permissions
- WorkerPool REST resource and Private Service Connect fields
- Beta gcloud worker-pool creation reference
- Alpha gcloud worker-pool creation reference
- Stable gcloud worker-pool creation reference
- Cloud Build Build REST resource and pool options