Skip to content

Implementation


Step-by-step guide to enable Container Insights with ContainerLogV2 on an AKS cluster.


Environment Variables

Set these before running the commands below:
export SUBSCRIPTION_ID=<subscription id>
export RESOURCE_GROUP=<resource group name>
export CLUSTER_NAME=<aks cluster name>
export LOCATION=<azure region, e.g. eastus>
export LAW_NAME=<log analytics workspace name>

Install Required CLI Extensions

az extension add --name aks-preview --upgrade
az provider register --namespace Microsoft.Monitor
az provider register --namespace Microsoft.Insights

Step 1 — Create a Log Analytics Workspace

A Log Analytics Workspace is the destination for all container logs. Skip this step if you already have one.
# Create the workspace
az monitor log-analytics workspace create \
  --resource-group $RESOURCE_GROUP \
  --workspace-name $LAW_NAME \
  --location $LOCATION \
  --subscription $SUBSCRIPTION_ID

# Save the workspace resource ID for later steps
export LAW_RESOURCE_ID=$(az monitor log-analytics workspace show \
  --resource-group $RESOURCE_GROUP \
  --workspace-name $LAW_NAME \
  --subscription $SUBSCRIPTION_ID \
  --query id -o tsv)

echo "Workspace ID: $LAW_RESOURCE_ID"

Step 2 — Get AKS Cluster Credentials

az aks get-credentials \
  -g $RESOURCE_GROUP \
  -n $CLUSTER_NAME \
  -a --overwrite-existing \
  --subscription $SUBSCRIPTION_ID

Step 3 — Enable Container Insights with ContainerLogV2

This single command enables the Azure Monitor Agent on your AKS cluster:
az aks enable-addons \
  --addon monitoring \
  --name $CLUSTER_NAME \
  --resource-group $RESOURCE_GROUP \
  --workspace-resource-id $LAW_RESOURCE_ID \
  --subscription $SUBSCRIPTION_ID

What this does:

  • Deploys the ama-logs DaemonSet into kube-system namespace
  • Creates a Data Collection Rule (DCR) linked to the cluster
  • Starts collecting container stdout/stderr, Kubernetes events, and performance metrics
  • Sends logs to the Log Analytics Workspace in ContainerLogV2 format

Step 4 — Configure Log Filtering (ConfigMap)

Create `container-logs-configmap.yaml` to control which namespaces are collected and enable metadata enrichment:
apiVersion: v1
kind: ConfigMap
metadata:
  name: container-azm-ms-agentconfig
  namespace: kube-system
data:
  schema-version: v1
  config-version: ver1
  log-data-collection-settings: |-
    [log_collection_settings]
      [log_collection_settings.stdout]
        enabled = true
        exclude_namespaces = ["kube-system", "gatekeeper-system"]
      [log_collection_settings.stderr]
        enabled = true
        exclude_namespaces = ["kube-system", "gatekeeper-system"]
      [log_collection_settings.env_var]
        enabled = true
      [log_collection_settings.enrich_container_logs]
        enabled = true
      [log_collection_settings.collect_all_kube_events]
        enabled = true
Apply it:
kubectl apply -f container-logs-configmap.yaml

Note: After updating the ConfigMap, AMA pods automatically pick up changes within ~5 minutes. To force an immediate reload: kubectl rollout restart daemonset ama-logs -n kube-system


Step 5 — Configure Data Collection Rule (DCR) for Namespace Filtering

The DCR controls what data gets collected at the platform level. You can scope collection to specific namespaces.
Create `container-logs-dcr.json`:
{
  "properties": {
    "dataSources": {
      "extensions": [
        {
          "name": "ContainerInsightsExtension",
          "streams": ["Microsoft-ContainerLogV2"],
          "extensionSettings": {
            "dataCollectionSettings": {
              "interval": "1m",
              "namespaceFilteringMode": "Include",
              "namespaces": ["default", "app", "production"],
              "enableContainerLogV2": true
            }
          },
          "extensionName": "ContainerInsights"
        }
      ]
    },
    "destinations": {
      "logAnalytics": [
        {
          "workspaceResourceId": "<LAW_RESOURCE_ID>",
          "name": "ciworkspace"
        }
      ]
    },
    "dataFlows": [
      {
        "streams": ["Microsoft-ContainerLogV2"],
        "destinations": ["ciworkspace"]
      }
    ]
  }
}
Find and inspect the DCR created by the addon:
az monitor data-collection rule list \
  --resource-group $RESOURCE_GROUP \
  --subscription $SUBSCRIPTION_ID \
  --query "[?contains(name,'MSCI')].{name:name, id:id}" -o table

Step 6 — (Optional) Export Logs to Event Hub

If you need logs forwarded to an Event Hub, set up a Diagnostic Setting:
# Get Event Hub Authorization Rule ID
export EVENTHUB_RULE_ID=$(az eventhubs namespace authorization-rule show \
  --resource-group $RESOURCE_GROUP \
  --namespace-name $EVENTHUB_NAMESPACE \
  --name RootManageSharedAccessKey \
  --subscription $SUBSCRIPTION_ID \
  --query id -o tsv)

# Get AKS cluster resource ID
export AKS_RESOURCE_ID=$(az aks show \
  --name $CLUSTER_NAME \
  --resource-group $RESOURCE_GROUP \
  --subscription $SUBSCRIPTION_ID \
  --query id -o tsv)

# Create diagnostic setting to export logs to Event Hub
az monitor diagnostic-settings create \
  --name "aks-logs-to-eventhub" \
  --resource $AKS_RESOURCE_ID \
  --event-hub $EVENTHUB_INSTANCE_NAME \
  --event-hub-rule $EVENTHUB_RULE_ID \
  --logs '[{"categoryGroup":"allLogs","enabled":true}]' \
  --subscription $SUBSCRIPTION_ID

Verification

Check AMA Agent Pods

kubectl get pods -n kube-system -l component=ama-logs -o wide
Expected output — one pod per node, all `Running` with `1/1` READY:
NAME              READY   STATUS    RESTARTS   AGE
ama-logs-xxxxx    1/1     Running   0          5m
ama-logs-rs-xxxx  1/1     Running   0          5m

Check Agent Logs

kubectl logs -n kube-system -l component=ama-logs --tail=50
kubectl logs -n kube-system -l component=ama-logs | grep -i "started\|success\|heartbeat"

Verify Addon Is Enabled

az aks show -g $RESOURCE_GROUP -n $CLUSTER_NAME \
  --subscription $SUBSCRIPTION_ID \
  --query "addonProfiles.omsagent.enabled"

Verify Logs in Log Analytics

Allow 5–10 minutes after enabling, then run in Log Analytics:
ContainerLogV2
| where TimeGenerated > ago(30m)
| summarize Count = count() by PodNamespace
| order by Count desc

Troubleshooting

Symptom Fix
No ama-logs pods found Run az aks enable-addons --addon monitoring ... again
Pods in CrashLoopBackOff Check pod logs: kubectl logs -n kube-system -l component=ama-logs
0 rows in ContainerLogV2 Verify addon enabled (az aks show ... --query "addonProfiles.omsagent.enabled"), check workspace ID is correct, ensure workspace is in same or peered region
Logs missing for a namespace Update ConfigMap exclude_namespaces and restart: kubectl rollout restart daemonset ama-logs -n kube-system
High log volume / cost Switch to Basic tier or add namespace filtering in DCR
ConfigMap changes not applied Wait 5 min or force: kubectl rollout restart daemonset ama-logs -n kube-system

Quick Deploy Script

#!/bin/bash
# container-insights-deploy.sh
# Usage: sh ./container-insights-deploy.sh <SUBSCRIPTION_ID> <RESOURCE_GROUP> <CLUSTER_NAME> <LAW_NAME> <LOCATION>

set -e

SUBSCRIPTION_ID=$1
RESOURCE_GROUP=$2
CLUSTER_NAME=$3
LAW_NAME=$4
LOCATION=$5

echo "=== Container Insights Deployment ==="
echo "Subscription: $SUBSCRIPTION_ID"
echo "Cluster:      $CLUSTER_NAME"
echo "Workspace:    $LAW_NAME"

# Step 1: Create Log Analytics Workspace (idempotent)
echo "[1/3] Creating Log Analytics Workspace..."
az monitor log-analytics workspace create \
  --resource-group $RESOURCE_GROUP \
  --workspace-name $LAW_NAME \
  --location $LOCATION \
  --subscription $SUBSCRIPTION_ID \
  --only-show-errors 2>/dev/null || true

LAW_RESOURCE_ID=$(az monitor log-analytics workspace show \
  --resource-group $RESOURCE_GROUP \
  --workspace-name $LAW_NAME \
  --subscription $SUBSCRIPTION_ID \
  --query id -o tsv)

# Step 2: Get AKS credentials
echo "[2/3] Getting AKS credentials..."
az aks get-credentials -g $RESOURCE_GROUP -n $CLUSTER_NAME -a \
  --overwrite-existing --subscription $SUBSCRIPTION_ID

# Step 3: Enable Container Insights
echo "[3/3] Enabling Container Insights..."
az aks enable-addons \
  --addon monitoring \
  --name $CLUSTER_NAME \
  --resource-group $RESOURCE_GROUP \
  --workspace-resource-id $LAW_RESOURCE_ID \
  --subscription $SUBSCRIPTION_ID

echo ""
echo "=== Deployment Complete ==="
echo "Verify: kubectl get pods -n kube-system -l component=ama-logs"
echo "Query:  Go to Log Analytics → ContainerLogV2 table"
Usage:
sh ./container-insights-deploy.sh $SUBSCRIPTION_ID $RESOURCE_GROUP $CLUSTER_NAME $LAW_NAME $LOCATION

Terraform Alternative

# Log Analytics Workspace
resource "azurerm_log_analytics_workspace" "law" {
  name                = var.law_name
  location            = var.location
  resource_group_name = var.resource_group_name
  sku                 = "PerGB2018"
  retention_in_days   = 30
}

# Log Analytics Solution for Container Insights
resource "azurerm_log_analytics_solution" "container_insights" {
  solution_name         = "ContainerInsights"
  location              = var.location
  resource_group_name   = var.resource_group_name
  workspace_resource_id = azurerm_log_analytics_workspace.law.id
  workspace_name        = azurerm_log_analytics_workspace.law.name

  plan {
    publisher = "Microsoft"
    product   = "OMSGallery/ContainerInsights"
  }
}

# AKS Cluster with Container Insights enabled
resource "azurerm_kubernetes_cluster" "aks" {
  name                = var.cluster_name
  location            = var.location
  resource_group_name = var.resource_group_name
  dns_prefix          = var.cluster_name

  default_node_pool {
    name       = "default"
    node_count = 3
    vm_size    = "Standard_DS2_v2"
  }

  identity {
    type = "SystemAssigned"
  }

  oms_agent {
    log_analytics_workspace_id = azurerm_log_analytics_workspace.law.id
  }
}