Prepare and test your skills
Prepare and test your skills
Cloud Deploy (opens in a new tab) is the delivery service that moves a release through an ordered sequence of targets by rendering manifests and then applying them to each runtime. A release starts from container images built by continuous integration (CI), a skaffold.yaml file, Kubernetes manifests or Cloud Run service YAML, and registered delivery pipeline and target resources. Google Kubernetes Engine (GKE) (opens in a new tab) and Cloud Run are supported runtimes, and Skaffold separates the work into skaffold render, which fills templates and binds image tags, and skaffold apply, which deploys the rendered output. When rendering fails, promotion stalls, or deployment to GKE fails, the cause is usually a missing manifest, an unsupported Skaffold version, an incomplete target definition, or unreachable cluster networking.
Skaffold configuration tells Cloud Deploy which manifests to render and how to deploy them to GKE. A minimal skaffold.yaml file must start with a supported apiVersion, such as skaffold/v4beta7, declare manifests under manifests.rawYaml, and declare the deployer under deploy.kubectl. Cloud Deploy calls skaffold render to produce the final Kubernetes manifests and then calls skaffold apply to apply them to the target cluster. If manifests are missing, they must be created before invoking the pipeline, and if manifests are templated, they must be managed with Kustomize, Helm, or kpt so rendering has complete values to expand.
A Cloud Deploy-generated skaffold.yaml file is suitable only for onboarding, learning, or demonstrating Cloud Deploy and must not be used for production workloads. Production pipelines need an owned skaffold.yaml file with the correct apiVersion and explicit manifest and deploy sections. Rendering failures most often trace to a wrong apiVersion, a missing deployment.yaml reference, or an unresolved Helm or Kustomize template. Fixing the Skaffold config and re-creating the release unblocks the pipeline before any target is touched.
Release creation is the promotion mechanism that submits built artifacts to the delivery pipeline and progresses them through its ordered targets. The prerequisites for a successful release are distinct resources that must all exist before invocation:
skaffold.yaml configuration owned by the team and referencing a supported Skaffold apiVersionA release moves through an ordered workflow where each stage depends on the previous stage:
gcloud deploy releases create RELEASE_NAME --delivery-pipeline=PIPELINE_NAME --region=REGION from the directory containing the Skaffold config, or pass --source= to point at that directory.The release command packages the entire contents of the current directory and subdirectories into a tar file, so running it from a home or root directory captures unwanted files. RELEASE_NAME must be unique among all releases for the delivery pipeline, and dynamic names can use $DATE, $TIME, or both, where rel-$TIME invoked at 3:07pm UTC resolves to rel-1507. Running from the Skaffold directory or using --source= keeps the upload scoped to manifests, Skaffold config, and related sources.
Target connectivity controls whether the Cloud Deploy control plane and execution environment can reach the GKE control plane to apply rendered manifests. For organizations that access clusters only through an HTTP proxy, the target configuration adds a proxyUrl property to the gke stanza alongside the cluster resource name. The target then routes deployment traffic from Cloud Deploy to the cluster through the named proxy URL. A missing or incorrect proxyUrl value appears as a deployment-stage failure even when rendering succeeded.
Deployment to a private GKE cluster uses one of three connectivity paths: a DNS-based endpoint, a Virtual Private Cloud (VPC) network with a private worker pool, or GKE attached clusters with Connect gateway. The DNS-based endpoint is the simplest path because a private cluster whose nodes and Pods are isolated from the public internet can still expose a DNS-based control-plane endpoint. To use it, enable the DNS-based endpoint on the cluster and set dnsEndpoint to true under gke in the target configuration, although no explicit setting is needed when the cluster has no IP-based endpoint because Cloud Deploy connects to the DNS endpoint by default.
The VPC path keeps render and deploy operations inside the private network by running them on a Cloud Build private worker pool. First, create the VPC-native private cluster and set internalIp to true under gke when the target should use the cluster internal IP. Then create a Cloud Build private worker pool that has network access to the private cluster. Then configure the delivery pipeline executionConfigs to use that pool, where the worker pool resource name has the form projects/p123/locations/us-central1/workerPools/wp123. The private pool must be used for RENDER and can also be used for DEPLOY and for VERIFY, so a common fix for private-cluster rollout blockages is adding both RENDER and DEPLOY usages to the same private pool.
Exam tip: The private worker pool is required for RENDER when deploying to a private GKE cluster over VPC, while DEPLOY and VERIFY can optionally use the same pool.
The Cloud Deploy execution environment determines where rendering, deployment, and verification run and which network they can reach. The default pool cannot reach a private cluster internal IP or DNS-isolated control plane, so the pipeline must override it with executionConfigs that bind usages to a private worker pool. Because RENDER produces the manifests that later stages apply, a release that renders in the default pool but deploys to a private cluster fails with missing or unreachable output. Aligning RENDER and DEPLOY on the same private pool removes that boundary mismatch.
Cross-project deployments add an ownership boundary between Cloud Deploy, the worker pool, and the target cluster. When Cloud Deploy and the worker pool live in separate projects, permissions must allow Cloud Deploy to submit work to the pool and allow the pool service account to reach the cluster. Supported runtime environments also change the target schema, since GKE, GKE attached clusters, Cloud Run, and custom targets each require different target configuration fields. Matching the target definition to the runtime, confirming execution service account IAM, and verifying private-pool routing together resolve most delivery pipeline blockages that are not caused by Skaffold rendering errors.
Remediation of pipeline integration, security, and authentication bottlenecks means finding why a CI/CD pipeline stalls at the artifact stage and restoring secure delivery to the target environment. In Google Cloud, Artifact Registry (opens in a new tab) stores Docker images and language packages, Artifact Analysis scans those artifacts for vulnerabilities, secrets, licenses, and dependencies, and deployment to runtimes depends on both identity permissions and machine scopes. When scanning is misconfigured, permissions are missing, or scan metadata is stale, builds cannot be promoted safely.
Artifact Analysis is the scanning service that evaluates artifacts after they arrive in Artifact Registry. Data flows from the push to Artifact Registry to Artifact Analysis, which extracts system packages and supported language packages from the container and creates metadata in Container Analysis. Vulnerability knowledge is stored as a note, and each instance of that note on a specific image is stored as an occurrence, so a pipeline gate reads occurrences to decide whether an image digest is allowed to deploy.
The console exposes this gate in the Vulnerabilities column for each image digest and in the Scan results section, which summarizes package types scanned, total vulnerabilities, vulnerabilities with fixes available, vulnerabilities without fixes, and effective severity. Results can also be read with the Google Cloud CLI or the Container Analysis API, which is important when console totals and automation disagree. If a pipeline blocks on a high-severity finding, the fix path is to patch the base image or dependency, push a new digest to Artifact Registry, wait for a fresh scan, and then promote only the new digest.
Scanning depends on both project-level APIs and repository-level settings, and the pipeline depends on both being correct. First the Artifact Registry API and Container Scanning API must be enabled in the project, which requires the serviceusage.services.enable permission granted through the Owner role (roles/owner) or Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Then a Docker repository must exist in Artifact Registry to receive the pushed image.
When the Artifact Analysis API is enabled, Artifact Analysis automatically begins scanning each new image as it is pushed to Artifact Registry repositories in the project. Scanning is disabled by default for language packages pushed directly to Artifact Registry repositories, so package repositories need explicit opt-in through the per-repository scanning control. Enabling the API also enables language package scanning support, including Node.js (npm) and Python packages in Docker containers (opens in a new tab) stored in Artifact Registry, while Container Registry is not supported for those language scans.
Exam tip: New container images are scanned automatically after API enablement, but language packages pushed to Artifact Registry stay unscanned until scanning is enabled on that individual repository.
Pipeline failures that look like missing scan results or denied pulls are often authentication failures, not scanner failures. To view package and image scan results, an identity needs Container Analysis Occurrences Viewer (roles/containeranalysis.occurrences.viewer), Container Analysis Notes Viewer (roles/containeranalysis.notes.viewer), Artifact Registry Reader (roles/artifactregistry.reader), and the Container Scanner Service Agent (roles/containerscanning.ServiceAgent) context for the scanner. To scan images for secrets during vulnerability scans, the identity needs Artifact Registry Writer (roles/artifactregistry.writer) plus Container Analysis Occurrences Viewer.
Deploying artifacts to Google Cloud runtimes depends on two separate access controls that must both allow the request:
| Control | What it governs | Pipeline impact |
|---|---|---|
| Identity and Access Management (IAM) permissions | Which users, service accounts, and other identities can access Artifact Registry repositories | A missing Artifact Registry permission blocks pull or push even if the VM looks correctly configured |
| Access scopes | Default OAuth scopes for requests made through the gcloud CLI and client libraries on a VM instance using application default credentials | A narrow scope further limits API methods, so a valid IAM grant can still fail from the instance |
Google Cloud runtime environments are preconfigured with access to repositories in the same project. Manual configuration is required when a service account in one project accesses Artifact Registry in a different project, when a service account has read-only storage access but needs both upload and download, or when a custom service account interacts with Artifact Registry.
Scan metadata is the stored vulnerability, license, and dependency record for an image or package, and the metadata moves through fresh, stale, and archived states. Artifact Analysis continues to update metadata as long as the image or package has been pulled within the last 30 days. After 30 days without a pull, metadata is no longer updated and results are stale, so a pipeline may block on outdated severity data.
Metadata that has been stale for more than 90 days becomes archived and can be evaluated only by using the API, not the console. An image with stale or archived metadata can be re-scanned by pulling that image, with refreshed metadata taking up to 24 hours to appear. Packages with stale or archived metadata cannot be rescanned, so the remediation is to publish and push a new package version rather than waiting for a refresh.
Viewing the image vulnerability occurrence is the triage path when a pipeline stops at Artifact Registry. The console workflow moves data from the repository list to the specific digest and its findings in order:
Along with vulnerabilities, the same scan generates dependency and license metadata for OS packages and supported language packages each time an image is pushed. That metadata helps explain why a block occurred, such as a transitive dependency introducing a license or security issue, and it follows the same 30-day freshness and 90-day archive lifecycle.
Troubleshooting Cloud Build (opens in a new tab) execution and resource allocation failures means tracing the failure signal in logs, correcting the build configuration, adjusting timeout and machine resources, and fixing the identity that executes the build. Cloud Build runs each build as an orchestrated set of steps, and a failure in a step, in the worker virtual machine (VM), or in the Identity and Access Management (IAM) permissions stops the pipeline. The resolution depends on where the failure occurs: script errors require live VM or disk inspection, long runs require a longer timeout, and permission errors require a role grant to the correct service account.
Build logs are the starting point for diagnosing why a Cloud Build job failed because they separate orchestrator progress from guest-system output. Logs written to standard output (stdout) or standard error (stderr) are viewable in the Google Cloud console and the gcloud command-line interface (CLI). When a step fails, the console links to the corresponding workdir directory in Cloud Storage so truncated output can be inspected in full.
Image Builder pipelines (opens in a new tab), which run on Cloud Build, write to four distinct logging channels:
stdout and stderr from customization steps, stream them into the Cloud Build trace, and store the full copy in the folder matching the build ID in the _GCS_WORKDIR bucket.journal copy uploaded to the workdir bucket at the end of the run for system-level troubleshooting.Data flows from the customization agent on the worker VM to the orchestrator and then to Cloud Storage, so a missing agent stream plus a boot failure points to the serial log, while a script failure points to the agent logs and journal.
Interactive debugging with the debug flag keeps a failing worker VM running so commands can be tested directly on the failed disk. By default, Image Builder terminates execution and deletes the worker VM immediately on failure to control costs. Setting debug: true under the infrastructureConfig block in imagebuilder.yaml changes that lifecycle so the orchestrator pauses instead of deleting.
The interactive debug workflow runs in order:
debug: true, machineType such as e2-standard-4, zone such as us-central1-a, and instanceDurationHours such as 1.5 in infrastructureConfig.instanceDurationHours expires and automatic termination occurs.gcloud compute ssh WORKER_VM_NAME --zone=BUILD_ZONE --project=PROJECT_ID, adding --tunnel-through-iap for Identity-Aware Proxy (IAP) TCP forwarding when externalIP: none removes the external IP address.Once connected, commands run against the live guest system to inspect target files, review running processes, check installer history logs, and test script fixes directly on disk before updating the recipe.
Intermediate debug images preserve the partially customized boot disk when interactive access was not enabled. A debug image is automatically exported whenever a build fails with debug: false, which is the default. The image is named image-builder-debug-image-BUILD_ID and assigned to the image-builder-debug-images image family, so the failed disk state can be examined after the worker VM is gone.
Inspection follows an ordered sequence:
image-builder-debug-image-BUILD_ID image in the image-builder-debug-images family for the failed build ID.gcloud compute instances create temp-debug-vm --image-family=image-builder-debug-images --zone=ZONE --project=PROJECT_ID.temp-debug-vm over SSH, using IAP tunneling when the network has no external address.The flow moves from the failed worker VM disk to a Compute Engine image to a temporary VM, which separates post-mortem disk analysis from the cost of keeping the original worker running.
A Cloud Build timeout failure occurs when the job exceeds its allowed execution time and stops with a TIMEOUT status. The default Cloud Build timeout is 1 hour (3600s) when no timeout is set. Larger machine types and longer customization phases increase build time, so a job that is progressing normally can still time out if the limit is too low.
To resolve timeouts, set the timeout field at the root level of cloudbuild.yaml and re-run the build to verify completion. For example, timeout: '7200s' allows 2 hours for the pipeline to execute. Resource allocation in imagebuilder.yaml controls the worker that must finish within that window, including machineType, zone, and instanceDurationHours for how long a debug VM stays alive. Choose a larger machine type when customization is compute-bound, then increase timeout to match the longer expected duration rather than leaving the 1-hour default.
Exam tip: The default Cloud Build timeout is 1 hour (3600s); a run that exceeds it fails with TIMEOUT until the root-level timeout field is increased, for example to 7200s.
The Cloud Build service account determines which Google Cloud resources the build steps can access during execution. If no account is specified, Cloud Build may select a default service account with broad access, such as access to Cloud Source Repositories and Cloud Storage buckets in the project. A user-specified service account (opens in a new tab) follows the principle of least privilege by granting only the roles scoped to the task, such as building and pushing images to Artifact Registry.
Configuration moves from identity creation to role assignment to log storage. First the administrator creates the service account and enables the Cloud Build, IAM, and IAM Service Account Credentials application programming interfaces (APIs) when short-lived credentials are needed. Then the administrator selects the account in the Cloud Build Permissions settings page and enables only the required roles, granting any additional roles from the IAM page and consulting the Cloud Build IAM roles list for build-specific needs. When a custom service account executes the build, build logs must be stored in an accessible location such as Cloud Storage buckets in the user project, because the custom identity does not inherit the default logging path permissions.
Common Cloud Build failures map a specific error string to a missing permission, a deleted Google-managed identity, or a source configuration error. The Cloud Build service agent, named service-PROJECT_NUMBER@gcp-sa-cloudbuild.iam.gserviceaccount.com, is distinct from the build execution service account; the service agent calls Google Cloud APIs on behalf of the build service, while the execution account performs the build steps. Audit logs in Logs Explorer show the principalEmail that removed the roles/cloudbuild.serviceAgent role when permissions disappear unexpectedly.
| Failure signal | Cause | Resolution |
|---|---|---|
Access denied. [EMAIL_ADDRESS] does not have storage.objects.get on manual build | User running the build cannot read the default Cloud Storage logs bucket | Grant the Project Viewer role plus the Cloud Build Editor role to the user, or store logs in a user-created bucket |
Missing necessary permission iam.serviceAccounts.actAs for [USER] on [SERVICE ACCOUNT] when deploying to Cloud Run or App Engine | Build service account cannot impersonate the managed-service service account | Configure Cloud Build service account impersonation for the target managed service on the specified or default Cloud Build service account |
Permission 'cloudfunctions.functions.get' denied with status 403 on Cloud Run functions | Build service account lacks function read access | Grant the Cloud Run functions Developer role to the build service account |
Failed to trigger build: Permission 'cloudbuild.builds.create' denied | Trigger service account cannot create builds | Grant the Cloud Build Service Account role containing cloudbuild.builds.create to the user-specified or default service account |
Caller does not have required permission to use project $PROJECT_ID with serviceusage.services.use | Cloud Build service agent is deleted or missing roles/cloudbuild.serviceAgent | Recreate it with gcloud beta services identity create --service=cloudbuild.googleapis.com --project=PROJECT_ID, then bind roles/cloudbuild.serviceAgent to serviceAccount:service-PROJECT_NUMBER@gcp-sa-cloudbuild.iam.gserviceaccount.com |
Trigger and source errors that are not IAM denials also block execution. Failed to trigger build: Couldn't read commit means the trigger references a branch that does not exist, so branch and directory names must be corrected in the trigger definition. Failed to create trigger: Request is prohibited by organization's policy for Pub/Sub triggers means the Pub/Sub API is restricted in the perimeter, so the API must be temporarily allowed, the trigger created, and the restriction reapplied. fatal: could not read Username on git pull or git fetch from a private repository is expected because the credential helper is removed after initial clone, so authorization with API tokens or SSH keys must be configured as an explicit build step.
skaffold render to produce final manifests and skaffold apply to deploy them, and a production skaffold.yaml must declare a supported apiVersion such as skaffold/v4beta7 with explicit manifest and deploy sections.RENDER, with DEPLOY and VERIFY optionally using the same pool, configured through executionConfigs with internalIp or dnsEndpoint and proxyUrl as needed.3600s) and a job that exceeds it fails with TIMEOUT until the root-level timeout field in cloudbuild.yaml is increased.Cloud Deploy calls skaffold render to produce the final Kubernetes manifests and skaffold apply to deploy them, so rendering failures stall promotion before any target is touched. Rendering failures most often trace to a wrong apiVersion, a missing deployment.yaml reference, or an unresolved Helm or Kustomize template. Fixing the owned skaffold.yaml to use a supported apiVersion such as skaffold/v4beta7 with explicit manifest and deploy sections and re-creating the release unblocks the pipeline.
Deployment to a private Google Kubernetes Engine cluster requires a private Cloud Build worker pool for RENDER configured through executionConfigs, with DEPLOY and VERIFY optionally using the same pool. For Virtual Private Cloud connectivity, set internalIp to true under gke and run RENDER and DEPLOY on a private worker pool that has network access to the cluster, while for DNS-based access enable the DNS-based endpoint and set dnsEndpoint to true. The default pool cannot reach a private internal IP or DNS-isolated control plane, so aligning RENDER and DEPLOY on the same private pool removes the boundary mismatch.
Artifact Analysis evaluates artifacts after they arrive in Artifact Registry and stores vulnerability knowledge as a note with each instance on a specific image as an occurrence, so a pipeline gate reads occurrences to decide whether an image digest is allowed to deploy. If a pipeline blocks on a high-severity finding, the fix path is to patch the base image or dependency, push a new digest to Artifact Registry, wait for a fresh scan, and then promote only the new digest. Scan metadata becomes stale after 30 days without a pull and archived after more than 90 days stale, and only images can be re-scanned by pulling while packages require publishing a new version.
A Cloud Build job that exceeds its allowed execution time stops with TIMEOUT status and the default timeout is 1 hour or 3600s when no timeout is set. To resolve timeouts, set the timeout field at the root level of cloudbuild.yaml to a longer value such as 7200s for 2 hours and re-run the build to verify completion. Choose a larger machine type when customization is compute-bound, then increase timeout to match the longer expected duration rather than leaving the 1-hour default.
Your team uses Google Cloud Deploy to deliver microservices to a production Google Kubernetes Engine (GKE) cluster using a canary deployment strategy. You recently updated the delivery pipeline YAML configuration to enable automated deployment verification by setting verify: true under the canaryDeployment strategy.
During the subsequent release rollout, the deployment phase succeeds, but the rollout immediately fails and halts during the verification phase before executing any test suites. Inspection of the clouddeploy-operations Pub/Sub notification logs confirms a JobRun failure with JobType: Verify.
What is the root cause of this pipeline failure, and what action should you take to resolve it?
The delivery pipeline is missing predeploy and postdeploy lifecycle hooks in DeliveryPipeline; you must declare custom action hooks pointing to Skaffold lifecycle scripts.
The delivery pipeline target configuration is using standard kubectl rendering instead of Helm; you must change the deployer stanza in skaffold.yaml to deploy.helm.
The target GKE cluster lacks the GKE security posture dashboard advanced vulnerability insights; you must enable container OS and language package scanning.
The skaffold.yaml configuration lacks a verify stanza with test container definitions; you must add the verify stanza and ensure the Skaffold apiVersion is skaffold/v3alpha1 or greater.
Last updated