Deployment Manager: Declarative Configs and Template Language
Automate GCP with Deployment Manager: declarative YAML configs, Jinja/Python templates, schemas, config merger for scale, preview mode, CI/CD integration, and modular IaC patterns..
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
- ✓Google Cloud Platform account with billing enabled, gcloud CLI installed and configured (version 400.0.0+), basic knowledge of YAML and Jinja templating, familiarity with GCP resources (Compute Engine, VPC, IAM).
Deployment Manager: Declarative Configs and Template Language is like having a specialized tool that handles deployment manager so you don't have to build and manage it yourself — it just works out of the box with Google Cloud's infrastructure.
You pushed a config change at 3 AM. Five minutes later, your production database is unreachable because a firewall rule got overwritten. Deployment Manager could have prevented that. Unlike Terraform or Pulumi, DM is native to GCP—no state file to corrupt, no backend to configure. But its template language is quirky, and most teams misuse it. This article shows you how to use DM the right way: declarative configs that survive audits, templates that don't explode, and patterns that scale from one project to a hundred.
What Is Deployment Manager?
Deployment Manager (DM) is Google Cloud's native infrastructure-as-code service. You define resources in YAML or Python templates, and DM creates, updates, or deletes them in the correct order. It handles dependencies automatically—no need to specify depends_on like in Terraform. DM also supports preview mode, so you can see what will change before applying. The key difference from other tools: DM is fully managed by GCP, meaning no state file to store or lock. However, it only works within GCP, so multi-cloud teams should look elsewhere.
Declarative Configs: The YAML Schema
Every DM deployment starts with a config file—typically YAML. The schema is straightforward: a top-level resources array, each with name, type, and properties. Types are GCP resource types like compute.v1.instance or storage.v1.bucket. Properties mirror the REST API. You can also import templates (more on that later). One gotcha: DM is case-sensitive. machineType vs machinetype will fail silently. Always validate your YAML with gcloud deployment-manager deployments validate before applying.
gcloud deployment-manager types list to see correct casing.storageClass: MULTI_REGIONAL (wrong case) and DM created it with default STANDARD class silently. Always validate.Template Language: Jinja vs Python
DM supports two template languages: Jinja (YAML-based) and Python. Jinja is simpler for most use cases—it's a templating engine that lets you parameterize configs. Python templates are more powerful but harder to debug. I recommend Jinja for 90% of deployments. Templates accept properties and env variables. Use properties for user-supplied values, env for deployment metadata like project ID. Templates must return a config object with resources array.
properties.Dependency Management: Automatic Ordering
DM automatically orders resource creation based on references. If resource A references resource B (e.g., a VM references a subnet), DM creates B first. You can also force ordering with metadata.dependsOn. But overusing dependsOn is a code smell—let DM infer dependencies from property references. For example, if your VM's networkInterfaces.subnet references a subnet resource, DM knows the subnet must exist first. If you use hardcoded values, DM can't infer dependencies.
$(ref.resourceName.property) to let DM handle ordering automatically.Preview Mode: Safe Before Apply
Always use --preview before creating or updating a deployment. Preview shows you what resources will be created, changed, or deleted without actually making changes. This is your safety net. The output is a list of operations with before/after states. You can cancel a preview with gcloud deployment-manager deployments cancel-preview. Never skip preview in production—it catches typos, permission errors, and unexpected deletions.
gcloud deployment-manager deployments describe to parse the preview output.Update and Rollback Strategies
DM supports two update strategies: --create-policy and --delete-policy. By default, DM creates resources and deletes orphans. You can change these to CREATE_OR_ACQUIRE or DELETE_ON_DESTROY. For rollbacks, DM keeps the previous deployment manifest. You can roll back with gcloud deployment-manager deployments update --config previous-config.yaml. However, DM does not support stateful rollback—if a resource was deleted, you must recreate it. Always test rollbacks in a non-prod environment.
Managing Multiple Environments
Use separate deployments for each environment (dev, staging, prod). DM deployments are isolated—resources in one deployment don't affect another unless you explicitly reference them. Use Jinja templates with environment-specific properties files. For example, have a properties-dev.yaml and properties-prod.yaml. This prevents accidental cross-environment changes. Never use the same deployment for multiple environments—it's a recipe for disaster.
myapp-prod.Testing Deployments Locally
DM doesn't have a local emulator, but you can validate configs and templates without creating resources. Use gcloud deployment-manager deployments validate to check syntax and schema. For templates, you can render them locally with gcloud deployment-manager templates render. This is essential for CI/CD—validate before every deployment. Also, consider using yamllint for YAML syntax and jinja2 for template syntax.
Common Pitfalls and How to Avoid Them
- Name collisions: Resource names must be unique within a deployment. Use
{{ env["deployment"] }}-{{ name }}to avoid collisions. 2. Quota limits: DM doesn't check quotas before deploying. Usegcloud compute regions describeto check quotas. 3. IAM permissions: DM uses the service account of the user or the default compute engine service account. Ensure it has necessary permissions. 4. Template complexity: Keep templates simple. If a template is over 100 lines, break it into smaller templates. 5. State drift: DM doesn't detect changes made outside of DM. Usegcloud deployment-manager deployments updateto reconcile.
Advanced: Composing Templates and Outputs
You can compose templates by importing other templates. Use imports in the config to reference template files. Templates can also expose outputs using outputs in the template. Outputs are values that can be used by other deployments or by the user. For example, output the VM's external IP. Outputs are accessed via $(ref.resourceName.outputName). This enables building reusable infrastructure modules.
Integrating with CI/CD Pipelines
DM fits well into CI/CD pipelines. Use Cloud Build, Jenkins, or GitLab CI to run gcloud deployment-manager deployments update on every merge to main. Always run preview first, then apply if changes are expected. Use service account impersonation for secure authentication. Store configs and templates in a Git repository. Tag deployments with labels for traceability. Example Cloud Build step: run preview, fail if unexpected changes, then apply.
When Not to Use Deployment Manager
DM is not a silver bullet. Avoid it for: 1. Multi-cloud deployments—use Terraform or Pulumi. 2. Complex state management—DM's state is simple but lacks features like state locking. 3. Resources not supported by DM—check the type list. 4. Teams that need fine-grained access control—DM uses GCP IAM but doesn't support per-resource permissions. 5. Deployments that require frequent partial updates—DM updates the entire deployment. Consider using Config Controller or Terraform for those cases.
Schema Validation: Enforcing Template Contracts
Deployment Manager schemas (.schema files) define the contract for your templates—required properties, types, allowed values, and documentation. Placed alongside a template (e.g., vm-template.jinja.schema), DM automatically validates deployments against the schema before creating resources. Schemas follow JSON Schema draft 4 with two DM-specific additions: info (metadata like title, version) and imports (files automatically included). Use schemas to enforce that required properties are provided, types are correct (string, integer, boolean), and values meet constraints (min, max, pattern). This catches misconfigurations early, before resources are created. In a team environment, schemas serve as documentation: other engineers can see exactly what properties a template needs without reading the template code. Best practice: always create a schema for every template shared across teams. Include type, description, and default for every property. Use required for mandatory fields and pattern for naming conventions.
Configuration Merger: Managing Complex Deployments at Scale
For large deployments with multiple environments, a single YAML config file becomes unmanageable. The configuration merger pattern uses Python files as hierarchical configuration stores, merged in order: global defaults → environment overrides → module overrides. Create a config_merger.py helper that loads configs dictionaries from multiple Python files and merges them using deep dictionary merge. Each file defines a configs = {...} dictionary with properties. The merger loads files in priority order (e.g., global_config.py → prod_config.py → networking_config.py). This follows the DRY principle: define each property once, override only when necessary. Templates receive the merged config and access properties via context.properties. This pattern scales to 100+ resources across multiple modules. In production, we organize configs as: system-level (global), environment-level (prod/staging/dev), and module-level (networking, compute, storage). The merger is a single Python class shared across all deployments.
| File | Command / Code | Purpose |
|---|---|---|
| simple-deployment.yaml | resources: | What Is Deployment Manager? |
| config.yaml | imports: | Declarative Configs |
| vm-template.jinja | resources: | Template Language |
| dependency.yaml | resources: | Dependency Management |
| preview.sh | gcloud deployment-manager deployments create my-deployment \ | Preview Mode |
| rollback.sh | gcloud deployment-manager deployments describe my-deployment \ | Update and Rollback Strategies |
| properties-prod.yaml | zone: us-central1-a | Managing Multiple Environments |
| validate.sh | gcloud deployment-manager deployments validate \ | Testing Deployments Locally |
| avoid-collision.yaml | resources: | Common Pitfalls and How to Avoid Them |
| output-template.jinja | resources: | Advanced |
| cloudbuild.yaml | steps: | Integrating with CI/CD Pipelines |
| check-types.sh | gcloud deployment-manager types list | grep -i compute | When Not to Use Deployment Manager |
| vm-template.jinja.schema | info: | Schema Validation |
| config_merger.py | class ConfigMerger: | Configuration Merger |
Key takeaways
properties and env.--preview to see changes before applying. Integrate into CI/CD to catch errors early.Common mistakes to avoid
3 patternsIgnoring gcp deployment manager best practices
Over-provisioning without rightsizing analysis
Skipping IAM least-privilege principles
Interview Questions on This Topic
What is Deployment Manager: Declarative Configs and Template Language and when would you use it in production?
Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
That's Google Cloud. Mark it forged?
4 min read · try the examples if you haven't