FastAPI Microservices Deployment Using Kubernetes
Tags: fastapi, docker, kubernetes, minikube
Published: 2024-06-02 09:05:14

In this article we are going to create 2 microservices in FastAPI and deploy them using kubernetes on minkube. We are going to use kubernetes ingress to route requests to respective microservices.

Fist let’s go through kubernetes features we are going to use in this article.

Kubernetes Deployment: A Kubernetes Deployment automates the management of application updates and scaling. It defines the desired state for an application, such as the number of replicas, the container image to use, and update strategies. The Deployment controller ensures that the actual state of the application matches the desired state by creating and updating pods as needed. Deployments support rolling updates, rollback capabilities, and self-healing, making it easier to maintain application availability and reliability during changes. This abstraction simplifies deploying, scaling, and managing stateless applications in a Kubernetes cluster. [https://kubernetes.io/docs/concepts/workloads/controllers/deployment/](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)

Kuberenetes Service: A Kubernetes Service is an abstraction that defines a logical set of pods and a policy for accessing them, usually via a stable IP address and DNS name. Services enable communication between different parts of an application without needing to know the pod’s IP addresses, which can change.

[https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/](https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/)

Kubernetes Ingress: Kubernetes Ingress manages external access to services within a Kubernetes cluster. In our application we are going to use it to route the traffics to respective services (i.e microservice 1 or microservice 2). It defines rules to route traffic based on hostnames and paths to specific services. An Ingress controller, such as NGINX or Traefik, implements these rules, providing centralized management, load balancing, SSL termination, and path-based routing. Deploying an Ingress controller is required to use Ingress resources effectively.

[https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress)

**Microservice 1**:
Microservice 1 is going to be pretty straightforward. It is going to have only one endpoint which is going to return “You requested microservice 1”.

- Create a folder named microservice_1 and add a file named main.py.

```
# main.py (microservice 1)

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "You requested microservice 1"}
```

- Add requirements.txt file


`fastapi==0.111.0`

- Create Dockerfile

```
FROM python:3.10-slim

WORKDIR /app

COPY requirements.txt requirements.txt

RUN pip install -r requirements.txt

COPY . .

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
```

- Build the docker image and push it to dockerhub.

Make sure to tag the image in format username/image_name:version format. Otherwise kubernetes won’t be able to recognize the image. Run this command from the directory where Dockerfile for microservice 1 is located.

```
$ docker build . -t sumangaire96/microservice1:v1
$ docker push sumangaire96/microservice1:v1
```

**Microservice 2**:
Microservice 2 is also going to have only one endpoint which is going to return “You requested microservice 2”.

- Create a folder named microservice_1 and add a file named main.py.

```
`# main.py (microservice 2)
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "You requested microservice 2"}`
```

- Add requirements.txt

`fastapi==0.111.0`

- Add Dockerfile

```
FROM python:3.10-slim

WORKDIR /app

COPY requirements.txt requirements.txt

RUN pip install -r requirements.txt

COPY . .

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
```

- Build the docker image and push it to dockerhub.

`$ docker build . -t sumangaire96/microservice2:v1
$ docker push sumangaire96/microservice2:v1`

**Minikube**:
Make sure you have minikube installed. If it is not installed follow this link https://minikube.sigs.k8s.io/docs/start/. Make sure to have kubectl installed to interact with minikube cluster from the terminal. If it is not installed follow this link [https://kubernetes.io/docs/tasks/tools/](https://kubernetes.io/docs/tasks/tools/).

- Create a kubernetes cluster.

`$ minikube start`

- Enable ingress in minikube.

`$ minikube addons enable ingress`

- Create kubernetes manifest file for microservice 1.

```
# kubernetes/microservice_1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice1-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: microservice1
  template:
    metadata:
      labels:
        app: microservice1
    spec:
      containers:
      - name: microservice1
        image: sumangaire96/microservice1:v1
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: microservice1-service
spec:
  selector:
    app: microservice1
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP
```

- Create kubernetes manifest file for microservice 2.

```
# kubernetes/microservice_2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice2-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: microservice2
  template:
    metadata:
      labels:
        app: microservice2
    spec:
      containers:
      - name: microservice2
        image: sumangaire96/microservice2:v1
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: microservice2-service
spec:
  selector:
    app: microservice2
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP

```

- Create kubernetes ingress manifest file.

```
# kubernetes/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: microservice1.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: microservice1-service
            port:
              number: 80
  - host: microservice2.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: microservice2-service
            port:
              number: 80
```

- Apply manifests

`$ kubectl apply -f microservice_1.yaml`
`$ kubectl apply -f microservice_2.yaml`
`$ kubectl apply -f ingress.yaml`

- Update hosts file to map the hostnames to the Minikube IP.

`$ echo "$(minikube ip) microservice1.local" | sudo tee -a /etc/hosts`
`$ echo "$(minikube ip) microservice2.local" | sudo tee -a /etc/hosts`

- Now go to url microservice1.local and microservice2.local. You should see output like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhk5f2k8eid3l1vfipih.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9942uf8ytb2u1wmdewq0.png)





Congratulations! We have created 2 microservices in FastAPI and successfully deployed them using kubernetes. Make sure to follow me for upcoming articles.