ARM Template – Deploy an AKS cluster using managed identity and managed Azure AD integration

As I mentioned in my other blog post before I have updated my Azure Resource Manager template as well. Switching from the AAD service principal to managed identity option and from the AAD v1 integration to AAD v2 which is also managed.

Other changes and improvements are the following ones:

  • Private cluster support
  • Managed control plane SKU tier support
  • Windows node pool support
  • Node labels and taints support

-> https://github.com/neumanndaniel/armtemplates/blob/master/container/aks.json
-> https://github.com/neumanndaniel/armtemplates/blob/master/container/aks-nodepool.json

Overall the switch to managed identity and the managed AAD integration takes some operational burden away like regular credential rotation and makes the deployment way easier.

...
        "aadProfile": {
          "managed": true,
          "adminGroupObjectIDs": "[parameters('adminGroups')]"
        },
        ...
      },
      "identity": {
        "type": "SystemAssigned"
      },
...

Here is an example how to use the template and deploy an Azure Kubernetes service cluster using managed identity and the managed AAD integration.

> az deployment group create -g azst-aks-demo -f aks.json -p aks.parameters.json --verbose
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "name": {
      "value": "azst-aks-demo"
    },
    "agentPoolProfiles": {
      "value": [
        {
          "name": "nodepool1",
          "nodeCount": 2,
          "nodeVmSize": "Standard_D4_v3",
          "availabilityZones": [
            "1",
            "2",
            "3"
          ],
          "osType": "Linux",
          "enableAutoScaling": false,
          "mode": "System",
          "nodeLabels": {
            "environment": "demo"
          },
          "nodeTaints": []
        }
      ]
    },
    "kubernetesVersion": {
      "value": "1.18.6"
    },
    "workspaceName": {
      "value": "azurekubernetesservicedemo"
    },
    "workspaceResourceGroup": {
      "value": "operations-management"
    },
    "acrName": {
      "value": "azstcr"
    },
    "acrResourceGroupName": {
      "value": "acr"
    },
    "vnetName": {
      "value": "azst-aks-demo"
    },
    "vnetSubnetName": {
      "value": "azst-aks-demo"
    },
    "vnetResourceGroupName": {
      "value": "azst-aks-demo"
    },
    "controlPlaneSku": {
      "value": "Free"
    },
    "aksPolicy": {
      "value": false
    },
    "adminGroups": {
      "value": [
        "00000000-0000-0000-0000-000000000000"
      ]
    },
    "ipWhitelist": {
      "value": []
    },
    "privateCluster": {
      "value": false
    }
  }
}

The RBAC role assignment for the managed identity option is different to the one using a service principal.

...
    {
      "apiVersion": "[variables('apiVersion').deployments]",
      "type": "Microsoft.Resources/deployments",
      "name": "[concat(parameters('name'), '-vnet-subnet-rbac')]",
      "resourceGroup": "[parameters('vnetResourceGroupName')]",
      "dependsOn": [
        "[concat('Microsoft.ContainerService/managedClusters/', parameters('name'))]"
      ],
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {},
          "variables": {},
          "resources": [
            {
              "apiVersion": "[variables('apiVersion').rbac]",
              "type": "Microsoft.Network/virtualNetworks/subnets/providers/roleAssignments",
              "name": "[concat(parameters('vnetName'), '/', parameters('vnetSubnetName'), '/Microsoft.Authorization/', guid(resourceGroup().id, parameters('name'), 'Network Contributor'))]",
              "properties": {
                // Network Contributor = 4d97b98b-1d4f-4787-a291-c67834d212e7
                "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]",
                "principalId": "[reference(concat('Microsoft.ContainerService/managedClusters/', parameters('name')), variables('apiVersion').aks, 'Full').identity.principalId]",
                "scope": "[variables('agentPoolProfiles').vnetSubnetId]"
              }
            }
          ],
          "outputs": {}
        }
      }
    },
...

For the necessary permissions on the Virtual Network subnet you use the AKS cluster managed identity. Allowing the AKS cluster to pull images from your Azure Container Registry you use another managed identity that got created for all node pools called kubelet identity.

Beside that when you enable the add-ons Azure Monitor for containers and Azure Policy for AKS, each add-on gets its own managed identity.

Facebooktwitterlinkedinmail