forked from ungleich-public/dynamicweb
Rewrite the Kubernetes guide around the Helm chart
This commit is contained in:
parent
fdb9ce6033
commit
a80010c0bc
1 changed files with 30 additions and 33 deletions
63
K8S.md
63
K8S.md
|
|
@ -1,59 +1,56 @@
|
|||
# Deploying dynamicweb on Kubernetes
|
||||
|
||||
[k8s/dynamicweb.yaml](k8s/dynamicweb.yaml) describes what runs: the web app, the Celery worker,
|
||||
Redis, a volume for uploaded media, and an Ingress. PostgreSQL 18 is **not** included: use your
|
||||
own database and point the app at it.
|
||||
The Helm chart in [charts/dynamicweb/](charts/dynamicweb/) runs the web app, a Celery worker,
|
||||
Redis, a volume for uploaded media and an Ingress, and runs the database migrations as a Job
|
||||
before each install or upgrade. PostgreSQL 18 is **not** in the chart: bring your own (an
|
||||
operator such as CloudNativePG, a managed service, or any Postgres) and point the app at it.
|
||||
|
||||
> Tested on a local `kind` cluster with a scratch Postgres (migrate Job, then web and the admin
|
||||
> answer 200). Not tested on your cluster, ingress controller or real data.
|
||||
> Tested on a local `kind` cluster with a scratch Postgres. Not tested on your cluster, your
|
||||
> ingress controller or real data.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Push the image** (build it once, from the repo):
|
||||
1. **Push the image** (built once from the repo):
|
||||
```sh
|
||||
docker compose build
|
||||
docker tag dynamicweb:latest <registry>/dynamicweb:<version>
|
||||
docker push <registry>/dynamicweb:<version>
|
||||
```
|
||||
2. **Make an env file** from `.env.docker` with your real values. Change at least:
|
||||
2. **Database.** Create an empty database and user. To keep old data, restore the dump into it now
|
||||
(`psql -h <host> -U <user> <db> < dump.sql`). The Job in step 5 migrates it to the new schema.
|
||||
3. **Env file and Secret.** Copy `.env.docker`, set your real values, then store it:
|
||||
```
|
||||
DEBUG=False
|
||||
SEED_DUMMY_DATA=False
|
||||
DJANGO_SECRET_KEY=<a long random string>
|
||||
POSTGRES_HOST=<your database host> # and POSTGRES_PORT/DB/USER/PASSWORD
|
||||
POSTGRES_HOST=<host> POSTGRES_PORT=5432 POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD
|
||||
BEHIND_TLS_PROXY=True # TLS ends at the ingress
|
||||
UNGLEICH_SITE_CONFIGS=<your real JSON>
|
||||
```
|
||||
plus your OpenNebula, LDAP, Stripe, email and reCAPTCHA values. Leave the Redis URLs alone;
|
||||
the manifest creates a service called `redis`.
|
||||
3. **Store it as a Secret:**
|
||||
plus your OpenNebula, LDAP, Stripe, email and reCAPTCHA values. Leave the Redis URLs alone.
|
||||
```sh
|
||||
kubectl create secret generic dynamicweb --from-env-file=<your env file>
|
||||
```
|
||||
4. **Edit the manifest:** your image name (it appears three times) and the Ingress hosts (one rule
|
||||
for each domain, with `www.` variants). Set `ingressClassName` to your controller.
|
||||
5. **Migrate, then start.** If you have old data, restore it into the empty database first (for
|
||||
example `psql -h <host> -U <user> <db> < dump.sql`). Then:
|
||||
4. **Values.** Edit `image.repository`, `image.tag` and `ingress.hosts` (one per domain, with `www.`
|
||||
variants) in [charts/dynamicweb/values.yaml](charts/dynamicweb/values.yaml), or pass them with `--set`.
|
||||
5. **Install.** Helm starts the pods and runs the migrate Job (on upgrades, before the rollout). The site answers once the Job completes:
|
||||
```sh
|
||||
kubectl apply -f k8s/dynamicweb.yaml
|
||||
kubectl logs -f job/dynamicweb-migrate # takes a few minutes; ends when the Job completes
|
||||
kubectl rollout restart deploy/dynamicweb-web
|
||||
kubectl logs -f deploy/dynamicweb-web # ready at "Listening at"
|
||||
helm install dynamicweb charts/dynamicweb
|
||||
kubectl logs -f job/dynamicweb-migrate # a few minutes
|
||||
kubectl logs -f deploy/dynamicweb-web # ready at "Listening at"
|
||||
```
|
||||
The `dynamicweb-migrate` Job runs the migrations once. The web pods don't migrate, so restart
|
||||
them after the Job completes (a web pod that started earlier serves errors until you do).
|
||||
6. **Check:** `curl -I -H 'Host: ungleich.ch' http://<ingress-address>/en-us/` returns 200. Admin
|
||||
is at `/en-us/admin/login/` on any site's address.
|
||||
6. **Check:** `curl -I -H 'Host: ungleich.ch' http://<ingress-address>/en-us/` returns 200. Admin is
|
||||
at `/en-us/admin/login/` on any site's address.
|
||||
|
||||
## Good to know
|
||||
|
||||
- **Scaling:** `kubectl scale deploy/dynamicweb-web --replicas=2`, with the media volume changed
|
||||
to `ReadWriteMany` so every pod sees the same uploads.
|
||||
- **Ingress must keep the original `Host` header** (the default). The site is chosen from the
|
||||
host, and every domain must be in `UNGLEICH_SITE_CONFIGS` and in `ALLOWED_HOSTS`
|
||||
(`dynamicweb/settings/prod.py` lists the current ones).
|
||||
- **Updating:** push a new image tag, change the image in the manifest, delete the old Job
|
||||
(`kubectl delete job dynamicweb-migrate`) and apply again, then restart web.
|
||||
- **Logs:** `kubectl logs deploy/dynamicweb-web` and `kubectl logs deploy/dynamicweb-celery`.
|
||||
- **Don't name a Service `postgres` without `enableServiceLinks: false`.** Kubernetes would inject
|
||||
`POSTGRES_PORT=tcp://...` and the app crashes. The manifest already sets it on every pod.
|
||||
- **Update:** push a new tag, then `helm upgrade dynamicweb charts/dynamicweb --set image.tag=<new>`.
|
||||
The migrate Job runs again first.
|
||||
- **Scale web:** `--set web.replicas=2 --set media.accessMode=ReadWriteMany` (every pod must see the
|
||||
same uploads, so the storage class has to support it).
|
||||
- **Keep the original `Host` header** at the ingress (the default). The site is chosen from the host,
|
||||
and every domain must be in `UNGLEICH_SITE_CONFIGS` and `ALLOWED_HOSTS` (`dynamicweb/settings/prod.py`).
|
||||
- **The Secret must exist before `helm install`** (the Job reads it).
|
||||
- **Logs:** `kubectl logs deploy/dynamicweb-web`, `deploy/dynamicweb-celery`.
|
||||
- **Why a database Service named `postgres` is safe:** the pods set `enableServiceLinks: false`;
|
||||
otherwise Kubernetes injects `POSTGRES_PORT=tcp://...` and the app crashes.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue