Azure Container Apps
Azure Container Apps is Microsoft's serverless container platform; its jobs run a container to completion on demand, on a schedule or on an event. The Azure platform runs two event-driven Container Apps jobs: the self-hosted GitHub runners of the Azure Enterprise Baseline and the ETL trigger of the Azure Data and ETL Blueprint.
What it does
An environment is the network and logging boundary, placed in a subnet delegated to it and either internal or external. It offers workload profiles: the serverless Consumption profile, billed per vCPU-second and GiB-second, and dedicated profiles. Inside it a container app runs continuously, while a job runs executions that end. An event-driven job scales with a KEDA scaler (Kubernetes Event-driven Autoscaling): every polling interval the scaler reads a queue length and starts executions between a minimum and a maximum, each with a timeout and a retry limit. A job pulls its image and resolves Key Vault references with its managed identity, so no credential is stored in the job.
How BuiltForProd uses it
| GitHub runners | ETL trigger | |
|---|---|---|
| Product and unit | Azure Enterprise Baseline, github-runners | Data and ETL Blueprint, etl-trigger |
| Subscription | acme-core-auto | Each plat stage |
| Environment | <prefix>-runners-cae, internal, zone-redundant, snet-aca-runners | <prefix>-cae, internal, zone-redundant, the spoke's snet-aca |
| Job | <prefix>-github-runner-caj | <prefix>-etl-trigger-caj |
| Scaler | KEDA github-runner, 0 to 5 executions | KEDA azure-queue on etl-trigger, 0 to 3 executions |
| Size, timeout | 2 vCPU, 4 GiB, 3,600 s, no retry | 0.5 vCPU, 1 GiB, 300 s, one retry |
| Identity | id-acme-github-runners | id-<prefix>-etl-trigger |
| Logs | Audit workspace | Stage application workspace |
| Cost (code comments) | $0 idle, ~$0.12 per running runner-hour | $0.000024 per vCPU-second and $0.000003 per GiB-second after the monthly free grant |
GitHub runners. enable_github_runners is on by default. Every 30 seconds the scaler asks GitHub for queued workflow jobs with the labels self-hosted,linux,aks-deploy across the organization and starts one execution per job; each execution registers one ephemeral runner, takes that job and exits. The acme-runner GitHub App's private key, App ID and installation ID stay in the CI platform vault kv-acme-eus2-auto-plat as Key Vault references, which the job identity resolves at run time with Key Vault Secrets User on those three secrets only; it also holds AcrPull for the github-runner image. That image adds the Azure CLI, OpenTofu, Terragrunt, kubectl, kubelogin, Helm, sops and yq to the GitHub runner base, each at a pinned, checksum-verified version. Private endpoints in the runner network reach the state storage and the CI platform vault, which is why the blueprint applies and the secrets sync select these runners through RUNNER_LABELS; see GitHub Actions. A dedicated D4 profile (~$0.17 per instance-hour) is the @optional: alternative to Consumption.
ETL trigger. Azure Event Grid writes a message to the lake's etl-trigger queue for every new input file. The scaler reads the queue length every 30 seconds with the job identity and starts an execution while messages wait. The container dequeues up to 32 messages, keeps the raw/input/*.json files that still exist and are not empty, reads etl--job-id from the stage's contract vault and starts one run of the Azure Databricks job for the batch with a Microsoft Entra token. It deletes the messages once the run has started. A failed start leaves them in the queue for a later execution, and the run's idempotency token, derived from the message IDs, stops a retry from starting a second run.
The trigger's image tag lives in the contract vault secret etl-trigger--image-tag. The code repository's deploy step updates the job image and writes every tag it deploys there; the unit reads the secret back, so a later plan matches the running image and never rolls a deployment back. Both jobs work in either egress mode of the hub.
Terms you will see
| Term | Meaning |
|---|---|
| Environment | The network and logging boundary of the jobs, in a delegated subnet. |
| Job execution | One run of a job's container to completion: one runner, or one ETL batch. |
| KEDA scaler | The rule that turns a queue length into executions. |
| Key Vault reference | A secret the job resolves from Key Vault at run time with its identity. |
| Workload profile | Consumption (per second, scale to zero) or a dedicated VM size. |
RUNNER_LABELS | The repository variable that sends a workflow job to the self-hosted runners. |
Where to read more
- Azure Enterprise Baseline overview and Azure Data and ETL Blueprint overview.
- GitHub Actions for the workflows that run on the runners.
- Azure Databricks for the job the trigger starts.