Share the love

If you have followed previous two posts on creating AKS cluster and connecting to AKS cluster, you should be having an accessible Kubernetes cluster. In this post, we will cover how to deploy application on AKS. We will use simple voting application from Microsoft document. This link gives full YAML file. Here I will try to explain different parts of this code.

Instead of using one single YAML file, I have segregated it into multiple files. You can clone the code files from GitHub.

git clone https://github.com/praveen-krg/cloudiseasy-aks.git cloudiseasy-aks-basics

You should be able to find required files in folder named simple-vote-app. I have divided it into 4 files – frontend deployment, frontend service, backend deployment and backend service.

I guess you’re in hurry to deploy application on AKS. Lets do that first and then dig into YAML code.

Deploy Application on AKS

By now, you should be having kubectl installed. If not, follow this link. Run following commands:

kubectl create -f vote-back.yaml
kubectl create -f vote-back-svc.yaml
kubectl create -f vote-front.yaml
kubectl create -f vote-front-svc.yaml

Remember, you always keep everything in one single file and deploy it. I personally recommend getting used to multiple files since it’s much easier to work with Helm charts this way. We will get to Helm charts in our future posts. Your outcome should be something similar to mine:

Deploy application on AKS - kubectl create command.

Kubectl create uses the file mentioned after -f and creates the respective resource mentioned in the file. Using kubectl apply is a better option compared to kubectl create. In order to understand the difference run the same command again. It will throw and error stating “Error from server (AlreadyExists): error when creating “vote-front-svc.yaml”: services “azure-vote-front” already exists”. This can be avoided using kubectl apply command. It can be used to deploy resources that don’t yet exist or to redeploy modified code.

Validate Application Deployment

From above output, we could see that our app deployments and services went through successfully. Time to check what were deployed in our cluster.

Check Pods

Run following command:

kubectl get pods
Deploy application on AKS - kubectl get pods

We see both front-end and back-end deployed. If STATUS shows up as ContainerCreating, hold on for a couple of seconds and try again. Alternatively you watch the progress as well using –watch. Add –watch at the end of your command to follow the status. You can check further details by describing them. Use kubectl describe for this purpose.

# Syntax is kubectl describe <resource> <resource-name>
kubectl describe pod azure-vote-back-5f46f8f4cc-4xjr8

You would get long output. This would include details of the containers deployed, volumes, node and events (among many other details) associated with the pod. Here’s my output:

Name:         azure-vote-back-5f46f8f4cc-4xjr8
Namespace:    default
Priority:     0
Node:         aks-nodepool1-19593774-vmss000000/10.240.0.4
Start Time:   Sat, 26 Jun 2021 17:46:34 +0530
Labels:       app=azure-vote-back
              pod-template-hash=5f46f8f4cc
Annotations:  <none>
Status:       Running
IP:           10.244.0.15
IPs:
  IP:           10.244.0.15
Controlled By:  ReplicaSet/azure-vote-back-5f46f8f4cc
Containers:
  azure-vote-back:
    Container ID:   containerd://647bc01d2b9ec2c9620c1c2e127b94042017ce33c4cc95723e99f781f282a6d5
    Image:          mcr.microsoft.com/oss/bitnami/redis:6.0.8
    Image ID:       mcr.microsoft.com/oss/bitnami/redis@sha256:9b53ae0f1cf3f7d7854584c8b7c5a96fe732c48d504331da6c00f892fdcce102
    Port:           6379/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 26 Jun 2021 17:46:45 +0530
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     250m
      memory:  256Mi
    Requests:
      cpu:     100m
      memory:  128Mi
    Environment:
      ALLOW_EMPTY_PASSWORD:  yes
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-g8rxx (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-g8rxx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-g8rxx
    Optional:    false
QoS Class:       Burstable
Node-Selectors:  beta.kubernetes.io/os=linux
Tolerations:     node.kubernetes.io/memory-pressure:NoSchedule
                 node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From                                        Message
  ----    ------     ----       ----                                        -------
  Normal  Scheduled  <unknown>                                              Successfully assigned default/azure-vote-back-5f46f8f4cc-4xjr8 to aks-nodepool1-19593774-vmss000000
  Normal  Pulling    66m        kubelet, aks-nodepool1-19593774-vmss000000  Pulling image "mcr.microsoft.com/oss/bitnami/redis:6.0.8"
  Normal  Pulled     66m        kubelet, aks-nodepool1-19593774-vmss000000  Successfully pulled image "mcr.microsoft.com/oss/bitnami/redis:6.0.8" in 3.687445878s
  Normal  Created    66m        kubelet, aks-nodepool1-19593774-vmss000000  Created container azure-vote-back
  Normal  Started    66m        kubelet, aks-nodepool1-19593774-vmss000000  Started container azure-vote-back

Validate Service

You can similarly check details of other pods as well. Along with the apps layer we also deployed something call “service“. Our application needs to be exposed publicly so that we could access it. Here, we have created service and it, internally, creates an Azure Load Balancer with public IP. To check the public IP, run following kubectl get command.

kubectl get service azure-vote-front

You see an output similar to:

NAME               TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
azure-vote-front   LoadBalancer   10.0.74.189   52.154.212.91   80:30754/TCP   76m

This means that our service has successfully deployed and our app is exposed on a public IP (shown in above result).

Check all resources

Just run following command and it will show all the resources present in your cluster:

kubectl get all
kubectl get all

Remember, this command just show you resourced from your current namespace. Provided that you have followed the exact same steps from this “AKS Basics” series, you must be using default namespace. Yes, name of default namespace is default. If you want to go a step beyond and check all resources from all namspaces, just add -A at the end of above command (for that matter, most of other commands we used till now).

Validate Deployed Application From Browser

Once you know the public IP, use that to browse to the application in your browser. You should see and output similar to below one:

Deploying app on AKS - Application deployed.

If you have followed all the steps mentioned above, you should have above result. However, there is always possibility of something going wrong.

Quick Troubleshooting

If you don’t see above result. You can check your pods and services again to see if they are still in good shape.

# Get all pods fron current namespace.
kubectl get pods

# Get all services from current namespace.
# Yes, I typed just typed svc. I am lazy!
kubectl get svc

If everything looks good, check for logs from the pods. Here’s how to quickly get logs from Kubernetes pods.

# Get all pods
kubectl get pods

# Copy the name of the pod you want to fetch logs from and use it in below command
kubectl logs <pod_name>

This should help you narrow down on the issue. If you still thinking logging into the container and running any shell commands would help, you can easily do it.

# Get all pods. Yes! I used po and it's not a typo.
# You can just type po instead of pods.
kubectl get po

# Enter container shell
# Replace <pod_name> with pod name from above command.
kubectl exec -it <pod_name> -- sh

Depending on the error, further troubleshooting can be carried out. For now, lets stick with only these commands.

Understanding YAML File

Lets take a quick look at the YAML files – 1 service and 1 app deployment. Lets start with frond end deployment.

Deployment YAML

     1  apiVersion: apps/v1
     2  kind: Deployment
     3  metadata:
     4    name: azure-vote-front
     5  spec:
     6    replicas: 1
     7    selector:
     8      matchLabels:
     9        app: azure-vote-front
    10    template:
    11      metadata:
    12        labels:
    13          app: azure-vote-front
    14      spec:
    15        nodeSelector:
    16          "beta.kubernetes.io/os": linux
    17        containers:
    18        - name: azure-vote-front
    19          image: mcr.microsoft.com/azuredocs/azure-vote-front:v1
    20          resources:
    21            requests:
    22              cpu: 100m
    23              memory: 128Mi
    24            limits:
    25              cpu: 250m
    26              memory: 256Mi
    27          ports:
    28          - containerPort: 80
    29          env:
    30          - name: REDIS
    31            value: "azure-vote-back"
  • Line 1 and 2: They mention the API version and the kind as deployment. Deployments can be used to update pods and your replicasets.
  • Line 3 and 4: These lines contain metadata for the deployment.
  • Line 6: Mentions the number of replica we want. In our case we just did 1. Change this number and see the difference for yourself. However, we will cover these in depth later as well.
  • Line 7 – 9: Selector is used to identify a set of objects. In our case, containers matching the label would managed by our deployment.
  • Line 11 – 13: This mentions the labels. If you notice, the labels match with that of label selector. Hence, we see this deployment managing these containers. These labels will be used to group and connect to other pods as well.
  • Line 14 – 16: We are using nodeSelector to select node with a Linux OS.
  • Line 17 – 19: We are giving a name to our container. In line 19, we are telling it from where it could fetch the image for the container.
  • Line 20 – 26: Kubernetes will reserve the resources we mentioned. Limits are the cap of each of those resources. One cpu unit is equivalent to 1 vCPU/core. Here we are allocating 100 millicores (0.1 cpu). It can go upto 250 millicores (0.25 cpu) before it is throttled. We are also allocating 128 Mi (mebibytes) and go upto 256 Mi before it reboots the pod.
  • Line 27 – 28: The port on which our container would be listening on.
  • Line 29 – 31: These are optional environment variables for the container. Don’t confuse yourself! These are pretty much similar to how you have environment variables on your device or a Linux machine. If your application doesn’t use any, you can skip it. But, in real-time scenarios, it is almost impossible to not use environment variables at all.

Service YAML

Now, that you understand the deployment YAML, lets take a look at service.

     1  apiVersion: v1
     2  kind: Service
     3  metadata:
     4    name: azure-vote-front
     5  spec:
     6    type: LoadBalancer
     7    ports:
     8    - port: 80
     9    selector:
    10      app: azure-vote-front
  • Line 2: It suggest that we are deploying a service. Service is used to expose pod to outside world or other pods (depending on what you intend to do).
  • Line 3 – 4: Metadata for your service.
  • Line 5 – 6: We are mentioning the type for the service. In this case we will be creating a LoadBalancer.
  • Line 7 – 8: This mentions the incoming port for the service. Our service is taking traffic on port 80.
  • Line 9 – 10: We are telling what are the pods this would be exposing. In our case, we know that label belongs to front-end deployment.

You can easily go through other 2 files on your own and explore a bit.

Cleanup AKS Cluster

By now, you should be good to deploy application on AKS cluster on your own. If you’re done with your testing, lets cleanup our cluster. Kubectl delete will get the work done.

kubectl delete -f vote-back.yaml
kubectl delete -f vote-back-svc.yaml
kubectl delete -f vote-front.yaml
kubectl delete -f vote-front-svc.yaml
Deploying app on AKS - Cleaning up deployed resources.

Next Steps

Now that you know how to deploy a simple application on AKS, next we will tackle a something that little more complex.

Meanwhile, if you’ve any queries, questions or stuck with troubleshooting, post them in comments section.