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-binary
package has been added to enable the PostgreSQL database connection.
Thegunicorn
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"]
TheDockerfile
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 therequirements.txt
file from the local directory to the container's/app
directory.
RUN pip install -r requirements.txt
: Installs the Python dependencies specified inrequirements.txt
usingpip
.
The secondCOPY
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 thescript.sh
script.
CMD ["./script.sh"]
: Specifies the command to run when the container starts. In this case, it executes thescript.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 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
and
with 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.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 aLoadBalancer
type service that listens on port80
and directs traffic to port8000
on the application pods. The service is associated with pods that have the labelsapp: drf-app
andtype: 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: drf
andtype: 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: