Déployer une application Django évolutive et sécurisée avec Kubernetes
Introduction
Dans ce tutoriel, nous allons déployer une application de sondages Django conteneurisée sur un cluster Kubernetes.
Django est un framework Web puissant qui vous permet de déployer rapidement votre application Python à partir de zéro. Il comprend un certain nombre de fonctionnalités pratiques, notamment object relational map, l’authentification des utilisateurs et une interface d’administration personnalisable pour votre application. Il comprend également un système de cache et aide à concevoir des applications optimisées avec un gestionnaire d’URL et template systems.
Dans le tutoriel Building a Django and Gunicorn Application with Docker nous avons changé Application de sondages du tutoriel Django selon la méthodologie Twelve Factors pour la construction d’un web évolutif - applications optimisées pour le cloud. Le conteneur a été mis à l’échelle et sécurisé à l’aide d’un proxy inverse Nginx et d’un certificat TLS signé Let’s Encrypt (décrit dans le module du didacticiel Scaling and secure a Django application with Docker, Nginx, and Let’s Encrypt). Dans ce dernier tutoriel de la série De conteneurs à Kubernetes avec Django, nous allons vous montrer comment déployer une application Django modernisée polls sur le cluster Kubernetes.
Kubernetes est un puissant système d’orchestration de conteneurs open source qui permet d’automatiser le déploiement, la mise à l’échelle et la gestion des applications conteneurisées. Les objets Kubernetes tels que ConfigMaps et Secrets vous permettent de centraliser la configuration et de la détacher des conteneurs, tandis que les contrôleurs tels que Deployments rechargent automatiquement les conteneurs inactifs et vous permettent de mettre rapidement à l’échelle les répliques de conteneurs. Le chiffrement TLS est activé à l’aide de l’objet Ingress et du contrôleur open source ingress-nginx. Le module complémentaire Kubernetes cert-manager valide et émet des certificats à l’aide de l’autorité de certification gratuite Let’s Encrypt.
Pré requis
Pour ce tutoriel, vous aurez besoin des éléments suivants :
- Cluster Kubernetes version 1.15 ou ultérieure avec contrôle d’accès basé sur les rôles (RBAC) activé. Notre exemple utilisera un cluster DigitalOcean Kubernetes, mais vous pouvez créer un cluster en utilisant une autre méthode.
- L’outil de ligne de commande
kubectl
installé sur votre machine locale et configuré pour se connecter à votre cluster. Vous trouverez plus d’informations sur l’installation dekubectl
dans la documentation officielle. Si vous utilisez un cluster DigitalOcean Kubernetes, veuillez vous référer au guide Connexion à un cluster DigitalOcean Kubernetes pour apprendre comment se connecter au cluster aveckubectl
. - Nom de domaine enregistré. Dans ce tutoriel, nous utiliserons le nom
votre_domaine.com
. Vous pouvez obtenir un domaine gratuit auprès de Freenom ou enregistrer un nom de domaine de votre choix. - Le contrôleur ingress-nginx et le gestionnaire de certificats TLS cert-manager doivent être installés dans votre cluster et configuré pour utiliser des certificats TLS. Pour savoir comment installer et configurer Ingress à l’aide de cert-manager, consultez le guide [Configuring Nginx Ingress with Cert-Manager on a DigitalOcean Kubernetes Cluster] (https://www.digitalocean.com/community/tutorials/how-to-set -up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes).
- Enregistrement DNS “A” pour “votre_domaine.com” pointant vers l’adresse IP publique de l’équilibreur de charge Ingress. Si vous utilisez DigitalOcean pour gérer les enregistrements DNS de votre domaine, le guide [Gestion des enregistrements DNS] (https://www.digitalocean.com/docs/networking/dns/how-to/manage-records/) vous aidera à apprendre comment pour créer des ‘enregistrements de classe A’.
- Un magasin d’objets S3, tel que l’espace DigitalOcean, pour stocker les fichiers statiques du projet Django et un ensemble de clés pour accéder à cet espace. Pour savoir comment créer un espace, consultez le document Comment créer des espaces. Pour savoir comment créer des clés d’accès, consultez l’article Partager l’accès à l’espace avec des clés d’accès (https://www.digitalocean.com/docs/spaces/how-to/administrative-access/#access-keys). Avec des modifications mineures, vous pouvez utiliser n’importe quel service de stockage pris en charge par le plug-in django-storages.
- Instance de serveur PostgreSQL, base de données et utilisateur pour l’application Django. Avec des modifications mineures, vous pouvez utiliser n’importe quelle base de données supportée par Django.
- La base de données PostgreSQL doit être nommée polls (vous pouvez utiliser n’importe quel autre nom mémorable à entrer dans les fichiers de configuration ci-dessous). Ce tutoriel utilisera sammy comme nom d’utilisateur de la base de données Django. Pour obtenir des instructions sur la façon de procéder, consultez l’étape 1 de Construire une application Django et Gunicorn avec Docker. Ces étapes doivent être effectuées sur l’ordinateur local.
- Ce tutoriel utilise Managed PostgreSQL Cluster de DigitalOcean. Pour savoir comment créer un cluster, consultez la documentation de la base de données gérée par DigitalOcean.
- Vous pouvez également installer et exécuter votre propre instance PostgreSQL. Pour obtenir des instructions sur l’installation et l’administration de PostgreSQL sur un serveur Ubuntu, consultez le guide [Installation et utilisation de PostgreSQL sur Ubuntu 18.04] (https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql -sur -ubuntu-18-04).
- Compte Docker Hub et référentiel public. Vous trouverez plus d’informations sur leur création dans la section Référentiels de la documentation Docker.
- Système Docker installé sur la machine locale. Pour plus d’informations, consultez le guide [Installation et utilisation de Docker sur Ubuntu 18.04] (https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker
Étape 1 - Clonage et configuration de l’application
Dans cette étape, nous allons cloner le code de l’application à partir de GitHub et configurer des paramètres tels que les informations d’identification de la base de données et les clés de stockage d’objets.
Le code de l’application et le Dockerfile se trouvent dans la branche “polls-docker” du [dépôt GitHub de l’application Django Tutorial Polls] (https://github.com/do-community/django-polls/tree/polls-docker). Ce référentiel contient le code de l’application Polls utilisé comme exemple dans la documentation de Django, qui montre comment créer une application de sondage à partir de rien.
La branche polls-docker
contient la version hébergée par Docker de l’application Polls. Pour plus d’informations sur les modifications apportées à l’application Polls pour fonctionner efficacement dans un environnement conteneurisé, consultez le guide [Building a Django and Gunicorn Application with Docker] (https://www.digitalocean.com/community/tutorials/how-to - construire-une-application-django-et-gunicorn-avec-docker).
Tout d’abord, utilisez git
pour cloner la branche polls-docker
de la branche Django Tutorial Polls App GitHub repository sur votre machine locale :
git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git
Accédez au répertoire django-polls
:
cd django-polls
Ce répertoire contient le code Python de l’application Django, un Dockerfile
que Docker utilisera pour construire l’image du conteneur et un fichier env
contenant une liste de variables d’environnement à transmettre à l’environnement d’exécution du conteneur. Vérifiez le 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"]
Le Dockerfile est basé sur l’image Docker Python 3.7.4, qui installe les packages Python requis pour Django et Gunicorn conformément aux exigences de django-polls/. txt
. Il supprime ensuite certains fichiers de construction inutiles, copie le code de l’application dans l’image et définit l’option d’exécution PATH
. Déclare enfin que le port 8000
sera utilisé pour accepter les connexions de conteneur entrantes et démarre gunicorn
avec trois éléments de travail écoutant sur le port 8000
.
Pour plus d’informations sur chaque étape du Dockerfile, consultez l’étape 6 de Building a Django and Gunicorn Application with Docker.
Construisez maintenant l’image avec docker build
:
docker build -t polls .
Nommons l’image polls
en utilisant le drapeau -t
et passons dans le répertoire courant comme contexte de construction un ensemble de fichiers pour référence lors de la construction de l’image.
Une fois que Docker a créé et balisé l’image, répertoriez les images disponibles à l’aide de docker images
:
docker images
Vous devriez voir l’image polls
:
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
Avant de démarrer un conteneur Django, nous devons configurer son environnement à l’aide du fichier env
présent dans le répertoire courant. Ce fichier est transmis à la commande docker run
, qui est utilisée pour démarrer le conteneur, après quoi Docker injectera les variables d’environnement configurées dans l’environnement d’exécution du conteneur.
Ouvrez le fichier env
avec nano
ou votre éditeur préféré :
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
Remplissez les valeurs manquantes pour les clés suivantes :
-
DJANGO_SECRET_KEY
: spécifie une valeur unique et imprévisible, comme décrit dans la documentation Django. Une méthode pour générer cette clé est présentée dans la section Changing Application Settings du guide Django Scalable App. -
DJANGO_ALLOWED_HOSTS
: Cette variable sécurise l’application et empêche les attaques via les en-têtes d’hôte HTTP. À des fins de test, définissez*
comme caractère générique correspondant à tous les hôtes. Dans un environnement de production, la valeur “votre_domaine.com” doit être utilisée. Pour plus d’informations sur ce paramètre Django, consultez la section Core Settings de la documentation Django. -
DATABASE_USERNAME
: spécifie l’utilisateur de la base de données PostgreSQL créé lors des étapes préliminaires. -
DATABASE_NAME
: spécifiepolls
ou le nom de la base de données créée lors des étapes préliminaires. -
DATABASE_PASSWORD
: définit le mot de passe de l’utilisateur de la base de données PostgreSQL créé lors des étapes préliminaires. -
DATABASE_HOST
: spécifie le nom d’hôte de la base de données. -
DATABASE_PORT
: spécifiez le port de votre base de données. -
STATIC_ACCESS_KEY_ID
: Spécifiez la clé d’accès de votre espace ou magasin d’objets. -
STATIC_SECRET_KEY
: Spécifiez la clé secrète de votre espace ou de votre magasin d’objets. -
STATIC_BUCKET_NAME
: spécifiez le nom de votre compartiment de magasin d’espace ou d’objets. -
STATIC_ENDPOINT_URL
: spécifiez l’URL de l’espace correspondant ou du point de terminaison du magasin d’objets, tel quehttps://your_space_name.nyc3.digitaloceanspaces.com
si votre espace se trouve dans la zonenyc3
.
Une fois l’édition terminée, enregistrez et fermez le fichier.
Dans l’étape suivante, nous exécuterons le conteneur configuré sur site et créerons le schéma de base de données. Nous vérifierons également les ressources statiques telles que les feuilles de style et les images dans le magasin d’objets.
Étape 2 - Création du schéma de base de données et téléchargement des ressources dans le magasin d’objets
Après avoir construit et configuré le conteneur, utilisez docker run
pour remplacer la commande CMD
donnée dans le Dockerfile et créez le schéma de base de données à l’aide des commandes manage.py makemigrations
et manage.py migrate
:
docker run --env-file env polls sh -c "python manage.py makemigrations && python manage.py migrate"
Nous exécutons l’image de conteneur polls:latest
, transmettons la variable d’environnement que nous venons de modifier et remplaçons la commande Dockerfile par sh -c "python manage.py makemigrations && python manage.py migrate"
qui créera le schéma de la base de données défini par le code d’application.
Si vous exécutez ces commandes pour la première fois, vous devriez voir ce qui suit :
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
Cela signifie que le schéma de base de données a été créé avec succès.
La prochaine fois que vous exécuterez la commande migrate
, Django n’effectuera aucune opération à moins que le schéma de la base de données ait changé.
Nous allons ensuite démarrer une autre instance de conteneur d’application et utiliser un shell interactif à l’intérieur pour créer un utilisateur administratif pour le projet Django.
docker run -i -t --env-file env polls sh
Vous obtiendrez une chaîne shell dans un conteneur en cours d’exécution que vous pourrez utiliser pour créer un utilisateur Django :
python manage.py createsuperuser
Entrez le nom d’utilisateur, l’adresse e-mail et le mot de passe de l’utilisateur, et après avoir créé l’utilisateur, appuyez sur CTRL + D
pour quitter le conteneur et le supprimer.
Enfin, nous allons créer les fichiers statiques de l’application et les charger dans l’espace DigitalOcean à l’aide de collectstatic
. Veuillez noter que le processus peut prendre du temps.
docker run --env-file env polls sh -c "python manage.py collectstatic --noinput"
Après avoir créé et téléchargé les fichiers, vous obtiendrez la sortie suivante.
Output121 static files copied.
Maintenant, nous pouvons exécuter l’application :
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
Nous allons exécuter la commande par défaut définie dans le Dockerfile gunicorn --bind :8000 --workers 3 mysite.wsgi:application
et ouvrir le port de conteneur 8000
pour faire correspondre le port 80
sur la machine locale avec le port 8000
du conteneur ` sondages`.
Vous devriez maintenant pouvoir ouvrir l’application polls
dans votre navigateur en tapant http://localhost
dans la barre d’adresse. Étant donné que l’itinéraire pour le chemin /
n’est pas défini, vous obtiendrez très probablement une erreur 404 Page Not Found
.
Entrez http://localhost/polls
dans la barre d’adresse pour voir l’interface de l’application Polls :
Pour ouvrir l’interface d’administration, entrez l’adresse http://localhost/admin
. Vous devriez voir la fenêtre d’authentification de l’administrateur de l’application Polls :
Entrez le nom d’utilisateur et le mot de passe de l’administrateur que vous avez créés avec la commande createsuperuser
.
Une fois authentifié, vous pourrez accéder à l’interface d’administration de l’application Polls :
Notez que les actifs statiques de l’application admin
et polls
proviennent directement du magasin d’objets. Consultez le Testing Space Static File Delivery.
Une fois que vous avez terminé d’explorer les données, appuyez sur CTRL + C
dans la fenêtre du terminal où le conteneur Docker est en cours d’exécution pour supprimer le conteneur.
Une fois que l’image Docker de l’application Django a été testée, les actifs statiques seront récupérés dans le magasin d’objets et le schéma de la base de données sera configuré et prêt à pousser l’image de l’application Django vers un registre d’images tel que Docker Hub.
Étape 3 - Hébergement de l’image de l’application Django sur Docker Hub
Pour déployer une application sur Kubernetes, vous devez télécharger l’image de l’application dans un registre tel que Docker Hub. Kubernetes extrait l’image de l’application du référentiel, puis la déploie sur le cluster.
Vous pouvez utiliser un registre Docker privé, tel que le DigitalOcean Container Registry, qui est actuellement en préversion gratuite, ou un registre Docker public tel que comme Docker Hub. Docker Hub vous permet également de créer des référentiels Docker privés. Le référentiel public permet à quiconque de voir et d’extraire des images de conteneur, tandis que le référentiel privé n’autorise l’accès qu’à vous et aux membres de votre équipe.
Dans ce didacticiel, nous allons déployer l’image Django dans le référentiel public Docker Hub que nous avons créé à l’étape des prérequis. Vous pouvez également transférer une image vers un référentiel privé, mais l’extraction d’images à partir d’un référentiel privé n’est pas abordée dans cet article. Pour plus d’informations sur l’authentification Kubernetes avec Docker Hub et l’extraction d’images à partir d’un référentiel privé, consultez Extraire une image d’un registre privé (Récupération d’une image à partir d’un registre privé) dans la documentation de Kubernetes.
Pour commencer, connectez-vous à Docker Hub sur votre ordinateur local :
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:
Entrez votre nom d’utilisateur et votre mot de passe Docker Hub pour vous connecter.
L’image Django est maintenant taguée avec polls:latest
. Pour le transférer vers votre référentiel Docker Hub, modifiez les balises d’image pour inclure votre nom d’utilisateur Docker Hub et le nom du référentiel :
docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest
Placez l’image dans le dépôt :
docker push sammy/sammy-django:latest
Dans ce didacticiel, nous utilisons le nom d’utilisateur Docker Hub sammy et le nom du référentiel sammy-django. Vous devez remplacer ces valeurs par votre nom d’utilisateur Docker Hub et le nom du référentiel.
Lorsque vous déployez des couches d’images sur Docker Hub, vous verrez certains messages à l’écran.
Votre image est maintenant disponible pour Kubernetes dans le référentiel Docker Hub et vous pouvez commencer à la déployer sur votre cluster.
Étape 4 - Configuration de la ConfigMap
Lors de l’exécution locale du conteneur Django, nous avons transmis le fichier env
à docker run
pour injecter des variables de configuration dans le runtime. Pour insérer des variables de configuration dans Kubernetes, les ConfigMap et Secret.
Les éléments ConfigMap doivent être utilisés pour stocker des informations de configuration non sensibles telles que les paramètres d’application, et les éléments Secret doivent être utilisés pour stocker des informations sensibles telles que les clés API et les identifiants de connexion à la base de données. Ils sont insérés dans des conteneurs de la même manière, mais les éléments secrets ont des fonctionnalités de contrôle d’accès et de sécurité supplémentaires telles que chiffrement au repos . Les éléments secrets stockent les données au format base64, tandis que les éléments ConfigMap stockent les données au format texte brut.
Nous devons d’abord créer un répertoire yaml
où nous stockerons nos manifestes Kubernetes. Allez dans le répertoire.
mkdir yaml
cd
Ouvrez le fichier polls-configmap.yaml
dans nano
ou votre éditeur de texte préféré :
nano polls-configmap.yaml
Collez-y le ConfigMap suivant :
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"
Nous avons extrait les données de configuration non confidentielles du fichier env
modifié à l’étape 1 et les a transmis au manifeste ConfigMap. L’objet ConfigMap est nommé polls-config
. Copiez les mêmes valeurs saisies dans le fichier “env” à l’étape précédente.
Pour les tests, laissez DJANGO_ALLOWED_HOSTS
défini sur *
pour désactiver le filtrage basé sur les en-têtes d’hôte. Dans un environnement de production, il doit s’agir de votre domaine d’application.
Lorsque vous avez terminé de modifier le fichier, enregistrez-le et fermez-le.
Créez un élément ConfigMap dans votre cluster à l’aide de kubectl apply
:
kubectl apply -f polls-configmap.yaml
Outputconfigmap/polls-config created
Nous avons créé un élément ConfigMap et à l’étape suivante, nous allons créer un élément Secret qui sera utilisé par notre application.
Étape 5 - Personnalisation de l’élément secret
Les valeurs secrètes doivent être encodées en base64, ce qui signifie que la création d’objets secrets dans un cluster est légèrement plus difficile que la création d’objets ConfigMaps. Vous pouvez répéter la procédure décrite à l’étape précédente en encodant manuellement en base64 les valeurs secrètes et en les collant dans le fichier manifeste. Vous pouvez également les créer en utilisant un fichier de variable d’environnement, kubectl create
et le drapeau --from-env-file
, ce que nous ferons dans cette étape.
Nous utilisons à nouveau le fichier env
de étape 1 en supprimant les variables insérées dans le ConfigMap. Faites une copie du fichier env
nommé polls-secrets
dans le répertoire yaml
:
cp ../env ./polls-secrets
Modifiez le fichier avec votre éditeur préféré :
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
Supprimez toutes les variables insérées dans le manifeste ConfigMap. Lorsque vous avez terminé, le contenu du fichier devrait ressembler à ceci :
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
Assurez-vous d’utiliser les mêmes valeurs qu’à l’Étape 1. Lorsque vous avez terminé, enregistrez et fermez le fichier.
Créez un objet secret sur le cluster à l’aide de kubectl create secret
:
kubectl create secret generic polls-secret --from-env-file=poll-secrets
Outputsecret/polls-secret created
Ici, nous allons créer un objet secret nommé polls-secret
et transmettre le fichier secrets que nous avons créé.
Vous pouvez inspecter l’objet secret à l’aide de kubectl describe
:
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
Nous avons stocké la configuration de votre application dans le cluster Kubernetes à l’aide des types d’objet Secret et ConfigMap. Nous sommes prêts à déployer l’application sur le cluster.
Étape 6 - Déploiement d’une application Django avec un contrôleur de déploiement
Dans cette étape, nous allons créer un déploiement pour votre application Django. Kubernetes Deployment est un controller que vous pouvez utiliser pour gérer des applications sans état dans votre cluster. Le contrôleur est une boucle de contrôle qui régule les tâches de travail grâce à une mise à l’échelle verticale. Les contrôleurs redémarrent et nettoient également les conteneurs défaillants.
Les contrôleurs de déploiement contrôlent un ou plusieurs pods. Un pod est la plus petite unité déployable dans un cluster Kubernetes. Les pods contiennent un ou plusieurs conteneurs. Pour en savoir plus sur les différents types de charges de travail, consultez le didacticiel Introduction à Kubernetes.
Commencez par ouvrir le fichier polls-deployment.yaml
avec votre éditeur de texte préféré :
nano polls-deployment.yaml
Collez-y le manifeste de déploiement suivant :
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
Saisissez le nom d’image de conteneur approprié, en vous référant à l’image Django Polls que vous avez hébergée sur Docker Hub à l’étape 2.
Ici, nous définissons un contrôleur de déploiement Kubernetes nommé polls-app
et lui attribuons une paire clé-valeur app: polls
. Nous indiquons que nous souhaitons exécuter deux répliques du pod défini dans le champ template
.
En utilisant envFrom
avec secretRef
et configMapRef
, nous spécifions que toutes les données des objets polls-secret
et polls-config
doivent être injectées dans des conteneurs en tant que variables d’environnement. Les clés ConfigMap et Secret deviennent des noms de variables d’environnement.
Enfin, nous allons ouvrir le containerPort
8000
et le nommer gunicorn
.
Pour en savoir plus sur la configuration des contrôleurs de déploiement Kubernetes, consultez la section Déploiements de la documentation Kubernetes.
Lorsque vous avez terminé de modifier le fichier, enregistrez-le et fermez-le.
Créez un contrôleur de déploiement sur le cluster à l’aide de kubectl apply -f
:
kubectl apply -f polls-deployment.yaml
deployment.apps/polls-app created
Vérifiez que le contrôleur de déploiement est correctement déployé à l’aide de kubectl get
:
kubectl get deploy polls-app
OutputNAME READY UP-TO-DATE AVAILABLE AGE
polls-app 2/2 2 2 6m38s
Si vous rencontrez une erreur ou si quelque chose ne fonctionne pas, vous pouvez utiliser kubectl describe
pour tester un contrôleur de déploiement défectueux :
kubectl describe deploy
Pour inspecter deux pods, utilisez kubectl get pod
:
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
Les clusters ont deux répliques de votre application Django en cours d’exécution. Pour accéder à l’application, vous devez créer un service Kubernetes, et nous le ferons à l’étape suivante.
Étape 7 - Fournir un accès externe à l’aide d’un service
Dans cette étape, nous créons un service pour notre application Django. Le service Kubernetes est une abstraction qui vous permet d’exposer un ensemble de pods en cours d’exécution en tant que service réseau. En utilisant un service, vous pouvez créer un point de terminaison stable pour votre application qui ne change pas lorsque les pods sont détruits et recréés.
Il existe plusieurs types de service, notamment ClusterIP, qui expose un service via l’adresse IP interne du cluster, NodePorts, qui expose un service sur chaque nœud d’un NodePort statique, et LoadBalancer, qui fournit un équilibreur de charge basé sur le cloud pour gérer les le trafic des Pods de votre cluster (via les NodePorts qu’il crée automatiquement). Pour en savoir plus à ce sujet, consultez la section Service de la documentation Kubernetes.
Dans l’étape de configuration finale, nous utilisons le service ClusterIP, accessible via Ingress et le contrôleur Ingress configuré en préparation de ce didacticiel. Nous allons maintenant nous assurer que tous les éléments fonctionnent correctement. Pour ce faire, nous allons créer un service NodePort temporaire pour accéder à l’application Django.
Tout d’abord, créez un fichier appelé polls-svc.yaml
dans votre éditeur préféré :
nano polls-svc.yaml
Collez-y le manifeste de service suivant :
polls-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: polls
labels:
app: polls
spec:
type: NodePort
selector:
app: polls
ports:
- port: 8000
targetPort: 8000
Ici, nous créons un service NodePort appelé polls
et lui donnons le label app:polls
. Nous allons sélectionner les pods backend étiquetés “app: polls” et définir les ports sur “8000” comme cibles.
Lorsque vous avez terminé de modifier le fichier, enregistrez-le et fermez-le.
Déployez le service à l’aide de la commande “kubectl apply” :
kubectl apply -f polls-svc.yaml
Outputservice/polls created
Vérifiez que le service a été créé à l’aide de kubectl get svc
:
kubectl get svc polls
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
polls NodePort 10.245.197.189 <none> 8000:32654/TCP 59s
Cette sortie affiche l’adresse IP interne du cluster de service et le numéro NodePort (‘32654’). Afin de se connecter au service, nous aurons besoin d’une adresse IP externe pour notre nœud de cluster :
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
Ouvrez l’application Polls dans un navigateur en utilisant l’adresse IP externe et le NodePort de n’importe quel nœud. Compte tenu de la sortie ci-dessus, l’URL de l’application serait http://203.0.113.1:32654/polls
.
Vous devriez voir la même interface d’application Polls que celle que vous avez ouverte localement à l’étape 1 :
Vous pouvez répéter la même vérification en utilisant la route /admin
: http://203.0.113.1:32654/admin
. Vous retrouverez la même interface d’administration qu’avant :
Nous avons déployé deux répliques du conteneur d’application Django Polls à l’aide de Deployment. Nous avons également créé un point de terminaison réseau stable pour ces deux réplicas et les avons rendus accessibles en externe via le service NodePort.
La dernière étape de ce didacticiel consiste à sécuriser le trafic externe de notre application à l’aide de HTTPS. Pour ce faire, nous utilisons le contrôleur ingress-nginx
installé à l’étape des prérequis et créons un objet Ingress pour rediriger le trafic externe vers le service polls
de Kubernetes.
Étape 8 - Configuration de HTTPS à l’aide de Nginx Ingress et de cert-manager
Les entités Ingress dans Kubernetes fournissent un routage flexible du trafic externe du cluster Kubernetes entre les services au sein du cluster. Ceci est réalisé via les ressources Ingress, qui définissent les règles de routage du trafic HTTP et HTTPS pour les services Kubernetes, et Ingress _Controllers, qui implémentent les règles en équilibrant la charge du trafic et en le transmettant aux services backend appropriés.
Dans l’étape des prérequis, nous avons installé le contrôleur [ingress-nginx] (https://github.com/kubernetes/ingress-nginx) et le module complémentaire [cert-manager] (https://github.com/jetstack/ cert-manager) à l’automatisation des certificats TLS. Nous avons également configuré un environnement de test et de production ClusterIssuers pour votre domaine à l’aide d’une autorité de certification Let’s Encrypt et créé un objet Ingress pour vérifier l’émission de certificats et le chiffrement TLS pour deux services backend factices. Avant de poursuivre cette étape, supprimez l’objet echo-ingress
créé dans le tutoriel préparatoire:
kubectl delete ingress echo-ingress
En option, vous pouvez également supprimer des services et des déploiements factices à l’aide des commandes kubectl delete svc
et kubectl delete deploy
, mais cela n’est pas requis pour ce didacticiel.
Vous deviez également créer un enregistrement DNS “A” pour “votre_domaine.com” pointant vers l’adresse IP publique de l’équilibreur de charge Ingress. Si vous utilisez un équilibreur de charge DigitalOcean, vous pouvez trouver cette adresse IP dans la section Load Balancers de votre panneau de contrôle. Si vous utilisez également DigitalOcean pour gérer les enregistrements DNS de votre domaine, le guide DNS Records Management vous aidera à apprendre comment créer des enregistrements de classe ‘A’.
Si vous utilisez DigitalOcean Kubernetes, assurez-vous d’avoir implémenté la solution de contournement décrite dans Étape 5 du didacticiel Configuration de Nginx Ingress avec Cert-Manager dans DigitalOcean Kubernetes.
Une fois que vous avez un enregistrement “A” pointant vers l’équilibreur de charge du contrôleur Ingress, vous pouvez créer un Ingress pour “votre_domaine.com” et le service “polls”.
Ouvrez le fichier nommé “polls-ingress.yaml” dans votre éditeur de texte préféré :
nano polls-ingress.yaml
Collez le fichier manifeste Ingress suivant :
[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
Nous créons un objet Ingress appelé “polls-ingress” et l’annotons de sorte que le plan de contrôle utilise le contrôleur ingress-nginx et héberge le ClusterIssuer. Nous activons également TLS pour le domaine votre_domaine.com
et stockons le certificat et la clé privée dans un objet secret nommé polls-tls
. Enfin, nous définissons une règle de redirection du trafic pour l’hôte votre_domaine.com
vers le service polls
sur le port 8000
.
Lorsque vous avez terminé de modifier le fichier, enregistrez-le et fermez-le.
Créez un objet Ingress sur le cluster à l’aide de kubectl apply
:
kubectl apply -f polls-ingress.yaml
Outputingress.networking.k8s.io/polls-ingress created
Vous pouvez utiliser kubectl describe
pour suivre l’état de l’objet Ingress nouvellement créé :
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
Vous pouvez également exécuter la commande describe
sur le certificat polls-tls
pour vérifier qu’il a été créé avec succès :
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
Cela confirme que le certificat TLS a été émis avec succès et que le cryptage HTTPS pour le domaine “votre_domaine.com” est actif.
Parce que nous utilisions une version de test de ClusterIssuer, la plupart des navigateurs ne feront pas confiance au faux certificat Let’s Encrypt qu’il émet, et donc une page d’erreur apparaîtra lorsque vous naviguez vers votre_domaine.com
.
Pour envoyer une requête de test, nous utilisons wget
depuis la ligne de commande :
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'.
Nous utilisons le drapeau suggéré --no-check-certificate
pour ignorer la vérification du certificat :
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>
Cette sortie affiche le code HTML de la page d’interface /polls
et confirme également que la feuille de style est renvoyée par le magasin d’objets.
Nous avons vérifié avec succès l’émission de certificats avec le ClusterIssuer de test et pouvons maintenant modifier Ingress pour utiliser le ClusterIssuer de production.
Ouvrez à nouveau le fichier polls-ingress.yaml
pour le modifier :
nano polls-ingress.yaml
Modifiez l’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
Apportez les modifications nécessaires, puis enregistrez et fermez le fichier. Mettez à jour l’objet Ingress à l’aide de kubectl apply
:
kubectl apply -f polls-ingress.yaml
Outputingress.networking.k8s.io/polls-ingress configured
Vous pouvez utiliser les commandes kubectl describe certificate polls-tls
et kubectl describe ingress polls-ingress
pour suivre l’état d’émission du certificat :
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"
La sortie ci-dessus confirme que le nouveau certificat de production a été émis avec succès et stocké dans l’objet secret “polls-tls”.
Ouvrez your_domain.com/polls
dans un navigateur pour vérifier que le cryptage HTTPS est activé et que tout fonctionne comme prévu. Vous devriez voir l’interface de l’application Polls :
Assurez-vous que votre navigateur a activé le cryptage HTTPS. Si vous utilisez Google Chrome, si la page ci-dessus s’ouvre sans erreur, cela signifie que tout fonctionne correctement. De plus, il devrait y avoir une image de cadenas dans la barre d’URL. En cliquant sur le cadenas, vous pouvez visualiser les détails du certificat Let’s Encrypt.
Pour un nettoyage final, vous pouvez basculer le type de service “polls” de NodePort vers le type interne ClusterIP.
Modifiez le fichier polls-svc.yaml
dans un éditeur de texte :
nano polls-svc.yaml
Remplacez type
de NodePort
par 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
Lorsque vous avez terminé de modifier le fichier, enregistrez-le et fermez-le.
Déployez les modifications avec la commande kubectl apply
:
kubectl apply -f polls-svc.yaml --force
Outputservice/polls configured
Vérifiez que le service a été modifié à l’aide de kubectl get svc
:
kubectl get svc polls
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
polls ClusterIP 10.245.203.186 <none> 8000/TCP 22s
Cette sortie montre que le type de service est ClusterIP. Seuls le domaine et Ingress créés à cette étape peuvent être utilisés pour l’accès.
Conclusion
Dans ce tutoriel, nous avons déployé une application Django évolutive avec sécurité HTTPS sur un cluster Kubernetes. Le contenu statique est servi directement à partir du magasin d’objets, et le nombre de pods en cours d’exécution peut être rapidement augmenté ou diminué à l’aide du champ replicas
dans le manifeste de déploiement polls-app
.
Si vous utilisez DigitalOcean Space, vous pouvez également activer la diffusion de ressources statiques via votre réseau de diffusion de contenu et créer un sous-domaine personnalisé pour votre espace. Pour plus d’informations, consultez la section Enabling a CDN du tutoriel Setting up a Scalable Django Application with Managed Databases and DigitalOcean Spaces.
Le reste de la série est disponible sur From Containers to Kubernetes with Django.