Infrastructure as Code & Provisioning
Infrastructure as Code (IaC) defines cloud infrastructure in version-controlled, machine-readable files instead of manual console clicks, so environments are repeatable, reviewable, and auditable.
At a glance
Section titled “At a glance”- What it is: tools like Bicep, Terraform, or ARM/CloudFormation templates that describe infrastructure declaratively, deployed through a pipeline rather than a person clicking through a portal.
- Why it matters: manual changes drift silently between environments until “works on staging, breaks in prod” becomes routine — IaC makes environments reproducible and changes reviewable.
- For developers: if you can’t answer “what changed and who approved it” for a piece of infrastructure, it probably wasn’t provisioned through IaC.
- When to use it: for any environment beyond a disposable personal sandbox.
- When not to use it: a genuinely throwaway individual experiment may not need full pipeline rigor — but promote it to IaC before anything depends on it.
- Prerequisites: Landing Zone Design.
Mental model
Section titled “Mental model”graph LR
Code["IaC files in source control"] --> PR["Pull request + review"] --> Pipeline["CI/CD pipeline"] --> Deploy["Deployed infrastructure"]
Deploy -.drift detected.-> Code
Step-by-step walkthrough
Section titled “Step-by-step walkthrough”- Choose an IaC tool consistent with the platform (e.g., Bicep for Azure-only, Terraform for multi-cloud).
- Model the landing zone and workload infrastructure as code, stored in source control.
- Require changes to flow through pull requests and a pipeline, removing direct console/CLI access to production where possible.
- Add drift detection so out-of-band manual changes are surfaced, not silently tolerated.
- Treat infrastructure changes with the same review rigor as application code changes.
Worked example
Section titled “Worked example”Northwind’s logistics team’s environments have quietly diverged — someone tweaked a firewall rule in the portal here, resized a VM there — and nobody can say for certain what’s actually deployed anymore.
- Input: infrastructure originally provisioned by hand, now drifted across environments with no change history.
- Process: the team reverse-engineers the current state into Terraform/Bicep, removes standing console/CLI write access for individual engineers, and routes all future changes through pull requests and a pipeline; a drift-detection job runs nightly and flags any resource that no longer matches the code.
- Output: within a few weeks, the drift-detection job catches and reverts an accidental manual change before it causes an incident, and every infrastructure change afterward has a reviewable pull-request history.
resource plan 'Microsoft.Web/serverfarms@2023-12-01' = { name: 'checkout-plan' location: location sku: { name: 'P1v3' tier: 'PremiumV3' capacity: 2 }}
resource webApp 'Microsoft.Web/sites@2023-12-01' = { name: 'checkout-web' location: location properties: { serverFarmId: plan.id httpsOnly: true }}This is the actual Bicep behind the pull-request-reviewed pipeline in the example above — checked into source control, so the drift-detection job has something authoritative to compare the live App Service against.
Common use cases
Section titled “Common use cases”| Use case | When to use | Notes |
|---|---|---|
| Standing up a new environment identical to an existing one | Reuse the same IaC module/template | Environments genuinely match instead of “close enough” |
| Auditing what changed before an incident | Read the IaC pull-request history | Faster root-cause than reconstructing portal click history |
| Removing standing admin access to production | Route all changes through IaC pipelines | Reduces both accidental and malicious out-of-band changes |
Advanced details
Section titled “Advanced details”- Declarative IaC (Bicep/Terraform) describes the desired end state; the tool computes the diff. Imperative scripting describes steps to take — declarative is generally preferred for infrastructure because it’s idempotent by default.
- State files (Terraform) or deployment history (Bicep/ARM) must themselves be protected and backed up — losing track of state is its own outage risk.
- Modules/reusable templates for common patterns (landing zone, network, standard VM) reduce copy-paste drift between teams.
Quick reference
Section titled “Quick reference”| Term | Meaning |
|---|---|
| IaC | Defining infrastructure in version-controlled, machine-readable files |
| Declarative | Describes the desired end state; the tool computes how to get there |
| Drift | When actual infrastructure no longer matches the code that should define it |
| State file | Terraform’s record of what it believes is currently deployed |
| Module / template | A reusable, parameterized IaC package for a common pattern |
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely cause | Fix |
|---|---|---|
| “Works in staging, breaks in prod” despite supposedly identical environments | Environments were provisioned manually and have drifted apart | Reprovision both from the same IaC module/template |
| Nobody can say who changed a piece of infrastructure or why | Manual console/CLI changes bypassing IaC | Remove standing write access; require changes through pipeline + pull request |
| Terraform plan shows unexpected changes on every run | Drift from manual out-of-band changes | Import the actual state or revert the manual change, then re-run |
Check your understanding
Section titled “Check your understanding”- Why is declarative IaC generally preferred over imperative scripts for infrastructure?
- If a pipeline is the only way to change production, what should happen to “quick manual fixes” during an incident?
Related pages
Section titled “Related pages”Part of Introduction to Cloud & Infrastructure Architecture. See also Landing Zone Design, Cloud Service & Deployment Models, Infrastructure Observability & Monitoring, and the Glossary.