How to Deploy a Reddit Clone App on Kubernetes with Ingress — A Complete Guide for DevOps Learners
Learn how to deploy a web application on Kubernetes with Ingress in this step-by-step tutorial.
Introduction
Reddit is one of the most popular social media platforms that allows users to create and join communities, post and vote on content, and comment and interact with other users. Reddit is also known for its open-source culture and its use of cutting-edge technologies.
In this blog post, I will show you how to deploy a Reddit clone app on Kubernetes with Ingress. This app is a simplified version of Reddit that has the basic features of creating posts, voting, commenting, and browsing subreddits. You can find the source code of the app on GitHub.
Kubernetes is an open-source platform that allows you to automate the deployment, scaling, and management of your containerized applications across multiple hosts. Kubernetes is also known as K8s, which is derived from the number of letters between K and s in Kubernetes.
Ingress is a resource that defines rules to expose services to external traffic. Ingress allows you to route the traffic from outside the cluster to the appropriate service based on the host name or path. Ingress can also provide features such as load balancing, SSL termination, name-based virtual hosting, etc.
Why should we deploy a Reddit clone app on Kubernetes with Ingress? There are several reasons, such as:
- To learn how to use Kubernetes and Ingress to deploy and expose a web application.
- To demonstrate the benefits of Kubernetes and Ingress, such as portability, scalability, availability, efficiency, and security.
- To showcase your skills and knowledge as a DevOps learner.
In this blog post, I will guide you through the following steps:
- Creating two servers on AWS EC2: one for the CI server and one for the deployment server.
- Cloning the repository: cloning the source code of the app from GitHub.
- Containerizing the application using Docker: creating a Dockerfile, building a Docker image, and pushing it to Dockerhub.
- Deploying the application to Kubernetes: writing a deployment.yml file and a service.yml file, applying them using
kubectl
, and verifying that they are running. - Configuring Ingress: explaining what Ingress is and why it is used, exposing the application using Ingress, and testing the Ingress.
By the end of this blog post, you will have a fully functional Reddit clone app running on Kubernetes with Ingress. You will also have a better understanding of Kubernetes and Ingress concepts and features.
Let’s get started!
Creating two servers on AWS EC2
The first step is to create two servers on AWS EC2: one for the CI server and one for the deployment server. The CI server will be used to clone the source code, build the Docker image, and push it to Dockerhub. The deployment server will be used to install Kubernetes using Minikube and deploy the application using kubectl
.
To create two servers on AWS EC2, follow these steps:
Step 1: Create a t2 micro instance for the CI server.
- Log in to your AWS account and go to the EC2 dashboard.
- Click on Launch Instance and select Ubuntu Server 22.04 LTS (HVM), SSD Volume Type as the AMI.
- Choose t2.micro as the instance type and click on Next: Configure Instance Details.
- Leave everything as default and click on Next: Add Storage.
- Leave everything as default and click on Next: Add Tags.
- Add a tag with Key as Name and Value as CI-server and click on Next: Configure Security Group.
- Create a new security group with Type as SSH, Protocol as TCP, Port Range as 22, Source as Anywhere (0.0.0.0/0), Description as SSH access. Click on Review and Launch.
- Review your instance details and click on Launch.
- Select an existing key pair or create a new one. Check the acknowledgment box and click on Launch Instances.
- Wait for your instance to launch and note down its public IP address.
Step 2: Create a t2 medium instance for the deployment server.
- Repeat the same steps as above but choose t2.medium as the instance type instead of t2.micro.
- Add a tag with Key as Name and Value as Deployment-server instead of CI-server.
- Create a new security group with Type as Custom TCP Rule, Protocol as TCP, Port Range as 30000–32767, Source as Anywhere (0.0.0.0/0), Description as NodePort access. This will allow us to access the NodePort service from outside the cluster.
- Select the same key pair as before and launch the instance.
- Wait for your instance to launch and note down its public IP address.
Step 3: Install the required components on both servers.
- Connect to both servers using SSH. For example, ssh -i <keypair.pem> ubuntu@<public-ip-address>.
- On the CI server, install git, docker, and docker-compose using the following commands:
sudo apt update
sudo apt install git -y
sudo apt install docker.io -y
sudo usermod -aG docker $USER && newgrp docker
sudo apt install docker-compose
sudo chmod +x /usr/local/bin/docker-compose
- On the deployment server, install
kubectl
and minikube using the following commands:
sudo apt update
sudo apt install curl docker.io -y
sudo snap install kubectl --classic
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
minikube start --driver=docker
Cloning the repository
The next step is to clone the repository that contains the source code of the Reddit clone app. The repository is available on GitHub.
To clone the repository, follow these steps:
Step 1: Clone the repository from https://github.com/LondheShubham153/reddit-clone-k8s-ingress.git.
- On the CI server, create a directory called reddit-clone and cd into it:
mkdir reddit-clone && cd reddit-clone
- Clone the repository using git:
git clone https://github.com/LondheShubham153/reddit-clone-k8s-ingress.git .
- You should see the following files and directories in your reddit-clone directory:
.
├── Dockerfile
├── README.md
├── deployment.yml
├── firebase.json
├── functions
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ ├── tsconfig.dev.json
│ └── tsconfig.json
├── ingress.yml
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── images
│ │ ├── googlelogo.png
│ │ ├── recCommsArt.png
│ │ ├── redditFace.svg
│ │ ├── redditPersonalHome.png
│ │ ├── redditText.svg
│ │ └── redditlogo.png
│ └── vercel.svg
├── service.yml
├── src
│ ├── atoms
│ │ ├── authModalAtom.ts
│ │ ├── communitiesAtom.ts
│ │ ├── directoryMenuAtom.ts
│ │ ├── postsAtom.ts
│ │ └── userAtom.ts
│ ├── chakra
│ │ ├── button.ts
│ │ ├── input.ts
│ │ └── theme.ts
│ ├── components
│ │ ├── Community
│ │ │ ├── About.tsx
│ │ │ ├── CommunityNotFound.tsx
│ │ │ ├── CreatePostLink.tsx
│ │ │ ├── Header.tsx
│ │ │ ├── PersonalHome.tsx
│ │ │ ├── Premium.tsx
│ │ │ ├── Recommendations.tsx
│ │ │ └── Temp.tsx
│ │ ├── Layout
│ │ │ ├── InputField.tsx
│ │ │ ├── InputItem.tsx
│ │ │ ├── PageContent.tsx
│ │ │ └── index.tsx
│ │ ├── Main
│ │ │ └── index.tsx
│ │ ├── Modal
│ │ │ ├── Auth
│ │ │ │ ├── Inputs.tsx
│ │ │ │ ├── Login.tsx
│ │ │ │ ├── OAuthButtons.tsx
│ │ │ │ ├── ResetPassword.tsx
│ │ │ │ ├── SignUp.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── CreateCommunity
│ │ │ │ └── index.tsx
│ │ │ └── ModalWrapper.tsx
│ │ ├── Navbar
│ │ │ ├── Directory
│ │ │ │ ├── Communities.tsx
│ │ │ │ ├── MenuListItem.tsx
│ │ │ │ ├── Moderating.tsx
│ │ │ │ ├── MyCommunities.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── RightContent
│ │ │ │ ├── ActionIcon.tsx
│ │ │ │ ├── AuthButtons.tsx
│ │ │ │ ├── Icons.tsx
│ │ │ │ ├── ProfileMenu
│ │ │ │ │ ├── MenuWrapper.tsx
│ │ │ │ │ ├── NoUserList.tsx
│ │ │ │ │ └── UserList.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── SearchInput.tsx
│ │ │ └── index.tsx
│ │ └── Post
│ │ ├── Comments
│ │ │ ├── CommentItem.tsx
│ │ │ ├── Input.tsx
│ │ │ └── index.tsx
│ │ ├── Loader.tsx
│ │ ├── PostForm
│ │ │ ├── ImageUpload.tsx
│ │ │ ├── NewPostForm.tsx
│ │ │ ├── TabItem.tsx
│ │ │ └── TextInputs.tsx
│ │ ├── PostItem
│ │ │ └── index.tsx
│ │ ├── Posts.tsx
│ │ └── PostsHome.tsx
│ ├── firebase
│ │ ├── authFunctions.ts
│ │ ├── clientApp.ts
│ │ └── errors.ts
│ ├── helpers
│ │ └── firestore.ts
│ ├── hooks
│ │ ├── useAuth.ts
│ │ ├── useCommunityData.ts
│ │ ├── useDirectory.ts
│ │ ├── usePosts.ts
│ │ └── useSelectFile.ts
│ ├── pages
│ │ ├── _app.tsx
│ │ ├── _document.tsx
│ │ ├── api
│ │ │ └── hello.ts
│ │ ├── index.tsx
│ │ └── r
│ │ └── [community]
│ │ ├── comments
│ │ │ └── [pid].tsx
│ │ ├── index.tsx
│ │ └── submit.tsx
│ └── styles
│ └── globals.css
└── tsconfig.json
Containerizing the application using Docker
The next step is to containerize the application using Docker. Docker is a tool that allows you to create, run, and share containers that contain your application and its dependencies.
To containerize the application using Docker, follow these steps:
Step 1: Create a Dockerfile
A Dockerfile is a file that contains instructions on how to build a Docker image. A Docker image is a snapshot of your application and its dependencies that can be run as a container.
To create a Dockerfile, use your favorite text editor and write the following code:
FROM node:19-alpine3.15
WORKDIR /reddit-clone
COPY . /reddit-clone
RUN npm install
EXPOSE 3000
CMD ["npm","run","dev"]
Save the file as Dockerfile in your reddit-clone directory.
Step 2: Build the Docker image.
To build the Docker image from the Dockerfile, use the following command:
docker build -t <DockerHub_Username>/reddit-clone .
Replace <DockerHub_Username> with your own username on Dockerhub. For example, if your username is londheshubham153, use:
docker build -t ajitfawade14/reddit-clone .
This command will create a Docker image with the name reddit.
Deploying the application to Kubernetes
The next step is to deploy the application to Kubernetes using kubectl
. Kubectl is a command-line tool that allows you to interact with the Kubernetes cluster and manage your resources.
To deploy the application to Kubernetes, follow these steps:
Step 1: Write a deployment.yml file.
A deployment.yml file is a file that defines the desired state of your application, such as the number of replicas, the image, the ports, etc. A deployment.yml file can be used to create or update a deployment resource in Kubernetes. A deployment resource is a higher-level abstraction that manages replica sets and provides declarative updates to pods.
To write a deployment.yml file, use your favorite text editor and write the following code:
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: ajitfawade14/reddit-clone
ports:
- containerPort: 3000
Save the file as deployment.yml in your reddit-clone directory.
Step 2: Write a service.yml file.
A service.yml file is a file that defines how to expose your application to other pods or external clients. A service.yml file can be used to create or update a service resource in Kubernetes. A service resource is an abstraction that defines a logical set of pods and a policy to access them. A service resource can be of different types, such as ClusterIP, NodePort, LoadBalancer, or ExternalName.
To write a service.yml file, use your favorite text editor and write the following code:
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
Save the file as service.yml in your reddit-clone directory.
Step 3: Apply the deployment and service files using kubectl
To apply the deployment and service files using kubectl
, use the following commands:
kubectl apply -f deployment.yml
kubectl apply -f service.yml
These commands will create or update the deployment and service resources in your Kubernetes cluster.
Step 4: Verify that the deployment and service are running
To verify that the deployment and service are running, use the following commands:
kubectl get deployments
kubectl get services
These commands will show you the status and details of your deployments and services. You should see something like this:
NAME READY UP-TO-DATE AVAILABLE AGE
reddit-clone-deployment 2/2 2 2 95s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2m48s
reddit-clone-service LoadBalancer 10.108.185.100 <pending> 3000:31000/TCP 43s
This means that your deployment has created three pods that are running your Reddit clone app, and your service has exposed them on port 80 externally and port 3000 internally. The NodePort type of service has also allocated a port from a range (default 30000–32767) for your service. In this case, it is 31000. This port will be accessible from outside the cluster using any node IP address and this port number.
Expose the app
- First We need to expose our deployment so use
kubectl expose deployment reddit-clone-deployment --type=NodePort
command. - You can test your deployment using curl -L http://192.168.49.2:31000. 192.168.49.2 is a minikube ip & Port 31000 is defined in Service.yml
- Then We have to expose our app service
kubectl port-forward svc/reddit-clone-service 3000:3000 --address 0.0.0.0 &
Configuring Ingress
The final step is to configure Ingress for your application. Ingress is a resource that defines rules to expose services to external traffic. Ingress allows you to route traffic from outside the cluster to your services based on host name or path. Ingress can also provide features such as load balancing, SSL termination, name-based virtual hosting, etc.
To configure Ingress for your application, follow these steps:
Step 1: Explain what Ingress is and why it is used.
Ingress is a resource that defines rules to expose services to external traffic. Ingress allows you to:
- Expose your services to the internet or other networks using a single IP address or domain name
- Route the traffic to your services based on the host name or path
- Provide features such as load balancing, SSL termination, name-based virtual hosting, etc.
- Simplify the management and configuration of your services
Ingress is useful for scenarios where you want to:
- Host multiple services or applications on the same cluster and expose them using different host names or paths
- Use a custom domain name or SSL certificate for your services
- Use advanced load balancing or routing features for your services
Step 2: Expose the application using Ingress.
To expose the application using Ingress, you need to do two things:
- Enable the Ingress addon on Minikube
- Write an ingress.yml file that defines the Ingress rules for your service
To enable the Ingress addon on Minikube, use the following command:
minikube addons enable ingress
This command will install and start the Ingress controller on your cluster. The Ingress controller is responsible for fulfilling the Ingress rules by routing the traffic to the appropriate services.
To write an ingress.yml file that defines the Ingress rules for your service, use your favorite text editor and write the following code:
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
Save the file as ingress.yml in your reddit-clone directory.
To apply the ingress.yml file using kubectl
, use the following command:
kubectl apply -f ingress.yml
This command will create or update the Ingress resource in your Kubernetes cluster.
Step 3: Test the Ingress.
To test the Ingress, use the following command in the terminal.
curl -L domain/test
You should see something like this:
Congratulations! You have successfully deployed a Reddit clone app on Kubernetes with Ingress!
Conclusion
In this blog post, we have learned how to deploy a Reddit clone app on Kubernetes with Ingress. We have covered the following steps:
- Creating two servers on AWS EC2: one for the CI server and one for the deployment server.
- Cloning the repository: cloning the source code of the app from GitHub.
- Containerizing the application using Docker: creating a Dockerfile, building a Docker image, and pushing it to Dockerhub.
- Deploying the application to Kubernetes: writing a deployment.yml file and a service.yml file, applying them using
kubectl
, and verifying that they are running. - Configuring Ingress: explaining what Ingress is and why it is used, exposing the application using Ingress, and testing the Ingress.
We have also demonstrated some of the benefits of Kubernetes and Ingress, such as portability, scalability, availability, efficiency, and security.
We hope you enjoyed this blog post and learned something new from it. Please feel free to share your feedback or queries in the comments section below.
Happy learning! 😊