title: Hosting Django Apps in Kubernetes [WIP] --- pub_date: 2022-06-03 --- author: ungleich django team --- twitter_handle: ungleich --- _hidden: no --- _discoverable: yes --- abstract: Django running on top of k8s --- body: ## Situation At ungleich we are hosting quite a lot of Django applications. As of 2022-06-03, most of them are still deployed on a traditional VM based setup. We are using this blog entry to document a possible blueprint and the progress of migration at ungleich. ## General design Our Kubernetes clusters usually use [ArgoCD](https://argo-cd.readthedocs.io/en/stable/) for deployments, so Django applications should potentially be defined the same way. Most of our kubernetes applications are defined in helm charts and thus the "general django application" should probably also be defined in a helm chart. ## Freedom of choice While as a hoster it might be tempting to define a specific image that Django applications should be using (like [python](https://hub.docker.com/_/python)), but we want to give us and our customers the freedom to choose the image they use themselves. It might potentially even come from a private registry. ## Interface definition All of our Django applications are using Postgresql for storing data. Postgresql is used by quite some other applications that we deployed in k8s, so this is a no-brainer - Django hosting at ungleich even in k8s will be based on Postgresql. Static data of Django applications can easily be stored on a PVC. This has the drawback that filesystem PVCs based on ceph block devices are RWO and thus in case of restart, there will be a short downtime. This is, generally speaking probably accepted, like a deploy would have caused a short downtime on a VM as well. However alternatives would be a shared filesystem (such as NFS/CephFS), but they are usually slower than dedicated block devices. ## Django startup On startup, Django will need to ensure the database schema has been upgraded to the latest version. so something like `python manage.py migrate` should probably be called in an InitContainer for most apps. ## Secrets Django applications usually have some kind of secrets and most Django applications have DIFFERENT types of secrets. Thus defining a specific environment variable does not seem to be a smart idea. Instead, we should probably offer to store secrets in something like [SealedSecrets](https://github.com/bitnami-labs/sealed-secrets). Database connection information is provided by default and is cluster/app specific. ## Deployment We are likely going with a git-ops style deployment in which everything is defined for the Django app. This repository is read write for each client/customer. This probably includes: - Possible encrypted secrets - Image definition - Maybe even (part of) a pod definition? Some parameters are likely to be stored in a different, ungleich only writable repository, such as: - Size of RAM - Number of CPUs - Storage size (Postgresql, Static files, ...)