Skip to content
This repository was archived by the owner on Mar 27, 2023. It is now read-only.

Commit 421a097

Browse files
committed
wip added kubernetes resources for local development with minikube
1 parent 748f555 commit 421a097

File tree

12 files changed

+371
-5
lines changed

12 files changed

+371
-5
lines changed

backend/backend/settings/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@
141141
'NAME': os.environ.get('RDS_DB_NAME', 'postgres'),
142142
'USER': os.environ.get('RDS_USERNAME', 'postgres'),
143143
'PASSWORD': os.environ.get('RDS_PASSWORD', 'postgres'),
144-
'HOST': os.environ.get('RDS_HOSTNAME', 'db'),
144+
'HOST': os.environ.get('RDS_HOSTNAME', 'postgres'),
145145
'PORT': os.environ.get('RDS_PORT', 5432),
146146
}
147147
}

backend/backend/settings/development.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
from .base import * # noqa
22

3+
SECRET_KEY = "my-secret-key"
4+
5+
DATABASES = {
6+
'default': {
7+
'ENGINE': 'django.db.backends.postgresql_psycopg2',
8+
'NAME': os.environ.get('RDS_DB_NAME', 'postgres'),
9+
'USER': os.environ.get('RDS_USERNAME', 'postgres'),
10+
'PASSWORD': os.environ.get('RDS_PASSWORD', 'postgres'),
11+
'HOST': os.environ.get('RDS_HOSTNAME', 'postgres'),
12+
'PORT': os.environ.get('RDS_PORT', 5432),
13+
}
14+
}
15+
16+
17+
318
DEBUG_APPS = [
419
'django_extensions',
520
'debug_toolbar'
@@ -54,3 +69,4 @@ def show_toolbar(request):
5469
STATIC_URL = '/static/'
5570

5671
STATIC_ROOT = '/static/'
72+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from .development import * # noqa
2+
3+
DATABASES = {
4+
'default': {
5+
'ENGINE': 'django.db.backends.postgresql_psycopg2',
6+
'NAME': os.environ.get('POSTGRES_NAME', 'kubernetes_django'),
7+
'USER': os.environ.get('POSTGRES_USER', 'postgres'),
8+
'PASSWORD': os.environ.get('POSTGRES_PASSWORD', 'postgres'),
9+
'HOST': os.environ.get('POSTGRES_HOST', 'postgres'),
10+
'PORT': os.environ.get('POSTGRES_PORT', 5432),
11+
}
12+
}

docker-compose.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ version: '3.7'
22

33
services:
44

5-
db:
6-
container_name: db
5+
postgres:
6+
container_name: postgres
77
image: postgres
88
networks:
99
- main
@@ -66,7 +66,7 @@ services:
6666
- ./quasar:/app/:rw
6767
depends_on:
6868
- backend
69-
- db
69+
- postgres
7070
environment:
7171
- CHOKIDAR_USEPOLLING=true
7272
- GITHUB_KEY=${GITHUB_KEY}
@@ -107,7 +107,7 @@ services:
107107
- GOOGLE_OAUTH2_KEY=${GOOGLE_OAUTH2_KEY}
108108
- GOOGLE_OAUTH2_SECRET=${GOOGLE_OAUTH2_SECRET}
109109
depends_on:
110-
- db
110+
- postgres
111111

112112
asgiserver:
113113
<<: *backend

documentation/docs/.vuepress/config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ module.exports = {
5555
{ text: "Vue Authentication", link: "/guide/vue-authentication/" }
5656
]
5757
},
58+
{
59+
text: "Topics",
60+
items: [{ text: "Minikube", link: "/topics/minikube/" }]
61+
},
5862
{
5963
text: "Source Code",
6064
link:
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# Minikube
2+
3+
Minikube is a tool for running a single-node kubernetes cluster inside of a virtual machine. It is a popular tool for developing Kubernetes applications locally.
4+
5+
This topic will cover using `minikube` to set up the project Kubernetes locally.
6+
7+
I'll be following [this guide](https://medium.com/@markgituma/kubernetes-local-to-production-with-django-1-introduction-d73adc9ce4b4) to get started.
8+
9+
## Getting started
10+
11+
### Start minikube
12+
13+
To get started, bring up `minikube` with
14+
15+
```bash
16+
minikube start
17+
```
18+
19+
Optionally, run `minikube delete`, and then `minikube start` to start with a clean cluster.
20+
21+
I'll be using the following alias to use `kubectl`:
22+
23+
```bash
24+
alias k='kubectl'
25+
```
26+
27+
## Build the Django server Deployment
28+
29+
We need to build our `backend` image. In order for minikube to be able to use the image, we can set our docker client to point to the minikube docker host. To do this, run the following command:
30+
31+
```
32+
eval $(minikube docker-env)
33+
```
34+
35+
`$(minikube docker-env)` results in the following output:
36+
37+
```bash
38+
export DOCKER_TLS_VERIFY="1"
39+
export DOCKER_HOST="tcp://192.168.99.100:2376"
40+
export DOCKER_CERT_PATH="/home/brian/.minikube/certs"
41+
# Run this command to configure your shell:
42+
# eval $(minikube docker-env)
43+
```
44+
45+
Notice that the `DOCKER_HOST` is pointing to the minikube VM on docker's default port `2376`.
46+
47+
With these environment variables set, let's build the Django container image with the following command:
48+
49+
```bash
50+
docker-compose build backend
51+
```
52+
53+
**`deployment.yml`**
54+
55+
```yml
56+
apiVersion: apps/v1
57+
kind: Deployment
58+
metadata:
59+
name: django-backend
60+
labels:
61+
app: django-backend
62+
spec:
63+
replicas: 1
64+
selector:
65+
matchLabels:
66+
app: django-backend
67+
template:
68+
metadata:
69+
labels:
70+
app: django-backend
71+
spec:
72+
containers:
73+
- name: django-backend-container
74+
image: localhost:5000/backend
75+
command: ["./manage.py", "runserver"]
76+
ports:
77+
- containerPort: 8000
78+
```
79+
80+
Let's send this file to Kubernete API server with the following command:
81+
82+
```
83+
kubectl apply -f kubernetes/django/deployment.yml
84+
```
85+
86+
Your pod for the deployment should be starting. Inspect the pods with `k get pods`. If there is an error with container startup, you might see something like this:
87+
88+
```
89+
k get pods
90+
NAME READY STATUS RESTARTS AGE
91+
django-backend-dd798db99-hkv2p 0/1 Error 0 3s
92+
```
93+
94+
If this is the case, inspect the logs of the container with the following command:
95+
96+
I have intentionally cause the container to fail by not providing a `SECRET_KEY` environment variable (this is something that Django needs in order to start).
97+
98+
Let's inspect the container logs to confirm this:
99+
100+
```bash
101+
k logs django-backend-dd798db99-hkv2p
102+
Traceback (most recent call last):
103+
File "./manage.py", line 16, in <module>
104+
execute_from_command_line(sys.argv)
105+
File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
106+
utility.execute()
107+
File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
108+
self.fetch_command(subcommand).run_from_argv(self.argv)
109+
File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
110+
self.execute(*args, **cmd_options)
111+
File "/usr/local/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 60, in execute
112+
super().execute(*args, **options)
113+
File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
114+
output = self.handle(*args, **options)
115+
File "/usr/local/lib/python3.7/site-packages/django/core/management/commands/runserver.py", line 67, in handle
116+
if not settings.DEBUG and not settings.ALLOWED_HOSTS:
117+
File "/usr/local/lib/python3.7/site-packages/django/conf/__init__.py", line 79, in __getattr__
118+
self._setup(name)
119+
File "/usr/local/lib/python3.7/site-packages/django/conf/__init__.py", line 66, in _setup
120+
self._wrapped = Settings(settings_module)
121+
File "/usr/local/lib/python3.7/site-packages/django/conf/__init__.py", line 176, in __init__
122+
raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
123+
django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
124+
```
125+
126+
We could either provide a fallback value in the Django settings (which would require rebuilding the image), or we could add an environment variable to the container definition in the Pod `spec` in `deployment.yml`:
127+
128+
```yml
129+
spec:
130+
containers:
131+
- name: backend
132+
imagePullPolicy: IfNotPresent
133+
image: backend:latest
134+
command: ["./manage.py", "runserver"]
135+
ports:
136+
- containerPort: 8000
137+
env:
138+
- name: SECRET_KEY
139+
value: "my-secret-key"
140+
```
141+
142+
This should work, but we will still see errors in logs because we Django will attempt to establish a connection with the Postgres database which we will be setting up next.
143+
144+
We can hit our public facing `hello-world` endpoint which should serve as a nice health check for the Django container.
145+
146+
Let's test this endpoint with `curl`. We haven't set up a Kubernetes `Service` yet, so we will have to curl the Django application from within the cluster. We can do this with:
147+
148+
```
149+
k exec django-backend-757b5944d8-htssm -- curl -s http://172.17.0.5/api/hello-world/
150+
```
151+
152+
This gives us:
153+
154+
```
155+
command terminated with exit code 7
156+
```
157+
158+
Our container has started, but the database connection has prevented the Django process from starting. In our Pod logs, we can see that no request have been received and the Django application is not listening on `0.0.0.0:8000`.
159+
160+
Let's come back to this once we have set up our Postgres database.
161+
162+
## Postgres
163+
164+
First, we create a `PersistentVolume` resource:
165+
166+
**`kubernetes/postgres/volume.yml`**
167+
168+
```yml
169+
kind: PersistentVolume
170+
apiVersion: v1
171+
metadata:
172+
name: postgres-pv
173+
labels:
174+
type: local
175+
spec:
176+
storageClassName: manual
177+
capacity:
178+
storage: 2Gi
179+
accessModes:
180+
- ReadWriteOnce
181+
hostPath:
182+
path: /data/postgres-pv
183+
```
184+
185+
::: warning storageClassName
186+
Clicking on the `storageClassName` gave a 404 error
187+
:::

kubernetes/django/deployment.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
apiVersion: apps/v1beta2
2+
kind: Deployment
3+
metadata:
4+
name: django
5+
spec:
6+
replicas: 1
7+
selector:
8+
matchLabels:
9+
app: django-container
10+
template:
11+
metadata:
12+
labels:
13+
app: django-container
14+
spec:
15+
containers:
16+
- name: backend
17+
imagePullPolicy: IfNotPresent
18+
image: backend:2
19+
command: ["./manage.py", "runserver", "0.0.0.0:8000"]
20+
ports:
21+
- containerPort: 8000
22+
env:
23+
- name: DJANGO_SETTINGS_MODULE
24+
value: 'backend.settings.minikube'
25+
26+
- name: SECRET_KEY
27+
value: "my-secret-key"
28+
29+
- name: POSTGRES_USER
30+
value: postgres
31+
# valueFrom:
32+
# secretKeyRef:
33+
# name: postgres-credentials
34+
# key: user
35+
36+
- name: POSTGRES_PASSWORD
37+
value: postgres
38+
# valueFrom:
39+
# secretKeyRef:
40+
# name: postgres-credentials
41+
# key: password
42+
43+
- name: POSTGRES_HOST
44+
value: postgres-service
45+
46+
volumeMounts:
47+
- name: postgres-volume-mount
48+
mountPath: /var/lib/busybox
49+
50+
volumes:
51+
- name: postgres-volume-mount
52+
persistentVolumeClaim:
53+
claimName: postgres-pvc
54+

kubernetes/postgres/deployment.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
apiVersion: apps/v1beta2
2+
kind: Deployment
3+
metadata:
4+
name: postgres-deployment
5+
spec:
6+
replicas: 1
7+
selector:
8+
matchLabels:
9+
app: postgres-container
10+
template:
11+
metadata:
12+
labels:
13+
app: postgres-container
14+
tier: backend
15+
spec:
16+
containers:
17+
- name: postgres-container
18+
image: postgres:9.6.6
19+
env:
20+
- name: POSTGRES_USER
21+
value: postgres
22+
# valueFrom:
23+
# secretKeyRef:
24+
# name: postgres-credentials
25+
# key: user
26+
27+
- name: POSTGRES_PASSWORD
28+
value: postgres
29+
# valueFrom:
30+
# secretKeyRef:
31+
# name: postgres-credentials
32+
# key: password
33+
34+
- name: POSTGRES_NAME
35+
value: kubernetes_django
36+
37+
ports:
38+
- containerPort: 5432
39+
volumeMounts:
40+
- name: postgres-volume-mount
41+
mountPath: /var/lib/postgresql/data
42+
43+
volumes:
44+
- name: postgres-volume-mount
45+
persistentVolumeClaim:
46+
claimName: postgres-pvc

kubernetes/postgres/secrets.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: v1
2+
kind: Secret
3+
metadata:
4+
name: postgres-credentials
5+
type: Opaque
6+
data:
7+
user: postgres
8+
password: postgres

0 commit comments

Comments
 (0)