Azure infrastructure repository for provisioning AKS on Azure using Bicep and Azure Verified Modules (AVM), orchestrated by Azure Pipelines.
pipelines/- Parent pipeline entrypoint.templates/- Bicep and parameter templates (AVM-based)..github/- GitHub Copilot instructions, custom agent profile, and reusable prompt files.
Agent profiles:
.github/agents/devops-expert.agent.md
Shared pipeline assets are hosted in infra-pipeline-common:
pipelines/stages/pipelines/extends/pipelines/steps/pipelines/variables/scripts/
Primary pipeline definition is at pipelines/azure-pipelines.yml.
The parent pipeline passes a deploymentTemplates object array into the shared extends template (pipelines/extends/infra-deploy.yml@pipeline_common) where each entry contains:
nametemplateFileparameterFile
Validate, What-If, and Deploy execute in loops across this array so multiple resource templates can be processed in one run.
Shared variable templates are stored in repository infra-pipeline-common:
pipelines/variables/common.ymlpipelines/variables/dev.ymlpipelines/variables/prd.yml
The pipeline imports infra-pipeline-common as an external repository resource (pipeline_common) and extends a shared orchestration template from that repository.
Deployment order inside each environment is:
templates/network/network.bicep(shared VNet + subnets)templates/loganalytics/loganalytics.bicep(shared Log Analytics workspace)templates/acr/acr.bicep(ACR integrated to shared VNet via private endpoint)templates/aks/aks.bicep(managed cluster only, consuming existing VNet and workspace)
The pipeline runs Validate first, then executes environment-specific What-If and Deploy flow based on each environment's performWhatIf flag in the shared environments object (default: dev=false, prd=true).
- Validate - Lint/build/validate Bicep.
- env-whatif - Runs only when
performWhatIf: truefor that environment. - env-deploy - Runs after WhatIf when enabled, otherwise after the environment's configured predecessor.
During Validate, tokenized .bicepparam files are transformed per environment and template under transformed-artifacts/<env>/<template>/..., then published as one artifact per environment (transformed-<env>).
WhatIf and Deploy download the environment artifact once per environment job and use the transformed files from that directory.
The deploy stage template is iterated with a loop over fixed environments (dev then prd), using environment names directly.
Supported deployment environments:
- dev
- prd
This repo currently includes:
templates/network/network.bicep(Virtual Network and subnets)templates/loganalytics/loganalytics.bicep(Log Analytics workspace)templates/acr/acr.bicep(Azure Container Registry)br/public:avm/res/container-service/managed-cluster:0.12.0br/public:avm/res/container-registry/registry:0.10.0br/public:avm/res/network/virtual-network:0.7.2br/public:avm/res/operational-insights/workspace:0.15.0
AKS template now contains only managed cluster deployment logic. Networking and observability prerequisites are deployed independently and consumed as existing resources by AKS and ACR templates.
Network access controls are parameterized per environment:
- AKS API server access is restricted with
apiServerAuthorizedIpRanges. - AKS control-plane pricing tier is parameterized with
aksSkuTier(dev:Free, prd:Standard). - ACR SKU is environment-tuned for cost (
Basicin dev,Standardin prd). - Log Analytics cost controls are parameterized with
logAnalyticsSkuName,logAnalyticsRetentionInDays, andlogAnalyticsDailyQuotaGb(dev defaults:PerGB2018,30,0.5; prd defaults:PerGB2018,90,-1). - ACR public endpoint is enabled with selected-network firewall rules via
acrAllowedIpRules. - ACR is VNet integrated through a private endpoint on
privateEndpointSubnetName.
AKS is configured with the AVM fluxExtension enabled (flux-system release namespace) to support Flux GitOps extension deployment.
Flux extension configuration settings are parameterized via fluxExtensionConfigurationSettings (JSON object string), with a safe default of {} in infra-pipeline-common/pipelines/variables/common.yml.
Flux configurations are parameterized via fluxConfigurations and point to https://github.com/jeevan-spark-org/flux-cd with infra and apps kustomizations (apps depends on infra) for environment-specific paths.
Flux app deployment in this setup expects OCI Helm charts and container images published to environment ACRs, with Flux reconciling those artifacts based on flux-cd manifests.
Parameter strategy:
- One shared parameter file:
templates/aks/aks.bicepparam aks.bicepparamuses#{{ variableName }}placeholders for all parameter values- Environment-specific values are injected at deploy time from
infra-pipeline-common/pipelines/variables/dev.ymlandinfra-pipeline-common/pipelines/variables/prd.ymlvia qetza ReplaceTokens initialization in the deploy stage - Complex values (arrays/objects/integers) are passed as strings and converted inside Bicep using
json()/int()helper variables - Network address space (
vnetAddressPrefixes) is passed as a string token and normalized into an array intemplates/network/network.bicepbefore module invocation. - AKS autoscaling is parameterized separately for system and user node pools (
systemNodePoolEnableAutoScaling,userNodePoolEnableAutoScaling) with separate min/max settings per pool (systemNodePoolMinCount,systemNodePoolMaxCount,userNodePoolMinCount,userNodePoolMaxCount).
Review and update module versions regularly after validation.
-
Create an Azure Resource Manager service connection with least privilege.
-
Configure pipeline variables or variable groups:
azureServiceConnection- environment-specific values are provided in
infra-pipeline-common/pipelines/variables/dev.ymlandinfra-pipeline-common/pipelines/variables/prd.yml
-
Configure environment approvals/checks for deployment environments.
- Never commit credentials or secrets.
- Use Azure DevOps variable groups/Key Vault-backed secrets.
- Prefer private networking and production-hardening settings for non-dev environments.