Deploying a Container App on a Kubernetes Cluster.
Tags: kubernetes, docker, cloud, learning
Published: 2023-05-14 18:16:32

Delving into the world of Containers and Container Orchestration, one might wonder what these terms mean.

Containers are a way to package software in a format that can run isolated on a shared operating system. Unlike Virtual Machines, containers do not bundle a full operating system - only libraries and settings required to make the software work.

Container Orchestration automates the provisioning, deployment, networking, scaling, availability, and lifecycle management of containers.

In this article, I will demo how to containerize an application and deploy on a kubernetes cluster.

**Prerequisites**
- Docker installed on your local machine - which will be used to build image and push to a registry.
- Azure account with active subscription
- Terraform installed - an IAC tool that will be used to provision infrastructure on a cloud provider (Azure in this demo)
- Code Editor or IDE with a terminal- which will be used to write code that will be containerized.
- Azure CLI - to connect to kubernetes cluster.

**Steps**
There are 4 main steps which include:
**Writing code for the application that will be containerized with docker**  
 
This section involves writing the code in a preferred programming language (I will be using node js).  
 
**Using terraform to provision infrastructure to Azure**  
Terraform is an infrastructure as code tool used to provision resources, instead of using the azure portal to create my resources, I will be using terraform, [see terraform code](https://github.com/KeneOjiteli/deploy-container-app-on-k8s-cluster/tree/main/deploy-container-app-on-k8s-cluster/terraform) 


To make this creation possible, the following terraform commands will be used:

**terraform init**: initializes a working directory that contains terraform configuration files (note that a terraform file has a `.tf` extension)
![Terraform init](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3tfft7b5v2rylsaibqo.png)
- Formatting and validating my code using the command below

![Validate terraform code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/to1f9uevgc9e7cvszx93.png)  

**terraform plan**: used to preview the action terraform would take to modify your infrastructure.

![terraform plan](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxsf9f59720y6npax87s.png)

![terraform plan](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yq46npwisr6zhiwpgmsl.png)  

**terraform apply**: similar to terraform plan but actually carries out the planned changes to each resource using the relevant infrastructure provider's API.

![terraform apply](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tb7k5c4ciy2u6iphmun5.png)

![terraform apply](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a87cg9fftyri48wtj5or.png)
![terraform apply](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16c225vk8pwieap0ohpt.png)
I created a resource group, container registry and azure kubernetes service on azure.  


**Using Docker to containerize the application and pushing to a registry**

Dockerizing an application requires a [Dockerfile](https://github.com/KeneOjiteli/deploy-container-app-on-k8s-cluster/blob/main/deploy-container-app-on-k8s-cluster/Dockerfile) which is a template that contains all the commands a user could call on the command line to build an image after which the image will be pushed to a container registry.

To push to a container registry, a connection first need to be established before login to the container registry.

I will head over to azure => container registry => settings => access keys

![container registry](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n40xc02hiikt1va18qdm.png)

![container registry access keys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n22dzzh1ricmh4n4a78v.png)
- Navigate to your project directory via terminal and login using the details from the step above `docker login <login server> --username <username> --password <password>`

![ACR login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9euoylu7mgxv9eauzyh7.png)
- Build docker image using this command `docker build -t <name>:<tag> .` where `.` is the current directory.

![build docker image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2dwmviajtfh7ne1ihf4x.png)
- Check the image exists using `docker images` command ( this lists all available images, the first image is my newly created image).

![list docker images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i4iiu9j3g4a3cn5zl63f.png)
- Push the image to ACR using `docker push <name>:<tag>`

![push docker image to acr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6ivs10or5479tj3m9tb.png)
- Going over to azure portal => container registry, to verify the push is successful.

![Image on ACR](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wb8igwgbpwoj5jbl15m.png)
**Deploying the web application to azure kubernetes cluster**
- Having created an azure kubernetes cluster using terraform, go over to azure portal to verify.

![AKS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/91ov2efbmcd7myanm1j0.png)
- I will be using azure CLI to get credentials so as to connect to my cluster using the commands below  

`az login`
`az aks get-credentials --resource-group <resourcegroupname> --name <clustername>` (this command downloads credentials and configures the kubernetes CLI to use them)

![login with azure cli](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xsa7ic0crb4hn9q4zxti.png)

![credentials to manage cluster](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdngtc45n0yd7exqdjt4.png)

- Verifying connection to my cluster using `kubectl get nodes` to return a list of the cluster nodes (note that I declared 1 cluster node and status = ready).

![list nodes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fs8svjuvs8up5mauhkr6.png)
- Create a deployment using a YAML manifest file that will roll out a replicaset to bring up specified number of instances of a specified pod and create a service (which enables network access to a set of pods) using `kubectl apply -f <deploymentfile-name>`.

![create deployment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ryw2v0uqysma65us3nad.png)
A kubernetes deployment tells kubernetes how to create or modify instances of the pods that hold a containerized application.

- To get more details about the deployment, use `kubectl describe deployments <deploymentname>` command
![Describe deployments](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/th3m0u76y1or16zb6fbj.png)
- Using the commands below to get deployments, replicasets (a deployment automatically creates a replica set), service and pods (pod name usually starts with the deployment name).

![get deployments](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11ita56p6qzwqxwjtp61.png)
- Notice there are 2 pods, this is because my deployment file specified **2 replicas**
![get pods](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yep9vlqonsdi1znlp0ry.png)

![get replicasets](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b6q4nnhnjmhd7w4ieyzl.png)

![get service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qpmrvjonqjnnawgarll8.png)

- Checking azure portal => kubernetes cluster => kubernetes resources => services and ingresses to view ports and pods.

![service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54epjxpbz30en4711miu.png)

![pod overview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sba8rmp667oibarnjozn.png)
![pod details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vt637votfpdmuico8ck3.png)
- Using external IP of the service with port to access the app
![service url](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tq1k6hing16g5sq5c4ix.png)
- A use case of replicas (which specifies the number of pods that will run concurrently) can be seen when a pod is deleted and a new pod is automatically created based on the number of replicas stated in the manifest file, as shown below

![delete pod](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2jytpk1c320dst0dprr.png)
![get new pods](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3gzmybjnnbtqemenj9mf.png)

- `kubectl get all` lists all objects created at once
![All details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8c54bw26u4pwi71xo1wz.png)
- A deployment can also be updated to either increase or decrease number of instances by changing the replica value or changing the version of a container image, the former can be done using the command below:
![Edit deployment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/prsm6wuht41h503ozlv9.png)
- The updated number of pods on AKS.
![updated deployment on cluster](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6pzqv71x6dghpfd1r0c4.png)
![details showing updated replica](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kxwpki3nosxf068ql10b.png)
- A list of updated pods
![new running pods](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vz5vv3wn39o2k9bt70aj.png)
- Cleaned up my resources using `terraform destroy` command.

Thank you for reading and I hope you learned something new, project code can be found on my [repo](https://github.com/KeneOjiteli/deploy-container-app-on-k8s-cluster)