Prepare and test your skills
Prepare and test your skills
Declarative manifest customization with Kustomize (opens in a new tab) is the practice of keeping one shared set of Kubernetes manifests and generating a complete version for each environment at release time. In Google Cloud Deploy (opens in a new tab), Skaffold (opens in a new tab) acts as the renderer that runs Kustomize, while the delivery pipeline controls progression across targets and Skaffold profiles select which Kustomization is rendered for each target.
Two-stage rendering in Google Cloud Deploy separates manifest generation from image injection. First, Kustomize generates the hydrated Kubernetes manifest from a kustomization.yaml file and its referenced resources. Then Skaffold substitutes image references in that generated manifest with the release images supplied at release creation, for example through --images=my-app-image=gcr.io/...@sha256:....
Google Cloud Deploy orchestrates this work through Cloud Build at release creation. The rendering source and image references are passed to Google Cloud Deploy when the release is created, Cloud Build invokes skaffold diagnose and skaffold render to produce a rendered manifest for every target profile before the first rollout, and Google Cloud Deploy later calls skaffold apply to apply the already-rendered manifest to each Google Kubernetes Engine (GKE) cluster. Because all targets are rendered up front, the full declarative state can be reviewed, approved, and reapplied safely for rollbacks, and deployment uses kubectl as the deployer even when Kustomize or Helm is the renderer.
Kustomize configuration in skaffold.yaml tells Skaffold where to find the Kustomization to render. A Kustomize entry lives under the manifests stanza and points to one or more directories that contain a kustomization.yaml file:
apiVersion: skaffold/v4beta7
kind: Config
manifests:
kustomize:
paths:
- PATH_TO_KUSTOMIZE
The Kustomize configuration in skaffold.yaml depends on Kustomize files stored alongside the configuration. The kustomization.yaml files can live in a local directory or in a Cloud Storage bucket, and Artifact Registry can store artifacts such as Kustomizations. The paths value defaults to ["."] when no explicit path is set, and additional renderer options follow the Skaffold renderer reference.
Skaffold profiles in Google Cloud Deploy are named variants inside one skaffold.yaml that select different rendering inputs for different targets. A profile isolates environment variance, such as more replicas in production than in staging, so the base definition stays consistent while each environment applies only its own Kustomization directory.
Each target that uses Kustomize gets its own profile entry with its own manifests.kustomize.paths value. The profile name is an arbitrary label chosen by the team, while the path must resolve to the Kustomization for that environment:
apiVersion: skaffold/v4beta7
kind: Config
profiles:
- name: staging
manifests:
kustomize:
paths:
- environments/staging
- name: prod
manifests:
kustomize:
paths:
- environments/prod
A larger configuration can extend the same pattern to local, test, staging, and prod, with paths such as my-app-application-profiles/kubernetes/staging and my-app-application-profiles/kubernetes/prod. Profiles are optional in Skaffold, but they are the supported mechanism for per-target customization with different kustomization.yaml files.
Binding profiles to delivery pipeline targets connects the Skaffold rendering choice to the Google Cloud Deploy progression model. The delivery pipeline defines the ordered list of stages by targetId, and each stage lists the Skaffold profile names to activate when rendering for that target. The pipeline does not contain manifest details, and the Skaffold profile does not contain target topology; the profiles list on the stage is the join between them.
The binding flows from the delivery pipeline stage to the Skaffold profile to the Kustomize directory, as shown in this mapping:
| Skaffold profile | Kustomize path | Delivery pipeline stage |
|---|---|---|
| staging | environments/staging | staging-target renders with profile staging |
| prod | environments/prod | prod-target renders with profile prod |
The corresponding pipeline fragment references those profile names verbatim:
serialPipeline:
stages:
- targetId: staging-target
profiles:
- staging
- targetId: prod-target
profiles:
- prod
When the profile name on the stage matches the profile name in skaffold.yaml, Google Cloud Deploy renders that stage with that stage's Kustomization. This separation lets teams change Kustomize overlays without editing pipeline progression.
The release-to-rollout lifecycle with Kustomize defines the order in which declarative configuration becomes a running workload. The lifecycle preserves the same container images across environments while allowing each environment's rendered YAML to differ:
skaffold.yaml and Kustomize files, plus image bindings such as --images=my-app-image=....skaffold diagnose and skaffold render, so Kustomize first generates each profile's manifest and Skaffold then substitutes the release images into each generated manifest.skaffold apply to apply that target's rendered manifest to its cluster.Exam tip: Kustomize is a renderer, not a deployer, in Google Cloud Deploy; Skaffold uses the Kustomize paths to render manifests and always applies them with kubectl, unless custom targets are used.
Skaffold (opens in a new tab) is a command-line tool for continuous development of Kubernetes-native applications that gives discrete control over build, render, test, and deploy activities. Cloud Deploy (opens in a new tab) uses Skaffold for render and deploy operations, while Skaffold can also orchestrate local development, image building, testing, and advanced deployment features. Cloud Deploy requires only a Skaffold configuration in skaffold.yaml that identifies which manifests to render and apply, and Skaffold is included as part of Cloud Deploy so no separate install is needed for pipeline execution.
Separation of rendering from delivery in Cloud Deploy means the delivery pipeline defines progression from target to target while skaffold.yaml defines which manifests are rendered and how. This division lets teams change rendering tools, Kustomize overlays, or Helm values without redefining the pipeline itself. The rendering source plus container image references are combined to generate fully rendered manifests, and Skaffold performs deployment health checks that Cloud Deploy consumes to determine rollout status.
Skaffold provides consistent control across diverse targets through this model:
skaffold.yaml across the teamThe Cloud Deploy release flow orchestrates work from CI output to cluster state through distinct Skaffold commands. Rendering happens for all targets at release creation, so approvers can inspect the exact YAML that will be applied to each target before the first rollout, which enables safe repeats and rollbacks.
skaffold.yaml and references to container images built by Cloud Build and stored in Artifact Registry are passed to Cloud Deploy when a release is created.skaffold diagnose to validate configuration and skaffold render to hydrate manifests using that source and those images.skaffold apply to apply the rendered manifest to the target cluster using kubectl as the deployer.Cloud Deploy supports only kubectl as the deployer and supports only static Skaffold modules. Other deployers are not supported for standard targets, although Helm or Kustomize can be used as renderers and custom targets can implement alternative deploy logic.
Exam tip: Helm and Kustomize are supported as Skaffold renderers in Cloud Deploy, not as deployers; deployment itself uses kubectl unless you use custom targets.
The skaffold.yaml manifest orchestrates the container image building, tagging, and manifest rendering pipeline that integrates with Cloud Deploy. A build stanza lists artifacts with an image name and build context, and can delegate remote builds to Cloud Build with googleCloudBuild and a projectId. A manifests stanza declares how Kubernetes YAML is produced, and a deploy stanza declares the deployer, typically kubectl: {} for Google Kubernetes Engine or cloudrun: {} for Cloud Run.
The three manifest renderer options differ by source type and configuration:
| Renderer | Configuration field | Source consumed |
|---|---|---|
| Raw YAML | manifests.rawYaml with list of file paths | Plain Kubernetes manifests applied without pre-processing, for example k8s-manifests/deployment.yaml |
| Helm | manifests.helm.releases with name and chartPath | Local packaged chart, unpacked chart directory, or OCI chart reference expanded into manifests |
| Kustomize | manifests.kustomize.paths with list of directories, default ["."] | kustomization.yaml bases and overlays that generate environment-specific manifests |
If no skaffold.yaml exists, running skaffold init --skip-build in the repository generates a starting apiVersion: skaffold/v4beta7, kind: Config file that references discovered manifests. For production use, edit the generated file in the rendering source archive, not the rendered copy stored under target artifacts, because only the source drives future renders.
Skaffold profiles in skaffold.yaml are named variations of build, manifest, and deploy configuration stored in a profiles: stanza for different environments. Profiles are optional, but they are the mechanism for rendering a different set of manifests per Cloud Deploy target, such as more replicas in production than in staging or different Kustomize overlays per environment. Each profile contains its own manifests definition, for example rawYaml: [prod.yaml] versus rawYaml: [staging.yaml], or kustomize.paths: [environments/prod] versus [environments/staging].
The delivery pipeline selects profiles per stage, which binds a Cloud Deploy target to a Skaffold rendering variant. A serialPipeline with stages lists each targetId with a profiles array, such as staging-target using profile staging and prod-target using profile prod. At release creation Cloud Deploy renders manifests for every target-profile combination, so one release carries distinct hydrated output for each step in the progression.
The local-to-cloud workflow in Skaffold uses the same skaffold.yaml and commands locally as in the remote pipeline to keep development and delivery consistent. In dev mode Skaffold watches source files on a local machine, and on change it rebuilds images, retests, and redeploys containers to a local cluster such as minikube; stopping dev mode cleans up deployed artifacts from that cluster. Teams commonly keep a default deploy stanza for local iteration alongside named profiles for test, staging, and prod, and can choose Docker, Jib, or Buildpacks builders with local or Cloud Build execution depending on machine speed and processor architecture.
Image substitution connects CI-built images to CD manifests through placeholders replaced at release time. A Kubernetes Deployment or Cloud Run service definition stores a placeholder such as image: my-app-image, and gcloud deploy releases create passes --images=my-app-image=gcr.io/PROJECT/nginx@sha256:DIGEST to inject the exact image to deploy. The resulting rendered manifest contains the fully qualified image reference instead of the placeholder, which preserves traceability from artifact registry to cluster state.
Cloud Deploy (opens in a new tab) is a continuous delivery service that moves a versioned release through an ordered series of targets using a delivery pipeline, while Skaffold (opens in a new tab) handles rendering and applying Kubernetes manifests. Deployment verification (opens in a new tab) is the optional post-deploy check that runs after the deploy job, and deploy analysis (opens in a new tab) is the separate check that evaluates observability metrics over time. A release binds a rendering source and container images together, and each promotion of that release creates a rollout to the next target.
A delivery pipeline is the Cloud Deploy resource that lists deployment stages in sequence order in its serialPipeline.stages list. The first targetId in the list receives the first automatic rollout when a release is created, and each later target receives the release only after promotion. Targets are separate resources that describe a single deployment destination, such as a Google Kubernetes Engine (GKE) cluster or a Cloud Run service, and the same target can be reused by multiple delivery pipelines.
Pipeline registration uses a YAML file with apiVersion: deploy.cloud.google.com/v1 and kinds DeliveryPipeline and Target, applied with gcloud deploy apply --file=clouddeploy.yaml. The pipeline metadata.name must be unique per project and location, and it supports description, metadata.annotations, metadata.labels, and suspended. When suspended is true, the pipeline cannot create, promote, roll back, or redeploy releases, and rollouts from that pipeline cannot be approved or rejected; the default is false. Each stage binds a target to rendering and strategy choices through targetId, profiles, strategy, and deployParameters.
A release is the central Cloud Deploy resource that represents the code and configuration being delivered through the lifecycle defined by the delivery pipeline. Release creation passes the rendering source from skaffold.yaml plus image references to Cloud Deploy, typically with gcloud deploy releases create --delivery-pipeline=PIPELINE --images=PLACEHOLDER=REGISTRY-IMAGE@sha256:DIGEST. The placeholder image name in the manifest, such as my-app-image, is replaced during rendering with the fully qualified image supplied at release time.
Rendering and deployment flow through Cloud Deploy to Cloud Build to the target cluster in order:
--images mappings to Cloud Deploy.skaffold diagnose and then skaffold render to generate hydrated manifests from the source plus container images.skaffold apply to apply the rendered manifests to the first target in serialPipeline.stages.Skaffold health checks run during deployment, and Cloud Deploy uses their results to determine rollout health. Cloud Deploy does not use other deployers to deploy the application, except through custom targets, but Helm, Kustomize, and kpt can be used as renderers whose output Skaffold then applies.
Skaffold profiles let one pipeline render different manifests for different targets, which is essential when staging and production need different replica counts, services, or overlays. Profiles defined in skaffold.yaml are selected per stage in the delivery pipeline:
serialPipeline:
stages:
- targetId: staging-target
profiles: [staging]
- targetId: prod-target
profiles: [prod]
The rendering process itself has two logical stages in prose order: first the manifest-management tool generates the manifest, then Skaffold substitutes image references with the release images. Raw manifests need no preprocessing beyond that image substitution and are listed under manifests.rawYaml with paths such as k8s-manifests/deployment.yaml. Helm charts are declared under manifests.helm.releases with a name for the chart instance and a chartPath to the packaged chart or unpacked directory. Kustomize overlays are declared under manifests.kustomize.paths pointing to directories containing Kustomization files, with a default of ["."], and each target normally gets its own profile path such as environments/staging versus environments/prod.
Exam tip: The delivery pipeline selects which Skaffold profile renders for a target, while skaffold.yaml defines what that profile renders; omitting strategy selects the standard deployment strategy with verification disabled.
Strategy is the per-stage pipeline setting that controls how a rollout places the new version onto a target. If strategy is omitted, Cloud Deploy uses the standard strategy, which deploys the application fully to the target in one step. A canary strategy instead replaces the running version in percentage-based increments, such as 50% then 100%, so traffic shifts progressively to the new version.
| Strategy | Deployment unit | Choose when |
|---|---|---|
| Standard | Full release to one target | The target should receive the entire new version at once, with optional verify and analysis |
| Automated canary | Percentage phases defined by canaryDeployment.percentages | Traffic must shift gradually using built-in service networking, Gateway API, or Cloud Run traffic control |
| Custom canary | Named phases in customCanaryDeployment with per-phase percent, profiles, verify, and analysis | Each phase needs different manifests, manual control, or distinct verification, ending with a stable phase at percent: 100 |
Canary configuration depends on the runtime that owns traffic splitting. For Cloud Run targets, strategy.canary.runtimeConfig.cloudRun.automaticTrafficControl must be true unless the canary is fully custom. For GKE targets using service-based networking, strategy.canary.runtimeConfig.kubernetes.serviceNetworking names the existing service and deployment and can set disablePodOverprovisioning. For GKE targets using Gateway API, strategy.canary.runtimeConfig.kubernetes.gatewayServiceMesh names the httpRoute, service, and deployment, and it can set routeUpdateWaitTime to wait after HTTPRoute changes propagate so requests are not sent to unavailable resources.
Deployment verification is the optional post-deploy check that runs immediately after the deploy job in a rollout. Verification is enabled under strategy.standard, under strategy.canary.canaryDeployment, or under each phase of customCanaryDeployment, either as verify: true with a verify stanza in skaffold.yaml or as verify.tasks listing Cloud Deploy tasks to run sequentially. Deploy analysis is a separate optional check inside the same strategy stanza that evaluates Google Cloud Observability alert policies over a duration, for example checking uptime-check failures before allowing promotion.
Deploy parameters pass key-value pairs into manifests for label-matched targets without duplicating pipeline stages. Parameters set on the pipeline use deployParameters.values plus matchTargetLabels, so a value such as replicaCount: "2" flows only to targets whose labels match, where the manifest consumes it through a from-param: ${replicaCount} annotation. The same mechanism can set Cloud Run values such as minInstances consumed through from-param: ${minInstances}.
Predeploy and postdeploy hooks are jobs that run immediately before the deploy job or after all other rollout jobs, including verify and analysis. Hooks are configured under strategy.standard or strategy.canary either as task lists with predeploy.tasks and postdeploy.tasks, or as Skaffold custom actions with predeploy.actions and postdeploy.actions where the action name matches customActions.name in skaffold.yaml. Because hooks, verification, and analysis all live under the per-target strategy, staging can run lightweight checks while production runs canary phases, strict verification, longer analysis, and additional postdeploy work.
kubectl.skaffold diagnose and skaffold render, then runs skaffold apply on each rollout and promotion.profiles list bind each targetId to its own rendering inputs, such as environments/staging versus environments/prod.strategy selects the standard deployment strategy, while canary strategies shift traffic in percentage phases using Cloud Run traffic control, GKE service networking, or GKE Gateway API configuration.Google Cloud Deploy uses two-stage rendering where Kustomize first generates the hydrated manifest from a kustomization.yaml file and Skaffold then substitutes the release images supplied at release creation. Cloud Build runs skaffold diagnose and skaffold render for every target profile at release creation, and Google Cloud Deploy later runs skaffold apply to apply the already-rendered manifest to each Google Kubernetes Engine (GKE) cluster using kubectl as the deployer.
Each delivery pipeline stage lists Skaffold profile names in its profiles list, and each named profile in skaffold.yaml defines its own manifests.kustomize.paths value such as environments/staging versus environments/prod. When the profile name on the stage matches the profile name in skaffold.yaml, Google Cloud Deploy renders that stage with that stage's Kustomization, so the base definition stays consistent while each environment applies only its own overlay.
Omitting strategy selects the standard strategy, which deploys the application fully to the target in one step. A canary strategy instead replaces the running version in percentage-based increments such as 50 percent then 100 percent, using Cloud Run traffic control, Google Kubernetes Engine (GKE) service networking, or GKE Gateway API configuration to shift traffic gradually.
Your DevOps engineering team is designing a continuous delivery pipeline using Google Cloud Deploy and Skaffold to deploy microservices onto Google Kubernetes Engine (GKE) clusters across development, staging, and production environments.
You need to implement declarative configuration management using Kustomize that satisfies the following technical requirements:
How should you structure and configure the Kustomize manifests?
Last updated