AKS - Create and Import Cluster

This document describes how to create AksCluster with Kosmos operator with managed identity

Prerequisite

  • Login to Kosmos operator endpoints by Kosmos CLI

    kosmos login console.kosmos.spcplatform.com --access-key [AccessKey]
    
  • IAM account with root or admin access policies for setting up the permissions

  • kubectl

  • Install Helm CLI


1. Create managed identity service principal

ParameterDescriptionExample
<AZURE_LOCATION_NAME>Azure regionkoreacentral
<RESOURCE_GROUP_NAME>Azure resource groupkosmos-resource-group
<IDENTITY_NAME>Name for the managed identitykosmos-managed-identity
<SUBSCRIPTION_ID>Azure subscription IDxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  • Use ${azure-location-name}: ex) koreacentral
  • Set ${resource-group-name} : ex) kosmos-resource-group

Step 1-A: Create a resource group

Use the desired Azure location and resource group name:

az group create --location ${azure-location-name} --resource-group ${resource-group-name}

Step 1-B: Select subscription ID

List all subscriptions to get the required subscription and tenant IDs:

az account list --all

Example output:

[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "2d...",
    "id": "[SUBSCRIPTION_ID]", // Use this
    "isDefault": true,
    "managedByTenants": [],
    "name": "kosmos.name",
    "state": "Enabled",
    "tenantId": "[TENANT_ID]", // Use this
    "user": {
      "name": "[account]@samsungemail.com",
      "type": "user"
    }
  }
]

Step 1-C: Create managed identity service principal with contributor role

az identity create \
  --subscription <SUBSCRIPTION_ID> \
  --resource-group <RESOURCE_GROUP_NAME> \
  --name <IDENTITY_NAME> \
  --location <AZURE_LOCATION_NAME>

Example output:

{
  "clientId": "[CLIENT_ID]",
  "id": "/subscriptions/[SUBSCRIPTION_ID]/resourcegroups/[RESOURCE_GROUP_NAME]/providers/Microsoft.ManagedIdentity/userAssignedIdentities/[IDENTITY-NAME]",
  "location": "[AZURE_LOCATION_NAME]",
  "name": "[IDENTITY_NAME]",
  "principalId": "[PRINCIPAL_ID]",
  "resourceGroup": "[RESOURCE_GROUP_NAME]",
  "systemData": null,
  "tags": {},
  "tenantId": "[TENANT_ID]",
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
}

Then run command:

az role assignment create --assignee <CLIENT_ID> \
  --role Contributor \
  --scope /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP_NAME>


2. OIDC federation setting

Step 2-A: Create federated-credential

ParameterDescriptionExample
<FLEET_NAME>Kosmos fleet namemy-fleet
<FEDERATED_CREDENTIAL_NAME>Federated credential nameKosmosFederationTest
az identity federated-credential create \
  --resource-group <RESOURCE_GROUP_NAME> \
  --name <FEDERATED_CREDENTIAL_NAME> \
  --issuer "https://console.kosmos.spcplatform.com/kosmos-oidc" \
  --subject fleet-<FLEET_NAME> \
  --audience kosmos-operator \
  --identity-name <IDENTITY_NAME>

Step 2-B: Describe the federated credential

  • Use ${resource-group-name} as 1-A
  • Use 1-C [IDENTITY_NAME] for ${IDENTITY_NAME}
  • Use 2-A [FEDERATED_CREDENTIAL_NAME] for ${FEDERATED_CREDENTIAL_NAME}
az identity federated-credential show \
  --resource-group <RESOURCE_GROUP_NAME> \
  --name <FEDERATED_CREDENTIAL_NAME> \
  --identity-name <IDENTITY_NAME>

Output:

{
  "audiences": [
    "kosmos-operator"
  ],
  "id": "/subscriptions/[SUBSCRIPTION_ID]/resourcegroups/[RESOURCE_GROUP_NAME]/providers/Microsoft.ManagedIdentity/userAssignedIdentities/[IDENTITY_NAME]/federatedIdentityCredentials/[FEDERATED_CREDENTIAL_NAME]",
  "issuer": "https://console.kosmos.spcplatform.com/kosmos-oidc",
  "name": "[FEDERATED_CREDENTIAL_NAME]",
  "resourceGroup": "[RESOURCE_GROUP_NAME]",
  "subject": "fleet-${FLEET_NAME}",
  "systemData": null,
  "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials"
}

Step 2-C: Create Tags for federated-credential at ServicePrincipal

az identity create --name <IDENTITY_NAME> \
  --resource-group <RESOURCE_GROUP_NAME> \
  --tags <FEDERATED_CREDENTIAL_NAME>=Azure_<TENANT_ID>_<SUBSCRIPTION_ID>

Caution for update tags: There is no update command in azure, so if you are going to add additional tags for another federated_credential. Please add the previous tags with the new tags like below.

TAGS=$(az identity show --name <IDENTITY_NAME> --resource-group <RESOURCE_GROUP_NAME> --query 'tags' --output json | jq -r 'to_entries | map("\(.key)=\(.value)") | join(" ")')
az identity create --name <IDENTITY_NAME> --resource-group <RESOURCE_GROUP_NAME> --tags $TAGS <FEDERATED_CREDENTIAL_NAME>=Azure_<TENANT_ID>_<SUBSCRIPTION_ID>
az identity create --name <IDENTITY_NAME> --resource-group <RESOURCE_GROUP_NAME> --tags $TAGS <FEDERATED_CREDENTIAL_NAME>=Azure_<TENANT_ID>_<SUBSCRIPTION_ID>

3. Create a role for the service principal

Step 3-A: Create sample files

Create the following files locally:

  • kosmosOperatorRole.json — access to AKS-related operations in the resource group
  • kosmosRegisterActionRole.json — permission to register container service at subscription level

Make sure to replace:

  • <SUBSCRIPTION_ID>

  • <RESOURCE_GROUP_NAME>

  • [ROLE_NAME1], [ROLE_NAME2] with your desired role names

Sample file 1: kosmosOperatorRole.json

{
    "Name": "[ROLE_NAME1]",
    "IsCustom": true,
    "Description": "Everything needed by Rancher AKSv2 operator",
    "Actions": [
        "Microsoft.Compute/disks/delete",
        "Microsoft.Compute/disks/read",
        "Microsoft.Compute/disks/write",
        "Microsoft.Compute/diskEncryptionSets/read",
        "Microsoft.Compute/locations/DiskOperations/read",
        "Microsoft.Compute/locations/vmSizes/read",
        "Microsoft.Compute/locations/operations/read",
        "Microsoft.Compute/proximityPlacementGroups/write",
        "Microsoft.Compute/snapshots/delete",
        "Microsoft.Compute/snapshots/read",
        "Microsoft.Compute/snapshots/write",
        "Microsoft.Compute/virtualMachineScaleSets/manualUpgrade/action",
        "Microsoft.Compute/virtualMachineScaleSets/delete",
        "Microsoft.Compute/virtualMachineScaleSets/read",
        "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/networkInterfaces/read",
        "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/networkInterfaces/ipconfigurations/publicipaddresses/read",
        "Microsoft.Compute/virtualMachineScaleSets/virtualmachines/instanceView/read",
        "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read",
        "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/write",
        "Microsoft.Compute/virtualMachineScaleSets/write",
        "Microsoft.Compute/virtualMachines/read",
        "Microsoft.Compute/virtualMachines/write",
        "Microsoft.ContainerService/managedClusters/read",
        "Microsoft.ContainerService/managedClusters/write",
        "Microsoft.ContainerService/managedClusters/delete",
        "Microsoft.ContainerService/managedClusters/accessProfiles/listCredential/action",
        "Microsoft.ContainerService/managedClusters/agentPools/read",
        "Microsoft.ContainerService/managedClusters/agentPools/write",
        "Microsoft.ContainerService/managedClusters/agentPools/delete",
        "Microsoft.ManagedIdentity/userAssignedIdentities/assign/action",
        "Microsoft.Network/applicationGateways/read",
        "Microsoft.Network/applicationGateways/write",
        "Microsoft.Network/loadBalancers/write",
        "Microsoft.Network/loadBalancers/backendAddressPools/join/action",
        "Microsoft.Network/loadBalancers/delete",
        "Microsoft.Network/loadBalancers/read",
        "Microsoft.Network/networkInterfaces/join/action",
        "Microsoft.Network/networkInterfaces/read",
        "Microsoft.Network/networkInterfaces/write",
        "Microsoft.Network/networkSecurityGroups/read",
        "Microsoft.Network/networkSecurityGroups/write",
        "Microsoft.Network/publicIPAddresses/delete",
        "Microsoft.Network/publicIPAddresses/join/action",
        "Microsoft.Network/publicIPAddresses/read",
        "Microsoft.Network/publicIPAddresses/write",
        "Microsoft.Network/publicIPPrefixes/join/action",
        "Microsoft.Network/privatednszones/*",
        "Microsoft.Network/routeTables/read",
        "Microsoft.Network/routeTables/routes/delete",
        "Microsoft.Network/routeTables/routes/read",
        "Microsoft.Network/routeTables/routes/write",
        "Microsoft.Network/routeTables/write",
        "Microsoft.Network/virtualNetworks/read",
        "Microsoft.Network/virtualNetworks/subnets/join/action",
        "Microsoft.Network/virtualNetworks/subnets/read",
        "Microsoft.Network/virtualNetworks/joinLoadBalancer/action",
        "Microsoft.OperationalInsights/workspaces/sharedkeys/read",
        "Microsoft.OperationalInsights/workspaces/read",
        "Microsoft.OperationsManagement/solutions/write",
        "Microsoft.OperationsManagement/solutions/read",
        "Microsoft.Resources/subscriptions/resourcegroups/read",
        "Microsoft.Resources/subscriptions/resourcegroups/write",
        "Microsoft.Storage/operations/read",
        "Microsoft.Storage/storageAccounts/listKeys/action",
        "Microsoft.Storage/storageAccounts/delete",
        "Microsoft.Storage/storageAccounts/read",
        "Microsoft.Storage/storageAccounts/write"
    ],
    "NotActions": [],
    "DataActions": [],
    "NotDataActions": [],
    "AssignableScopes": [
        "/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}"
    ]
}

Sample file 2: kosmosRegisterActionRole.json

{
    "Name": "[ROLE_NAME2]",
    "IsCustom": true,
    "Description": "Everything needed by Rancher AKSv2 operator with subscription",
    "Actions": [
        "Microsoft.ContainerService/register/action"
    ],
    "NotActions": [],
    "DataActions": [],
    "NotDataActions": [],
    "AssignableScopes": [
        "/subscriptions/${SUBSCRIPTION_ID}"
    ]
}

Step 3-B: Create roles

az role definition create --role-definition kosmosOperatorRole.json
az role definition create --role-definition kosmosRegisterActionRole.json

Step 3-C: Assign the roles

az role assignment create --assignee <CLIENT_ID> \
  --scope /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP_NAME> \
  --role <ROLE_NAME1>

az role assignment create --assignee <CLIENT_ID> \
  --scope /subscriptions/<SUBSCRIPTION_ID> \
  --role <ROLE_NAME2>

If the --role <ROLE_NAME> does not work, use the ROLE_ID instead:

az role assignment create --assignee <CLIENT_ID> \
  --scope /subscriptions/<SUBSCRIPTION_ID> \
  --role <ROLE_ID>

4. AKS - Create cluster

Note: Replace the placeholders in the YAML file before using kosmos create.

Create a sample file

Use the following:

FieldValue
metadata.name<CLUSTER_NAME>
aksConfig.resourceLocation<AZURE_LOCATION_NAME>
aksConfig.resourceGroup<RESOURCE_GROUP_NAME>
aksConfig.tenantID<TENANT_ID>
aksConfig.subscriptionID<SUBSCRIPTION_ID>
aksConfig.clientID<CLIENT_ID>

Sample file: akscluster_sample.yaml

apiVersion: storage.kosmos.spcplatform.com/v1
kind: AKSCluster
metadata:
  name: ${CLUSTER_NAME}
  namespace: pds-test
spec:
    name: ${CLUSTER_NAME}
    aksConfig:
        resourceLocation: "${azure-location-name}"
        resourceGroup: "${resource-group-name}"
        clusterName: "${CLUSTER_NAME}"
        tenantID: "${tenant_ID}"
        subscriptionID: "${SUBSCRIPTION_ID}"
        clientID: "${CLIENT_ID}"
        imported: false
        dnsPrefix: "${DNS_SAMPLE}"
        networkPlugin: "azure"
        virtualNetwork: "${VPC_SAMPLE}"
        subnet: "${SUBNET_SAMPLE}"
        dnsServiceIp: "10.96.0.10"
        kubernetesVersion: "1.29"
        privateCluster: false
        linuxAdminUsername: "ADMIN_USERNAME"
        loadBalancerSku: "Standard"
        nodePools:
        - name: "${NODEPOOL_NAME}"
          count: 3
          maxPods: 10
          osDiskSizeGB: 30
          vmSize: "Standard_DS2_v2"
          mode: "System"
          osType: "Linux"
          osDiskType: "Managed"
        podCidr: "192.169.0.0/23"
        serviceCidr: "10.96.0.0/24"

Login to Kosmos

kosmos login https://console.kosmos.spcplatform.com/

Create the cluster

kosmos create aks --file akscluster_sample.yaml

Verify cluster status

Check cluster status in Kosmos:

kosmos list aks --fleet <FLEET_ID>

Verify the cluster in Azure

az login
az aks list -o table

5. Connect and validate cluster

Update kube config

az aks get-credentials -n <CLUSTER_NAME> -g <RESOURCE_GROUP_NAME>

Verify kubectl works

kubectl get ns

Connect to the cluster**

kosmos join cluster <CLUSTER_NAME> --fleet <FLEET_ID>

After connecting, the status in Kosmos changes from “connecting” to “ready.”

Validate cluster connectivity

Open a new terminal window and execute:

kosmos login https://console.kosmos.spcplatform.com/
kosmos use cluster <CLUSTER_NAME> --fleet <FLEET_ID>
kubectl get ns

AKS - Import cluster

Note: (If working ) Connect to VPN

Connect to the ALL-traffic-us-west.joyent.us VPN server.

Create an AKS cluster and node

Verify the cluster in Azure

az aks list -o table

Update kube config

az aks get-credentials -n <CLUSTER_NAME> -g <RESOURCE_GROUP_NAME>

Verify kubectl works

kubectl get ns

Create a YAML file

apiVersion: storage.kosmos.spcplatform.com/v1
kind: AKSCluster
metadata:
  labels:
    app.kubernetes.io/name: ${CLUSTER_NAME}
    app.kubernetes.io/instance: ${FLEET_ID}
    app.kubernetes.io/part-of: kosmos
    app.kubernetes.io/managed-by: kustomize
    app.kubernetes.io/created-by: kosmos
  name: ${CLUSTER_NAME}
  namespace: ${FLEET_ID}
spec:
    name: ${CLUSTER_NAME}
    description: "This AKS cluster is imported using kosmos CLI."
    aksConfig:
        resourceLocation: "westus2"
        resourceGroup: "Kosmos-USW2"
        clusterName: ${CLUSTER_NAME}
        tenantID: ${TENANT_ID}
        subscriptionID: ${SUBSCRIPTION_ID}
        clientID: ${CLIENT_ID}
        imported: true
        kubernetesVersion: "1.30.7"

Login to Kosmos

kosmos login https://console.kosmos.spcplatform.com/

Import the cluster

kosmos create aks --file <YAML-file>

Verify cluster status

Check cluster status in Kosmos:

kosmos list aks --fleet <FLEET_ID>

Connect to the cluster

kosmos join cluster <CLUSTER_NAME> --fleet <FLEET_ID>

After connecting, the status in Kosmos changes to “ready.”

Validate cluster connectivity

Open a new terminal window and execute:

kosmos login https://console.kosmos.spcplatform.com/
kosmos use cluster <CLUSTER_NAME> --fleet <FLEET_ID>
kubectl get ns

Edit this page on GitHub