loading...
Mega Therion AS

Using Azure CLI and Powershell to create Kubernetes cluster in Azure

alexanderviken profile image Alexander Viken Updated on ・5 min read

Here's a guide on how to set up a Azure Kubernetes Service cluster using Azure CLI and powershell. I use this environment to set up a default cluster for testing and it takes me about 3 minutes to set up a full basic environment for dev/test.

A tip, I use VSCode and the Azure CLI tool plugin with Powershell Core. This gives me almost the same functionality as I get through the Powershell ISE.

Requirements:

Once you have Powershell and Azure CLI installed run

az aks install-cli
Enter fullscreen mode Exit fullscreen mode

to install the kubectl client. Follow the instruction to set up the environment variable in system.

Open VSCode, or any other text editor and start building your script.

First thing first..

#login to your azure subscripiton
az login

#see your subscriptions
az account list

#set active subscription if you have more than one
az account set --name "<name of your azure subscripiton>"
Enter fullscreen mode Exit fullscreen mode

First we define the variables we need to use. change the value of the variables as you see fit. I am choosing location "North Europe" since I am in Norway but important part is that your AKS name must be unique within the location/region you choose and if you plan to deploy ACS also it's name must be globally unique.

# general
$location = "northeurope"
$aksrg = "cluster_rg"

# VNET##
$vnet = "cluster-vnet"
$vnet_address_range = "10.0.0.0/16"

# aks subnet
$akssn = "aks-sn"
$aks_cidr = "10.0.2.0/23"

# aks
$aks = "<define a unique name for your cluster (unique within $location)>"
$aks_srv_cidr = "192.168.6.0/23"
$aks_dns_ip = "192.168.6.10"
$aks_pod_cidr = "192.168.8.0/21"
$aks_docker_bridge = "172.17.0.1/16"

# acr
$registry = "<define a globally unique name for your registry>"
Enter fullscreen mode Exit fullscreen mode

Next we will create some resources. We start with our resource group and then create the virtual network and subnet.

# create the resource group
az group create --name $aksrg --location $location

# define a VNET
az network vnet create --name $vnet --resource-group $aksrg --address-prefixes 
$vnet_address_range

# create the AKS subnet inside the vnet
az network vnet subnet create -g $aksrg --vnet-name $vnet -n $akssn --address-prefixes $aks_cidr

# get id of the vnet
$vnetid = $(az network vnet show -n $vnet -g $aksrg --query id --output tsv)

# get the id of the subnet
$akssnid = $(az network vnet subnet show -g $aksrg --vnet-name $vnet -n $akssn --query id --output tsv)
Enter fullscreen mode Exit fullscreen mode

We also need to create a service principal that enables the AKS service to interact with the virtual network we created. One tip I have while working with Azure CLI and powershell is to install "jq". It is a lightweight and flexible command-line JSON processor that can be installed through Chocolatey. All of the Azure CLI commands can output json response values by applying the switch "--output json" to the command.
If you want your service principal to be a bit easier to spot in AAD you can attach a name to to the SP using the --name switch (ie: --name "${aks}_sp"). Also, if you attach name to the service principal and don't remove it in clean up, it'll be reused and patched the next time you run the script.

#create the service prinsipal and store the output in a json file
$outputfile = "aks_sp.json"
$filecontent = $(az ad sp create-for-rbac --skip-assignment --name "${aks}_sp" --output json)
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($outputfile, $filecontent, $Utf8NoBomEncoding)


#read the values from the json file
$aks_appid = $(jq -r ".appId" $outputfile)
$aks_secret = $(jq -r ".password" $outputfile)
Enter fullscreen mode Exit fullscreen mode

"jq" is a bit peckish about file encoding so to make sure it is stored in a compatible format we can force it to UTF8. On my laptop VScode integrated shell stores it as UTF-16 LE when I just dump the az ad sp create-for-rbac with "> $outputfile"

With the service principal created and loaded into the variables using jq we can assign the role of Contributor to the virtual network. Notice also the UTF8 converting. While I've been testing I've found that jq is a bit peckish on how it likes it's files encoded. Utf8 works fine so the converter just forces that.

NOTE!
If you run all of this as a single script you will most likely receive an error that "Principal <guid> does not exist in the directory <guid>". A "small hack" is to let the script sleep for about 10 seconds to give AAD time to create the service principal. I haven't found any better way to do this yet so if anyone have a "wait-for-it" command that works with "az ad" commands let me know in the comments :)

#ZzzzZZz
Start-Sleep -s 10
az role assignment create --assignee $aks_appid --scope $vnetid --role Contributor
Enter fullscreen mode Exit fullscreen mode

Now everything is set up and we can create the Azure Kubernetes Service. Another service that can be useful to deploy with AKS is a container registry. Especially when I use this as part of setting up a CI/CD

# optional create Azure Container Registry
az acr create --name $registry --resource-group $aksrg --sku basic
Enter fullscreen mode Exit fullscreen mode

If you didn't create an ACR, remove the --attach-acr parameter. ACR can also be attached later.

NOTE!
This is a small cluster, with no autoscale and no real plan for networking. To create a production ready cluster you need a bit more planning around ip/network etc. Look at the network requirements on the Azure Doc and plan your networking using the Visual Subnet Calculator.

#create the aks service (remove linebreaks before running
az aks create --resource-group $aksrg \
       --name $aks \
       --attach-acr $registry \
       --node-count 3 \
       --network-plugin kubenet \
       --service-cidr $aks_srv_cidr \
       --dns-service-ip $aks_dns_ip \
       --pod-cidr $aks_pod_cidr \
       --docker-bridge-address $aks_docker_bridge \
       --vnet-subnet-id $akssnid \
       --service-principal $aks_appid \
       --client-secret $aks_secret

# get the aks resource id
$aks_resourceId = $(az aks show -n $aks -g $aksrg --query id -o tsv)
# wait for aks to be up and running
az resource wait --exists --ids $aks_resourceId
Enter fullscreen mode Exit fullscreen mode

Now the cluster is up and running. To set the context for kubectl to your newly created cluster run.

az aks get-credentials --resource-group $aksrg --name $aks  --overwrite-existing
Enter fullscreen mode Exit fullscreen mode

To verify that everything is up and running get the cluster info using kubectl

kubectl cluster-info
Enter fullscreen mode Exit fullscreen mode

It is important to understand that this is not a service that is designed and secured for production so do spend more time customizing and add security, network and capacity planning before deploying anything for production.

When you are done, running two simple commands will remove everything we have created.

#cleanup
az group delete --name $aksrg --yes
az group delete --name "NetworkWatcherRG" --yes
az ad sp delete --id $aks_appid
Remove-Item path $outputfile
Enter fullscreen mode Exit fullscreen mode

To do this in bash should require minimal changes. All of the Azure CLI commands are cross platform equal.

Feel free to leave a comment if you have any optimization tips or feedback!

Discussion

pic
Editor guide