This tutorial is going to provide you with a comprehensive guide on deploying a Django Rest Framework (DRF) application to Kubernetes. In this tutorial, you'll be taken through a step-by-step tutorial covering the entire process, starting from setting up the development environment, building the DRF application, containerizing it, and finally deploying it to Kubernetes.

By the end of this tutorial, you'll have a clear understanding of how to take your Django Rest Framework application from development to production, leveraging Kubernetes to manage and scale the application efficiently.

Let's get started and dive into the world of deploying DRF applications on Kubernetes!

Overview of the DRF

Django Rest Framework (DRF) is a robust and widely-used web framework, built on Django, the renowned Python web development framework. DRF specializes in streamlining the development of RESTful APIs (Application Programming Interfaces) for web applications. By leveraging DRF, developers can efficiently handle data serialization, authentication, and various other features essential for modern web development. With its user-friendly design and extensive toolkit, DRF empowers developers to create high-performance APIs with ease and flexibility.

Prerequisites

Before getting started, there are some prerequisites you’ll need to have in place:

Setting up the development environment

Follow these steps to set up the development environment:

Step 1: Open a terminal or command prompt.

Step 2: Verify if you have virtualenv installed by running the following command:


pip install virtualenv

Step 3: Create and activate a virtual environment:


virtualenv venv

On macOS/Linux:


source venv/bin/activate

On Windows:


venv\Scripts\activate

Step 4: Create a project directory for the Django Rest Framework application:


mkdir drf_kubernetes
cd drf_kubernetes

Step 5: Install the Required Packages.

Create a requirements.txt file and add the following contents:


djangorestframework==3.13.1
Django==4.1.2

Run the command below to install the packages:


pip install -r requirements.txt

Step 6: Create a Django Project.

With the virtual environment activated, create the Django project. In this case, we'll name the project drf_kubernetes:


django-admin startproject drf_kubernetes  .

Note: Take note of the . after the django-admin startproject drf_kubernetes command.

Building the DRF application

With the development environment set up and the project created, let's proceed to build the DRF application. We will create a REST API for a sample Movie database model, which will involve implementing all CRUD operations.

Step 1: Create the Movie App

Run the following command to create a Django app named Movie:


django-admin startapp Movie

Step 2: Edit the settings.py file:

Add restframework and the created app Movie to the INSTALLEDAPPS in the settings.py file:


INSTALLED_APPS = [
    # Other installed apps
    'rest_framework',  # Add this line
    'Movie.apps.MovieConfig',  # Add this line
]

Step 3: Update the urls.py in the drf_kubernetes directory to include the Movie app URLs:


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

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

Step 4: Add the following code to the models.py file inside the Movie app directory:


from django.db import models

class Movie(models.Model):
    class Genre(models.TextChoices):
        ACTION = 'action'
        FANTASY = 'fantasy'
        ADVENTURE = 'adventure'
        ROMANCE = 'romance'
        SCI_FI = 'sci-fi'
        Anime = 'anime'

    title = models.CharField(max_length=100)
    producer = models.CharField(max_length=50)
    genre = models.CharField(max_length=20, choices=Genre.choices)
    release_date = models.DateField()

    def __str__(self):
        return self.title

The Movie class represents the database model for a movie in our API. It includes columns for the movie's title, producer, genre, and release date.

Step 5: Create a serializers.py file inside the Movie app directory with the following code:


from rest_framework import serializers
from .models import Movie

class MovieSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)

    class Meta:
        model = Movie
        fields = [
            'id',
            'title',
            'producer',
            'genre',
            'release_date',
        ]

The MovieSerializer defines a serializer that allows us to convert the Movie model data into Python data types for API requests and responses.

Step 6: Update the views.py file in the Movie app with the following code:


from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from .models import Movie
from .serializers import MovieSerializer

class MovieListCreate(ListCreateAPIView):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer

class MovieRetrieveUpdateDestroy(RetrieveUpdateDestroyAPIView):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer

The MovieListCreate class defines the views for creating and getting all movies, while the MovieRetrieveUpdateDestroy class handles retrieving, updating, and deleting movies.

Step 7: Create a urls.py file inside the Movie app with the following code:


from django.urls import path
from . import views

urlpatterns = [
    path('movies/', views.MovieListCreate.as_view(), name='movie-list-create'),
    path('movies//', views.MovieRetrieveUpdateDestroy.as_view(), name='movie-retrieve-update-destroy'),
]

Step 8: Run Migrations:

To create the necessary database tables, run the following commands in your terminal:


python manage.py makemigrations
python manage.py migrate

Step 9: Start the development server to test the Django Rest Framework application:


python manage.py runserver

Now the Django Rest Framework application is up and running! You can access the API endpoints for the `Movie` model at the following URLs:

  • List and Create: http://localhost:8000/movies/
  • Retrieve, Update, and Destroy: http://localhost:8000/movies//

Containerization of Django Rest Framework (DRF) with Docker

Before proceeding with containerizing the Django Rest Framework application, some changes need to be made.

Step 1: Update SECRET_KEY and DEBUG handling:

In the settings.py file, modify the SECRET_KEY and DEBUG settings to use environment variables. This helps keep sensitive information separate from the codebase and enhances security. Use the following code:


import os

SECRET_KEY = os.getenv('SECRET_KEY')
DEBUG = bool(os.getenv('DEBUG', 'True'))

Step 2: Update the database settings in the settings.py file to use PostgreSQL:

Replace the existing DATABASES section with the following:


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'USER': os.getenv('POSTGRES_USER'),
        'NAME': os.getenv('POSTGRES_NAME'),
        'PASSWORD': os.getenv('POSTGRES_PASSWORD'),
        'HOST': os.getenv('POSTGRES_HOST'),
        'PORT': os.getenv('POSTGRES_PORT'),
    }
}

Step 3: Update allowed hosts:

In the settings.py file, update the ALLOWED_HOSTS setting to allow all hosts:


ALLOWED_HOSTS = ['*']

Step 4: Enable static files:

Static files need to be served correctly in our containerized environment. In the settings.py file, add the following code to set the STATIC_ROOT:


STATIC_ROOT= ‘/static/’

Additionally, update the urls.py file in the drf_kubernetes directory to correctly handle static file serving:


from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.contrib.staticfiles.urls import static
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('Movie.urls'))
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) # add this 

Step 5: Update the requirements.txt file with the following content:


djangorestframework==3.13.1
Django==4.1.2
gunicorn==20.1.0
psycopg2-binary==2.9.3
The psycopg2-binary package has been added to enable the PostgreSQL database connection.

The gunicorn package has been added as a production-ready WSGI server, which will serve the Django application efficiently.

Step 6: Create a file named script.sh in the project directory and add the following content:


#!/bin/sh

# Change to the app directory
cd /app

# Apply database migrations
echo "Applying database migrations"
python manage.py makemigrations
python manage.py migrate --noinput

# Collect static files
echo "Collecting static files"
python manage.py collectstatic --noinput

# Start the server using gunicorn
echo "Starting the server"
gunicorn drf_kubernetes.wsgi:application --bind 0.0.0.0:8000

This script will be executed when the container starts and will take care of necessary setup tasks.

Docker configuration and deployment

Now, let's proceed with containerizing the application:

Step 1: Ensure that Docker is installed on your system. If you don't have it installed, refer to the Docker installation guide and install Docker.

Step 2: Create a Dockerfile in the project directory and include the following contents:


FROM python:3.9-alpine

WORKDIR /app

COPY ./requirements.txt .

RUN pip install -r requirements.txt

COPY . .

RUN chmod +x /app/script.sh

CMD ["./script.sh"]
The Dockerfile starts with the base image of Python 3.9-alpine.

WORKDIR command: Sets the working directory inside the container as /app, which will be the root directory for the application.

COPY ./requirements.txt .: Copies the requirements.txt file from the local directory to the container's /app directory.

RUN pip install -r requirements.txt: Installs the Python dependencies specified in requirements.txt using pip.

The second COPY command: Copies the entire project directory (including the application code) into the container's /app directory.

RUN chmod +x /app/script.sh: Gives execution permissions to the script.sh script.

CMD ["./script.sh"]: Specifies the command to run when the container starts. In this case, it executes the script.sh script, which applies database migrations, collects static files, and starts the server using gunicorn.

Step 3: Build the Docker image by running the following command in the terminal: Replace your-username and your-repository-name with the appropriate values:


docker build -t /:drf-app .
-t specifies the tag for the image.

It builds the Docker image with the name drf-app (you can change this name if desired).

. points to the current directory containing the Dockerfile.

Step 4: Once the image is built, push it to a Docker repository. Here are the steps to push the image to Docker Hub:

  1. Sign up for a Docker Hub account.
  2. Log in to the Docker repository using the following command and provide your credentials when prompted:
    docker login
    
  3. Push the repository to the container registry using the following command:
    docker push /:drf-app
    
    Replace and with your Docker Hub username and the repository name where you want to push the image.
Step 5: Finally, before proceeding with deployment, you need to provision a PostgreSQL database on Civo:
  1. Sign in to your Civo account.
  2. Create a new PostgreSQL instance with the desired specifications, such as CPU and RAM.
  3. Make a note of the connection details, including the hostname, port, database name, user, and password.

Deploying the DRF Application on Civo

To successfully deploy your Django Rest Framework (DRF) application on a managed Kubernetes cluster using Civo, you can follow these steps:

Step 1: Begin by making sure you have completed the initial setup, including launching a cluster on Civo, downloading the cluster's kubeconfig credential, and installing the Kubernetes command-line tool, kubectl on your local machine.

Step 2: Configure your local kubectl with the cluster credentials you've downloaded by executing the following commands:

export KUBECONFIG=/path/to/downloaded/kubeconfig/credential

Note: Replace /path/to/downloaded/kubeconfig/credential with the actual path to your downloaded kubeconfig cluster credential.

Step 3: In your project directory, create a .env file with the necessary environment variables:


POSTGRES_HOST=
POSTGRES_PORT=
POSTGRES_NAME=
POSTGRES_USER=
POSTGRES_PASSWORD=
SECRET_KEY=

Note: Replace the placeholders with actual details from your managed PostgreSQL database on Civo and your Django SECRET_KEY.

Step 4: Create a Kubernetes secret using the command below to securely manage the secrets:

kubectl create secret generic --from-env-file .env drf-app-secret

Step 5: Create a drf.yaml file that outlines both the service and deployment manifests required for deploying the DRF application:


apiVersion: v1
kind: Service
metadata:
   name: drf-app
spec:
   type: LoadBalancer
   ports:
   - protocol: TCP
     port: 80
     targetPort: 8000
   selector:
      app: drf-app
      type: api
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: drf-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: drf
      type: api
  template:
    metadata:
      labels:
        app: drf-app
        type: api
    spec:
      containers:
      - name: drf-app
        image: your-username/your-repository-name:drf-app
        imagePullPolicy: Always
        ports:
        - containerPort: 8000
        envFrom:
          - secretRef:
              name: drf-app-secret
        env:
        - name: DEBUG
          value: "False"
The drf.yaml file contains Kubernetes manifest definitions that outline how your Django Rest Framework (DRF) application should be deployed and managed within a Kubernetes cluster. It consists of two main parts:

Service Manifest: This section defines a Kubernetes Service, which acts to enable network communication to your application. Specifically, it configures a LoadBalancer type service that listens on port 80 and directs traffic to port 8000 on the application pods. The service is associated with pods that have the labelsapp: drf-appand type: api.

Deployment Manifest: This section specifies a Kubernetes Deployment, which orchestrates the management of your application's pods. It sets up two replicas of your application to ensure high availability. The deployment is linked to pods labeled with app: drf and type: api.

Inside the deployment's template, the containers section defines the main application container named drf-app. It pulls the application image from a specified container registry (e.g., your-username/your-repository-name:drf-app). The container listens on port 8000 and is configured with environment variables obtained from the secret drf-app-secret`.

The env section also includes an environment variable named DEBUG set to "False", which indicates that the DRF application is not in debugging mode.

Step 6: Deploying with a Private Repository:

If your repository is private, you need to create an image pull secret to allow Kubernetes to access the private images. Use the following command to create the necessary image pull secret:


kubectl create secret docker-registry registry-secret --docker-server=https://index.docker.io/v1/ --docker-username= --docker-password= --docker-email=

Replace your-name, your-password and your-email with your actual Docker username, email and password.

Next, modify the drf.yaml file to include the newly created image pull secret. Add the imagePullSecrets field under the deployment spec.template.spec section:


   spec:
     containers:
     - name: drf-app
       image: your-username/your-repository-name:drf-app
       imagePullPolicy: Always
       ports:
       - containerPort: 8000
       envFrom:
         - secretRef:
             name: drf-app-secret
       env:
       - name: DEBUG
         value: "False"
     imagePullSecrets:
     - name: registry-secret
   

By adding the image pull secret, Kubernetes will be able to retrieve images from your private repository.

Step 7: Apply the defined resources to your cluster using the following command:

kubectl apply -f drf.yaml

Step 8: Retrieve the external IP assigned to the DRF application service using:

kubectl get service drf-app

With the external IP in hand, you can access the Django Rest Framework Application Movie APIs through your browser:

List and Create:

http://(external-ip-address)/movies

list and create apis

Retrieve, Update, and Destroy:

http://(external-ip-address)/movies

Your Alt Text

By following these steps, you'll have your DRF application up and running on Civo's managed Kubernetes cluster.

Summary

This tutorial provided you with a comprehensive guide to deploying a Django Rest Framework (DRF) application to Kubernetes. Throughout the tutorial, we have covered all the necessary steps, from setting up the development environment to containerizing the application and deploying it to a Kubernetes Cluster on Civo.

Further resources

To further enhance your skills and expand your knowledge, consider exploring the following resources: