Post

IaC - Part 2

IaC - Part 2

Part 2: Building and Deploying the Environment (Step‑by‑Step)

This section walks through the exact steps to build and deploy a modular Azure environment using Bicep. The goal is simplicity: follow the steps, run the commands within PowerShell, and watch the environment come to life! I use PowerShell vs the VS Code extension for better reproducibility and management. Copy/Paste vs Point/Click.

1. Create the Project Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
iac-repo/
├── main.bicep
├── modules/                     # Reusable building blocks (no env-specific values)
│   ├── compute/
│   │   ├── vm/
│   │   └── vmss/
│   ├── networking/
│   │   ├── vnet/
│   │   ├── subnet/
│   │   └── nsg/
│   ├── data/
│   │   ├── storage-account/
│   │   └── sql/
│   └── messaging/
│       └── service-bus/
│
├── environments/                # Environment-specific configs
│   ├── dev/
│   ├── test/
│   └── prod/
│
├── pipelines/                   # CI/CD automation
│   ├── github-actions/
│   ├── azure-devops/
│   └── templates/
│
├── policies/                    # Policy-as-code (OPA, Azure Policy, Sentinel)
│   └── azure-policy/
│
├── docs/                        # Architecture diagrams, runbooks, ADRs
│   ├── architecture.md          # Diagram in Mermaid
│   └── decisions/
│
└── tools/                       # Helper scripts (linting, validation, wrappers)
    └── pre-commit-hooks/

Steps:

  1. Create a folder named iac-repo
  2. Create a modules subfolder
  3. Add empty .bicep files for each module
  4. Add parameter files for each environment

2. Install Required Tools

Verify:

1
2
az version
az bicep version

3. Log In and Select Subscription

1
2
3
az login
az account list --output table
az account set --subscription "<subscription-id>"

4. Create a Resource Group

1
2
3
az group create `
  --name rg-iac-lab `
  --location centralus

5. Build the Modules

Each module should define one responsibility. Example structure:

  • network.bicep → VNet + subnets
  • nsg.bicep → NSGs + rules
  • vm.bicep → VM + NIC + PIP
  • keyvault.bicep → Key Vault + access policies
  • storage.bicep → Storage account

    Steps:

    1. Define parameters.
    2. Define resources.
    3. Output values needed by other modules.
    4. Keep modules small and reusable.

6. Write the Root Template (main.bicep)

main.bicep should:

  • Accept environment parameters
  • Call each module
  • Pass outputs between modules
  • Produce final outputs (e.g., VM IP, Key Vault name)

    Structure:

  • param block
  • module calls
  • output block

7. Create Parameter Files

Example: dev.bicepparam Store it in iac-repo\environments\dev\

1
2
param environment string = 'dev'
param location string = 'centralus'

Repeat for prod in .\environments\prod\

8. Validate the Deployment

1
2
3
4
az deployment group what-if `
  --resource-group rg-iac-lab `
  --template-file .\main.bicep `
  --parameters .\environments\dev\dev.bicepparam

Did you notice the what-if argument?

Look for:

  • Resources to be created
  • Resources to be updated
  • Unexpected changes

9. Deploy the Environment

1
2
3
4
az deployment group create `
  --resource-group rg-iac-lab `
  --template-file .\main.bicep `
  --parameters .\environments\dev\dev.bicepparam

10. Verify the Deployment

Check:

  • Resource Group
  • VNet + subnets
  • NSGs
  • VM + NIC + PIP
  • Key Vault
  • Storage account

    Use:

    1
    
    az resource list --resource-group rg-iac-lab --output table
    

11. Update the Environment

Modify a module → redeploy → ARM handles idempotency.

1
2
3
4
az deployment group create `
  --resource-group rg-iac-lab `
  --template-file main.bicep `
  --parameters dev.bicepparam

12. Deploy to Another Environment

Just swap parameter files:

1
2
3
4
az deployment group create `
  --resource-group rg-iac-lab-prod `
  --template-file main.bicep `
  --parameters prod.bicepparam

13. Commit and Push to GitHub

1
2
3
4
5
git init
git add .
git commit -m "Initial IaC commit"
git remote add origin <repo-url>
git push -u origin main

14. Optional Next Steps (Part 3 - Enhancements?)

  • Add Key Vault secrets
  • Add CI/CD with GitHub Actions
  • Add logging?
  • Add hub‑and‑spoke networking?
This post is licensed under CC BY 4.0 by the author.