How to Deploy a Fast API Application to a Kubernetes Cluster using Podman and Minikube
Tags: kubernetes, python, minikube, podman
Published: 2024-04-22 13:39:03

This tutorial is designed to guide you through deploying a FastAPI application to a Kubernetes cluster using Podman and Minikube. I developed this guide with insights from @bravinsimiyu and his tutorial, which is listed in the sources section at the end of this document.

<br>

## Prerequisites
- [Python](https://www.python.org/downloads/)
- [Podman](https://podman.io/docs/installation)
- [MiniKube](https://minikube.sigs.k8s.io/docs/start/)
- [Kubernetes CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/)
- [FastAPI](https://fastapi.tiangolo.com/) & [Uvicorn](https://www.uvicorn.org/)

<br>

## Write some code
Through this tutorial, we will be using this simple code in a file named 'main.py':
```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}
```

<br>

## Running the FastAPI application using Uvicorn
To run your FastAPI application, use the following command in your terminal:
```shell
uvicorn main:app
```
This command starts your application and makes it accessible at http://127.0.0.1:8000.
_NOTE: In the command 'uvicorn main:app', 'main' refers to the name of your Python file (without the .py extension), and 'app' is the name of the FastAPI instance created in your code._

<br>

## Running the FastAPI application using Podman

### Create a requirements.txt file
A 'requirements.txt' file contains the framework and the dependencies for the FastAPI application. Podman will install all these requirements when creating a podman image for the FastAPI application.
Create a new file named 'requirements.txt'. Open the file and add the following:
```
fastapi
uvicorn
```

### Write a Dockerfile for the FastAPI application
A Dockerfile is an executable file that contains a list of commands or instructions for creating a podman image. Podman Engine will execute all these commands in chronological order and create a podman image.
Create a new file named 'Dockerfile'. Open the file and add the following:
```dockerfile
#Instruct Podman Engine to use official python:3.12 as the base image
FROM python:3.12

#Create a working directory(app) for the Podman image and container
WORKDIR /app

#Copy the framework and the dependencies of the FastAPI application into the working directory
COPY requirements.txt .

#Install the framework and the dependencies in the requirements.txt file in our Podman image and container
RUN pip install -r requirements.txt

#Copy the remaining files and the source code from the host fast-api folder to the FastAPI application container working directory
COPY . .

#Expose the FastAPI application on port 8000 inside the container
EXPOSE 8000

#Start and run the FastAPI application container
CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]
```

### Build a podman image for the FastAPI application using the Dockerfile
We will build the podman image for the FastAPI application using the instructions in the Dockerfile. 
Run this podman command:
```shell
podman build -t docker.io/louisalexandrelaguet/fast-api .
```
_NOTE: Ensure you name the podman image using your Docker Hub account username. It will make it easier to push the podman image to the Docker Hub repository._

### Run a podman container using the podman image
We will run a podman container using the podman image. When you run a podman image, it will run a podman container for the application. In your terminal, run this podman command:
```shell
podman run -p 8000:8000 docker.io/louisalexandrelaguet/fast-api
```
The command will start your application and it will be reachable at http://127.0.0.1:8000

<br>

## Running the FastAPI application using Minikube

### Push your podman image to the Docker Hub
You must push the image you created previously to the Docker Hub so that the deployment in your cluster can pull it and run it inside a pod. You can do that by running this command:
```shell
podman push docker.io/louisalexandrelaguet/fast-api
```

### Kubernetes YAML file
The Kubernetes YAML file describes the resources for the Kubernetes application and pods that will be created in the Kubernetes Cluster. This file also configures the Kubernetes Service for the application. Kubectl will use this file to deploy the Dockerized Fast API application to Minikube. 
Create a new file named 'kubernetes.yaml'. Open the file and add the following code:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fast-api-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: fast-api
  template:
    metadata:
      labels:
        app: fast-api
    spec:
      containers:
      - name: fast-api
        image: docker.io/louisalexandrelaguet/fast-api
        resources:
          limits:
            memory: "256Mi"
            cpu: "500m"
        ports:
        - containerPort: 8000

---

apiVersion: v1
kind: Service
metadata:
  name: fast-api-service
spec:
  selector:
    app: fast-api
  ports:
  - port: 8000
    targetPort: 8000
  type: LoadBalancer
```

The 'kubernetes.yaml' is divided into two. The first part is known as Deployment while the second is known as Service.

**Deployment:** The first part of the file will configure the application pods and the resources of your deployed application. It will create two pods. Pods are replicas or instances of the deployed application. It will use your image to create the Podman Container.

**Service:** This second type of file configures the Kubernetes Service for the application. It uses the LoadBalancer Kubernetes Service to equally distribute traffic to the two container pods. Minikube will assign an External IP address to the Kubernetes Service. It will enable us to access the deployed Fast API application.

### Start MiniKube
Open a terminal as an administrator and run the following command to start Minikube: 
```shell
minikube start
```

Once Minikube is running, you can create the deployment and the service that will run your podman image by calling the 'kubectl' command on your 'kubernetes.yaml' file:
```shell
kubectl apply -f kubernetes.yaml
```

### Accessing the Deployed FastAPI application
To access the deployed FastAPI application, Minikube will assign an External IP address to the _fast-api-service_. You will type the External IP address in your web browser and access the application. To get the External IP address, run this minikube command:
```shell
minikube service fast-api-service
```
Simply type the assigned IP address in your web browser to access your deployed FastAPI application.

### Stop the deployment
To stop the deployment of your FastAPI application, you must delete the deployment and the service you created with the commands:
```shell
kubectl delete deployment.apps/fast-api-deployment
kubectl delete service/fast-api-service
```

Then, if you want to stop Minikube, simply run:
```shell
minikube stop
```

<br>

## Sources

- [How to Dockerize and Deploy a Fast API Application to Kubernetes Cluster](https://dev.to/bravinsimiyu/how-to-dockerize-and-deploy-a-fast-api-application-to-kubernetes-cluster-35a9) from @bravinsimiyu