Deploying a Django App with Ingress for Multi-Path Routing on Kubernetes Pods
Tags: kubernetes, devops, nginx, docker
Published: 2023-02-24 18:42:56

In this blog post, I will guide you through the process of creating a Django app and deploying it in a Kubernetes cluster. Additionally, we will explore how to use an Ingress resource to route traffic to multiple paths on the Kubernetes pods.

Firstly, we will create a basic Django app and containerize it. Once we have our container image, we will create a deployment and service for our app. The deployment will manage the replicas of our app running in the cluster, and the service will expose our app to the cluster.

Next, we will create an Ingress resource to route traffic to our app. The Ingress resource will define the routing rules for incoming traffic based on the paths specified in the rules. We will create rules for two paths in our app, '/home' and '/page'.

Finally, we will deploy the Ingress controller in our cluster. The Ingress controller is a crucial component that will manage the Ingress resources in our cluster and route the incoming traffic to our app.

With these steps, we will have a fully functional Django app running in a Kubernetes cluster, and incoming traffic will be routed to our app based on the rules defined in the Ingress resource.

### What is Kubernetes?

Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. It provides features such as automatic scaling, rolling updates, self-healing, and service discovery, making it a popular choice for deploying containerized applications in production environments. It can be deployed on-premises, in the cloud, or in a hybrid environment, and integrates with a wide range of other tools and platforms.

### What is Ingress?

Ingress is an API object that provides a way to manage external access to services in a cluster. It allows you to route traffic to different services based on rules defined in the Ingress resource. Ingress can be used to configure load balancing, SSL termination, and virtual host routing. In short, Ingress is a powerful tool for managing external access to applications running in a Kubernetes cluster.

An Ingress Controller is a component that is responsible for managing and configuring Ingress resources. It reads the rules defined in the Ingress resources and routes the incoming traffic to the appropriate services in the cluster. There are different types of Ingress controllers available, such as NGINX, Traefik, and Istio. Ingress controllers are an essential component in managing external access to services in a Kubernetes cluster.

### Creating Django app

Open a terminal or command prompt and navigate to the directory where you want to create your project.

Run the following command to create a new Django project.

```apache
django-admin startproject <project_name>
```

Here I replace my `<project_name>` with `djangokubernetesproject` .Navigate to the project directory.Run the following command to create a new app.

```apache
python manage.py startapp <app_name>
```

Here I replace my `<app_name>` with `app` .Open the `urls.py` file in the project directory and add the following lines.

```python
from django.contrib import admin
from django.urls import path , include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]
```

Now create an `urls.py` file inside your `app` directory. Define the URLs for your app.

```python
from django.contrib import admin
from django.urls import path
from app.views import home , page
urlpatterns = [
    path('home/', home , name='home' ),
    path('page/', page , name='page' ),
]
```

Open your `views.py` file located in your `app` directory and add the following lines.

```python
import os
from django.http import HttpResponse
# Create your views here.

def home(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    print('ip address of the client = ' , ip)
    pod_name = os.environ.get('HOSTNAME') 


    return HttpResponse(
        '<h1>Hello World . ip address of the client = ' + str(ip) + '</h1>'
        '<h1>Hello World . pod name = ' + str(pod_name) + '</h1>' 
        )

def page(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    print('ip address of the client = ' , ip)
    pod_name = os.environ.get('HOSTNAME') 


    return HttpResponse(
        '<h1>Hello World . ip address of the client = ' + str(ip) + '</h1>'
        '<h1>Hello World . pod name = ' + str(pod_name) + '</h1>' 
        )
```

Now open your `settings.py` file and add you app name in the `INSTALLED_APPS`.

```python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app'
]
```

\[Optional\] : Open a terminal or command prompt and navigate to the project directory and run the following command to start the development server.

```python
python manage.py runserver 0.0.0.0:8000
```

This will start the development server, and we can access our app by visiting [**http://localhost:8000**](http://localhost:8000) in a web browser.

### Creating Docker file

Create a `dockerfile` in your django project directory. Here I am creating my dockerfile inside `djangokubernetesproject` directory.

```python
# Base image
FROM python:3.9-slim-buster

# Set working directory
WORKDIR /app

# Copy and install requirements
COPY requirements.txt .
RUN pip install -r requirements.txt

# Copy project files
COPY . .

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Expose port
EXPOSE 8000

# Run the command to start the server
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
```

### Build a docker image

Once we have created the Dockerfile to configure our Django app, the next step is to build the Docker image and push it to a container registry. To do this, navigate to the project directory in the terminal and run the following commands

```python
docker build -t <docker_hub_name>/django-ingress .
```

Here, replace `<docker_hub_name>` with your Docker Hub username. For example, if your username is `ndrohith09`, the command would be

```python
docker build -t ndrohith09/django-ingress .
```

This command will build the Docker image with the specified name and tag. Make sure to include the period at the end of the command, as it indicates the build context.

Once the image is built, it's time to push it to the Docker Hub registry. To do this, run the following command:

```python
docker push ndrohith09/django-ingress .
```

Now that your Docker image is pushed to the Docker Hub registry, you can use it to deploy your Django app on Kubernetes using Ingress.

### Create kubernetes deployment file

To deploy our Django app on Kubernetes, we need to create a Kubernetes deployment file called `django-ingress.yaml` that defines the specifications for our application. In this case, we want to create a deployment that has two paths - `/home` and `/page`Now we will create a kubernetes deployment file for the django app which has two paths '/home' and '/page'.

We will use the Docker image that we built and pushed to the Docker Hub container registry in the previous step. Here is an example deployment file that you can use:

```apache
 apiVersion: apps/v1
kind: Deployment
metadata:
  name: home
spec:
  replicas: 2
  selector:
    matchLabels:
      app: home
  template:
    metadata:
      labels:
        app: home
    spec:
      containers:
      - name: home
        image: ndrohith09/django-ingress
        ports:
        - containerPort: 8000

---

apiVersion: v1
kind: Service
metadata:
  name: home-svc 
spec:
  type: LoadBalancer
  ports:
  - port: 8000
    targetPort: 8000
    protocol: TCP
    name: http
  selector:
    app: home

--- 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: page 
spec:
  replicas: 2
  selector:
    matchLabels:
      app: page
  template:
    metadata:
      labels:
        app: page
    spec:
      containers:
      - name: page
        image: ndrohith09/django-ingress
        ports:
        - containerPort: 8000

---

apiVersion: v1
kind: Service
metadata:
  name: page-svc 
spec:
  type: LoadBalancer
  ports:
  - port: 8000
    targetPort: 8000
    protocol: TCP
    name: http
  selector:
    app: page
```

Thus to configure the Django app with two paths `/home` and `/page`, we created two Kubernetes deployments, named `home` and `page`, and two services, named `home-svc` and `page-svc`.

After configuring the deployments and services, the next step is to update the `django-ingress.yaml` file to configure the ingress. We need to add specific rules and paths for routing the incoming traffic to the appropriate Kubernetes services.

```apache
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: django-ing
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  tls:
  - secretName: tls-secret
  rules:
  - http:
      paths:
      - path: /home
        pathType: Prefix
        backend:
          service:
            name: home-svc
            port:
              number: 8000
  - http:
      paths:
      - path: /page
        pathType: Prefix
        backend:
          service:
            name: page-svc
            port:
              number: 8000
```

To create the Kubernetes services for the Django app, navigate to the project directory in the terminal and execute the relevant commands. These commands will create the services based on the deployment configurations and make them accessible to external traffic through the ingress controller.

```apache
kubectl create -f django-ingress.yaml
```

**Note :** It is important to understand that the ingress controller does not generate a public IP in local systems. As a result, we need to use cloud providers such as Oracle Cloud Infrastructure (OCI), Amazon Web Services (AWS), Google Cloud Platform (GCP), or Microsoft Azure, among others, that provide Kubernetes services to provision our services and generate a public IP. This will enable us to access our Django app from anywhere on the internet.

### Deployment in Cloud platforms

Here, we will be deploying our Django app on a cloud platform, specifically on the `Oracle Kubernetes Cluster (OKE)`. First, you need to create an Oracle Cloud account and navigate to the Kubernetes Clusters (OKE) page to create your own Kubernetes cluster. You can refer to the official documentation for creating a Kubernetes cluster in Oracle Cloud.

Docs: [Creating a Kubernetes Cluster](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengcreatingclusterusingoke_topic-Using_the_Console_to_create_a_Quick_Cluster_with_Default_Settings.htm)

After creating the Kubernetes cluster, you can access it using either the `cloud shell access` or `local access`.

Docs: [Setting Up Cluster Access](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengdownloadkubeconfigfile.htm)

Once you have access to your Kubernetes cluster, the next step is to set up the Ingress controller on the cluster. Ingress controllers are not a part of the Kubernetes core components, and there are different Ingress controllers available to choose from.

For Oracle Kubernetes Engine (OKE), the recommended Ingress controller is the Oracle Cloud Infrastructure (OCI) Load Balancing Ingress Controller. This controller is specifically designed for OKE and integrates with the Oracle Cloud Infrastructure Load Balancing service to provide a fully-managed, scalable and secure ingress solution for your cluster.

You can follow the official documentation to set up the OCI Load Balancing Ingress Controller on your OKE cluster.

Docs: [Setting Up an Ingress Controller on a Cluster](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengsettingupingresscontroller.htm)

Once the Ingress controller is installed and configured, you can proceed with creating and applying your Ingress resource YAML file (`django-ingress.yaml)` to configure routing to your Django app's services.

Note that the process for setting up an Ingress controller may differ depending on the cloud provider or infrastructure you are using. Make sure to refer to the relevant documentation for your platform to ensure proper setup and configuration of your Ingress controller.

To apply the services in the cluster, navigate to the project directory and use the following command to apply the `django-ingress.yaml` file

```apache
kubectl apply -f django-ingress.yaml
```


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



This will create the necessary resources in the cluster, including the ingress controller and the defined routes for our Django app. To get more details about the resources in your Kubernetes cluster, you can use the following command:

```apache
kubectl get all
```

This command will list all the resources in your cluster, including deployments, pods, services, and ingress. You can use this command to verify that your Django app is up and running, and that your ingress rules have been properly configured.


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



Once the resources are created, we can check the status of the ingress controller by running the following command

```apache
kubectl get ingress
```


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



This will display the details of the ingress resources created in the cluster, including the host, path, and backend service details. If the external IP address is not automatically generated by the cloud provider, we can check the status of the ingress resources by running the following command:

```apache
kubectl describe ingress
```


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


This will provide more detailed information about the ingress controller, including the IP address and any errors or warnings encountered during configuration.

With our ingress controller and services configured, we can now access our Django app using the external IP address provided by the ingress controller. You can retrieve the external IP address by running the command `kubectl get ingress` in your terminal. Once you have the external IP address, you can access your Django app by navigating to the defined paths in the browser, such as `http://<external_ip_address>/home` and `http://<external_ip_address>/page`.

To access the Django app, we can navigate to the defined paths '/home' and '/page' in the browser using the external IP provided by the ingress controller `144.24.133.172`. This will route the requests to the respective Kubernetes pods and display the output on the browser.

To access the `/home` path of the Django app, you can use the following URL: [`http://144.24.133.172/home`](http://144.24.133.172/page). This should display the HTML response that corresponds to the `/home` path that we defined earlier in our ingress configuration.


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



Similarly To access the `/page` path of the Django app, you can use the following URL: [`http://144.24.133.172/page`](http://144.24.133.172/page). This should display the HTML response that corresponds to the `/page` path that we defined earlier in our ingress configuration.


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


Hope you have gained a good understanding of how to create a Django app and use Ingress to route traffic to multiple paths on Kubernetes pods.

{% embed https://github.com/ndrohith09/django-ingress
 %}
Thank You!
Disclaimer: This article was created with the help of AI.