How to write YAML file for Azure Kubernetes Service (AKS)
Author: Sakaldeep Yadav
May 03, 2020
There are primarily two parts of the Azure Kubernetes Service (AKS) deployment, first deploy AKS cluster and second deploy an application. To create the AKS Cluster, we can use Azure Portal, Azure CLI, ARM Template, etc. and to deploy an application to the AKS cluster we can use a YAML file. In this article, we’ll look at how YAML works and how to use it to deploy the application to the AKS Cluster. We will deploy dockerized application 'demoimage' from Docker Hub to demonstrate that is available at sakaldeep/demoimage:1. Let's start with YAML basics.
It’s difficult to escape YAML if you’re using any form of Kubernetes — Minikube, AKS, EKS, and GKE. YAML stands for Yet Another Markup Language, or YAML Ain’t Markup Language (depending who you ask) is a human-readable text-based format for specifying configuration-type information such as definitions for creating Pod, Deployment, and Services. There are only two types of structures you need to know in YAML:
You might have maps of lists and lists of maps, and so on, but if you’ve got those two structures down, you’re all set. That’s not to say there aren’t more complex things you can do, but in general, this is all you need to get started with.
Let’s start by looking at YAML maps. Maps let you associate name-value pairs, which of course is convenient when you’re trying to set up configuration information. For example, you might have a config file that starts like this:
--- apiVersion: apps/v1 kind: Deployment
The first line is a separator and is optional unless you’re trying to define multiple structures in a single file. From there, as you can see, we have two values, apps/v1 and Deployment, mapped to two keys, apiVersion and kind.
You can also specify more complicated structures by creating a key that maps to another map, rather than a string, as in:
--- apiVersion: v1 kind: Deployment metadata: name: skl labels: app: web
In this case, we have a key, metadata, that has as its value a map with 2 more keys, name and labels. The labels key itself has a map as its value. You can nest these as far as you want to.
The YAML processor knows how all of these pieces relate to each other because we’ve indented the lines. In this example I’ve used 2 spaces for readability, but the number of spaces doesn’t matter — as long as it’s at least 1, and as long as you’re CONSISTENT. For example, name and labels are at the same indentation level, so the processor knows they’re both part of the same map; it knows that app is a value for labels because it’s indented further.
Quick note: NEVER use tabs in a YAML file.
YAML lists are literally a sequence of objects. For example:
containers: - sleep - "100" - image - "nginx!"
As you can see here, you can have virtually any number of items in a list, which is defined as items that start with a dash (-) indented from the parent.
And of course, members of the list can also be maps:
--- apiVersion: apps/v1 kind: Deployment metadata: name: skl labels: app: web spec: containers: - name: demoimage image: sakaldeep/demoimage:1 ports: - containerPort: 80 - name: demoimage2 image: sakaldeep/demoimage2:1 ports: - containerPort: 81
So as you can see here, we have a list of containers “objects”, each of which consists of a name, an image, and a list of ports. Each list item under ports is itself a map that lists the containerPort and its value.
As you can see, we’re starting to get pretty complex, and we haven’t even gotten into anything particularly complicated!
So let’s review. We have:
maps, which are groups of name-value pairs
lists, which are individual items
maps of maps
maps of lists
lists of lists
lists of maps
Basically, whatever structure you want to put together, you can do it with those two structures.
Writing YAML for AKS
Finally, we’re down to creating the actual Deployment. Before we do that, though, it’s worth understanding what it is we’re actually doing.
AKS, manages container-based resources. In the case of a Deployment, you’re creating a set of resources to be managed. Deployment to tell AKS to manage a set of replicas of that Pod — literally, a ReplicaSet — to make sure that a certain number of them are always available. So we might start our Deployment definition like this:
---apiVersion: apps/v1kind: Deploymentmetadata:name: skllabels:app: webspec:replicas: 1
Finally, we get into the spec. In the Pod spec, we gave information about what actually went into the Deployment. We’ll start, in this case, by saying that the Deployment will have only 1 replica. You can set this number however you like, of course, and you can also set properties such as the selector that defines Deployment, or the minimum number of seconds a pod must be up without any errors before it’s considered “ready”. You can find a full list of the Deployment specification properties here.
OK, so now that we know we want only 1 replica, we need to answer the question: “Replicas of what?” They’re defined by templates:
---apiVersion: apps/v1kind: Deploymentmetadata:name: skllabels:app: webspec:replicas: 1selector:matchLabels:app: webtemplate:metadata:labels:app: webspec:containers:- name: demoimageimage: sakaldeep/demoimage:1ports:- containerPort: 80
Templates are simply definitions of objects to be replicated — objects that might, in other circumstances, by created on their own. Save the above code as a deployments.yaml. We will use this file in the next section.
Deploy Application using YAML
Create an AKS cluster if you are not created already as below. We will use Azure CLI here, log in to Azure CLI using az login, and run the below command. The first command will create a resource group 'AKS, and second command will create the AKS cluster 'SKL' having 1 node.
az group create --name AKS--location northeurope az aks create --resource-group AKS --name SKL --node-count 1 --enable-addons monitoring --generate-ssh-keys
After a few minutes, you will see the JSON info of the cluster that it has created. To connect to the AKS cluster install Kubectl, Kubernetes command-line client.
> az aks install-cli
To configure kubectl to connect to your Kubernetes cluster, use the az aks get-credentials command. This command downloads credentials and configures the Kubernetes CLI to use them.
> az aks get-credentials --resource-group AKS--name SKL
To verify the connection to your cluster, use the kubectl get command to return a list of the cluster nodes.
> kubectl get nodes NAME STATUS ROLES AGE VERSION aks-agentpool-13549453-vmss000000 Ready agent 6d19h v1.16.7
Now let’s go ahead and create the deployment using YAML file called deployment.yaml that you created earlier. Navigate to the path of the YAML file and run below command.
> kubectl apply -f deployments.yaml deployment.apps/skl created
To see how it’s doing, we can check on the deployments list.
>kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE skl 1/1 1 1 76s
You can see that Pod is running.
>kubectl get pods NAME READY STATUS RESTARTS AGE skl-5d65dd7cb8-bvwtx 1/1 Running 0 4m22s
You can check the event log by describing the Deployment.
> kubectl describe deployment skl Name: skl Namespace: default CreationTimestamp: Sun, 03 May 2020 12:36:59 +0100 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=web Containers: demoimage: Image: sakaldeep/demoimage:1 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: skl-5d65dd7cb8 (1/1 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 5m37s deployment-controller Scaled up replica set skl-5d65dd7cb8 to 1
As you can see here, Service has only private IP.
>kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 5m39s
You can see there is no public IP so we can't access the application from the Internet so we need to create service.
Kubernetes uses Services to logically group a set of pods together and provide network connectivity. The below code will create an Azure load balancer, configures an external IP address, and connects the requested pods to the load balancer backend pool. To allow customers' traffic to reach the application, load balancing rules are created on the desired ports.
--- apiVersion: v1 kind: Service metadata: name: web spec: type: LoadBalancer ports: - port: 80 selector: app: web
Combine both Deployment and Service as below and save it as a deployments.yaml. You can also download this code by clicking on it.
>kubectl apply -f deployments.yaml
Now, you can see the service has external/pubic IP that will listen to the application at port 80.
>kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 45m
web LoadBalancer 10.0.253.240 22.214.171.124 80:32505/TCP 2m41s
Open a web browser and hit 126.96.36.199 and you can see the app is running.
You have deployed your first docker image to the AKS cluster.
What we have covered so far
Total visits : 363