Kubernetes: A Complete Guide - Chapter 4

In the previous chapter, we learnt how to setup a nginx web server on Local Minikube Cluster. In this chapter, we are gonna deploy a Sample Node.js application on a cloud provider such as AWS. Here, we are gonna deploy our sample application on EKS (Elastic Kubernetes Service). Also, we are gonna learn about different types of components such as Service, Deployments, etc.

Pre-requisites:-

1.) Docker
2.) EKS Cluster
3.) aws cli

Now, let's proceed to deploy a Node.js Application on the currently running EKS Cluster.

We need Docker so that we can package the code as an image which we will later push it to our ECR repository.

Here's our sample Node.js Application code:

const express=require('express');

const port=3000
const app=express();

app.get('/',(req,res)=>{
    res.send('Hi, we are live now!')
})

app.listen(port,()=>{
    console.log(`App currently listening on port:${port}`)
})

Let's create a file called index.js and add the above code to it.

In order to create an image of the above Node.js application, we have to create a Dockerfile and add the following instructions to it.

FROM node:16-alpine

WORKDIR /src

RUN npm install express

COPY . /src

CMD node .

Now, let's build the image:-

 docker build -t node-sample-app .
 

If we want to run the image locally i.e. on our localhost, we can run the following command:-

docker run --rm -it -p 80:3000 nodejs-sample

In the above command, we are running the nodejs-sample image on port 3000 and we will be accessing it at http://127.0.0.1
Also, it'll remove the container once the execution is completed.

Now let us create a repository in AWS.

Considering our AWS Cli is configured, let us run the following command to create the repository on Amazon ECR:-

aws ecr create-repository \
    --repository-name node-sample-repo \
    --image-tag-mutability IMMUTABLE
    --image-scanning-configuration scanOnPush=true

In the above command, we are creating a repo called node-sample-repo in Amazon ECR and we are setting the tag immutability property which will prevent us to create images with the same tag i.e. we cannot have images with the same tag name. Also, we are setting up image scanning configuration where it'll scan for any vulnerabilities if present in the image.

Suppose, we want to update the existing image then we can disable mutability (by default its disabled)

Now, that the repo has been created, let's push the image to the ECR repository. We are gonna first authenticate our client.

aws ecr get-login-password --region <aws_region> | docker login --username AWS --password-stdin <account_id>.dkr.ecr.<aws_region>.amazonaws.com

Replace account_id and aws_region with the appropriate values.

The above command will retrieve an authentication token and authenticate the Docker client to our registry. Once that is done, let's tag our image in order to push it to the repository.

docker tag node-sample-app:latest <account_id>.dkr.ecr.<aws_region>.amazonaws.com/node-sample-repo:latest

Finally, push the image to the ECR repository

docker push <account_id>.dkr.ecr.<aws_region>.amazonaws.com/node-sample-repo:latest

Now, the image is present in our ECR, the ARN of the image would be something like this.

<account_id>.dkr.ecr.<aws_region>.amazonaws.com/node-sample-repo:latest

Now, let's proceed with deploying the above image to our Kubernetes cluster.

Considering an EKS Cluster is already setup (Refer this to create an EKS Cluster) and our local machine is configured to connect to EKS, let us create a file called Deployment.yml and paste the following piece of code:-

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: node-app
  name: node-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: node-app
  template:
    metadata:
      labels:
        app: node-app
    spec:
      containers:
      - image: <account_id>.dkr.ecr.<aws_region>.amazonaws.com/node-sample-repo:latest
        name: node-app
        imagePullPolicy: Always
        resources: {}
        ports:
          - containerPort: 3000

We create another file called Service.yml which will actually create the service:-

apiVersion: v1
kind: Service
metadata:
  name: node-app
  labels:
    run: node-app
spec:
  ports:
  - port: 3000
    protocol: TCP
  selector:
    app: node-app

We are gonna run the following two commands:-

kubectl create -f Deployment.yml
kubectl create -f Service.yml

The above 2 commands will deploy 1 replica/instance of the sample Node.js application on EKS Cluster where Deployment.yaml will create the sample Node.js application by pulling the image from the ECR and Service.yaml will be responsible for forwarding the requests to the pods. This will be an internal service. Now, suppose we want to have an endpoint and want to access the webpage, we can add the type to type: LoadBalancer followed by which if we run the following command:-

kubectl get pods -o wide

where, it'll provide the public ip through which it can be accessed.

Note:- What is the difference between the kind: Deployment vs the kind: Pod ?
Well, Deployment creates a replica of Pods where the ReplicaSet or the Replication Controller takes care of maintaining the healthy status and the required number of Pods where as the kind: Pod just creates the number of Pods as mentioned and it isn't maintained by any kind of controller. Also, the kind: Pod, is mostly used in a development environment and not commonly used in a Production Environment.

Hopefully, this chapter helps you in creating/deploying a Sample Application in your EKS cluster.

In the next chapter, we are gonna learn how to create services like Cassandra or MySQL which have storage involved in Kubernetes. Cheers!

Abhishek Roy

Abhishek Roy

DevOps Engineer who aims to automate and simplify stuff related to infra and CI/CD.
Kolkata, India