Kubernetes for Django: Scaling and Security with HTTPS
Django offers a powerful web framework for Python with numerous features. We’ll show you how to deploy a Django Polls application in a Kubernetes cluster.
In this tutorial, we will deploy a containerized Django Polls application in a Kubernetes cluster. Django is a powerful web framework that helps you quickly launch your Python application. It includes several convenient features, such as an object-relational mapper, user authentication, and a customizable administrative interface for your application. It also includes a caching framework and promotes a clean app design through its URL dispatcher and template system.
Prerequisites
To follow this tutorial, you will need:
- A Kubernetes cluster 1.15+ with role-based access control (RBAC) enabled.
- The `kubectl` command-line tool installed and configured on your local machine to connect to your cluster.
- A registered domain name.
- An ingress-nginx Ingress controller and the cert-manager TLS certificate manager installed and configured in your cluster to issue TLS certificates.
- An S3 object storage bucket, such as a centron Space, to store the static files of your Django project.
- A PostgreSQL server instance, database, and user for your Django app.
- A Docker Hub account and a public repository.
- The Docker engine installed on your local machine.
Step 1 — Cloning and Configuring the Application
In this step, we will clone the application code from GitHub and configure settings like database credentials and object storage keys. Start by cloning the application code from GitHub to your local machine and navigating to the appropriate directory.
git clone –single-branch –branch polls-docker https://github.com/do-community/django-polls.git
cd django-polls
The application code includes a Dockerfile that defines the container configuration. You can open this file with an editor of your choice and make adjustments as needed.
FROM python:3.7.4-alpine3.10
ADD django-polls/requirements.txt /app/requirements.txt
RUN set -ex \
&& apk add –no-cache –virtual .build-deps postgresql-dev build-base \
&& python -m venv /env \
&& /env/bin/pip install –upgrade pip \
&& /env/bin/pip install –no-cache-dir -r /app/requirements.txt \
&& runDeps=”$(scanelf –needed –nobanner –recursive /env \
| awk ‘{ gsub(/,/, “\nso:”, $2); print “so:” $2 }’ \
| sort -u \
| xargs -r apk info –installed \
| sort -u)” \
&& apk add –virtual rundeps $runDeps \
&& apk del .build-deps
ADD django-polls /app
WORKDIR /app
ENV VIRTUAL_ENV /env
ENV PATH /env/bin:$PATH
EXPOSE 8000
CMD [“gunicorn”, “–bind”, “:8000”, “–workers”, “3”, “mysite.wsgi”]
Step 2 — Creating the Database Schema and Uploading Assets to Object Storage
After creating and configuring the container, use `docker run` to override the CMD set in the Dockerfile and create the database schema using the `manage.py makemigrations` and `manage.py migrate` commands.
docker run –env-file env polls sh -c “python manage.py makemigrations && python manage.py migrate”
Then, you can create a superuser for the Django application:
docker run -i -t –env-file env polls sh
python manage.py createsuperuser
Next, generate the static files for the application and upload them to the centron Space:
docker run –env-file env polls sh -c “python manage.py collectstatic –noinput”
Step 3 — Pushing the Django App Image to Docker Hub
To deploy your app on Kubernetes, your app image must be uploaded to a repository such as Docker Hub. Start by logging into Docker Hub on your local machine.
docker login
Then tag the image with your Docker Hub username and repository name and push it to the repo.
docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest
docker push your_dockerhub_username/your_dockerhub_repo_name:latest
Step 4: Configuring the ConfigMap
To inject configuration variables into the runtime environment, we use ConfigMaps and Secrets in Kubernetes. ConfigMaps are used for non-sensitive information like app settings, while Secrets are suitable for sensitive data such as API keys and database credentials. The configuration is done by creating a YAML file and applying it with `kubectl apply`.
apiVersion: v1
kind: ConfigMap
metadata:
name: polls-config
data:
DJANGO_ALLOWED_HOSTS: “*”
STATIC_ENDPOINT_URL: “https://your_space_name.space_region.centronspaces.com”
STATIC_BUCKET_NAME: “your_space_name”
DJANGO_LOGLEVEL: “info”
DEBUG: “True”
DATABASE_ENGINE: “postgresql_psycopg2”
Step 5: Setting Up the Secret
Secret values must be base64 encoded. We create a Secret object in our cluster by extracting values from an environment variable file and encoding them in base64. This is done similarly to configuring the ConfigMap, but using the `kubectl create secret` command.
apiVersion: v1
kind: Secret
metadata:
name: polls-secret
type: Opaque
data:
DJANGO_SECRET_KEY: “”
DATABASE_NAME: “”
DATABASE_USERNAME: “”
DATABASE_PASSWORD: “”
DATABASE_HOST: “”
DATABASE_PORT: “”
STATIC_ACCESS_KEY_ID: “”
STATIC_SECRET_KEY: “”
STATIC_BUCKET_NAME: “”
STATIC_ENDPOINT_URL: “”
DJANGO_LOGLEVEL: “”
Step 6: Deploying the Django App with a Deployment File
A Kubernetes deployment is used to deploy our Django app. Here, we set the number of replicas and define the container configurations. The configuration is done in a YAML file, which is then applied using `kubectl apply`.
apiVersion: apps/v1
kind: Deployment
metadata:
name: polls-app
labels:
app: polls
spec:
replicas: 2
selector:
matchLabels:
app: polls
template:
metadata:
labels:
app: polls
spec:
containers:
– image: your_dockerhub_username/app_repo_name:latest
name: polls
envFrom:
– secretRef:
name: polls-secret
– configMapRef:
name: polls-config
ports:
– containerPort: 8000
name: gunicorn
Step 7: Enabling External Access with a Service
A Kubernetes service is created to provide a stable endpoint for our app, which persists even with pod changes. Here, we define a NodePort service to temporarily access the Django app. The configuration is also done in a YAML file, which is then applied.
apiVersion: v1
kind: Service
metadata:
name: polls
labels:
app: polls
spec:
type: NodePort
selector:
app: polls
ports:
– port: 8000
targetPort: 8000
Step 8: Configuring HTTPS with Nginx Ingress and cert-manager
Finally, we set up HTTPS encryption for our app. This is achieved using Ingress objects and the cert-manager add-on. Once the configuration is complete, the deployment of the Django app with HTTPS encryption in our Kubernetes cluster will be finalized.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: polls-ingress
annotations:
kubernetes.io/ingress.class: “nginx”
cert-manager.io/cluster-issuer: “letsencrypt-staging”
spec:
tls:
– hosts:
– your_domain.com
secretName: polls-tls
rules:
– host: your_domain.com
http:
paths:
– backend:
serviceName: polls
servicePort: 8000
Conclusion
Deploying a Django app on Kubernetes requires several steps to configure ConfigMaps, Secrets, Deployments, Services, and Ingresses. Following these steps, you can create a scalable and securely deployed application in your Kubernetes environment.