In this project, we’ll explore the process of deploying a Reddit Clone application on a Kubernetes cluster using Docker, CI/CD, and Ingress. We started by setting up an EC2 instance and cloning the Reddit source code onto it. After installing Docker on the instance, we proceeded to containerize the application using a Dockerfile. The Dockerfile defined a Node.js environment, installed dependencies, and exposed port 3000. Next, we built a Docker image for the application and pushed it to Docker Hub, making it accessible during deployment. Moving on, we logged into our deployment server, an EC2 instance where we installed Minikube. To deploy the application, we created a deployment.yaml file specifying the desired configuration and applied it using the kubectl command. We verified the successful creation of the deployment and then wrote a service.yaml file to expose the application to the outside world. After applying the service configuration, we obtained an accessible URL for our application. Finally, we tested the ingress functionality to ensure traffic routing to the Kubernetes cluster services.
Table of Contents:
- Introduction
- Setting up the CI Server
2.1. Launching an EC2 T2 Micro Instance
2.2. Cloning the Reddit Source Code and Installing Docker - Containerizing the Application with Docker
3.1. Creating a Dockerfile
3.2. Building the Docker Image - Pushing the Image to Docker Hub
4.1. Logging into Docker Hub
4.2. Pushing the Docker Image - Setting up the Deployment Server
5.1. Launching an EC2 Medium Instance and Installing Minikube - Creating the Deployment Configuration
6.1. Writing deployment.yaml
6.2. Applying the Deployment Configuration - Creating the Service Configuration
7.1. Writing service.yaml
7.2. Applying the Service Configuration - Exposing the Application
8.1. Using Port Forwarding for Local Access
8.2. Allowing External Access through Inbound Rule Configuration - Testing the Deployed Application
- Enabling Ingress and Testing
10.1. Applying the Ingress Configuration
10.2. Testing the Application using Curl - Conclusion
Step 1 — Clone the Source Code, Containerize the application using Docker, Building Docker Image, and Push the Image to Docker Hub on your CI Server (T2 Micro Instance)
Step 2 — Write a Kubernetes Manifest File (Deployment.yml and Service.yml) on your CD Server (T2 Medium Instance)
Step 3 — Deploy the app to Kubernetes using Deployment.yml
Step 4 — Create a Service.yml
Step 5 — Expose the app and test it. Configure ingress.yml
NOW, LET’S GET STARTED WITH DEEPER DIVE INTO ALL OF THESE STEPS
Here are two instances:
Login into your CI Server Ec2 instance:
First — Set up an EC2 T2 micro instance and clone the Reddit source code on your EC2 Instance. Use an Ubuntu image with a key-pair, and enable HTTP and HTTPS traffic. Install docker on this EC2 Instance.
The bellow command needs to install for the CI server
sudo apt-get update
sudo apt-get install docker.io -y
sudo usermod -aG docker $USER && newgrp docker
git clone https://github.com/nahidkishore/reddit-clone-k8s-ingress.git
cd reddit-clone-k8s-ingress
docker login (Enter your docker hub Username and Password)
docker build . -t nahid0002/reddit-clone
docker push nahid0002/reddit-clone
After Docker installation, we need the project code in our local machine to proceed further with image creation. To do so we have to clone the code from the git repository below:
git clone https://github.com/nahidkishore/reddit-clone-k8s-ingress.git
Now above you can see we have got our project directory named reddit-clone-k8s-ingress.
Containerizing the application with Docker
After getting the code in our Local machine we have to create the docker image of the code which will further be deployed.
Writing the Docker file for containerization
FROM node:19-alpine3.15
WORKDIR /reddit-clone
COPY . /reddit-clone
RUN npm install
EXPOSE 3000
CMD ["npm","run","dev"]
This Dockerfile creates a Docker image for a Reddit clone application using Node.js version 19 on Alpine Linux version 3.15.
The FROM instruction specifies the base image for the Docker image, which in this case is the node:19-alpine3.15 image.
The WORKDIR instruction sets the working directory for any subsequent instructions in the Dockerfile to /reddit-clone.
The COPY instruction copies the contents of the current directory (.) to the /reddit-clone directory in the Docker image.
The RUN instruction runs the npm install command to install the required dependencies for the Reddit clone application.
The EXPOSE instruction exposes port 3000 in the Docker image, which is the port used by the Reddit clone application.
The CMD instruction specifies the command to run when the Docker container is started, which in this case is the npm run dev command to start the application in development mode.
Overall, this Dockerfile sets up an environment to run a Node.js-based Reddit clone application, installs its dependencies, and starts the application in development mode on port 3000.
Building the Docker image from the above Dockerfile
After writing the Dockerfile we can build a Docker image out of it by using the command docker build . -t reddit-clone:latest
This command builds a Docker image for the Reddit clone application based on the Dockerfile in the current directory and tags it with the name reddit-clone:latest
Login into the docker repo
Docker Hub is nothing but a hub of repositories containing docker Images. Once the image is built from the docker file, we have to push the image to the Docker hub so that during the deployment the image can be fetched from DockerHub itself. It works like GitHub.
So, to push the image we have to log in to our docker hub account from the CLI using the command: docker login followed by the username and password of your docker account.
Pushing the image to Docker Hub
Once the login is successful we can push the image by using the command below where docker push nahid0002/reddit-clone:latest is the syntax:
docker push nahid0002/reddit-clone:latest
Now from the above image from Docker Hub, you can see that the image has been pushed.
Login into your Deployment Server:
We will launch an EC2 Medium Instance (2vCPU) and install Minikube on it. To install Minikube, Docker is a prerequisite.
The bellow command needs to install for the Deployment server
sudo apt-get update
sudo apt-get install docker.io -y
sudo usermod -aG docker $USER && newgrp docker
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
sudo snap install kubectl --classic
minikube start --driver=docker
mkdir k8s
cd k8s/
Create Deployment.yml
By creating and applying a deployment.yaml file, Kubernetes will create a Deployment object based on the specified configuration and ensure that the desired state of the Deployment is maintained, handling tasks such as scaling and rolling updates automatically.
So, for our application the deployment file will be as below:
apiVersion: apps/v1
kind: Deployment
metadata:
name: reddit-clone-deployment
labels:
app: reddit-clone
spec:
replicas: 2
selector:
matchLabels:
app: reddit-clone
template:
metadata:
labels:
app: reddit-clone
spec:
containers:
- name: reddit-clone
image: nahid0002/reddit-clone
ports:
- containerPort: 3000
Apply the deployment file:
After writing the deployment.yaml configuration we have to apply the configuration to complete the deployment.
kubectl apply -f deployment.yaml
kubectl get deployment
The kubectl apply -f deployment.yaml command applies the Kubernetes Deployment configuration specified in the deployment.yaml file.
When you run this command, Kubernetes reads the deployment.yaml file and creates a new Deployment object or updates an existing one, based on the information provided in the file.
After running kubectl apply -f deployment.yaml, you can use kubectl get deployments to verify that the Deployment has been created or updated successfully as shown below in which we can see there are 2 Pods available because we have defined 2 as Replicas:
Writing Service.yaml
Currently, our Reddit Clone application is running inside the Pods or the container of the Kubernetes Cluster that’s why it is not yet accessible to the outside world. This service.yaml file will help to expose and IP of the Cluster to the outside and will make is accessible for us.
apiVersion: v1
kind: Service
metadata:
name: reddit-clone-service
labels:
app: reddit-clone
spec:
type: NodePort
ports:
- port: 3000
targetPort: 3000
nodePort: 31000
selector:
app: reddit-clone
This configuration file defines a Kubernetes Service for the Reddit clone application using a NodePort service type, exposing the Service on port 31000 on each node in the cluster and routing traffic to the pods with the app: reddit-clone label.
Applying service.yaml
kubectl apply -f Service.yaml
When you run this command, Kubernetes reads the Service.yaml file and creates a new Service object or updates an existing one, based on the information provided in the file.
After applying the Service.yaml configuration we can see the app is deployed using the command:
minikube service reddit-clone-service
or
minikube service reddit-clone-service --url
NB: However, this URL is not yet accessible outside.
Exposing the Application
kubectl expose deployment reddit-clone-deployment --type=NodePort
The kubectl expose deployment reddit-clone-deployment — type=NodePort command creates a new Kubernetes Service object to expose the deployment named reddit-clone-deployment using the NodePort service type.
When you run this command, Kubernetes creates a new Service object and sets its selector to match the labels on the Pods managed by the reddit-clone-deployment. It also sets the Service’s type to NodePort, which exposes the Service on a static port on each node in the cluster.
Exposing the Service
kubectl port-forward svc/reddit-clone-service 3000:3000 --address 0.0.0.0 &
In the above step we have just exposed the deployment now we’ll be exposing the Service using the Port Forwarding method.
The kubectl port-forward svc/reddit-clone-service 3000:3000 — address 0.0.0.0 & command creates a port forwarding tunnel between your local machine and the Kubernetes Service named reddit-clone-service.
When you run this command, Kubernetes listens on port 3000 of your local machine and forwards any traffic received on that port to port 3000 of the reddit-clone-service in the Kubernetes cluster.
The — address flag specifies that the tunnel should be accessible from any IP address (0.0.0.0).
NB: Note that this command runs in the foreground, so you will need to keep the terminal window open for as long as you want the port forwarding tunnel to remain active. If you want to run the command in the background, you can remove the & at the end of the command.
kubectl port-forward svc/reddit-clone-service 3000:3000 --address 0.0.0.0
Exposing the IP of EC2 instance
As you can see above the port has been forwarded to 3000. However, this is still not accessible from Browser externally. To access this we need to edit the inbound rule of our Deployment Server. Here we have to add port 3000 and give it IvP4-Everywhere permission as below:
Application Deployed
After completing the above steps the Reddit clone app is finally deployed and now accessible from outside:
Test Ingress
Now It’s time to test your ingress so use the curl -L domain/test command in the terminal.
Ingress defines a set of rules that allows the inbound connection to access Kubernetes cluster services. Ingress is used to route external traffic to the Kubernetes endpoints by different URLs. We will need to enable ingress on our Minikube
minikube addons enable ingress
Write an Ingress File
vim Ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-reddit-app
spec:
rules:
- host: "domain.com"
http:
paths:
- pathType: Prefix
path: "/test"
backend:
service:
name: reddit-clone-service
port:
number: 3000
- host: "*.domain.com"
http:
paths:
- pathType: Prefix
path: "/test"
backend:
service:
name: reddit-clone-service
port:
number: 3000
You can apply the Ingress file using the below command and finally check whether the application is working or not by using the curl command with the specified domain name.
kubectl apply -f ingress.yml
curl -L domain.com/test
In this project, we successfully deployed a Reddit clone application using Docker and Kubernetes. By containerizing the application and leveraging the power of Kubernetes, we achieved efficient deployment, scaling, and management of our application. Through the use of deployment and service configurations, we were able to maintain the desired state of the application and expose it to external traffic. The integration of Docker Hub allowed for easy access to the Docker image during deployment. We also explored the capabilities of ingress in routing inbound connections to the Kubernetes cluster services. Overall, this project demonstrates the seamless combination of containerization, orchestration, and service exposure provided by Docker and Kubernetes, enabling smooth and scalable deployment of applications.
Thank you for reading this blog. If you found this blog helpful, please like, share, and follow me for more blog posts like this in the future.