Deploying a Reddit Clone with Ingress in Kubernetes using Minikube
Hands-On Kubernetes: Mastering Ingress with a Reddit Clone Deployment in Minikube
Table of contents
- Step 1: Clone the source code of the project
- Step 2: Build the Dockerfile
- Step 3: Push the docker image to Docker Hub
- Step 4: Creating a Deployment Manifest for K8s
- What is a Deployment?
- Step 5: Create a Service Manifest for K8s
- Step 6: Test your application
- Step 7: Configuring Ingress
- 1. Enable Ingress in Minikube
- 2. Write the Ingress K8s Manifest
- 3. Test the Ingress
- Well Done on Your Reddit Clone Deployment! 🔥
Welcome back, fellow Kubernetes explorers! In our previous blog, we took you on a journey to set up Minikube on your Linux machine. If you haven't already installed Minikube, make sure to check out our guide here as it's the first step toward today's exciting adventure.
We're diving deeper into the Kubernetes universe in this hands-on project guide. But, before we begin this exciting Reddit clone deployment journey, let's make sure you have the following prerequisites:
Prerequisites:
Basic Knowledge of Kubernetes: This adventure assumes that you have a basic understanding of Kubernetes objects such as Pod, Deployment, Service, and Ingress.
DockerHub Account: This blog requires an active DockerHub account that will be used to upload and download the docker image we will be building. You can create an account by visiting https://hub.docker.com/
Git: Git installed on your Ubuntu machine
Docker & Minikube Installed: If you haven't already set up docker & Minikube cluster, please refer to our installation guide here to get started.
With all the prerequisites satisfied, let’s dive into our project!
Step 1: Clone the source code of the project
Run the given command in your Linux terminal to download the project files
git clone https://github.com/kunal-gohrani/reddit-clone-k8s-ingress.git
Since the project is evolving continuously, we will be using the branch blog for the purpose of this guide. Let’s checkout into the blog branch using the command: git checkout blog
Step 2: Build the Dockerfile
The project folder includes a Dockerfile that will be used to build the image.
Dockerfile:
FROM node:19-alpine3.15
WORKDIR /reddit-clone
COPY . /reddit-clone
RUN npm install
EXPOSE 3000
CMD ["npm","run","dev"]
Run the below-given commands inside the root of the project folder to build the docker image, replace the placeholder <username>
with your DockerHub username.
docker build . -t <username>/reddit-clone:latest
Use the command docker images
to view your newly built image, the output should be similar to this:
Step 3: Push the docker image to Docker Hub
After building the image, we need to push it to docker hub, our Kubernetes deployment will later fetch the same image from docker hub to run the app.
Login to DockerHub from docker CLI:
This step is crucial to push docker images. Run the given command to log in to docker hub with your username and password. docker login
Push the Docker image to DockerHub:
Use the command docker push <username>/reddit-clone:latest
to push the image, replace the placeholder <username>
with your username.
After pushing the image, refresh your DockerHub website, and you will be able to see a new repository has been created containing your docker image.
Step 4: Creating a Deployment Manifest for K8s
Congrats on reaching here! 🥳 You have now successfully built a docker image and uploaded it to Docker Hub, thus completing the basic steps of the continuous integration Process.
Now we will be focusing on deploying the docker image in a K8s cluster. For this, we will be using the Deployment object of K8s to create Pods that run our image.
What is a Deployment?
In K8s, a Deployment object acts like the manager of the Pods, It ensures that the specified number of pod replicas with the desired container images are running normally. If a pod encounters problems or needs an update, the Deployment handles it seamlessly while maintaining the desired number of pods. K8s objects are declared using YAML files and are often referred to as manifests. You can read more about the Deployment object here.
You can view the deployment.yml
file present in the project folder or copy it from here.
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: <username>/reddit-clone:latest
ports:
- containerPort: 3000
Make sure to replace the value of image
key with that of your image name as shown in the YAML file.
The deployment creates 2 pods running 1 container each with the reddit-clone image we pushed earlier. The key containerPort declares that the container accepts connections from port 3000.
Run kubectl apply -f deployment.yml
to create the deployment object in K8s. You should see an output similar to this:
Run kubectl get deployment
and kubectl get pods
to ensure that your deployment has been successfully created and pods are running. Your output should look like this:
Step 5: Create a Service Manifest for K8s
Our next step is to create a service object that will allow us to connect to the pods created by the deployment file.
A Service in K8s serves as a link between distinct pods or microservices inside a cluster. Consider it a well-known phone number in a directory that enables pods to connect and converse despite their dynamic nature or changing IP addresses. Services are critical because they provide a consistent and discoverable endpoint for applications, as well as load balancing and abstraction of underlying pod modifications. The dynamic and scalable nature of Kubernetes would make it difficult for pods to identify and interact with one another without Services. You can read more about Service Objects here.
You can view the service.yml
file present in the project folder or copy the one below and paste it into your YAML file
apiVersion: v1
# Indicates this as a service
kind: Service
metadata:
# Service name
name: reddit-clone-service
spec:
selector:
# Selector for Pods
app: reddit-clone
ports:
# Port is the port service is gonna listen to
- port: 3000
# Target port is the port container is listening to
targetPort: 3000
protocol: TCP
# We are using ClusterIP service which is not directly
# accessible from outside the cluster, other types of services
# are NodePort, LoadBalancer
type: ClusterIP
Run kubectl apply -f service.yml
to create this service in K8s. Run kubectl get svc
to check if the service has been created, the output should look like this:
Step 6: Test your application
Now it is time to test our deployed application. Since our service object is of the type ClusterIP, it is not accessible outside the cluster, but for the purpose of testing, we can forward all requests received in a specific port on the host to the service port using kubectl port-forward
command.
Make sure port 3000 is not blocked by a firewall or a security group if you are running Linux on the cloud, This is crucial for testing the app.
You need to note the IP of the machine Minikube is running in, use ifconfig
command on Linux to find your machine’s IP address.
Run the command kubectl port-forward svc/reddit-clone-service 3000:3000 --address 0.0.0.0
After running this command, keep the terminal open.
Now in your browser, open the URL <LinuxIP>:3000
Replace the placeholder <LinuxIP>
with the IP of the Linux machine you noted above. If everything is configured well, you should see a site similar to this:
and in your terminal running the port-forward command, the output should look something like this:
The app has now been successfully deployed! Congratulations on reaching this far! 🥳
Now we will be configuring ingress.
Step 7: Configuring Ingress
Ingress is a clever traffic management and routing solution for Kubernetes apps running within the cluster. While LoadBalancer and NodePort Services are useful for exposing specific services, Ingress offers a more advanced solution. It serves as a single entry point for various services, making it an excellent solution when you need to access numerous microservices via distinct URLs or domains. You can read more about ingress and ingress controllers here
1. Enable Ingress in Minikube
In Minikube, ingress comes as an addon and we need to enable it before configuring it. Run minikube addons enable ingress
in the terminal to enable ingress. The output should be like this:
2. Write the Ingress K8s Manifest
You can use the ingress.yml
present in the project folder or copy the YAML from here:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-reddit-app
spec:
ingressClassName: nginx
rules:
- host: redditclone.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: reddit-clone-service
# Port Service is listening on
port:
number: 3000
- host: "*.redditclone.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: reddit-clone-service
# Port Service is listening on
port:
number: 3000
We have used the domain redditclone.com as our entry point to the ingress Create the ingress rule using the command kubectl apply -f ingress.yml
and then run kubectl get ingress
, the output should be like this:
We need to wait for the Address column to be populated, it will take some time before it is so keep checking kubectl get ingress
.
After the address column is populated like this
Note down the IP displayed in the address column.
3. Test the Ingress
We have now successfully deployed the ingress and now we can test it. To test the ingress, we need to send a request to redditclone.com
, however, we don’t own this domain, and there’s no DNS record pointing redditclone.com to our cluster. So, we will be using curl command to forcefully resolve redditclone.com to the IP of ingress as noted above. The command is:
curl --resolve "redditclone.com:80:<IP of Ingress>" redditclone.com
Upon executing this command, we immediately get a rather big output of the HTML file which is of our Reddit clone.
NOTE: If you are running minikube in a linux machine with GUI and want to access redditclone.com from your browser, you can edit /etc/hosts file using vi to add a line with the format like: <IP of Ingress>
redditclone.com
The file should then look something like this:
After saving the file, you should be able to access the app by using URL redditclone.com in your browser.
Well Done on Your Reddit Clone Deployment! 🔥
Congratulations on successfully deploying the Reddit clone app with Minikube! You've unlocked the door to the Kubernetes world, and this is just the beginning. Keep exploring, learning, and building with Kubernetes—it's a journey filled with endless possibilities.
If you run into issues while deploying this app or have some suggestions on improving the blog or just want to reach out to showcase your deployment, please contact me on LinkedIn.
Thank you fellow K8s adventurers, Do follow me for more such exciting blogs on K8s, Docker, and Linux. 🧑🏻💻