How to write YAML file for Azure Kubernetes Service (AKS)
There are primarily two parts of the Azure Kubernetes Service (AKS) deployment, first deploy the 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 demo image from Docker Hub to demonstrate that is available at sakaldeep/demoimage:
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 on 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, names, and labels. The label 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 parts of the same map; it knows that the app is a value for labels because it’s indented further.
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 container “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 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/v1 kind: Deployment metadata: name: skl labels: app: web spec: 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/v1 kind: Deployment metadata: name: skl labels: app: web spec: replicas: 1 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: demoimage image: sakaldeep/demoimage:1 ports: - containerPort: 80
Templates are simply definitions of objects to be replicated — objects that might, in other circumstances, be 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 it 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 the 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 the YAML file called deployment.yaml that you created earlier. Navigate to the path of the YAML file and run the 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 a 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.
Delete previous deployment (kubectl delete deployments --all) and re-deploy deployments.yaml. You can see below, this time both deployment and service have provisioned.
>kubectl apply -f deployments.yaml deployment.apps/skl unchanged service/web created
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
- YAML is a human-readable text-based format that lets you easily specify configuration-type information by using a combination of maps of name-value pairs and lists of items.
- YAML is the most convenient way to work with Kubernetes objects, and in this article, we looked at creating Deployments and Services.
So this is our basic YAML tutorial. We’re going to cover intermediate to advanced topics for AKS in the coming months, so if there’s something specific you want to hear about, let us know in the comments, or tweet us at @sakaldeep