Deploying a Python Flask App to Kubernetes
Tags: python, docker, kubernetes, cloud
Published: 2021-08-24 22:21:03

Welcome to back to THINK Days!

Today we will walk through the steps to deploy a Python Flask application on to a Kubernetes cluster. We will build just the simple ‘hello-world’ app. The technologies we would be working with are [Flask](https://flask.palletsprojects.com/en/2.0.x/), [Docker](https://www.docker.com/), and Kubernetes on [IBM Cloud Kubernetes Service](https://www.ibm.com/cloud/kubernetes-service).

#### Why Flask?
Flask is lightweight, minimalistic Python web framework designed to get an app up and running quickly. It is sometimes called a micro-framework as it does not require specific tools or plug-ins to run. Also, thought I would explore Python while I am at it :)

### Pre-requisites:
 - An IBM Cloud account – (sign up for a free account)
 - A basic, foundational knowledge of Flask and Python

## Building and Containerizing the Flask App
On a code editor of you choice, create a folder (ie py-app) and a file `main.py` file and enter the following:
```python
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World from Pycon Flask"

if __name__ == "__main__":
    # Only for debugging while developing
    app.run(host='0.0.0.0', debug=True, port=80)
```

Then create a `Dockerfile` in the root directory of the project and enter the following:
```
FROM tiangolo/uwsgi-nginx-flask:python3.7
COPY ./py-app /py-app
```

Now, let's containerize this simple app by running the following commands:
```
$ docker build -t hello-world .
$ docker run -d --name pycon -p 80:80 hello-world
```

To test the output from the Flask app just use curl to ping the app:
```
curl http://localhost
```

## Pushing the image to IBM Cloud Container Registry

I will quickly walk through the steps on the CLI, but do check out my [previous blog](https://dev.to/ibmdeveloper/deploy-a-nodejs-app-to-ibm-cloud-container-registry-46m2) on a detail walkthrough to push containers to IBM Cloud Container Registry .

Log in to your IBM Cloud account:
```
ibmcloud login -a https://cloud.ibm.com
``` 
Note, if you have a federated ID, like I do, log in to the IBM Cloud CLI:
```
ibmcloud login --sso
```

In the Select a region prompt select an approporiate region in my case that would be `us-south`

You can ensure that you're targeting the correct IBM Cloud Container Registry region by running: 
```
ibmcloud cr region-set us-south
```
Now if you don't already have one, create a namespace by running the following command. 
```
ibmcloud cr namespace-add $(kubectl config view --minify --output 'jsonpath={..namespace}')
```
To view and confirm your namespace run the command: 
```
kubectl config view --minify --output 'jsonpath={..namespace}'
```
Log your local Docker daemon into the IBM Cloud Container Registry. 
```
ibmcloud cr login
```
Select your repository and tag by which you can identify your image:
```
docker tag hello-world us.icr.io/<namespace>/hello-world:latest
```
Finally, Push the image to the registry:
```
docker push us.icr.io/<namespace>/hello-world:latest
```

## Kubernetes Deployment
Before we dig in here's a summary of what we get to accomplish wit Kubernetes. Kubernetes is a container orchestration tool used to manage and aid in deployments. Deployments are used to manage pods, which include containerized instances of an app. The following command deploys the app in a single pod by referring to the image that we built in the private registry. For the purposes of this walkthrough, the deployment is named hello-world-deployment, but you can give the deployment any name that you want.

```
kubectl create deployment hello-world-deployment --image=us.icr.io/<namespace>/hello-world:latest
```
This should output:
`deployment "hello-world-deployment" created`

But we aren't done just yet. We need to make the app available to the world. We do this by exposing the deployment as a NodePort service. NodePorts are randomly assigned when they are generated with the expose command, but within 30000-32767. The NodePort that you expose is the port on which the worker node listens for traffic:
```
kubectl expose deployment/hello-world-deployment --type=NodePort --port=80 --name=hello-world-service --target-port=80
```

Now that all the deployment work is done, you can test the app in a browser. To do that, we need to get the details to from the URL.

First, let's get information about the service to see which NodePort was assigned:
```
kubectl describe service hello-world-service
```
To get the public IP address for the worker node in the cluster, run:
```
ibmcloud ks worker ls --cluster <cluster_name>
```

Open a browser and check out the app with the following URL:
```
http://<IP_address>:<NodePort>
```
When you enter that URL in a browser, you can see the following text.
```
Hello World from Pycon Flask
```

Oila! You have successfully built setup a Python Flask App then containerized it using a Docker Image and deployed it onto an IBM Cloud Kubernetes Service.

Thank you for following along this THINK Day's Tutorial and be sure to look out for my next post, where I will continue sharing my Journey with IBM Cloud Services!!!

==== Follow me on Social Media(`@mrinasugosh`) ====
Dev.to: @mrinasugosh 
Github: [@mrinasugosh](https://github.com/mrinasugosh)
Twitter: [@mrinasugosh](https://twitter.com/mrinasugosh)
LinkedIn: [@mrinasugosh](https://www.linkedin.com/in/mrinasugosh/)