Deployed a Reddit Clone app with Mongodb  on Kubeadm using 2 nodes cluster with Ingress enabled

Deployed a Reddit Clone app with Mongodb on Kubeadm using 2 nodes cluster with Ingress enabled

Prerequisite:

First You have to install some Prerequisites for this deployment. For kubeadm installation

https://github.com/farzshamim/Installation-scripts/blob/main/kubernetes_installation_kubeadm.sh

or you can check my blog as well for installation kubeadm with docker and containerd.

https://hashnode.com/draft/64a5bb878bd112000f2654f6#:~:text=kubernetes-,architecture,-and%20Multi%2DNode

Here, i have created two ec2 instance of t2-medium for a smooth operation but you can choose t2-micro for worker node.

Open the ports in security inbound rule 6443, 31001 and whatever is required as per your preference.

Step 1: Clone the code

https://github.com/farzshamim/reddit-clone-k8s-ingress.git

or you can use the image farzshamim/reddit-clone:latest

Step 2: Containerize the Application using Docker

Build the docker image and push it to docker hub.

Dockerfile:

FROM node:19-alpine3.15

WORKDIR /reddit-clone

COPY . /reddit-clone

RUN npm install

EXPOSE 3000

CMD ["npm","run","dev"]

Step 3: Write a Kubernetes Manifest File.

You can refer to the website https://kubernetes.io/ for the format which are available there.

  1. Write mongo-config.yaml file

    For database i have choosen mongodb. In data:

    key:value=mongo-url: mongo-service

     apiVersion: v1
     kind: ConfigMap
     metadata:
       name: mongo-config
     data:
       mongo-url: mongo-service
    

    2. Write a mongo-secret.yaml file:

    In this file, the key:value pairs are specified by encoding in the CLI by using the code : generate yours one by the following

    echo -n <username> | base64

    echo -n <password> | base64

     apiVersion: v1
     kind: Secret
     metadata:
       name: mongo-secret
     data:
       mongo-user: bW9uZ28tdXNlcg==
       mongo-password: bW9uZ28tcGFzc3dvcmQ=
    

    3. Write a database.yaml file: i.e mongo.yaml

    The deployment and service both are in one file. Make sure the labels and selector should be the same. Specify the replicas, container image, and environment of the database you are using in this case: MongoDB and add the secret key reference to the deployment file environment.

    The service selector and the deployment label name should be the same and the target port of the service should be same as the deployment container port i.e 27017.

     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: mongo-deployment
       labels:
         app: mongo
     spec:
       replicas: 1
       selector:
         matchLabels:
           app: mongo
       template:
         metadata:
           labels:
             app: mongo
         spec:
           containers:
           - name: mongodb
             image: mongo:6.0
             ports:
             - containerPort: 27017
             env:
             - name: MONGO_INITDB_ROOT_USERNAME
               valueFrom:
                 secretKeyRef:
                   name: mongo-secret
                   key: mongo-user
             - name: MONGO_INITDB_ROOT_PASSWORD
               valueFrom:
                 secretKeyRef:
                   name: mongo-secret
                   key: mongo-password
    
     ---
     apiVersion: v1
     kind: Service
     metadata:
       name: mongo-service
     spec:
       selector:
         app: mongo
       ports:
         - protocol: TCP
           port: 27017
           targetPort: 27017
    

    4.Write an web-app.yaml file: i.e reddit-clone.yaml

    Here, everything will be the same as above mongo.yaml file. The addition will be:

    1. configMapKeyRef: name: mongo-config key: mongo-url which has been taken from the mongo-config .yaml.

    2. Type: NodePort

      with port 3000 redirecting to the external port 31001 to communicate with the browser.

    3.   apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: reddit-clone-deployment
          labels:
            app: reddit-clone
        spec:
          replicas: 3
          selector:
            matchLabels:
              app: reddit-clone
          template:
            metadata:
              labels:
                app: reddit-clone
            spec:
              containers:
              - name: reddit-clone
                image: farzshamim/reddit-clone:latest
                ports:
                - containerPort: 3000
                env:
                - name: USER_NAME
                  valueFrom:
                    secretKeyRef:
                      name: mongo-secret
                      key: mongo-user
                - name: USER_PWD
                  valueFrom:
                    secretKeyRef:
                      name: mongo-secret
                      key: mongo-password
                - name: DB_URL
                  valueFrom:
                    configMapKeyRef:
                      name: mongo-config
                      key: mongo-url
      
        ---
        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: 3000
            targetPort: 3000
            nodePort: 31001
            protocol: TCP
          type: NodePort
      

To deploy the app you need to run following the command: First, run the secret and config yaml file by the blow kubectl apply -f command and then the app and database yaml file. kubectl apply -f reddit-clone.yaml Just Like this create a mongo.yaml using kubectl apply -f mongo.yaml

If You want to check your deployment & Service use the command kubectl get deployment & kubectl get services

The app is running in your worker node http://43.204.96.206:31001/

Step 4: Configuring Ingress

Pods and services in Kubernetes have their own IP; however, it is normally not the interface you'd provide to the external internet. Though there is a service with node IP configured, the port in the node IP can't be duplicated among the services. It is cumbersome to decide which port to manage with which service. Furthermore, the node comes and goes, it wouldn't be clever to provide a static node IP to an external service. Ingress defines a set of rules that allows the inbound connection to access Kubernetes cluster services. It brings the traffic into the cluster at L7 and allocates and forwards a port on each VM to the service port. This is shown in the following figure. We define a set of rules and post them as source type ingress to the API server. When the traffic comes in, the ingress controller will then fulfill and route the ingress by the ingress rules. As shown in the following figure, ingress is used to route external traffic to the Kubernetes endpoints by different URLs:

  1. Write an ingress.yaml file

    Now you can able to create ingress for your service. kubectl apply -f ingress.yaml use this command to apply ingress settings.

    • Verify that the ingress resource is running correctly by using kubectl get ingress ingress-reddit-app command.

Install minikube to enable ingress:

Minikube doesn't enable ingress by default; we have to enable it first using minikube addons enable ingress command.

  • If you want to check the current setting for addons in minikube use minikube addons list command.

Now you can able to create ingress for your service. kubectl apply -f ingress.yaml use this command to apply ingress settings.

  • Verify that the ingress resource is running correctly by using kubectl get ingress ingress-reddit-app command.

Expose the app

  1. First We need to expose our deployment so use kubectl expose deployment reddit-clone-deployment --type=NodePort command.

  2. 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

  3. Then We have to expose our app service kubectl port-forward svc/reddit-clone-service 3000:3000 --address 0.0.0.0 &

Test Ingress

Now It's time to test your ingress so use the curl -L domain/test command in the terminal.

ou can also see the deployed application on Ec2_ip:3000

Note:- Make sure you open the 3000 port in a security group of your Ec2 Instance.

Get Connected:

If you have any suggestion about this post feel free to let me know and be updated on my blog in the following ways:

LinkedIn Twitter Github

#TrainWithShubham #DevOps #chatgpt #AI #devops #devopsengineer #devops2023 #devopscommunity #devopslife #devopsnotes #DevOpsGuys #DevOpsHandbook #devopsinuk #shellscript #linux #kubernetes #kubeadm