Tutorial - ACI Deployment

This is a step-by-step tutorial for deploying the Azure Container Host in ACI that runs custodian policies that are uploaded to an Azure Storage Account. This tutorial makes use of the Azure CLI, so make sure that it is installed and you are logged in to your subscription.

1. Create a Resource Group

This will hold all of the Azure resources created in this tutorial. You could use an existing resource group too.

az group create --name c7n-aci-tutorial --location westus2

2. Create a Storage Account

This storage account will hold all of the blobs and queues used by the container host. You could also use an existing resource here or multiple storage accounts.

We will also create two blob containers. One will host the uploaded policies, and the other will store the custodian output files of running policies.

az storage account create --resource-group c7n-aci-tutorial --name c7nstorage

account_key=$(az storage account keys list --account-name c7nstorage --query "[0].value" --output tsv)
az storage container create --account-name c7nstorage --account-key $account_key --name c7n-aci-policies
az storage container create --account-name c7nstorage --account-key $account_key --name c7n-aci-logs

3. Create a Managed Identity

This identity will be used with MSI on the ACI instance. You could also use an existing identity.

az identity create --resource-group c7n-aci-tutorial --name c7n-aci

This identity will need the proper permissions to interact with the storage account and any other azure resources that the Azure Container Host interacts with. This includes the resources that policies will run against.

The simplest way to grant these permissions is to make the identity a Contributor on the target subscription and a Storage Blob Data Contributor and Storage Queue Data Contributor on the storage account created above.

The <Target Subscription Resource Id> should be in the format /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. The <Storage Account Resource Id> should be in the format /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/c7n-aci-tutorial/providers/Microsoft.Storage/storageAccounts/c7nstorage, and is available in the json output from creating the storage account in step 2.

az role assignment create --assignee <Managed Identity Client Id> \
    --role "Contributor" --scope <Target Subscription Resource Id>

az role assignment create --assignee <Managed Identity Client Id> \
    --role "Storage Blob Data Contributor" --scope <Storage Account Resource Id>

az role assignment create --assignee <Managed Identity Client Id> \
    --role "Storage Queue Data Contributor" --scope <Storage Account Resource Id>

4. Create an Application Insights Instance

We will create an Application Insights instance to gather logs and telemetry generated by the running container host.

# You may need to add the application-insights extension
az extension add -n application-insights

az monitor app-insights component create --resource-group c7n-aci-tutorial --app c7n-aci-insights --location westus2

5. Create the ACI Container Host

Now all of the required Azure resources should exist, and we can deploy the Container Host ARM template. Create a parameters file called c7n-aci-tutorial.json. See the Container Host Documentation for information on filling out the environment variables.

    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "",
    "parameters": {
        "aci_name": {
            "value": "cloud-custodian"
        "user_assigned_identity_name": {
            "value": "c7n-aci"
        "azure_subscription_id": {
            "value": "<Target Subscription ID>"
        "azure_container_queue_name": {
            "value": "c7n-aci-events"
        "azure_container_policy_uri": {
            "value": "<Policy Storage Container URI>"
        "azure_container_storage_resource_id": {
            "value": "<Storage Account Resource ID>"
        "azure_container_log_group": {
            "value": "azure://<Instrumentation Key>"
        "azure_container_metrics": {
            "value": "azure://<Instrumentation Key>"
        "azure_container_output_dir": {
            "value": "<Log Storage Container URI>"

And deploy with this command

az group deployment create \
    --resource-group c7n-aci-tutorial \
    --template-file tools/ops/azure/container-host/aci/aci-template.json \
    --parameters @c7n-aci-tutorial.json

Once this deployment succeeds, the Azure Container Host should be running! You can see the logs with the following command:

az container logs --resource-group c7n-aci-tutorial --name cloud-custodian --follow

6. Upload a Custodian Policy

Finally, create a custodian policy called find-c7nstorage.yaml. This policy will just find the storage account we made earlier. We’ll set the mode to run every minute for easier testing.

- name: find-c7nstorage
  resource: azure.storage
    type: container-periodic
    schedule: "* * * * *"  # Run every minute as an example
  - type: value
    key: name
    op: eq
    value: c7nstorage

Upload this file to the policy storage container. Within a few minutes, the container host should pick it up and begin executing it.

az storage blob upload --account-name c7nstorage --account-key $account_key \
    --container-name c7n-aci-policies --file find-c7nstorage.yaml --name find-c7nstorage.yaml