Deploying Flask app to raspberry kubernetes cluster Part - 2
Published: 2023-08-19 08:48:35

before proceeding i would suggest you to go through the setup of k3s in raspberry pi

https://dev.to/rohit20001221/deploying-flask-app-to-raspberry-kubernetes-cluster-part-1-environment-setup-3nc5

**now we will create a simple flask app and create a docker image out of it**

**note:- (all the below code is written in your local system and deployed to raspberrypi)**

first we will create a project folder

```
mkdir flask-project
cd flask-project
```

now inside the flask project lets create `app.py` and paste the following code

**app.py**
```python
# app.py
from flask import Flask, render_template
import os

app = Flask(__name__)

@app.route('/')
def index():
    return render_template("index.html"), 200

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=os.environ.get("PORT", 8000))
```

**templates/index.html**
```html
# templates/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello World</title>
  </head>
  <body>
    <h1>This is a sample flask project.</h1>
  </body>
</html>
```

**requirements.txt**
```
flask
```

**now lets create a Docker file for our project**

```bash
FROM python:3-alpine

WORKDIR /app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

ENV PORT 80

CMD ["python", "app.py"]
```

this is a simple docker file which runs our flask application

now we will create a simple shell script to build and push our dockerfile to dockerhub

**build.sh**
```bash
docker build . -t flask-starter
docker tag flask-starter:latest <username>/flask-starter
docker push <username>/flask-starter
```

you can replace `username` with the dockerhub username

once you create the shell script run it by the following command it will push the docker image to the docker hub

```
sh ./build.sh

# [out]

```

in my case you can find the docker image at `rohit20001221/flask-starter`

```
pi@raspberrypi:~/starter-app-kubernetes-tutorial $ sudo sh build-docker.sh 
Sending build context to Docker daemon  72.19kB
Step 1/7 : FROM python:3-alpine
 ...
 ...
Successfully tagged flask-starter:latest
Using default tag: latest
The push refers to repository [docker.io/rohit20001221/flask-starter]
```

now lets start creating out config files for our kubernetes
create a folder called k8s in your project directory

inside the `k8s` folder create `flask-starter.yaml`


**flask-starter.yaml**
```yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-starter
  labels:
    app: flask
spec:
  replicas: 3
  selector:
    matchLabels:
      app: flask
  template:
    metadata:
      labels:
        app: flask
    spec:
      containers:
        - name: flask-starter
          image: rohit20001221/flask-starter:latest
          ports:
            - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: flask-starter
spec:
  selector:
    app: flask
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: flask-starter-ingress
spec:
  rules:
    - host: "raspberrypi.local"
      http:
        paths:
          - pathType: Prefix
            path: "/"
            backend:
              service:
                name: flask-starter
                port:
                  number: 8080
```

the yaml file contains 3 parts

**1. Deployment**
the main purpose of deployments is to create pods and manage them
it has the following functionalities
    1. creating replica set -> we can run multiple instances of our app
    2. auto healing -> if any our our pod's go down the deployment will spin up new instances of our pod

as you can see in the above deployment we created 3 replica sets and assigned each replica set a `label` and also we have mentioned the docker hub image name to tell the deployment from where it can find our application code

**2. Service**

In simple words we can think of Service as a discovery server with the help of which we can access our application pod's

as you can see above we need to specify the app `label` which we created in the deployment in the service and also we have to specify the port number at which our application pods run

**3. Ingress controller**

Ingress controller exposes our application to the external world through a domain since the raspberry pi can be accessed through `raspberrypi.local` we will assign it as the host name

and we will define the service which we want to expose along with the port number of that service

by `path: /` we are telling the `Ingress controller` that what ever requests come to the following url `http://raspberrypi.local/` we must send that request to our service `flask-starter`


now its time to deploy the application cd into the k8s folder
`cd ./k8s` and run the following command

```
kubectl apply -f flask-starter.yaml
```

now our flask app is deployed to the raspberry pi you can verify by `SSH`'ing into the pi and running the following command

```
# inside raspberry pi
pi@raspberrypi:~ $ sudo kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
flask-starter-5f5bf855dc-ljctk   1/1     Running   0          6s
flask-starter-5f5bf855dc-tnzbt   1/1     Running   0          6s
flask-starter-5f5bf855dc-5p86s   1/1     Running   0          6s

```


now open your browser and type `http://raspberry.local` and you will see that our flask app has opened