Tutorial

Bereitstellen einer skalierbaren und sicheren Django-Anwendung mit Kubernetes

DigitalOceanDockerPostgreSQLDjangoPython FrameworksKubernetes

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.
  • 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
Output
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"]

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:

Output
No 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.

Output
121 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
Output
Login 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
Output
configmap/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
Output
secret/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
Output
Name: 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
Output
NAME 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
Output
NAME 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
Output
service/polls created

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

  • kubectl get svc polls
Output
NAME 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
Output
NAME 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
Output
ingress.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
Output
Name: 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
Output
ingress.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
Output
service/polls configured

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

  • kubectl get svc polls
Output
NAME 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.

Creative Commons License