If you've been following along (yay I have fans!) I've been infected by the container bug for some time now. Well thanks to Kubernetes (k8s) it has recently taken me down the container orchestration "rabbit-hole".

Before I begin, I want to thank Mike for his tutorials with Kubernetes on GCP. Without it, I'd be lost in a huge ocean without a paddle. How is mine different? I will be showing you how to deploy on Azure's managed service offering of Kubernetes called Azure Kubernetes Service – AKS!


In this tutorial I will be building upon the previous container project and will be deploying it to the world with AKS. In the previous container project, I containerized a node.js based website and created a docker image to use for my containers. This tutorial will use the same image (myapp_image) and deploy it on AKS. I will be using Azure CLI and Visual Studio Code to do my deployment on AKS.

  1. Create a docker image
  2. Install Visual Studio Code
  3. Install Azure CLI
  4. Install kubectl

Setting Up…

First step is to fire up VS Code and log into the Azure CLI with your credentials. To do this press " CTRL + `  " keys, this will bring up integrated terminal on VS Code. In the terminal type in az login. This will open up a browser window and will prompt you for you Azure login details. Enter your credentials and continue below to create your cluster. You should see something similar to below.

Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.
PS C:\Users\phil\Documents\aks> az login
Note, we have launched a browser for you to login. For old experience with device code, use "az login --use-device-code"

Create an AKS Cluster

Now you can go through the Azure Portal and walk through the GUI to create your cluster, but there is absolutely no fun in that!


  1. Create a resource group for your AKS project
  2. Create AKS cluster

First we will create a resource group in Azure to store the AKS cluster and then we'll create the AKS cluster. To create the resource group using the Azure CLI, use the az group create command with the: --resource-group, --subcription, and --location options.

az group create --resource-group NAME-OF-RG --subscription SUBSCRIPTION --location AZURE-REGION

You may not have to specify a subscription ID, my account has two different subscription ID (dev and prod) and I have to specify the subscription ID for dev. If you're using a free trial account you can skip the subscription option because your account will only have one subscription ID.

Next order of business is to create the AKS cluster within the newly created resource group. We will be using az aks create command to create a new cluster. Supply the options: --resource-group, --name, --node-count, --generate-ssh-keys, and --subscription.

The --name denotes what name will be assigned to the AKS  cluster. --node-count indicates the number of nodes that will be created, for this tutorial I'll be using one node only. generate-ssh-keys will provide us with the SSH public and private keys needed for managing the nodes.

az aks create --resource-group NAME-OF-RG --name NAME-OF-CLUSTER --node-count 1 --generate-ssh-keys --subscription SUBSCRIPTION 

Be patient, the command may take some time to execute because it is creating the necessary infrastructure to support the cluster.

Once it has finished the creation process, if you search for your username in the resource group you should see another resource group starting with the name "MC_". This was automatically created by AKS and houses all of the underlying resources for Kubernetes.

Now if those were too many commands to type out, below are scripts written in bash and poswershell for you to execute. Make edits as you see fit; once again you may not need the subscription ID like me, your docker image maybe named differently or if you prefer to setup the AKS cluster on another region.


az group create --resource-group $NAME \
                --subscription $SUB \
                --location $LOCATION
az aks create --resource-group $NAME \
              --name $NAME-01 \
              --node-count 1 \
              --generate-ssh-keys \
              --subscription $SUB 


$USER = whoami
$NAME = $USER + "-aks-test"
$CLUSTER = $NAME + "-01"
$SUB = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$LOCATION = 'eastus'
$IMG = 'myapp_image'
az group create --resource-group $NAME `
                --subscription $SUB `
                --location $LOCATION
az aks create --resource-group $NAME `
              --name $CLUSTER `
              --node-count 1 `
              --generate-ssh-keys `
              --subscription $SUB 

Now to configure kubectl to connect to our node we need to use the az aks get-credentials.

az aks get-credentials --resource-group NAME-OF-RG --name NAME-OF-CLUSTER --subscription SUBSCRIPTION

After you have executed the az aks get-credentials command, go ahead and test if you can connect to your cluster using kubectl (kubectl get nodes) command below. If everything worked you should have one node.

kubectl get nodes
NAME                       STATUS   ROLES   AGE   VERSION
aks-nodepool1-90456543-0   Ready    agent   66m   v1.9.11

Create a Kubernetes Manifest Files

Time to write the files K8s will use to deploy the docker image I created. First up is a deployment manifest file that will tell K8s which image to use and how many containers to create when it spins up a pod. This deployment manifest will be written in yaml format (my-deployment.yaml).

I will gave the deployment a name called pafable-deployment. Replicas indicate how many pods it will be created and maintained at all times. In this example only one pod is needed.

A selector with matchLabels and component: web will link the deployment to a K8s loadbalancer object which we will create after this. Towards the end of the file there is a section for containers. In the container section, I specified the name of the container (pafable-container), image (myapp_image), and the container port to use.

Deployment Manifest

apiVersion: apps/v1
kind: Deployment 
  name: pafable-deployment
  replicas: 1
      component: web
        component: web
        - name: pafable-container
          image: myapp_image
            - containerPort: 80

Next on the docket is to create a service manifest specifically a loadbalancer. This service manifest will handle the networking aspect of our deployment and will assign a public IP that will allow us to reach the project from a web browser.

In my loadbalancer manifest, the kind is set to Service. The name of the service is called pafable-loadbalancer. In type I specified the type of service – LoadBalancer. The port to expose is 80. Now comes the important aspect, linking the loadbalancer to the deployment manifest. To do this I set the selector to component: web which I specified in the deployment manifest.

Loadbalancer Manifest

apiVersion: v1
kind: Service
  name: pafable-loadbalancer
  type: LoadBalancer
  - port: 80
    component: web

When you are creating these manifest, please be mindful of the indents! I have personally messed up numerous deployments with incorrect spaces.

Deploying to AKS Cluster

After you have created the two manifest files time to execute the kubectl command. I created my manifest files in a directory called k8s.

S C:\Users\phil\Desktop\k8s> dir
Directory: C:\Users\phil\Desktop\k8s>
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----         3/7/2019   6:12 PM            365 my-deployment.yaml
-a----         3/7/2019   6:12 PM            140 my-loadbalancer.yaml

Deploy our little "hello world" website, we will use kubectl apply command. To specify the two manifest files I'll use -f flag and provide the manifest files.

kubectl apply -f my-deployment.yaml
kubectl apply -f my-loadbalancer.yaml

You should see output indicating your deployment and service being created. Now let's check them out with the kubectl get command.

kubectl get all

This will output something similar to mine below.

NAME                                      READY   STATUS    RESTARTS   AGE
pod/pafable-deployment-6d676bb7ff-7qlpq   1/1     Running   0          81m
NAME                    TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
service/kubernetes      ClusterIP      <none>          443/TCP        9h
service/pafable-loadbalancer   LoadBalancer   80:30165/TCP   81m
NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/pafable-deployment   1/1     1            1           81m
NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.extensions/pafable-deployment-6d676bb7ff   1         1         1       81m
NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/pafable-deployment   1/1     1            1           81m
NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/pafable-deployment-6d676bb7ff   1         1         1       81m

As you can see a pod was created with the name pod/pafable-deployment-6d676bb7ff-7qlpq and the status is RUNNING. Under services there is a service called service/my-loadbalancer with an external IP We will use the public IP in a web browser and access the website.

Let's take a look at it now!

Excellent, it's party time! Kubernetes has successfully deployed the website. One final test before I leave you all to digest all of that k8s knowledge. Let's see what happens if we lose a pod. How will Kubernetes handle the outage.

Take a look at the list of pods we have deployed. There should only be one.

kubectl get pods
NAME                                  READY   STATUS    RESTARTS   AGE
pafable-deployment-6d676bb7ff-7qlpq   1/1     Running   0          92m

Okay I have one pod with the name pafable-deployment-6d676bb7ff-7qlpq, I will delete this pod with the kubectl delete command.

kubectl delete pods pafable-deployment-6d676bb7ff-7qlpq

After you have executed the delete command above, quickly check the pods with the kubectl get pods command.

If you were fast enough you should see something like below.

NAME                                  READY   STATUS        RESTARTS   AGE
pafable-deployment-6d676bb7ff-7qlpq   1/1     Terminating   0          95m
pafable-deployment-6d676bb7ff-ggnqk   1/1     Running       0          16s

The previous pod is being terminated and a new pod is already running! Fantastic it is working nicely! Hopefully you all liked my first dive into Kubernetes and AKS, please leave a comment if you see any mistakes. I'm still learning the nooks and crannies of Kubernetes and any guidance is appreciated!