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.
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!
- Create a resource group for your AKS project
- 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.
--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.
USER=$(whoami) NAME=$USER-aks SUB=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx LOCATION=eastus IMG=myapp_image 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.
apiVersion: apps/v1 kind: Deployment metadata: name: pafable-deployment spec: replicas: 1 selector: matchLabels: component: web template: metadata: labels: component: web spec: containers: - name: pafable-container image: myapp_image ports: - 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.
apiVersion: v1 kind: Service metadata: name: pafable-loadbalancer spec: type: LoadBalancer ports: - port: 80 selector: 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 10.0.0.1 <none> 443/TCP 9h service/pafable-loadbalancer LoadBalancer 10.0.130.93 220.127.116.11 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 18.104.22.168. 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!