Bereitstellen einer skalierbaren und sicheren Django-Anwendung mit Kubernetes

Einführung

In diesem Tutorial stellen Sie eine containerisierte Django-Umfrageanwendung in einem Kubernetes-Cluster bereit.

Django ist ein leistungsfähiges Web-Framework, das Ihnen dabei helfen kann, Ihre Python-Anwendung schnell bereitzustellen. Es enthält mehrere praktische Funktionen wie einen objektrelationalen Mapper, eine Benutzerauthentifizierung und eine anpassbare Verwaltungsoberfläche für Ihre Anwendung. Es beinhaltet auch ein Caching-Framework und fördert ein sauberes App-Design durch seinen URL Dispatcher und das Vorlagensystem.

In Erstellen einer Django- und Gunicorn-Anwendung mit Docker wurde die Django Tutorial Umfrageanwendung gemäß der Zwölf-Faktor-Methodik zur Erstellung skalierbarer Cloud-nativer Web-Apps modifiziert. Diese containerisierte Einrichtung wurde mit einem Nginx Reverse-Proxy und Let’s Encrypt-signierten TLS-Zertifikaten in Skalieren und Sichern einer Django-Anwendung mit Docker, Nginx und Let’s Encrypt skaliert und gesichert. In diesem letzten Tutorial der Reihe Von Containern zu Kubernetes mit Django wird die modernisierte Django-Umfrageanwendung in einem Kubernetes-Cluster bereitgestellt.

Kubernetes ist ein leistungsstarker Open-Source-Container-Orchestrator, der die Bereitstellung, das Skalieren und die Verwaltung von containerisierten Anwendungen automatisiert. Mit Kubernetes-Objekten wie ConfigMaps und Secrets können Sie die Konfiguration zentralisieren und von Ihren Containern entkoppeln, während Controller wie Deployments fehlgeschlagene Container automatisch neu starten und eine schnelle Skalierung von Container-Replikaten ermöglichen. Die TLS-Verschlüsselung wird mit einem Ingress-Objekt und dem Open-Source Ingress-Controller ingress-nginx aktiviert. Das Kubernetes Add-on cert-manager erneuert und stellt Zertifikate mit der kostenlosen Zertifizierungsstelle Let’s Encrypt aus.

Voraussetzungen

Um dieser Anleitung zu folgen, benötigen Sie:

  • Einen Kubernetes 1.15+-Cluster mit aktivierter rollenbasierter Zugriffskontrolle (RBAC). In diesem Setup wird ein DigitalOcean Kubernetes-Cluster verwendet, doch Sie können einen Cluster auch mit einer anderen Methode erstellen.
  • Das Befehlszeilen-Tool kubectl, das auf Ihrem lokalen Rechner installiert und für die Verbindung mit Ihrem Cluster konfiguriert ist. Weitere Informationen zur Installation von kubectl finden Sie in der offiziellen Dokumentation. Wenn Sie einen DigitalOcean Kubernetes-Cluster verwenden, lesen Sie bitte Verbinden mit einem DigitalOcean Kubernetes-Cluster, um zu erfahren, wie Sie sich mit kubectl mit Ihrem Cluster verbinden können.
  • Einen registrierten Domänennamen. In diesem Tutorial wird durchgängig your_domain.com verwendet. Einen Domänennamen können Sie kostenlos bei Freenom erhalten oder Sie nutzen eine Domänenregistrierungsstelle Ihrer Wahl.
  • Einen ingress-nginx Ingress-Controller und den TLS-Zertifizierungsmanager cert-manager, die in Ihrem Cluster installiert und zur Ausgabe von TLS-Zertifikaten konfiguriert sind. Um zu erfahren, wie Sie einen Ingress mit cert-manager installieren und konfigurieren, konsultieren Sie bitte Einrichten eines Nginx Ingress mit Cert-Manager in DigitalOcean Kubernetes.
  • Einen A-DNS-Datensatz mit your_domain.com, der auf die öffentliche IP-Adresse des Ingress Load Balancers verweist. Wenn Sie DigitalOcean zum Verwalten der DNS-Datensätze Ihrer Domäne verwenden, konsultieren Sie bitte Verwalten von DNS-Datensätzen, um zu erfahren, wie Sie A-Datensätze erstellen.
  • Einen S3-Objektspeicher-Bucket wie beispielsweise einen DigitalOcean Space zur Speicherung der statischen Dateien Ihres Django-Projekts und einen Satz von Zugriffsschlüsseln für diesen Space. Um zu erfahren, wie Sie einen Space erstellen können, lesen Sie die Produktdokumentation Erstellen von Spaces. Um zu erfahren, wie Sie Zugriffsschlüssel für Spaces erstellen können, lesen Sie Zugriff auf Spaces mit Zugriffsschlüsseln gemeinsam nutzen. Mit geringfügigen Änderungen können Sie jeden Objektspeicherdienst verwenden, der das Plugin django-storages verwendet.
  • Eine PostgreSQL-Server-Instanz, Datenbank und Benutzer für Ihre Django-Anwendung. Mit geringfügigen Änderungen können Sie jede Datenbank verwenden, die Django unterstützt.
    • Die PostgreSQL-Datenbank sollte polls genannt werden (oder einen anderen einprägsamen Namen erhalten, den Sie unten in Ihre Konfigurationsdatei eingeben) und in diesem Tutorial wird der Django-Datenbankbenutzer sammy genannt. Führen Sie zum Erstellen dieser den Schritt 1 von Erstellen einer Django- und Gunicorn-Anwendung mit Docker aus. Sie sollten diese Schritte von Ihrem lokalen aus durchführen.
    • In diesem Tutorial wird ein DigitalOcean Managed PostgreSQL-Cluster verwendet. Um mehr über die Erstellung eines Clusters zu erfahren, lesen Sie die Produktdokumentation zu verwalteten Datenbanken von DigitalOcean.
    • Sie können auch Ihre eigene PostgreSQL-Instanz installieren und ausführen. Eine Anleitung zur Installation und Verwaltung von PostgreSQL auf einem Ubuntu-Server finden Sie unter Installieren und Verwenden von PostgreSQL unter Ubuntu 18.04.
  • Ein Docker Hub-Konto und ein öffentliches Repository. Weitere Informationen zu deren Erstellung finden Sie in Repositories in der Docker-Dokumentation.
  • Die auf Ihrem lokalen Rechner installierte Docker-Engine. Weitere Informationen finden Sie unter Installieren und Verwenden von Docker unter Ubuntu 18.04.

Sobald Sie diese Komponenten eingerichtet haben, können Sie mit diesem Leitfaden beginnen.

Schritt 1 — Klonen und Konfigurieren der Anwendung

In diesem Schritt klonen wir den Anwendungscode von GitHub und konfigurieren Einstellungen wie Datenbankzugangsdaten und Objektspeicherschlüssel.

Der Anwendungscode und das Dockerfile befinden sich im Zweig polls-docker der Django Tutorial Umfrageanwendung GitHub-Repository. Dieses Repository enthält Code für die Beispiel-Umfrageanwendung aus der Django-Dokumentation, in der Sie lernen, wie Sie eine Umfrageanwendung von Grund auf erstellen.

Der Zweig polls-docker enthält eine dockerisierte Version der Umfrageanwendung. Um zu erfahren, wie die Umfrageanwendung modifiziert wurde, um effektiv in einer containerisierten Umgebung zu arbeiten, lesen Sie bitte Erstellen einer Django- und Gunicorn-Anwendung mit Docker.

Beginnen Sie mit der Verwendung von git zum Klonen des Zweigs polls-docker der Django Tutorial Umfrageanwendung GitHub-Repository auf Ihren lokalen Rechner:

  • git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git

Navigieren Sie in das Verzeichnis django-polls:

  • cd django-polls

Dieses Verzeichnis enthält den Python-Code der Django-Anwendung, ein Dockerfile, das Docker zum Erstellen des Container-Images verwendet, sowie eine Datei env, die eine Liste von Umgebungsvariablen enthält, die an die laufende Umgebung des Containers übergeben werden müssen. Prüfen Sie das Dockerfile:

  • cat Dockerfile
OutputFROM 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"] 

Dieses Dockerfile verwendet das offizielle Python 3.7.4 Docker-Image als Basis und installiert die Python-Paketanforderungen von Django und Gunicorn, wie sie in der Datei django-polls/requirements.txt definiert sind. Anschließend entfernt es einige unnötige Builddateien, kopiert den Anwendungscode in das Image und legt den Ausführungspfad PATH fest. Schließlich gibt es an, dass Port 8000 verwendet wird, um eingehende Container-Verbindungen zu akzeptieren und gunicorn mit 3 Workern ausgeführt wird, die Port 8000 abhören.

Um mehr über die einzelnen Schritte in diesem Dockerfile zu erfahren, lesen Sie bitte Schritt 6 von Erstellen einer Django- und Gunicorn-Anwendung mit Docker.

Erstellen Sie nun das Image mit docker build:

  • docker build -t polls .

Wir benennen das Image polls mit dem Flag -t und übergeben im aktuellen Verzeichnis als Build-Kontext den Satz von Daten, auf den beim Erstellen des Images verwiesen werden soll.

Nachdem Docker das Image erstellt und mit Tags versehen hat, listen wir die verfügbaren Images mit docker images auf:

  • docker images

Sie sollten die polls-Images aufgelistet sehen:

OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE polls               latest              80ec4f33aae1        2 weeks ago         197MB python              3.7.4-alpine3.10    f309434dea3a        8 months ago        98.7MB 

Bevor wir den Django-Container ausführen, müssen wir seine Betriebsumgebung mithilfe der im aktuellen Verzeichnis vorhandenen Datei env konfigurieren. Diese Datei wird an den Befehl docker run übergeben, der zum Ausführen des Containers verwendet wird, und Docker injiziert die konfigurierten Umgebungsvariablen in die Betriebsumgebung des Containers.

Öffnen Sie die Datei env mit nano oder Ihrem bevorzugten Editor:

  • nano env

django-polls/env

DJANGO_SECRET_KEY= DEBUG=True DJANGO_ALLOWED_HOSTS= DATABASE_ENGINE=postgresql_psycopg2 DATABASE_NAME=polls DATABASE_USERNAME= DATABASE_PASSWORD= DATABASE_HOST= DATABASE_PORT= STATIC_ACCESS_KEY_ID= STATIC_SECRET_KEY= STATIC_BUCKET_NAME= STATIC_ENDPOINT_URL= DJANGO_LOGLEVEL=info 

Geben Sie die fehlenden Werte für die folgenden Schlüssel ein:

  • DJANGO_SECRET_KEY: Setzen Sie diesen auf einen eindeutigen, nicht vorhersagbaren Wert, wie in den Django-Dokumentationen beschrieben. Eine Methode zur Generierung dieses Wertes wird in Anpassen der Anwendungseinstellungen in dem Tutorial Skalierbare Django-Anwendung angeboten.
  • DJANGO_ALLOWED_HOSTS: Diese Variable sichert die Anwendung und verhindert HTTP-Host-Header-Angriffe. Setzen Sie diese Variable für Testzwecke auf *, einen Platzhalter, der auf alle Hosts zutrifft. In der Produktion sollten Sie diese Variable auf your_domain.com setzen. Um mehr über diese Django-Einstellungen zu erfahren, konsultieren Sie die Core-Einstellungen der Django-Dokumentation.
  • DATABASE_USERNAME: Setzen Sie diesen auf den in den vorbereitenden Schritten erstellten PostgreSQL Datenbankbenutzer.
  • DATABASE_NAME: Setzen Sie diesen auf polls oder den in den vorbereitenden Schritten erstellten Namen der PostgreSQL-Datenbank.
  • DATABASE_PASSWORD: Setzen Sie dieses auf das in den vorbereitenden Schritten erstellte Passwort für den PostgreSQL Benutzer.
  • DATABASE_HOST: Setzen Sie diesen Wert auf den Hostnamen Ihrer Datenbank.
  • DATABASE_PORT: Setzen Sie diesen Wert auf den Port Ihrer Datenbank.
  • STATIC_ACCESS_KEY_ID: Setzen Sie dies auf den Zugriffsschlüssel Ihres Space oder Objektspeichers.
  • STATIC_SECRET_KEY: Setzen Sie dies auf den Zugriffsschlüssel Ihres Space- oder Objektspeicher-Secret.
  • STATIC_BUCKET_NAME: Setzen Sie dies auf den Namen Ihres Space- oder Objektspeicher-Buckets.
  • STATIC_ENDPOINT_URL: Setzen Sie diese auf die entsprechende Endpunkt-URL des Space oder Objektspeichers, z. B. https://space-name.nyc3.digitaloceanspaces.com, wenn sich Ihr Space in der Region nyc3 befindet.

Wenn Sie die Bearbeitung abgeschlossen haben, speichern und schließen Sie die Datei.

Im nächsten Schritt führen wir den konfigurierten Container lokal aus und erstellen das Datenbankschema. Wir laden ebenfalls statische Assets wie Stylesheets und Images in den Objektspeicher hoch.

Schritt 2 — Erstellen des Datenbankschemas und Hochladen von Assets in den Objektspeicher

Nachdem der Container erstellt und konfiguriert ist, verwenden wir nun docker run, um den CMD-Satz in dem Dockerfile zu überschreiben und das Datenbankschema mit den Befehlen manage.py makemigrations und manage.py migrate zu erstellen:

  • docker run --env-file env polls sh -c "python manage.py makemigrations && python manage.py migrate"

Wir führen das Container-Image polls:latest aus, übergeben die von uns gerade modifizierte Umgebungsvariablendatei und überschreiben den Dockerfile-Befehl mit sh -c "python manage.py makemigrations && python manage.py migrate", wodurch das durch den Anwendungscode definierte Datenbankschema erstellt wird.

Wenn Sie dies zum ersten Mal ausführen, sollten Sie Folgendes sehen:

OutputNo changes detected Operations to perform:   Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations:   Applying contenttypes.0001_initial... OK   Applying auth.0001_initial... OK   Applying admin.0001_initial... OK   Applying admin.0002_logentry_remove_auto_add... OK   Applying admin.0003_logentry_add_action_flag_choices... OK   Applying contenttypes.0002_remove_content_type_name... OK   Applying auth.0002_alter_permission_name_max_length... OK   Applying auth.0003_alter_user_email_max_length... OK   Applying auth.0004_alter_user_username_opts... OK   Applying auth.0005_alter_user_last_login_null... OK   Applying auth.0006_require_contenttypes_0002... OK   Applying auth.0007_alter_validators_add_error_messages... OK   Applying auth.0008_alter_user_username_max_length... OK   Applying auth.0009_alter_user_last_name_max_length... OK   Applying auth.0010_alter_group_name_max_length... OK   Applying auth.0011_update_proxy_permissions... OK   Applying polls.0001_initial... OK   Applying sessions.0001_initial... OK 

Dies zeigt an, dass das Datenbankschema erfolgreich erstellt wurde.

Wenn Sie migrate zu einem späteren Zeitpunkt ausführen, führt Django eine Nulloperation durch, es sei denn, das Datenbankschema wurde geändert.

Als Nächstes führen wir eine weitere Instanz des Anwendungscontainers aus und verwenden darin eine interaktive Shell, um einen Administratorbenutzer für das Django-Projekt zu erstellen.

  • docker run -i -t --env-file env polls sh

Dadurch erhalten Sie eine Shell-Eingabeaufforderung innerhalb des laufenden Containers, die Sie zum Erstellen des Django-Benutzers verwenden können:

  • python manage.py createsuperuser

Geben Sie einen Benutzernamen, eine E-Mail-Adresse und ein Passwort für Ihren Benutzer ein. Drücken Sie nach dem Erstellen des Benutzers STRG+D, um den Container zu verlassen und zu beenden.

Schließlich generieren wir die statischen Dateien für die Anwendung und laden sie mit collectstatic in den DigitalOcean Space hoch. Beachten Sie, dass dies möglicherweise einige Zeit dauern kann.

  • docker run --env-file env polls sh -c "python manage.py collectstatic --noinput"

Nachdem diese Dateien generiert und hochgeladen sind, erhalten Sie folgende Ausgabe.

Output121 static files copied. 

Wir können die Anwendung nun ausführen:

  • docker run --env-file env -p 80:8000 polls
Output[2019-10-17 21:23:36 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2019-10-17 21:23:36 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1) [2019-10-17 21:23:36 +0000] [1] [INFO] Using worker: sync [2019-10-17 21:23:36 +0000] [7] [INFO] Booting worker with pid: 7 [2019-10-17 21:23:36 +0000] [8] [INFO] Booting worker with pid: 8 [2019-10-17 21:23:36 +0000] [9] [INFO] Booting worker with pid: 9 

Hier führen wir den in dem Dockerfile definierten Standardbefehl gunicorn ---bind :8000 --workers 3 mysite.wsgi:application aus und geben den Container-Port 8000 frei, sodass Port 80 auf Ihrem lokalen Rechner dem Port 8000 des Containers polls zugeordnet wird.

Sie sollten nun über Ihren Webbrowser zu der Anwendung polls navigieren können, indem Sie http://localhost in die URL-Leiste eingeben. Da für den Pfad / keine Route definiert ist, erhalten Sie wahrscheinlich einen 404 Page Not Found-Fehler, der zu erwarten ist.

Navigieren Sie zu http://localhost/polls, um die Benutzeroberfläche der Umfrageanwendung zu sehen:

Oberfläche der Umfrageanwendung

Um die administrative Oberfläche anzuzeigen, besuchen Sie http://localhost/admin. Sie sollten das Authentifizierungsfenster für den Administrator der Umfrageanwendung sehen:

Authentifizierungsseite für Polls-Administrator

Geben Sie den administrativen Benutzernamen und das Passwort ein, das Sie mit dem Befehl createsuperuser erstellt haben.

Nach der Authentifizierung können Sie auf die administrative Oberfläche der Umfrageanwendung zugreifen:

Administrative Hauptoberfläche von Polls

Beachten Sie, dass statische Assets für die Anwendungen admin und polls direkt aus dem Objektspeicher bereitgestellt werden. Um dies zu bestätigen, konsultieren Sie Prüfen der statischen Dateizustellung von Spaces.

Wenn Sie die Erkundung abgeschlossen haben, drücken Sie STRG+C im Terminalfenster, in dem der Docker-Container ausgeführt wird, um den Container zu beenden.

Nachdem das Docker-Image der Django-Anwendung getestet, die statischen Assets in den Objektspeicher hochgeladen und das Datenbankschema konfiguriert und für die Verwendung mit Ihrer Anwendung bereit ist/sind, können Sie Ihr Django-App-Image in eine Bildregistrierung wie Docker Hub hochladen.

Schritt 3 — Verschieben des Django-App-Images zu Docker Hub

Um Ihre Anwendung unter Kubernetes bereitzustellen, muss Ihr App-Image in eine Registrierung wie Docker Hub hochgeladen werden. Kubernetes zieht das App-Image aus seinem Repository und stellt es dann in Ihren Cluster bereit.

Sie können eine private Docker-Registrierung verwenden, wie die DigitalOcean Container Registry, die derzeit kostenlos in Early Access ist, oder eine öffentliche Docker-Registrierung wie Docker Hub. Mit Docker Hub können Sie auch private Docker-Repositorys erstellen. Ein öffentliches Repository erlaubt jedem, die Container-Images zu sehen und abzurufen, während Sie mit einem privaten Repository den Zugriff auf Sie und Ihre Teammitglieder beschränken können.

In diesem Tutorial verschieben wir das Django-Image in das öffentliche Docker Hub-Repository, das in den Voraussetzungen erstellt wurde. Sie können Ihr Image auch in ein privates Repository verschieben, aber das Abrufen von Images aus einem privaten Repository liegt außerhalb des Rahmens dieses Artikels. Um mehr über die Authentifizierung von Kubernetes mit Docker Hub und das Abrufen von privaten Images zu erfahren, lesen Sie bitte Abrufen eines Images aus einer privaten Registrierung aus den Kubernetes-Dokumenten.

Beginnen Sie mit der Anmeldung an Docker Hub auf Ihrem lokalen Rechner:

  • docker login
OutputLogin with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: 

Geben Sie Ihren Docker Hub-Benutzernamen und Ihr Passwort ein, um sich anzumelden.

Das Django-Image hat derzeit die Markierung polls:latest. Um es in Ihr Docker Hub-Repository zu verschieben, markieren Sie das Image erneut mit Ihrem Docker Hub-Benutzernamen und dem Repository-Namen:

  • docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest

Verschieben Sie das Image in das Repository:

  • docker push sammy/sammy-django:latest

In diesem Tutorial ist der Docker Hub-Benutzername sammy und der Repository-Name ist sammy-django. Sie sollten diese Werte durch Ihren eigenen Docker Hub-Benutzernamen und Repository-Namen ersetzen.

Sie sehen eine Ausgabe, die sich aktualisiert, wenn Image-Schichten in Docker Hub verschoben werden.

Nachdem Ihr Image nun für Kubernetes unter Docker Hub verfügbar ist, können Sie es in Ihrem Cluster bereitstellen.

Schritt 4 — Einrichten der ConfigMap

Als wir den Django-Container lokal ausgeführt haben, haben wir die Datei env an docker run übergeben, um Konfigurationsvariablen in die Laufzeitumgebung zu injizieren. Bei Kubernetes können Konfigurationsvariablen mit ConfigMaps und Secrets injiziert werden.

ConfigMaps sollte verwendet werden, um nicht vertrauliche Konfigurationsdaten wie App-Einstellungen zu speichern, und Secrets sollte für sensible Informationen wie API-Schlüssel und Datenbank-Zugangsdaten verwendet werden. Sie werden beide auf ähnliche Weise in Container injiziert, aber Secrets haben zusätzliche Zugriffskontrolle und Sicherheitsfunktionen wie Verschlüsselung im Ruhezustand. Secrets speichern außerdem Daten in base64, während ConfigMaps Daten im Klartext speichern.

Erstellen Sie zunächst ein Verzeichnis namens yaml, in dem wir unsere Kubernetes-Manifeste speichern werden. Navigieren Sie in das Verzeichnis.

  • mkdir yaml
  • cd

Öffnen Sie eine Datei namens polls-configmap.yaml in nano oder Ihrem bevorzugten Texteditor:

  • nano polls-configmap.yaml

Fügen Sie das folgende ConfigMap-Manifest ein:

polls-configmap.yaml

apiVersion: v1 kind: ConfigMap metadata:   name: polls-config data:   DJANGO_ALLOWED_HOSTS: "*"   STATIC_ENDPOINT_URL: "https://your_space_name.space_region.digitaloceanspaces.com"   STATIC_BUCKET_NAME: "your_space_name"   DJANGO_LOGLEVEL: "info"   DEBUG: "True"   DATABASE_ENGINE: "postgresql_psycopg2" 

Wir haben die nicht sensible Konfiguration aus der in Schritt 1 geänderten Datei env extrahiert und in ein ConfigMap-Manifest eingefügt. Das ConfigMap-Objekt wird polls-config genannt. Kopieren Sie die gleichen Werte hinein, die Sie im vorherigen Schritt in die Datei env eingegeben haben.

Lassen Sie für Testzwecke DJANGO_ALLOWED_HOSTS auf * stehen, um die Host-Header-basierte Filterung zu deaktivieren. In einer Produktionsumgebung sollten Sie dies auf die Domäne Ihrer Anwendung setzen.

Wenn Sie mit der Bearbeitung der Datei fertig sind, speichern und schließen Sie sie.

Erstellen Sie die ConfigMap in Ihrem Cluster mit kubectl apply:

  • kubectl apply -f polls-configmap.yaml
Outputconfigmap/polls-config created 

Nachdem die ConfigMap erstellt wurde, erstellen wir im nächsten Schritt das von unserer Anwendung verwendete Secret.

Schritt 5 — Einrichten des Secret

Secret-Werte müssen base64-kodiert sein, d. h. das Erstellen von Secret-Objekten in Ihrem Cluster ist etwas aufwendiger als das Erstellen von ConfigMaps. Sie können den Vorgang aus dem vorherigen Schritt wiederholen, indem Sie Secret-Werte manuell base64-kodieren und in eine Manifestdatei einfügen. Sie können sie auch mit einer Umgebungsvariablendatei kubectl create und dem Flag --from-env-file erstellen, was wir in diesem Schritt tun werden.

Wir verwenden erneut die Datei env von Schritt 1 und entfernen die in die ConfigMap eingefügten Variablen. Erstellen Sie eine Kopie der Datei env mit dem Namen polls-secrets im Verzeichnis yaml:

  • cp ../env ./polls-secrets

Bearbeiten Sie die Datei in Ihrem bevorzugten Editor:

  • nano polls-secrets

polls-secrets

DJANGO_SECRET_KEY= DEBUG=True DJANGO_ALLOWED_HOSTS= DATABASE_ENGINE=postgresql_psycopg2 DATABASE_NAME=polls DATABASE_USERNAME= DATABASE_PASSWORD= DATABASE_HOST= DATABASE_PORT= STATIC_ACCESS_KEY_ID= STATIC_SECRET_KEY= STATIC_BUCKET_NAME= STATIC_ENDPOINT_URL= DJANGO_LOGLEVEL=info 

Löschen Sie alle in das ConfigMap-Manifest eingefügten Variablen. Wenn Sie fertig sind, sollte die Datei wie folgt aussehen:

polls-secrets

DJANGO_SECRET_KEY=your_secret_key DATABASE_NAME=polls DATABASE_USERNAME=your_django_db_user DATABASE_PASSWORD=your_django_db_user_password DATABASE_HOST=your_db_host DATABASE_PORT=your_db_port STATIC_ACCESS_KEY_ID=your_space_access_key STATIC_SECRET_KEY=your_space_access_key_secret 

Stellen Sie sicher, dass Sie die gleichen Werte wie in Schritt 1 verwenden. Wenn Sie fertig sind, speichern und schließen Sie die Datei.

Erstellen Sie das Secret in Ihrem Cluster mit kubectl create secret:

  • kubectl create secret generic polls-secret --from-env-file=poll-secrets
Outputsecret/polls-secret created 

Hier erstellen wir ein Secret-Objekt namens polls-secret und übergeben die soeben erstellte Secrets-Datei.

Sie können das Secret mit kubectl describe inspizieren:

  • kubectl describe secret polls-secret
OutputName:         polls-secret Namespace:    default Labels:       <none> Annotations:  <none>  Type:  Opaque  Data ==== DATABASE_PASSWORD:     8 bytes DATABASE_PORT:         5 bytes DATABASE_USERNAME:     5 bytes DJANGO_SECRET_KEY:     14 bytes STATIC_ACCESS_KEY_ID:  20 bytes STATIC_SECRET_KEY:     43 bytes DATABASE_HOST:         47 bytes DATABASE_NAME:         5 bytes 

Zu diesem Zeitpunkt haben Sie die Konfiguration Ihrer Anwendung in Ihrem Kubernetes-Cluster mithilfe der Objekttypen Secret und ConfigMap gespeichert. Wir sind nun bereit, die Anwendung in dem Cluster bereitzustellen.

Schritt 6 — Bereitstellen der Django-Anwendung mithilfe eines Deployment

In diesem Schritt erstellen Sie ein Deployment für Ihre Django-Anwendung. Eine Kubernetes Deployment ist ein Controller, der zur Verwaltung von zustandslosen Anwendungen in Ihrem Cluster verwendet werden kann. Ein Controller ist eine Kontrollschleife, die Arbeitslasten reguliert, indem er sie herauf- oder herunterskaliert. Controller starten auch fehlgeschlagene Container neu und leeren sie aus.

Deployments steuern ein oder mehrere Pods, die kleinste einsetzbare Einheit in einem Kubernetes-Cluster. Pods umschließen einen oder mehrere Container. Um mehr über die verschiedenen Arten von Arbeistlasten zu erfahren, die Sie starten können, lesen Sie bitte Eine Einführung in Kubernetes.

Öffnen Sie zunächst eine Datei namens polls-deployment.yaml in Ihrem bevorzugten Editor:

  • nano polls-deployment.yaml

Fügen Sie das folgende Deployment-Manifest ein:

polls-deployment.yaml

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 

Geben Sie den entsprechenden Container-Image-Namen ein und verweisen Sie dabei auf das Django Umfrage-Image, das Sie in Schritt 2 in Docker Hub verschoben haben.

Hier definieren wir eine Kubernetes Deployment namens polls-app und kennzeichnen es mit dem Schlüsselwertpaar app: polls. Wir geben an, dass wir zwei Replikate des Pods ausführen möchten, der unterhalb des Felds template definiert ist.

Durch die Verwendung von envFrom mit secretRef und configMapRef legen wir fest, dass alle Daten aus dem Secret polls-secret und der ConfigMap polls-config als Umgebungsvariablen in die Container injiziert werden sollen. Die Schlüssel ConfigMap und Secret werden zu den Namen der Umgebungsvariablen.

Abschließend geben wir containerPort 8000 frei und nennen ihn gunicorn.

Um mehr über die Konfiguration von Kubernetes Deployments zu erfahren, konsultieren Sie bitte Deployments aus der Kubernetes-Dokumentation.

Wenn Sie mit der Bearbeitung der Datei fertig sind, speichern und schließen Sie sie.

Erstellen Sie das Deployment in Ihrem Cluster mit kubectl apply -f:

  • kubectl apply -f polls-deployment.yaml
  • deployment.apps/polls-app created

Überprüfen Sie mit kubectl get, ob das Deployment korrekt bereitgestellt wurde:

  • kubectl get deploy polls-app
OutputNAME        READY   UP-TO-DATE   AVAILABLE   AGE polls-app   2/2     2            2           6m38s 

Wenn Sie auf einen Fehler stoßen, oder etwas nicht so ganz funktioniert, können Sie kubectl describe verwenden, um das fehlgeschlagene Deployment zu inspizieren:

  • kubectl describe deploy

Sie können die beiden Pods mit kubectl get pod inspizieren:

  • kubectl get pod
OutputNAME                         READY   STATUS    RESTARTS   AGE polls-app-847f8ccbf4-2stf7   1/1     Running   0          6m42s polls-app-847f8ccbf4-tqpwm   1/1     Running   0          6m57s 

Zwei Replikate Ihrer Django-Anwendung sind nun im Cluster in Betrieb. Um auf die Anwendung zuzugreifen, müssen Sie einen Kubernetes-Dienst erstellen, was wir als Nächstes tun.

Schritt 7 — Erlauben des externen Zugriffs unter Verwendung eines Dienstes

In diesem Schritt erstellen Sie einen Dienst für Ihre Django-Anwendung. Ein Kubernetes-Dienst ist eine Abstraktion, die es Ihnen ermöglicht, einen Satz laufender Pods als Netzwerkdienst bereitzustellen. Mit einem Dienst können Sie einen stabilen Endpunkt für Ihre Anwendung erstellen, der sich nicht ändert, wenn Pods sterben und neu erstellt werden.

Es gibt mehrere Dienstarten, einschließlich ClusterIP-Dienste, die den Dienst auf einer clusterinternen IP-Adresse bereitstellen, NodePort-Dienste, die den Dienst auf jedem Knoten an einem statischen Port, dem Nodeport, bereitstellen, und LoadBalancer-Dienste, die einen Cloud-Load-Balancer bereitstellen, um externen Datenverkehr zu den Pods in Ihrem Cluster zu leiten (über NodePorts, die er automatisch erstellt). Um mehr über diese zu erfahren, lesen Sie bitte Service in den Kubernetes-Dokumenten.

In unserer endgültigen Einrichtung verwenden wir einen ClusterIP-Dienst, der über einen Ingress und den in den Voraussetzungen für diesen Leitfaden eingerichteten Ingress-Controller freigegeben wird. Um zu testen, ob alles korrekt funktioniert, erstellen wir zunächst einen temporären NodePort-Dienst, um auf die Django-Anwendung zuzugreifen.

Beginnen Sie mit dem Erstellen einer Datei namens polls-svc.yaml mit Ihrem bevorzugten Editor:

  • nano polls-svc.yaml

Fügen Sie das folgende Dienst-Manifest ein:

polls-svc.yaml

apiVersion: v1 kind: Service metadata:   name: polls   labels:     app: polls spec:   type: NodePort   selector:     app: polls   ports:     - port: 8000       targetPort: 8000 

Hier erstellen wir einen NodePort-Dienst namens polls und geben ihm die Kennzeichnung app: polls. Dann wählen wir Backend-Pods mit der Kennzeichnung app: polls, und zielen auf deren Ports 8000.

Wenn Sie mit der Bearbeitung der Datei fertig sind, speichern und schließen Sie sie.

Stellen Sie den Dienst mit kubectl apply bereit:

  • kubectl apply -f polls-svc.yaml
Outputservice/polls created 

Bestätigen Sie mit kubectl get svc, dass Ihr Dienst erstellt wurde:

  • kubectl get svc polls
OutputNAME    TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE polls   NodePort   10.245.197.189   <none>        8000:32654/TCP   59s 

Diese Ausgabe zeigt die clusterinterne IP des Dienstes und den NodePort (32654). Um eine Verbindung mit dem Dienst herzustellen, benötigen wir die externen IP-Adressen für unsere Cluster-Knoten:

  • kubectl get node -o wide
OutputNAME                   STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP      OS-IMAGE                       KERNEL-VERSION          CONTAINER-RUNTIME pool-7no0qd9e0-364fd   Ready    <none>   27h   v1.18.8   10.118.0.5    203.0.113.1   Debian GNU/Linux 10 (buster)   4.19.0-10-cloud-amd64   docker://18.9.9 pool-7no0qd9e0-364fi   Ready    <none>   27h   v1.18.8   10.118.0.4    203.0.113.2    Debian GNU/Linux 10 (buster)   4.19.0-10-cloud-amd64   docker://18.9.9 pool-7no0qd9e0-364fv   Ready    <none>   27h   v1.18.8   10.118.0.3    203.0.113.3   Debian GNU/Linux 10 (buster)   4.19.0-10-cloud-amd64   docker://18.9.9 

Rufen Sie in Ihrem Webbrowser Ihre Umfrageanwendung mit der externen IP-Adresse eines beliebigen Knotens und dem NodePort auf. Mit der vorstehenden Ausgabe würde die URL der Anwendung lauten: http://203.0.113.1:32654/polls.

Sie sollten die gleiche Oberfläche der Umfrageanwendung sehen, auf die Sie in Schritt 1 lokal zugegriffen haben:

Oberfläche der Umfrageanwendung

Sie können den gleichen Test mit der Route /admin wiederholen: http://203.0.113.1:32654/admin. Sie sollten die gleiche Admin-Oberfläche wie zuvor sehen:

Authentifizierungsseite für Polls-Administrator

Zu diesem Zeitpunkt haben Sie zwei Replikate des Django Umfrageanwendungs-Containers mithilfe eines Deployments bereitgestellt. Außerdem haben Sie einen stabilen Netzwerk-Endpunkt für diese beiden Replikate erstellt und ihn mit einem NodePort-Dienst von außen zugänglich gemacht.

Der letzte Schritt in diesem Tutorial ist die Sicherung des externen Datenverkehrs zu Ihrer Anwendung mit HTTPS. Dazu verwenden wir den in den Voraussetzungen installierten Ingress-Controller ingress-nginx und erstellen ein Ingress-Objekt, um den externen Verkehr in den Kubernetes-Dienst polls zu leiten.

Schritt 8 — Konfigurieren von HTTPS unter Verwendung von Nginx Ingress und cert-manager

Mit Ingresses von Kubernetes können Sie den Datenverkehr von außerhalb Ihres Kubernetes-Clusters flexibel an Dienste innerhalb Ihres Clusters leiten. Dies geschieht mit der Verwendung von Ingress-Objekten, die Regeln für das Routing von HTTP- und HTTPS-Verkehr zu Kubernetes-Diensten definieren, und Ingress-Controllern, die die Regeln umsetzen, indem sie den Verkehr durch Lastverteilung an die entsprechenden Backend-Dienste weiterleiten.

In den Voraussetzungen haben den Ingress-Controller ingress-nginx und das TLS-Zertifizierungsautomatisierungs-Add-on cert-manager installiert. Außerdem haben Sie die Staging- und Produktions-ClusterIssuers für Ihre Domäne unter Verwendung der Zertifizierungsstelle Let’s Encrypt eingerichtet und einen Ingress erstellt, um die Ausstellung von Zertifikaten und die TLS-Verschlüsselung für zwei Dummy-Backend-Dienste zu testen. Bevor Sie mit diesem Schritt fortfahren, sollten Sie den in dem Voraussetzungs-Tutorial erstellten Ingress echo-ingress löschen:

  • kubectl delete ingress echo-ingress

Wenn Sie möchten, können Sie auch die Dummy-Dienste und -Deployments mit kubectl delete svc und kubectl delete delploy löschen, aber dies ist für die Durchführung des Tutorials nicht unbedingt erforderlich.

Sie sollten auch einen DNS-A-Datensatz mit your_domain.com erstellt haben, der auf die öffentliche IP-Adresse des Ingress Load Balancers verweist. Wenn Sie einen DigitalOcean Load Balancer verwenden, finden Sie diese IP-Adresse im Abschnitt Load Balancers des Bedienfelds. Wenn Sie DigitalOcean auch für die Verwaltung der DNS-Datensätze Ihrer Domäne verwenden, konsultieren Sie bitte Verwalten von DNS-Datensätzen, um zu erfahren, wie Sie A-Datensätze erstellen.

Wenn Sie DigitalOcean Kubernetes verwenden, stellen Sie außerdem sicher, dass Sie die in Schritt 5 von Einrichten eines Nginx-Ingress mit Cert-Manager unter DigitalOcean Kubernetes beschriebene Problemumgehung umgesetzt haben.

Sobald Sie einen A-Datensatz haben, der auf den Ingress Controller Load Balancer verweist, können Sie einen Ingress für your_domain.com und den Dienst polls erstellen.

Öffnen Sie eine Datei namens polls-ingress.yaml mit Ihrem bevorzugten Editor:

  • nano polls-ingress.yaml

Fügen Sie das folgende Ingress-Manifest ein:

[polls-ingress.yaml] 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 

Wir erstellen ein Ingress-Objekt namens polls-ingress und annotieren es, um die Steuerungsebene anzuweisen, den Ingress-Controller ingress-nginx und den ClusterIssuer „staging“ zu verwenden. Außerdem aktivieren wir TLS für your_domain.com und speichern das Zertifikat und den privaten Schlüssel in einem Secret namens polls-tls. Schließlich definieren wir eine Regel, um den Verkehr für den Host your_domain.com an den Dienst polls auf Port 8000 zu leiten.

Wenn Sie mit der Bearbeitung der Datei fertig sind, speichern und schließen Sie sie.

Erstellen Sie den Ingress in Ihrem Cluster mit kubectl apply:

  • kubectl apply -f polls-ingress.yaml
Outputingress.networking.k8s.io/polls-ingress created 

Sie können kubectl describe verwenden, um den Status des soeben erstellten Ingress zu verfolgen:

  • kubectl describe ingress polls-ingress
OutputName:             polls-ingress Namespace:        default Address:          workaround.your_domain.com Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>) TLS:   polls-tls terminates your_domain.com Rules:   Host        Path  Backends   ----        ----  --------   your_domain.com                  polls:8000 (10.244.0.207:8000,10.244.0.53:8000) Annotations:  cert-manager.io/cluster-issuer: letsencrypt-staging               kubernetes.io/ingress.class: nginx Events:   Type    Reason             Age   From                      Message   ----    ------             ----  ----                      -------   Normal  CREATE             51s   nginx-ingress-controller  Ingress default/polls-ingress   Normal  CreateCertificate  51s   cert-manager              Successfully created Certificate "polls-tls"   Normal  UPDATE             25s   nginx-ingress-controller  Ingress default/polls-ingress 

Sie können auch describe für das Zertifikat polls-tls ausführen, um dessen erfolgreiche Erstellung weiter zu bestätigen:

  • kubectl describe certificate polls-tls
Output. . . Events:   Type    Reason     Age    From          Message   ----    ------     ----   ----          -------   Normal  Issuing    3m33s  cert-manager  Issuing certificate as Secret does not exist   Normal  Generated  3m32s  cert-manager  Stored new private key in temporary Secret resource "polls-tls-v9lv9"   Normal  Requested  3m32s  cert-manager  Created new CertificateRequest resource "polls-tls-drx9c"   Normal  Issuing    2m58s  cert-manager  The certificate has been successfully issued 

Dies bestätigt, dass das TLS-Zertifikat erfolgreich ausgestellt wurde und die HTTPS-Verschlüsselung nun für your_domain.com aktiv ist.

Da wir den Staging-ClusterIssuer verwendet haben, werden die meisten Webbrowser dem gefälschten Let’s Encrypt-Zertifikat nicht vertrauen, das es ausgestellt hat, sodass die Navigation zu your_domain.com Sie zu einer Fehlerseite führt.

Um eine Testanfrage zu senden, verwenden wir wget von der Befehlszeile aus:

  • wget -O - http://your_domain.com/polls
Output. . . ERROR: cannot verify your_domain.com's certificate, issued by ‘CN=Fake LE Intermediate X1’:   Unable to locally verify the issuer's authority. To connect to your_domain.com insecurely, use `--no-check-certificate'. 

Wir verwenden das vorgeschlagene Flag --no-check-certificate, um die Zertifikatsprüfung zu umgehen:

  • wget --no-check-certificate -q -O - http://your_domain.com/polls
Output  <link rel="stylesheet" type="text/css" href="https://your_space.nyc3.digitaloceanspaces.com/django-polls/static/polls/style.css">       <p>No polls are available.</p> 

Diese Ausgabe zeigt das HTML für die Benutzeroberflächenseite /polls und bestätigt auch, dass das Stylesheet aus dem Objektspeicher bedient wird.

Nachdem Sie nun die Zertifikatausstellung mit dem Staging-ClusterIssuer erfolgreich getestet haben, können Sie den Ingress ändern, um den ClusterIssuer, zu verwenden.

Öffnen Sie polls-ingress.yaml zur erneuten Bearbeitung:

  • nano polls-ingress.yaml

Ändern Sie die Annotation cluster-issuer:

[polls-ingress.yaml] apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata:   name: polls-ingress   annotations:     kubernetes.io/ingress.class: "nginx"     cert-manager.io/cluster-issuer: "letsencrypt-prod" spec:   tls:   - hosts:     - your_domain.com     secretName: polls-tls   rules:   - host: your_domain.com     http:       paths:       - backend:           serviceName: polls           servicePort: 8000 

Wenn Sie fertig sind, speichern und schließen Sie die Datei. Aktualisieren Sie den Ingress mit kubectl apply:

  • kubectl apply -f polls-ingress.yaml
Outputingress.networking.k8s.io/polls-ingress configured 

Um den Status der Zertifikatausstellung zu verfolgen, können Sie kubectl describe certificate polls-tls und kubectl describe ingress polls-ingress verwenden:

  • kubectl describe ingress polls-ingress
Output. . . Events:   Type    Reason             Age                From                      Message   ----    ------             ----               ----                      -------   Normal  CREATE             23m                nginx-ingress-controller  Ingress default/polls-ingress   Normal  CreateCertificate  23m                cert-manager              Successfully created Certificate "polls-tls"   Normal  UPDATE             76s (x2 over 22m)  nginx-ingress-controller  Ingress default/polls-ingress   Normal  UpdateCertificate  76s                cert-manager              Successfully updated Certificate "polls-tls" 

Die obige Ausgabe bestätigt, dass das neue Produktionszertifikat erfolgreich ausgestellt und im Secret polls-tls gespeichert wurde.

Navigieren Sie in Ihrem Webbrowser zu your_domain.com/polls, um zu bestätigen, dass die HTTPS-Verschlüsselung aktiviert ist und alles wie erwartet funktioniert. Sie sollten die Oberfläche der Umfrageanwendung sehen:

Oberfläche der Umfrageanwendung

Überprüfen Sie, ob die HTTPS-Verschlüsselung in Ihrem Webbrowser aktiv ist. Wenn Sie Google Chrome verwenden, bestätigt die Ankunft auf der obigen Seite ohne Fehler, dass alles korrekt funktioniert. Außerdem sollten Sie ein Vorhängeschloss in der URL-Leiste sehen. Durch Klicken auf das Vorhängeschloss können Sie die Details des Let’s Encrypt-Zertifikats einsehen.

Als letzte Bereinigungsaufgabe können Sie optional den Typ des Dienstes polls von NodePort auf den nut internen Typ ClusterIP umstellen.

Ändern Sie polls-svc.yaml mit Ihrem Editor:

  • nano polls-svc.yaml

Ändern Sie den type von NodePort auf ClusterIP:

polls-svc.yaml

apiVersion: v1 kind: Service metadata:   name: polls   labels:     app: polls spec:   type: ClusterIP   selector:     app: polls   ports:     - port: 8000       targetPort: 8000 

Wenn Sie mit der Bearbeitung der Datei fertig sind, speichern und schließen Sie sie.

Stellen Sie die Änderungen mit kubectl apply bereit:

  • kubectl apply -f polls-svc.yaml --force
Outputservice/polls configured 

Bestätigen Sie mit kubectl get svc, dass Ihr Dienst geändert wurde:

  • kubectl get svc polls
OutputNAME    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE polls   ClusterIP   10.245.203.186   <none>        8000/TCP   22s 

Diese Ausgabe zeigt, dass der Diensttyp nun ClusterIP ist. Der einzige Weg darauf zuzugreifen, ist über Ihre Domäne und den in diesem Schritt erstellten Ingress.

Zusammenfassung

In diesem Tutorial haben Sie eine skalierbare HTTPS-gesicherte Django-Anwendung in einem Kubernetes-Cluster bereitgestellt. Statische Inhalte werden direkt aus dem Objektspeicher bedient, und die Anzahl der laufenden Pods kann über das Feld replicas in dem Deployment-Manifest polls-app schnell herauf- oder herunterskaliert werden.

Wenn Sie einen DigitalOcean Space verwenden, können Sie auch die Bereitstellung statischer Assets über ein Content Delivery-Netzwerk aktivieren und eine benutzerdefinierte Subdomäne für Ihren Space erstellen. Lesen Sie bitte Aktivieren von CDN aus Einrichten einer skalierbaren Django-Anwendung mit von DigitalOcean verwalteten Datenbanken und Spaces, um mehr zu erfahren.

Um den Rest der zu lesen, besuchen Sie bitte unsere Seite Von Containern zu Kubernetes mit Django.