How to write YAML file for Azure Kubernetes Service (AKS)

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.

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:

  • Maps
  • Lists

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.

YAML Maps

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.

💡
NEVER use tabs in a YAML file.

YAML lists

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.

Creating 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 51.104.184.162 80:32505/TCP 2m41s

Open a web browser and hit 51.104.184.162 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

  1. 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.
  2. 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