Django on K8s (Part III: Running on Kubernetes)
Tags: django, kubernetes, ubuntu, docker
Published: 2022-01-10 07:23:01


Welcome back,

In the last part, we were able to containerize our Django Application and run it on Docker and make sure it is working fine. In this part we will show how to load this image on Kubernetes and then add a deployment, and see how we can connect to it from our PC and from the network. so let's go.

## Adding image to Kubernetes

Simulating a real environment, MiniKube has its own Docker registry, so we need to upload the image to that registry so we can use it to start containers, there are 2 ways to do that.
1. Download the image from local registry using [docker save](https://docs.docker.com/engine/reference/commandline/save/) command on the disk and load it to the minikube's docker registry by [docker load](https://docs.docker.com/engine/reference/commandline/load/) command

    or
1. Build the image again on the minikube's registry using `docker build` command as shown in part II, which will be faster and easier as we won't save/load the full image everytime.

**Note** to interact with the docker registry on minikube, you have to change your ENV variables, which is easily done by running the following command
`eval $(minikube docker-env)` so to build the image against minikube registry run the following commands
Part
```
~/django-on-k8s$ eval $(minikube docker-env)
~/django-on-k8s$ docker build -t django-example:v1.0 .
```
Finally, check the image is there by running
```
 docker images
```
which shall show something like the image below

![K8s Images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bv2di76978c4dboto5t5.png)

So now we ready to deploy our app to Kubernetes, so lets see how.

## Deploy on Kubernetes

The smallest object in Kubernetes is 'Pod' which is a collection of containers running together and the one or more pods (of the same containers images) are replica-sets, which forms a deployment, so we will create a deployment with one replicas count as 1 and we will use our image as the container image.

We will use `django-example_initial.yaml` to do that 
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: django-example
  labels:
    app: django-example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: django-example
  template:
    metadata:
      labels:
        app: django-example
    spec:
      containers:
      - name: web-app
        image: django-example:v1.0
        ports:
        - containerPort: 80
```
So we created a deployment `django-example` and it has 1 replicaset and it has one container `web-app` which is based on our `django-example` image and it exports one port which is 80.

So lets apply the YAML using
```
kubectl apply -f django-example_initial.yaml
```

You shall get the output like the one below


![Deployment created](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p7x1z5v3k9n7puvaq6sz.png)

Then lets check the status of the deployment

```
 kubectl get deploy
```
and you shall get that the deployment is ready as in the image below.


![Deployment Ready](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yaftpkvp3l1fao5q08xw.png)

## Connect to the application

Now the deployment is up, we need to navigate to the web-app and that needs 2 things.

1. Expose the deployment on the network
2. Get the IP
3. Open a tunnel to the minikube network


### 1. Expose the deployment

We need to tell Kubernetes to expose the deployment so we interact with it from our network and since the port is already known from yaml file, it can be simply through the following command

```
kubectl expose deployment django-example
```

### 2. Get the Pod IP
After we exposed the deployment, let find the IP, this can be done through

``` 
kubectl get services
```
and IP is 

![Pod IP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oe7iyqwpl2o0j2scta2y.png)
Now, open a new browser window and Go to the http://IP/ and you shouldn't be able to connect to the Pod, that because there is no route for the minikube network, so you need to open a tunnel as show in the next section.

### 3. Opening a tunnel

As the minikube's containers are running under the docker container with their network CIDR, so we need to change our routes so we can reach them, that can be done by the following command
``` 
minikube tunnel
```
**Note**: You need the a sudoer account and run this command in a new terminal as it will keep running as shown below

![Minikube tunnel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yr0jw9zlxlzv2nnmr56a.png)

so go a the browser window, you opened before and refresh it, and you shall be see the login page of the application  and you shall be able to login as shown below.

![Kubernetes Working](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pi4sl3gyu5mo6p43ofxj.png)

### Bonus: Exposing the service to the network

This won't work on MiniKube as Kubernetes is working on your PC under a container, but in real production environment, Kubernetes will be running on a server which is accessible on the network so if you want to expose the service to the network, you can use 'NodePort' as follows

```
kubectl expose deployment django-example --type NodePort
```
then get the port from the service list using

```
kubectl get service
```
The output will be as below

![K8s services](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9foy80aqgvo38w1w73v.png)
 
On Minikube, you get the Kubernetes IP by running 

```
$ minikube ip
192.168.49.2
```
Then open a new browser window and connect to 
```
http://192.168.49.2:31394
```
You will be able to reach the web-app as shown below.

![NodePort Workin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4ao57cv08qx8oq2t1zv.png)

**Note**:  This does _NOT_ require a tunnel to work which simulates the real environment.

## Clean what we created

```
kubectl delete service django-example
kubectl delete deploy django-example
```
## Wrap Up
So now, we have our web-app working in Kubernetes and we can reach it, but if we start adding users to the web-app and the container fails, the databases will be lost, which isn't acceptable for a web-app, the next part will show how to persist the database file between container restarts, so  stay tuned.