IaC Accelerator¶
The IaC Accelerator is a complete, working example of an infrastructure-as-code project that uses the Managed Templates modules. It is meant for teams that are new to the library or to infrastructure as code. You copy it into your own repository and adapt it. It lowers the entry barrier and gives you a structure, a deployment pipeline and automated updates of your module versions.
A reference project, not a product
The accelerator shows a recommended approach. Specialised cases are not its goal: adapt the files to your needs. The names, pool, service connections, subscriptions and registry in the files are placeholders that you must replace. The maintaining team tests and supports the accelerator itself, not the changes you make to your copy.
What it contains¶
| Part | Terraform | Bicep |
|---|---|---|
| Project structure | Root module per environment, a shared main module, local modules |
One main.bicep, one parameter file per environment, local modules |
| Deployment pipeline | Plan stage, then an apply stage that waits for approval | An optional what-if stage, then a deploy stage that waits for approval |
| Automated updates | Renovate configuration and pipeline, for Azure DevOps or GitHub Actions | The same |
| Module source | git:: source with a version tag |
Container registry reference with a version |
What it deploys¶
The example workload consists of the following resources. It is a spread of modules, not a recommended architecture.
| Resource | Module |
|---|---|
| Resource group | Plain resource, named with the Azure naming module (Terraform) |
| User-assigned identity | user_assigned_identity |
| Log Analytics workspace | log_analytics_workspace |
| Key Vault, with an encryption key | key_vault |
| Storage account, encrypted with the key | storage_account |
| App Service plan and a Linux web app | serverfarm, app_service_site_linux |
| Windows virtual machine | virtual_machine_windows |
| SQL server | sql_server |
| Recovery Services vault with a VM backup policy | Local code in the accelerator (rsv), not a library module |
The example connects to an existing spoke: it looks up the virtual network and the subnet, and places the private endpoints there. The default names follow the naming convention of the spoke canvas (Naming and tags): change them when your spoke uses other names. This means the accelerator works best in a spoke that the platform has created for you (What you get).
Structure¶
Terraform¶
environments/ One root module per environment (dev, prod). Entry point, providers, backend, variables.
main/ Infrastructure for all environments: resources, module calls, data sources.
modules/ Project-specific modules.
pipelines/ terraform.yaml, templates for plan and apply, Renovate pipeline and workflow.
renovate.json Example Renovate configuration.
Each directory in environments/ is a root module that calls the shared main module with environment-specific values.
You can add environments by adding directories. The structure also lets you deploy from a workstation, over a VPN when
resources have public access disabled. Decide whether you set the Terraform version constraints in main/terraform.tf or
in each environment.
Bicep¶
main.bicep The infrastructure, at subscription scope.
dev.bicepparam Parameters of the dev environment.
prod.bicepparam Parameters of the prod environment.
modules/ Local modules: the backup vault, and a module that looks up the spoke network.
pipelines/ bicep.yaml, a single-environment template, Renovate pipeline and workflow.
renovate.json Example Renovate configuration.
Keep shared resources, naming and outputs in main.bicep, and environment-specific values in the parameter files.
Use it¶
- Copy the content of
iac_accelerator/terraform/oriac_accelerator/bicep/of the library repository to your repository. - Review and adjust all files. Search for the TODO comments, and for the repository address (Terraform) or the registry address (Bicep) that the files contain as an example. Replace them with yours.
- Adjust the pipeline definition to your CI/CD setup: agent pool, service connection names, subscriptions and the version of the tool (Terraform or Bicep).
- Create Azure DevOps environments that match your environment names (
dev,prod), and add approvers for all of them, so that nothing changes without review of the previous result. - Create service connections at subscription scope.
- Make sure the pipeline can read the library: see Give the pipeline access for Terraform and Give a Bicep pipeline access for Bicep. The Terraform pipeline already contains the git steps.
- Commit, push, add the pipeline file as a pipeline in Azure DevOps and run it.
Pass values from a variable group¶
| Terraform | Bicep | |
|---|---|---|
| How | List the variable group in the variables block, and map values with the envs parameter, for example TF_VAR_my_variable: $(variable-group-variable-name) |
Use variableGroupName for the group, secretToEnvMapping for secrets and bicepAdditionalParams for plain values |
| Secrets | Mark them as secret in the group and as sensitive in Terraform |
Mark them as secret in the group, and map them with secretToEnvMapping so that they are not logged |
Values that come from outside make it harder to run the code locally: provide them another way then (environment variables or a
.tfvars file that is not committed).
The pipelines¶
Terraform pipeline¶
The pipeline has the parameters environment (dev or prod) and operation (apply or destroy). The template runs two
stages: a plan stage, and a deploy stage that only runs when the plan contains changes. The deploy stage uses an
Azure DevOps environment, so the approvers you configure must approve it. The apply uses the saved plan, and after an
apply a refresh-only run stores API side effects in the state.
Bicep pipeline¶
The pipeline has stages for dev and prod, where prod depends on dev. Each stage can run a what-if first (the
parameter runWhatIf, off by default, because the output can be noisy), then deploys with az deployment sub create.
The Bicep version is installed from a pipeline variable.
Keep modules up to date¶
The accelerator includes a Renovate setup. Renovate checks the versions of the modules you
use (and of the Terraform providers) and opens a pull request when a newer version exists. It reads the Bicep registry
references and the Terraform git:: sources with tags of the form terraform/<module>/<version>, scoped per module, so that
a module never gets a version from the tags of another module. Updates are grouped by update type.
Set it up as follows:
- Keep the pipeline or workflow that matches your platform (Azure DevOps or GitHub Actions) and delete the other.
- Replace the placeholders in
renovate.jsonand in the pipeline (the registry, the repository, the agent pool). - Give Renovate permission to create branches and pull requests. In Azure DevOps this is Contribute and Contribute to pull requests for the build identity of the pipeline. In GitHub Actions you need a GitHub App, because pull requests that the default token creates do not start other workflows.
- For Bicep, give the pipeline access to the registry through a service connection that uses workload identity federation. For Terraform modules in another repository, grant read access there too.
- Run it once with
dryRunset totrue. The default isfalse, and the weekly schedule runs it for real. Check that all files with references appear in the log and that no dependency has askipReason. - Then run it without dry-run. After the first real run, check that a pull request only changes the version string.
Read the changelog before you merge
A Renovate pull request changes the version, not your code. Check the changelog and the upgrade notes
for major versions, and let your normal pipeline test the change in dev first.