Skip to main content

Command Palette

Search for a command to run...

Deployment of a Microservices Application on K8s

Updated
6 min readView as Markdown
D
Site Reliability Engineer passionate about cloud infrastructure, automation, scalability, and operational excellence. I write about SRE, DevOps, Azure, AWS, Kubernetes, CI/CD, and real-world troubleshooting experiences.

🕸️ What are Microservices ⁉️

Microservices architecture is an approach to software development where a complex application is broken down into smaller, loosely coupled, and independently deployable services. These services are responsible for specific, well-defined functions and communicate with each other through APIs or other messaging mechanisms. Kubernetes (K8s) is a powerful container orchestration platform that provides an ideal environment for deploying and managing microservices. Here's a brief overview of how microservices work on Kubernetes:

  1. Containerization: Microservices are typically packaged as containers using technologies like Docker. Containers provide a consistent and lightweight runtime environment, ensuring that services run consistently across various environments.

  2. Kubernetes as an Orchestrator: Kubernetes simplifies the deployment and management of microservices by automating tasks such as scaling, load balancing, and service discovery. It abstracts the underlying infrastructure, making it easier to focus on application development.

  3. Service Deployment: Each microservice is deployed as a separate container within a Kubernetes cluster. Kubernetes ensures that these containers are distributed across nodes for high availability and scalability.

  4. Service Discovery: Kubernetes provides built-in service discovery mechanisms that allow microservices to locate and communicate with each other. Services are exposed via Kubernetes Services, which act as load balancers and route traffic to the appropriate microservice instances.

  5. Scaling: Microservices can be independently scaled up or down based on demand. Kubernetes supports both manual and auto-scaling strategies, ensuring that resources are allocated efficiently.

  6. Fault Tolerance: Kubernetes monitors the health of microservices and automatically replaces failed instances with healthy ones. This enhances the fault tolerance of microservices applications.

  7. Configuration Management: Kubernetes allows you to manage configurations for each microservice through ConfigMaps and Secrets. This enables you to change configurations without modifying the application code.

  8. Rolling Updates: Kubernetes supports rolling updates, making it easy to update microservices without downtime. This is crucial for maintaining application availability and reliability.

  9. Logging and Monitoring: Kubernetes integrates with various logging and monitoring tools, allowing you to collect and analyze data from microservices for troubleshooting and performance optimization.

  10. Security: Kubernetes offers robust security features, such as RBAC (Role-Based Access Control) and network policies, to protect microservices from unauthorized access and secure communication between them.

  11. Resource Management: Kubernetes provides resource management features, such as resource quotas and limits, to ensure that microservices do not consume excessive CPU and memory resources.

  12. Cloud-Native: Kubernetes is designed to work seamlessly in cloud environments, making it suitable for building cloud-native microservices applications that can easily scale and leverage cloud services.

Kubernetes simplifies the deployment, scaling, management, and orchestration of microservices, making it an excellent choice for organizations looking to embrace a microservices architecture for building scalable and resilient applications. However, it's important to note that while Kubernetes provides many benefits, it also introduces complexities, and managing microservices effectively on Kubernetes requires careful planning and expertise.

🕸️ Hands-On Practice:

Let's make deploy a flask-api and mongo on kubernetes , where they both communicate to each other :

Prerequisites:

  • First we have to clone the repo ,build the docker image and push it to docker hub

  • Then create two instances one as master and other as worker having t2.medium and follow the steps.

Step 1: Clone the Repository

# Clone the microservices application repository
git clone <your-repo-url>
cd <your-repo-directory>

Step 2: Build and Push Docker Images

Build Docker images for your Flask and MongoDB services and push them to Docker Hub. Make sure you have Dockerfiles for both services:

FROM python:alpine3.7
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
ENV PORT 5000
EXPOSE 5000
ENTRYPOINT [ "python" ]
CMD [ "app.py" ]
# Build and push Flask service image
docker build -t your-docker-hub-username/taskmaster-python:latest
# docker login 
docker login
# push the image
docker push your-docker-hub-username/taskmaster-python:latest

Installing Kubeadm on both the nodes:

Create two instances with t2.medium:

On both Master and Worker Nodes:

  1. Install Docker and Kubernetes components:
sudo su
apt update -y
apt install docker.io -y
systemctl start docker
systemctl enable docker

# Add Kubernetes repository and install required packages
curl -fsSL "https://packages.cloud.google.com/apt/doc/apt-key.gpg" | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes-archive-keyring.gpg
echo 'deb https://packages.cloud.google.com/apt kubernetes-xenial main' > /etc/apt/sources.list.d/kubernetes.list

apt update -y
apt install kubeadm=1.20.0-00 kubectl=1.20.0-00 kubelet=1.20.0-00 -y

On the Master Node:

  1. Initialize Kubernetes and set the KUBECONFIG environment variable:
kubeadm init
export KUBECONFIG=/etc/kubernetes/admin.conf

  1. Install a network plugin (Weave in this case):
kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
  1. Obtain the join command for worker nodes:
kubeadm token create --print-join-command

On the Worker Node:

  1. Reset Preflight-checks on worker node
sudo su
kubeadm reset pre-flight checks

  1. Paste and run the join command obtained from the master node. Append --v=5 at the end to increase verbosity for debugging if needed.

Back on the Master Node:

  1. Check that the worker node has joined the cluster:
kubectl get nodes

  1. Clone your GitHub repository and navigate to the /flask-api/k8s/ directory.

Deploy Flask Application:

  1. Deploy Flask microservices using YAML files:

    • For the integration of Mongo and flask app we need to change the deployment manifest taskmaster.yml to include MONGO_HOST env. variable as shown below -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: taskmaster
      labels:
        app: taskmaster
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: taskmaster
      template:
        metadata:
          labels:
            app: taskmaster
        spec:
          containers:
            - name: taskmaster
              image: srahul0502/taskmaster-python:latest
              env:
                - name: MONGO_HOST
                  value: "mongo.default.svc.cluster.local:27017"
              ports:
                - containerPort: 5000
              imagePullPolicy: Always
  • Taskmaster-service.yml

      apiVersion: v1
      kind: Service
      metadata:
        name: taskmaster-svc
      spec:
        selector:
          app: taskmaster
        ports:
          - port: 80
            targetPort: 5000
            nodePort: 30007
        type: NodePort
    
kubectl apply -f taskmaster.yml
kubectl get pods
kubectl apply -f taskmaster-svc.yml
kubectl get svc

  1. Scale the Flask application if needed:
kubectl scale --replicas=3 deployment/taskmaster

On Worker-node:

Use docker ps to check the containers running :

Set Up MongoDB:

  1. Deploy a persistent volume for MongoDB storage:

    • Mongo-pv.yml

        apiVersion: v1
        kind: PersistentVolume
        metadata:
          name: mongo-pv
        spec:
          capacity:
            storage: 256Mi
          accessModes:
            - ReadWriteOnce
          hostPath:
            path: /tmp/db
      
kubectl apply -f mongo-pv.yml
kubectl get pv

  1. Create a Persistent Volume Claim (PVC):

    • mongo-pvc.yml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: mongo-pvc
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 256Mi
kubectl apply -f mongo-pvc.yml
kubectl get pv

  1. Deploy MongoDB:
kubectl apply -f mongo.yml
kubectl get pods

Check if the mongo is working or not

  • Use docker ps to check if the docker container is running or not :

  • Go to worker node , type docker exec -t <docker-id> bash , use mongosh to enter into mongo

  1. Create a MongoDB service:

    • Mongo-svc.yml

        apiVersion: v1
        kind: Service
        metadata:
          labels:
            app: mongo
          name: mongo
        spec:
          ports:
            - port: 27017
              targetPort: 27017
          selector:
            app: mongo
      
kubectl apply -f mongo-svc.yml
kubectl get svc

Testing:

  1. Test the Flask application using Postman or CURL by accessing the worker node IP and the exposed service port (e.g., IP:30007).

You can test if the application is working by trying to insert and then fetch data from the DB using the flask app requests GET /tasks and POST /task.

GET /tasks :

curl 34.229.68.229:30007/tasks

Insert Data to MongoDB using POST /task path and then get all data using GET /tasks path:

curl -X POST -H "Content-Type: application/json" -d '{"task":"Show everyone the project"}' http://34.229.68.229:30007/task
curl 34.229.68.229:30007/tasks
29 views

More from this blog

D

DevLog

61 posts