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:- Python 3.7+ installed on your local machine: You can check the Python version by running the command `python --version` in your terminal.
- Docker installed: Docker is used to containerize the application and can be installed by following the official documentation.
- Civo account: We will be using Civo in this tutorial as it provides a managed Kubernetes cluster for deploying our application.
- Launched cluster on Civo: Download the credentials to access the cluster.
- Basic understanding of Python: Familiarity with the Python programming language is required to understand and follow along with the tutorial.
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
Thepsycopg2-binarypackage has been added to enable the PostgreSQL database connection.
Thegunicornpackage 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"]
TheDockerfilestarts with the base image of Python 3.9-alpine.
WORKDIRcommand: Sets the working directory inside the container as/app, which will be the root directory for the application.
COPY ./requirements.txt .: Copies therequirements.txtfile from the local directory to the container's/appdirectory.
RUN pip install -r requirements.txt: Installs the Python dependencies specified inrequirements.txtusingpip.
The secondCOPYcommand: Copies the entire project directory (including the application code) into the container's/appdirectory.
RUN chmod +x /app/script.sh: Gives execution permissions to thescript.shscript.
CMD ["./script.sh"]: Specifies the command to run when the container starts. In this case, it executes thescript.shscript, 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 .
-tspecifies the tag for the image.
It builds the Docker image with the namedrf-app(you can change this name if desired).
.points to the current directory containing theDockerfile.
Step 4: Once the image is built, push it to a Docker repository. Here are the steps to push the image to Docker Hub:
- Sign up for a Docker Hub account.
- Log in to the Docker repository using the following command and provide your credentials when prompted:
docker login - Push the repository to the container registry using the following command:
Replacedocker push/ :drf-app andwith your Docker Hub username and the repository name where you want to push the image.
- Sign in to your Civo account.
- Create a new PostgreSQL instance with the desired specifications, such as CPU and RAM.
- 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"
Thedrf.yamlfile 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 aLoadBalancertype service that listens on port80and directs traffic to port8000on the application pods. The service is associated with pods that have the labelsapp: drf-appandtype: 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 withapp: drfandtype: 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

Retrieve, Update, and Destroy:
http://(external-ip-address)/movies

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: