introduction
Kubernetes est un système permettant d'exécuter à grande échelle des applications conteneurisées modernes. Grâce à ce logiciel, les développeurs peuvent déployer et gérer des applications sur des clusters de machines. Et bien qu'il puisse être utilisé pour améliorer l'efficacité et la fiabilité des configurations d'applications à une seule instance, Kubernetes est conçu pour exécuter plusieurs instances d'une application sur plusieurs groupes de machines.
Lors de la création de déploiements multiservices avec Kubernetes, de nombreux développeurs choisissent d'utiliser le gestionnaire de packagesHelm. Helm rationalise le processus de création de plusieurs ressources Kubernetes en proposant des graphiques et des modèles qui coordonnent les interactions de ces objets. Il propose également des graphiques prédéfinis pour les projets open source populaires.
Dans ce didacticiel, vous déploierez une applicationNode.js avec une base de données MongoDB sur un cluster Kubernetes à l'aide de graphiques Helm. Vous utiliserez lesofficial Helm MongoDB replica set chart pour créer unStatefulSet object composé de troisPods, unHeadless Service et troisPersistentVolumeClaims. Vous allez également créer un graphique pour déployer une application Node.js à répliques multiples à l'aide d'une image d'application personnalisée. La configuration que vous construirez dans ce didacticiel reflétera la fonctionnalité du code décrit dansContainerizing a Node.js Application with Docker Compose et sera un bon point de départ pour créer une application Node.js résiliente avec un magasin de données MongoDB qui peut évoluer avec vos besoins.
Conditions préalables
Pour compléter ce tutoriel, vous aurez besoin de:
-
Un cluster Kubernetes 1.10+ avec le contrôle d'accès basé sur les rôles (RBAC) activé. Cette configuration utilisera unDigitalOcean Kubernetes cluster, mais vous êtes libre decreate a cluster using another method.
-
L'outil de ligne de commande
kubectl
installé sur votre ordinateur local ou serveur de développement et configuré pour se connecter à votre cluster. Vous pouvez en savoir plus sur l'installation dekubectl
dans lesofficial documentation. -
Helm installé sur votre ordinateur local ou serveur de développement et Tiller installé sur votre cluster, en suivant les instructions décrites dans les étapes 1 et 2 deHow To Install Software on Kubernetes Clusters with the Helm Package Manager.
-
Docker installé sur votre machine locale ou serveur de développement. Si vous travaillez avec Ubuntu 18.04, suivez les étapes 1 et 2 deHow To Install and Use Docker on Ubuntu 18.04; sinon, suivez lesofficial documentation pour obtenir des informations sur l'installation sur d'autres systèmes d'exploitation. Assurez-vous d'ajouter votre utilisateur non root au groupe
docker
, comme décrit à l'étape 2 du didacticiel lié. -
Un compteDocker Hub. Pour un aperçu de la façon de configurer cela, reportez-vous àthis introduction vers Docker Hub.
[[step-1 -—- cloning-and-packaging-the-application]] == Étape 1 - Clonage et empaquetage de l'application
Pour utiliser notre application avec Kubernetes, nous aurons besoin de la conditionner afin que leskubelet
agent puissent extraire l'image. Avant d'empaqueter l'application, cependant, nous devrons modifier les MongoDBconnection URI dans le code de l'application pour nous assurer que notre application peut se connecter aux membres du jeu de réplicas que nous allons créer avec le graphique Helmmongodb-replicaset
.
Notre première étape sera de cloner lesnode-mongo-docker-dev repository à partir desDigitalOcean Community GitHub account. Ce référentiel comprend le code de la configuration décrite dansContainerizing a Node.js Application for Development With Docker Compose, qui utilise une application de démonstration Node.js avec une base de données MongoDB pour montrer comment configurer un environnement de développement avec Docker Compose. Vous pouvez trouver plus d'informations sur l'application elle-même dans la sérieFrom Containers to Kubernetes with Node.js.
Clonez le référentiel dans un répertoire appelénode_project
:
git clone https://github.com/do-community/node-mongo-docker-dev.git node_project
Accédez au répertoirenode_project
:
cd node_project
Le répertoirenode_project
contient des fichiers et des répertoires pour une application d'informations sur les requins qui fonctionne avec l'entrée utilisateur. Il a été modernisé pour fonctionner avec les conteneurs: les informations de configuration sensibles et spécifiques ont été supprimées du code de l’application et refactorisées pour être injectées au moment de l’exécution, et l’état de l’application a été transféré dans une base de données MongoDB.
Pour plus d'informations sur la conception d'applications conteneurisées modernes, consultezArchitecting Applications for Kubernetes etModernizing Applications for Kubernetes.
Lorsque nous déploierons le graphique Helmmongodb-replicaset
, il créera:
-
Un objet StatefulSet avec trois pods - les membres des MongoDBreplica set. Chaque pod aura une PersistentVolumeClaim associée et conservera une identité fixe en cas de replanification.
-
Un jeu de réplicas MongoDB constitué des pods du StatefulSet. L'ensemble comprendra un primaire et deux secondaires. Les données seront répliquées du primaire vers les secondaires, garantissant que les données de nos applications restent hautement disponibles.
Pour que notre application puisse interagir avec les répliques de base de données, l'URI de connexion MongoDB dans notre code doit inclure les noms d'hôte des membres du jeu de réplicas ainsi que le nom du jeu de réplicas lui-même. Nous devons donc inclure ces valeurs dans l'URI.
Le fichier de notre référentiel cloné qui spécifie les informations de connexion à la base de données est appelédb.js
. Ouvrez ce fichier maintenant en utilisantnano
ou votre éditeur préféré:
nano db.js
Actuellement, le fichier contient desconstants référencés dans l'URI de connexion à la base de données au moment de l'exécution. Les valeurs de ces constantes sont injectées à l'aide de la propriétéprocess.env
de Node, qui renvoie un objet contenant des informations sur votre environnement utilisateur au moment de l'exécution. La définition dynamique de valeurs dans notre code d'application nous permet de découpler le code de l'infrastructure sous-jacente, ce qui est nécessaire dans un environnement dynamique sans état. Pour plus d'informations sur la refactorisation du code d'application de cette manière, consultezStep 2 deContainerizing a Node.js Application for Development With Docker Compose et la discussion correspondante dansThe 12-Factor App.
Les constantes de l'URI de connexion et de la chaîne d'URI se présentent comme suit:
~/node_project/db.js
...
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB
} = process.env;
...
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
...
Conformément à l'approche 12FA, nous ne souhaitons pas coder en dur les noms d'hôte de nos instances de réplica ou le nom de notre jeu de réplicas dans cette chaîne d'URI. La constanteMONGO_HOSTNAME
existante peut être étendue pour inclure plusieurs noms d'hôte - les membres de notre jeu de répliques - donc nous la laisserons en place. Cependant, nous devrons ajouter une constante de jeu de réplicas auxoptions
section de la chaîne URI.
AjoutezMONGO_REPLICASET
à la fois à l'objet constant URI et à la chaîne de connexion:
~/node_project/db.js
...
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB,
MONGO_REPLICASET
} = process.env;
...
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?replicaSet=${MONGO_REPLICASET}&authSource=admin`;
...
L'utilisation desreplicaSet
option dans la section options de l'URI nous permet de passer le nom du jeu de répliques, qui, avec les noms d'hôte définis dans la constanteMONGO_HOSTNAME
, nous permettra de nous connecter à l'ensemble membres.
Enregistrez et fermez le fichier une fois l’édition terminée.
Une fois vos informations de connexion à la base de données modifiées pour fonctionner avec des jeux de réplicas, vous pouvez désormais empaqueter votre application, créer l'image avec la commandedocker build
et la pousser vers Docker Hub.
Construisez l'image avecdocker build
et l'indicateur-t
, ce qui vous permet de marquer l'image avec un nom mémorable. Dans ce cas, marquez l'image avec votre nom d'utilisateur Docker Hub et nommez-lanode-replicas
ou un nom de votre choix:
docker build -t your_dockerhub_username/node-replicas .
Le.
dans la commande spécifie que le contexte de construction est le répertoire courant.
Il faudra une minute ou deux pour construire l'image. Une fois terminé, vérifiez vos images:
docker images
Vous verrez la sortie suivante:
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
your_dockerhub_username/node-replicas latest 56a69b4bc882 7 seconds ago 90.1MB
node 10-alpine aa57b0242b33 6 days ago 71MB
Ensuite, connectez-vous au compte Docker Hub que vous avez créé dans les conditions préalables:
docker login -u your_dockerhub_username
Lorsque vous y êtes invité, entrez le mot de passe de votre compte Docker Hub. La connexion de cette manière créera un fichier~/.docker/config.json
dans le répertoire de base de votre utilisateur non root avec vos informations d'identification Docker Hub.
Poussez l'image de l'application vers Docker Hub avec lesdocker push
command. N'oubliez pas de remplaceryour_dockerhub_username
par votre propre nom d'utilisateur Docker Hub:
docker push your_dockerhub_username/node-replicas
Vous disposez maintenant d'une image d'application que vous pouvez extraire pour exécuter votre application répliquée avec Kubernetes. La prochaine étape consistera à configurer des paramètres spécifiques à utiliser avec le graphique MongoDB Helm.
[[step-2 -—- creating-secrets-for-the-mongodb-replica-set]] == Étape 2 - Création de secrets pour l'ensemble de répliques MongoDB
Le graphiquestable/mongodb-replicaset
fournit différentes options en ce qui concerne l'utilisation de Secrets, et nous en créerons deux à utiliser avec notre déploiement de graphique:
-
Un secret pour nosreplica set keyfile qui fonctionnera comme un mot de passe partagé entre les membres du jeu de réplicas, leur permettant d'authentifier les autres membres.
-
Un secret pour notre utilisateur administrateur MongoDB, qui sera créé en tant queroot user sur la base de données
admin
. Ce rôle vous permettra de créer des utilisateurs ultérieurs avec des autorisations limitées lors du déploiement de votre application en production.
Une fois ces secrets en place, nous pourrons définir nos valeurs de paramètre préférées dans un fichier de valeurs dédié et créer l'objet StatefulSet et le réplica MongoDB définis avec le graphique Helm.
Commençons par créer le fichier de clés. Nous utiliserons lesopenssl
command avec l'optionrand
pour générer une chaîne aléatoire de 756 octets pour le fichier de clés:
openssl rand -base64 756 > key.txt
La sortie générée par la commande sera encodée enbase64, assurant une transmission uniforme des données, et redirigée vers un fichier appelékey.txt
, en suivant les instructions indiquées dans lesmongodb-replicaset
chart authentication documentation. Leskey itself doivent comporter entre 6 et 1 024 caractères, composés uniquement de caractères de l'ensemble base64.
Vous pouvez maintenant créer un secret appelékeyfilesecret
en utilisant ce fichier aveckubectl create
:
kubectl create secret generic keyfilesecret --from-file=key.txt
Cela créera un objet Secret dans lesdefault
namespace, car nous n'avons pas créé d'espace de noms spécifique pour notre configuration.
Vous verrez la sortie suivante indiquant que votre secret a été créé:
Outputsecret/keyfilesecret created
Supprimerkey.txt
:
rm key.txt
Sinon, si vous souhaitez enregistrer le fichier, assurez-vous querestrict its permissions et ajoutez-le à votre.gitignore
file pour le garder hors du contrôle de version.
Ensuite, créez le secret pour votre utilisateur administrateur MongoDB. La première étape consistera à convertir votre nom d’utilisateur et votre mot de passe en base64.
Convertissez votre nom d'utilisateur de base de données:
echo -n 'your_database_username' | base64
Notez la valeur que vous voyez dans la sortie.
Ensuite, convertissez votre mot de passe:
echo -n 'your_database_password' | base64
Notez également la valeur dans la sortie.
Ouvrez un fichier pour le secret:
nano secret.yaml
[.Remarque]##
Note: Les objets Kubernetes sont destypically defined utilisantYAML, ce qui interdit strictement les tabulations et nécessite deux espaces pour l'indentation. Si vous souhaitez vérifier le formatage de l'un de vos fichiers YAML, vous pouvez utiliser unlinter ou tester la validité de votre syntaxe en utilisantkubectl create
avec les--dry-run
et--validate
drapeaux:
kubectl create -f your_yaml_file.yaml --dry-run --validate=true
En général, c'est une bonne idée de valider votre syntaxe avant de créer des ressources aveckubectl
.
Ajoutez le code suivant au fichier pour créer un secret qui définira unuser
et unpassword
avec les valeurs encodées que vous venez de créer. Assurez-vous de remplacer les valeurs factices ici par votre propre nom d'utilisateur et mot de passeencoded:
~/node_project/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
data:
user: your_encoded_username
password: your_encoded_password
Ici, nous utilisons les noms de clés attendus par le graphiquemongodb-replicaset
:user
etpassword
. Nous avons nommé l'objet secretmongo-secret
, mais vous êtes libre de le nommer comme vous le souhaitez.
Enregistrez et fermez le fichier une fois l’édition terminée.
Créez l'objet Secret avec la commande suivante:
kubectl create -f secret.yaml
Vous verrez la sortie suivante:
Outputsecret/mongo-secret created
Encore une fois, vous pouvez soit supprimersecret.yaml
, soit restreindre ses autorisations et l'ajouter à votre fichier.gitignore
.
Une fois vos objets Secret créés, vous pouvez passer à la spécification des valeurs de paramètres que vous utiliserez avec le graphiquemongodb-replicaset
et à la création du déploiement MongoDB.
[[step-3 -—- configuration-the-mongodb-helm-chart-and-creating-a-deployment]] == Étape 3 - Configuration du graphique de barre MongoDB et création d'un déploiement
Helm est livré avec un référentiel activement maintenu appeléstable qui contient le graphique que nous utiliserons:mongodb-replicaset
. Pour utiliser ce graphique avec les secrets que nous venons de créer, nous allons créer un fichier avec des valeurs de paramètres de configuration appelémongodb-values.yaml
, puis installer le graphique à l'aide de ce fichier.
Notre fichiermongodb-values.yaml
reflétera largement lesvalues.yaml
file par défaut dans le référentiel de graphiquesmongodb-replicaset
. Nous allons cependant apporter les modifications suivantes à notre dossier:
-
Nous allons définir le paramètre
auth
surtrue
pour nous assurer que nos instances de base de données commencent parauthorization enabled. Cela signifie que tous les clients devront s'authentifier pour accéder aux ressources et aux opérations de la base de données. -
Nous allons ajouter des informations sur les secrets que nous avons créés à l'étape précédente afin que le graphique puisse utiliser ces valeurs pour créer le fichier de clés du jeu de réplicas et l'utilisateur admin.
-
Nous allons réduire la taille des PersistentVolumes associés à chaque pod dans le StatefulSet pour utiliser lesminimum viable DigitalOcean Block Storage unit, 1 Go, bien que vous soyez libre de le modifier pour répondre à vos besoins de stockage.
Cependant, avant d'écrire le fichiermongodb-values.yaml
, vous devez d'abord vérifier que vous avez créé et configuré unStorageClass pour provisionner les ressources de stockage. Chacun des pods de votre base de données StatefulSet aura une identité persistante et unPersistentVolumeClaim associé, qui provisionneront dynamiquement un PersistentVolume pour le pod. Si un pod est replanifié, le volume persistant sera monté sur le nœud sur lequel le pod est programmé (bien que chaque volume doit être supprimé manuellement si son pod ou StatefulSet associé est définitivement supprimé).
Comme nous travaillons avecDigitalOcean Kubernetes, notre StorageClassprovisioner
par défaut est défini surdobs.csi.digitalocean.com
-DigitalOcean Block Storage - que nous pouvons vérifier en tapant:
kubectl get storageclass
Si vous travaillez avec un cluster DigitalOcean, vous verrez le résultat suivant:
OutputNAME PROVISIONER AGE
do-block-storage (default) dobs.csi.digitalocean.com 21m
Si vous ne travaillez pas avec un cluster DigitalOcean, vous devrez créer une StorageClass et configurer unprovisioner
de votre choix. Pour plus de détails sur la manière de procéder, consultez lesofficial documentation.
Maintenant que vous vous êtes assuré d'avoir configuré une StorageClass, ouvrezmongodb-values.yaml
pour l'édition:
nano mongodb-values.yaml
Vous allez définir des valeurs dans ce fichier qui vont faire ce qui suit:
-
Activer l'autorisation.
-
Référencez vos objets
keyfilesecret
etmongo-secret
. -
Spécifiez
1Gi
pour vos PersistentVolumes. -
Définissez le nom de votre jeu de réplicas sur
db
. -
Spécifiez les répliques
3
pour l'ensemble. -
Épinglez l'image
mongo
à la dernière version au moment de l'écriture:4.1.9
.
Collez le code suivant dans le fichier:
~/node_project/mongodb-values.yaml
replicas: 3
port: 27017
replicaSetName: db
podDisruptionBudget: {}
auth:
enabled: true
existingKeySecret: keyfilesecret
existingAdminSecret: mongo-secret
imagePullSecrets: []
installImage:
repository: unguiculus/mongodb-install
tag: 0.7
pullPolicy: Always
copyConfigImage:
repository: busybox
tag: 1.29.3
pullPolicy: Always
image:
repository: mongo
tag: 4.1.9
pullPolicy: Always
extraVars: {}
metrics:
enabled: false
image:
repository: ssalaues/mongodb-exporter
tag: 0.6.1
pullPolicy: IfNotPresent
port: 9216
path: /metrics
socketTimeout: 3s
syncTimeout: 1m
prometheusServiceDiscovery: true
resources: {}
podAnnotations: {}
securityContext:
enabled: true
runAsUser: 999
fsGroup: 999
runAsNonRoot: true
init:
resources: {}
timeout: 900
resources: {}
nodeSelector: {}
affinity: {}
tolerations: []
extraLabels: {}
persistentVolume:
enabled: true
#storageClass: "-"
accessModes:
- ReadWriteOnce
size: 1Gi
annotations: {}
serviceAnnotations: {}
terminationGracePeriodSeconds: 30
tls:
enabled: false
configmap: {}
readinessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
livenessProbe:
initialDelaySeconds: 30
timeoutSeconds: 5
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
Le paramètrepersistentVolume.storageClass
est commenté ici: la suppression du commentaire et la définition de sa valeur sur"-"
désactiveraient l'approvisionnement dynamique. Dans notre cas, parce que nous laissons cette valeur indéfinie, le graphique choisira leprovisioner
par défaut - dans notre cas,dobs.csi.digitalocean.com
.
Notez également lesaccessMode
associés à la clépersistentVolume
:ReadWriteOnce
signifie que le volume provisionné sera en lecture-écriture uniquement par un seul nœud. Veuillez consulter lesdocumentation pour plus d'informations sur les différents modes d'accès.
Pour en savoir plus sur les autres paramètres inclus dans le fichier, consultez lesconfiguration table inclus avec le dépôt.
Enregistrez et fermez le fichier une fois l’édition terminée.
Avant de déployer le graphiquemongodb-replicaset
, vous voudrez mettre à jour le repostable avec leshelm repo update
command:
helm repo update
Cela obtiendra les dernières informations graphiques du référentielstable.
Enfin, installez le graphique avec la commande suivante:
helm install --name mongo -f mongodb-values.yaml stable/mongodb-replicaset
[.Remarque]##
Note: Avant d'installer un graphique, vous pouvez exécuterhelm install
avec les options--dry-run
et--debug
pour vérifier les manifestes générés pour votre version:
helm install --name your_release_name -f your_values_file.yaml --dry-run --debug your_chart
Notez que nous nommons Helmreleasemongo
. Ce nom fera référence à ce déploiement particulier du graphique avec les options de configuration que nous avons spécifiées. Nous avons indiqué ces options en incluant l'indicateur-f
et notre fichiermongodb-values.yaml
.
Notez également que, comme nous n'avons pas inclus l'indicateur--namespace
avechelm install
, nos objets de graphique seront créés dans l'espace de nomsdefault
.
Une fois que vous avez créé la version, vous verrez une sortie sur son statut, ainsi que des informations sur les objets créés et des instructions pour interagir avec eux:
OutputNAME: mongo
LAST DEPLOYED: Tue Apr 16 21:51:05 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
mongo-mongodb-replicaset-init 1 1s
mongo-mongodb-replicaset-mongodb 1 1s
mongo-mongodb-replicaset-tests 1 0s
...
Vous pouvez maintenant vérifier la création de vos pods avec la commande suivante:
kubectl get pods
Vous verrez les résultats comme suit lors de la création des pods:
OutputNAME READY STATUS RESTARTS AGE
mongo-mongodb-replicaset-0 1/1 Running 0 67s
mongo-mongodb-replicaset-1 0/1 Init:0/3 0 8s
Les sortiesREADY
etSTATUS
ici indiquent que les pods de notre StatefulSet ne sont pas complètement prêts: lesInit Containers associés aux conteneurs du pod sont toujours en cours d'exécution. Étant donné que les membres StatefulSet sontcreated in sequential order, chaque pod du StatefulSet doit êtreRunning
etReady
avant la création du pod suivant.
Une fois que les pods ont été créés et que tous les conteneurs associés sont en cours d'exécution, vous verrez cette sortie:
OutputNAME READY STATUS RESTARTS AGE
mongo-mongodb-replicaset-0 1/1 Running 0 2m33s
mongo-mongodb-replicaset-1 1/1 Running 0 94s
mongo-mongodb-replicaset-2 1/1 Running 0 36s
LesRunning
STATUS
indiquent que vos pods sont liés à des nœuds et que les conteneurs associés à ces pods sont en cours d'exécution. READY
indique le nombre de conteneurs en cours d'exécution dans un pod. Pour plus d'informations, veuillez consulter lesdocumentation on Pod lifecycles.
[.Remarque]##
Note:
Si vous voyez des phases inattendues dans la colonneSTATUS
, n'oubliez pas que vous pouvez dépanner vos pods avec les commandes suivantes:
kubectl describe pods your_pod
kubectl logs your_pod
Chacun des pods de votre StatefulSet a un nom qui combine le nom du StatefulSet avec lesordinal index du pod. Parce que nous avons créé trois répliques, nos membres StatefulSet sont numérotés de 0 à 2, et chacun a unstable DNS entry composé des éléments suivants:$(statefulset-name)-$(ordinal).$(service name).$(namespace).svc.cluster.local
.
Dans notre cas, le StatefulSet et lesHeadless Service créés par le graphiquemongodb-replicaset
ont les mêmes noms:
kubectl get statefulset
OutputNAME READY AGE
mongo-mongodb-replicaset 3/3 4m2s
kubectl get svc
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 443/TCP 42m
mongo-mongodb-replicaset ClusterIP None 27017/TCP 4m35s
mongo-mongodb-replicaset-client ClusterIP None 27017/TCP 4m35s
Cela signifie que le premier membre de notre StatefulSet aura l'entrée DNS suivante:
mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local
Comme nous avons besoin que notre application se connecte à chaque instance de MongoDB, il est essentiel de disposer de ces informations pour pouvoir communiquer directement avec les pods, plutôt qu'avec le service. Lorsque nous créons notre diagramme Helm d'application personnalisé, nous transmettons les entrées DNS de chaque pod à notre application à l'aide de variables d'environnement.
Vos instances de base de données étant opérationnelles, vous êtes prêt à créer le graphique pour votre application Node.
[[step-4 -—- creation-a-custom-application-chart-and-configuring-parameters]] == Étape 4 - Création d'un graphique d'application personnalisé et configuration des paramètres
Nous allons créer un graphique Helm personnalisé pour notre application Node et modifier les fichiers par défaut du répertoire de graphique standard afin que notre application puisse fonctionner avec le jeu de réplicas que nous venons de créer. Nous allons également créer des fichiers pour définir les objets ConfigMap et Secret pour notre application.
Tout d'abord, créez un nouveau répertoire de graphiques appelénodeapp
avec la commande suivante:
helm create nodeapp
Cela créera un répertoire appelénodeapp
dans votre dossier~/node_project
avec les ressources suivantes:
-
Un fichier
Chart.yaml
contenant des informations de base sur votre graphique. -
Un fichier
values.yaml
qui vous permet de définir des valeurs de paramètres spécifiques, comme vous l'avez fait avec votre déploiement MongoDB. -
Un fichier
.helmignore
avec des modèles de fichiers et de répertoires qui seront ignorés lors de l'empaquetage des graphiques. -
Un répertoire
templates/
avec les fichiers de modèle qui généreront les manifestes Kubernetes. -
Un répertoire
templates/tests/
pour les fichiers de test. -
Un répertoire
charts/
pour tous les graphiques dont dépend ce graphique.
Le premier fichier que nous modifierons parmi ces fichiers par défaut estvalues.yaml
. Ouvrez ce fichier maintenant:
nano nodeapp/values.yaml
Les valeurs que nous allons définir ici incluent:
-
Le nombre de répliques.
-
L'image d'application que nous voulons utiliser. Dans notre cas, ce sera l'image
node-replicas
que nous avons créée dansStep 1. -
LesServiceType. Dans ce cas, nous spécifieronsLoadBalancer pour créer un point d'accès à notre application à des fins de test. Comme nous travaillons avec un cluster DigitalOcean Kubernetes, cela créera unDigitalOcean Load Balancer lorsque nous déploierons notre graphique. En production, vous pouvez configurer votre graphique pour utiliserIngress Resources etIngress Controllers pour acheminer le trafic vers vos services.
-
LestargetPort pour spécifier le port sur le pod où notre application sera exposée.
Nous n'entrerons pas de variables d'environnement dans ce fichier. Au lieu de cela, nous créerons des modèles pour les objets ConfigMap et Secret et ajouterons ces valeurs à notre manifeste de déploiement d'application, situé à~/node_project/nodeapp/templates/deployment.yaml
.
Configurez les valeurs suivantes dans le fichiervalues.yaml
:
~/node_project/nodeapp/values.yaml
# Default values for nodeapp.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 3
image:
repository: your_dockerhub_username/node-replicas
tag: latest
pullPolicy: IfNotPresent
nameOverride: ""
fullnameOverride: ""
service:
type: LoadBalancer
port: 80
targetPort: 8080
...
Enregistrez et fermez le fichier une fois l’édition terminée.
Ensuite, ouvrez un fichiersecret.yaml
dans le répertoirenodeapp/templates
:
nano nodeapp/templates/secret.yaml
Dans ce fichier, ajoutez des valeurs pour vos constantes d'applicationMONGO_USERNAME
etMONGO_PASSWORD
. Ce sont les constantes auxquelles votre application s'attend à avoir accès au moment de l'exécution, comme spécifié dansdb.js
, votre fichier de connexion à la base de données. Lorsque vous ajoutez les valeurs de ces constantes, n'oubliez pas d'utiliser les valeurs base64 -encoded que vous avez utilisées précédemment dansStep 2 lors de la création de votre objetmongo-secret
. Si vous devez recréer ces valeurs, vous pouvez revenir à l'étape 2 et réexécuter les commandes appropriées.
Ajoutez le code suivant au fichier:
~/node_project/nodeapp/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-auth
data:
MONGO_USERNAME: your_encoded_username
MONGO_PASSWORD: your_encoded_password
Le nom de cet objet Secret dépendra du nom de votre version de Helm, que vous spécifierez lors du déploiement du graphique d'application.
Enregistrez et fermez le fichier lorsque vous avez terminé.
Ensuite, ouvrez un fichier pour créer un ConfigMap pour votre application:
nano nodeapp/templates/configmap.yaml
Dans ce fichier, nous définirons les variables restantes attendues par notre application:MONGO_HOSTNAME
,MONGO_PORT
,MONGO_DB
etMONGO_REPLICASET
. Notre variableMONGO_HOSTNAME
inclura l'entrée DNS pour l'instanceeach dans notre jeu de répliques, puisque c'est ce que lesMongoDB connection URI requires.
Selon lesKubernetes documentation, lorsqu'une application implémente des contrôles de vivacité et de disponibilité, lesSRV records doivent être utilisés lors de la connexion aux pods. Comme indiqué dansStep 3, nos enregistrements Pod SRV suivent ce modèle:$(statefulset-name)-$(ordinal).$(service name).$(namespace).svc.cluster.local
. Puisque notre MongoDB StatefulSet implémente des contrôles de vivacité et de préparation, nous devons utiliser ces identificateurs stables lors de la définition des valeurs de la variableMONGO_HOSTNAME
.
Ajoutez le code suivant au fichier pour définir les variablesMONGO_HOSTNAME
,MONGO_PORT
,MONGO_DB
etMONGO_REPLICASET
. Vous êtes libre d'utiliser un autre nom pour votre base de donnéesMONGO_DB
, mais vos valeursMONGO_HOSTNAME
etMONGO_REPLICASET
doivent être écrites telles qu'elles apparaissent ici:
~/node_project/nodeapp/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-config
data:
MONGO_HOSTNAME: "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local,mongo-mongodb-replicaset-1.mongo-mongodb-replicaset.default.svc.cluster.local,mongo-mongodb-replicaset-2.mongo-mongodb-replicaset.default.svc.cluster.local"
MONGO_PORT: "27017"
MONGO_DB: "sharkinfo"
MONGO_REPLICASET: "db"
Comme nous avons déjà créé l'objet StatefulSet et le jeu de réplicas, les noms d'hôte répertoriés ici doivent être répertoriés dans votre fichier exactement comme ils apparaissent dans cet exemple. Si vous détruisez ces objets et renommez votre version de MongoDB Helm, vous devrez alors réviser les valeurs incluses dans cette carte de configuration. Il en va de même pourMONGO_REPLICASET
, puisque nous avons spécifié le nom du jeu de réplicas avec notre version MongoDB.
Notez également que les valeurs répertoriées ici sont indiquées, c'est-à-direthe expectation for environment variables in Helm.
Enregistrez et fermez le fichier une fois l’édition terminée.
Une fois vos valeurs de paramètre de graphique définies et vos manifestes Secret et ConfigMap créés, vous pouvez modifier le modèle de déploiement de l'application pour utiliser vos variables d'environnement.
[[step-5 -—- integrating-environment-variables-into-your-helm-deployment]] == Étape 5 - Intégration des variables d'environnement dans votre déploiement Helm
Avec les fichiers de notre application Secret et ConfigMap en place, nous devrons nous assurer que notre application de déploiement peut utiliser ces valeurs. Nous allons également personnaliser lesliveness and readiness probes qui sont déjà définis dans le manifeste de déploiement.
Ouvrez le modèle de déploiement de l'application pour le modifier:
nano nodeapp/templates/deployment.yaml
Bien qu'il s'agisse d'un fichier YAML, les modèles Helm utilisent une syntaxe différente de celle des fichiers Kubernetes YAML standard afin de générer des manifestes. Pour plus d'informations sur les modèles, consultez lesHelm documentation.
Dans le fichier, ajoutez d'abord une cléenv
aux spécifications de votre conteneur d'application, sous la cléimagePullPolicy
et au-dessus deports
:
~/node_project/nodeapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
ports:
Ensuite, ajoutez les clés suivantes à la liste des variablesenv
:
~/node_project/nodeapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: MONGO_USERNAME
valueFrom:
secretKeyRef:
key: MONGO_USERNAME
name: {{ .Release.Name }}-auth
- name: MONGO_PASSWORD
valueFrom:
secretKeyRef:
key: MONGO_PASSWORD
name: {{ .Release.Name }}-auth
- name: MONGO_HOSTNAME
valueFrom:
configMapKeyRef:
key: MONGO_HOSTNAME
name: {{ .Release.Name }}-config
- name: MONGO_PORT
valueFrom:
configMapKeyRef:
key: MONGO_PORT
name: {{ .Release.Name }}-config
- name: MONGO_DB
valueFrom:
configMapKeyRef:
key: MONGO_DB
name: {{ .Release.Name }}-config
- name: MONGO_REPLICASET
valueFrom:
configMapKeyRef:
key: MONGO_REPLICASET
name: {{ .Release.Name }}-config
Chaque variable comprend une référence à sa valeur, définie soit par unsecretKeyRef
key, dans le cas des valeurs secrètes, soit parconfigMapKeyRef
pour les valeurs ConfigMap. Ces clés pointent vers les fichiers Secret et ConfigMap que nous avons créés à l'étape précédente.
Ensuite, sous la cléports
, modifiez la définition decontainerPort
pour spécifier le port sur le conteneur où notre application sera exposée:
~/node_project/nodeapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
containers:
...
env:
...
ports:
- name: http
containerPort: 8080
protocol: TCP
...
Ensuite, modifions par défaut les contrôles de vivacité et de préparation inclus dans ce manifeste de déploiement. Ces vérifications garantissent que nos applications sont en cours d’exécution et prêtes à servir le trafic:
-
Les sondes de disponibilité évaluent si un pod est prêt à servir du trafic, en arrêtant toutes les demandes adressées au pod jusqu'à ce que les vérifications aboutissent.
-
Les sondes Liveness vérifient le comportement de base d'une application pour déterminer si l'application du conteneur est en cours d'exécution et se comporte comme prévu. Si une sonde d'activité survit, Kubernetes redémarre le conteneur.
Pour plus d'informations sur les deux, consultez lesrelevant discussion dansArchitecting Applications for Kubernetes.
Dans notre cas, nous allons construire sur leshttpGet
request que Helm a fournis par défaut et tester si notre application accepte ou non les requêtes sur le point de terminaison/sharks
. Leskubelet
service exécuteront la sonde en envoyant une requête GET au serveur Node s'exécutant dans le conteneur du pod d'application et en écoutant sur le port8080
. Si le code d'état de la réponse est compris entre 200 et 400, leskubelet
concluront que le conteneur est sain. Sinon, dans le cas d'un état 400 ou 500,kubelet
arrêtera le trafic vers le conteneur, dans le cas de la sonde de disponibilité, ou redémarrera le conteneur, dans le cas de la sonde de vivacité.
Ajoutez la modification suivante auxpath
indiqués pour les sondes de vivacité et de préparation:
~/node_project/nodeapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
containers:
...
env:
...
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /sharks
port: http
readinessProbe:
httpGet:
path: /sharks
port: http
Enregistrez et fermez le fichier une fois l’édition terminée.
Vous êtes maintenant prêt à créer votre version de l'application avec Helm. Exécutez leshelm install
command suivants, qui incluent le nom de la version et l'emplacement du répertoire du graphique:
helm install --name nodejs ./nodeapp
N'oubliez pas que vous pouvez d'abord exécuterhelm install
avec les options--dry-run
et--debug
, comme indiqué dansStep 3, pour vérifier les manifestes générés pour votre version.
Encore une fois, comme nous n'incluons pas l'indicateur--namespace
avechelm install
, nos objets de graphique seront créés dans l'espace de nomsdefault
.
Vous verrez la sortie suivante indiquant que votre version a été créée:
OutputNAME: nodejs
LAST DEPLOYED: Wed Apr 17 18:10:29 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
nodejs-config 4 1s
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nodejs-nodeapp 0/3 3 0 1s
...
Là encore, le résultat indiquera l'état de la version, ainsi que des informations sur les objets créés et sur la manière dont vous pouvez interagir avec eux.
Vérifiez l'état de vos pods:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
mongo-mongodb-replicaset-0 1/1 Running 0 57m
mongo-mongodb-replicaset-1 1/1 Running 0 56m
mongo-mongodb-replicaset-2 1/1 Running 0 55m
nodejs-nodeapp-577df49dcc-b5fq5 1/1 Running 0 117s
nodejs-nodeapp-577df49dcc-bkk66 1/1 Running 0 117s
nodejs-nodeapp-577df49dcc-lpmt2 1/1 Running 0 117s
Une fois que vos pods sont opérationnels, vérifiez vos services:
kubectl get svc
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 443/TCP 96m
mongo-mongodb-replicaset ClusterIP None 27017/TCP 58m
mongo-mongodb-replicaset-client ClusterIP None 27017/TCP 58m
nodejs-nodeapp LoadBalancer 10.245.33.46 your_lb_ip 80:31518/TCP 3m22s
LeEXTERNAL_IP
associé au servicenodejs-nodeapp
est l'adresse IP à laquelle vous pouvez accéder à l'application depuis l'extérieur du cluster. Si vous voyez un état<pending>
dans la colonneEXTERNAL_IP
, cela signifie que votre équilibreur de charge est toujours en cours de création.
Une fois que vous voyez une adresse IP dans cette colonne, accédez-y dans votre navigateur:http://your_lb_ip
.
Vous devriez voir la page de destination suivante:
Maintenant que votre application répliquée fonctionne, ajoutons quelques données de test pour vérifier que la réplication fonctionne entre les membres du jeu de réplicas.
[[step-6 -—- testing-mongodb-replication]] == Étape 6 - Test de la réplication MongoDB
Avec notre application en cours d'exécution et accessible via une adresse IP externe, nous pouvons ajouter des données de test et nous assurer que celles-ci sont répliquées entre les membres de notre jeu de réplicas MongoDB.
Tout d’abord, assurez-vous d’avoir navigué sur votre navigateur jusqu’à la page de destination de l’application:
Cliquez sur le boutonGet Shark Info. Vous verrez une page avec un formulaire de saisie où vous pouvez entrer un nom de requin et une description du caractère général de ce requin:
Dans le formulaire, ajoutez un premier requin de votre choix. Pour démontrer, nous ajouteronsMegalodon Shark
au champShark Name etAncient
au champShark Character:
Cliquez sur le boutonSubmit. Vous verrez une page contenant les informations sur ce requin qui vous seront renvoyées:
Revenez maintenant au formulaire d'informations sur les requins en cliquant surSharks dans la barre de navigation supérieure:
Entrez un nouveau requin de votre choix. Nous allons utiliserWhale Shark
etLarge
:
Une fois que vous cliquez surSubmit, vous verrez que le nouveau requin a été ajouté à la collection de requins dans votre base de données:
Vérifions que les données que nous avons entrées ont été répliquées entre les membres principaux et secondaires de notre jeu de réplicas.
Obtenez une liste de vos pods:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
mongo-mongodb-replicaset-0 1/1 Running 0 74m
mongo-mongodb-replicaset-1 1/1 Running 0 73m
mongo-mongodb-replicaset-2 1/1 Running 0 72m
nodejs-nodeapp-577df49dcc-b5fq5 1/1 Running 0 5m4s
nodejs-nodeapp-577df49dcc-bkk66 1/1 Running 0 5m4s
nodejs-nodeapp-577df49dcc-lpmt2 1/1 Running 0 5m4s
Pour accéder auxmongo
shell sur vos pods, vous pouvez utiliser leskubectl exec
command et le nom d'utilisateur que vous avez utilisé pour créer vosmongo-secret
dansStep 2. Accédez au shellmongo
sur le premier pod du StatefulSet avec la commande suivante:
kubectl exec -it mongo-mongodb-replicaset-0 -- mongo -u your_database_username -p --authenticationDatabase admin
Lorsque vous y êtes invité, entrez le mot de passe associé à ce nom d'utilisateur:
OutputMongoDB shell version v4.1.9
Enter password:
Vous serez déposé dans un shell administratif:
OutputMongoDB server version: 4.1.9
Welcome to the MongoDB shell.
...
db:PRIMARY>
Bien que l'invite elle-même inclue ces informations, vous pouvez vérifier manuellement quel membre du jeu de réplicas est le principal avec lesrs.isMaster()
method:
rs.isMaster()
Vous verrez une sortie comme celle-ci, indiquant le nom d’hôte du principal:
Outputdb:PRIMARY> rs.isMaster()
{
"hosts" : [
"mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
"mongo-mongodb-replicaset-1.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
"mongo-mongodb-replicaset-2.mongo-mongodb-replicaset.default.svc.cluster.local:27017"
],
...
"primary" : "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
...
Ensuite, passez à votre base de donnéessharkinfo
:
use sharkinfo
Outputswitched to db sharkinfo
Répertoriez les collections dans la base de données:
show collections
Outputsharks
Sortir les documents de la collection:
db.sharks.find()
Vous verrez la sortie suivante:
Output{ "_id" : ObjectId("5cb7702c9111a5451c6dc8bb"), "name" : "Megalodon Shark", "character" : "Ancient", "__v" : 0 }
{ "_id" : ObjectId("5cb77054fcdbf563f3b47365"), "name" : "Whale Shark", "character" : "Large", "__v" : 0 }
Quittez le shell MongoDB:
exit
Maintenant que nous avons vérifié les données de notre primaire, vérifions qu’elles sont répliquées sur un secondaire. kubectl exec
enmongo-mongodb-replicaset-1
avec la commande suivante:
kubectl exec -it mongo-mongodb-replicaset-1 -- mongo -u your_database_username -p --authenticationDatabase admin
Une fois dans le shell administratif, nous devrons utiliser la méthodedb.setSlaveOk()
pour permettre les opérations de lecture à partir de l'instance secondaire:
db.setSlaveOk(1)
Basculez vers la base de donnéessharkinfo
:
use sharkinfo
Outputswitched to db sharkinfo
Autorisez l'opération de lecture des documents de la collectionsharks
:
db.setSlaveOk(1)
Sortir les documents de la collection:
db.sharks.find()
Vous devriez maintenant voir les mêmes informations que lorsque vous avez exécuté cette méthode sur votre instance principale:
Outputdb:SECONDARY> db.sharks.find()
{ "_id" : ObjectId("5cb7702c9111a5451c6dc8bb"), "name" : "Megalodon Shark", "character" : "Ancient", "__v" : 0 }
{ "_id" : ObjectId("5cb77054fcdbf563f3b47365"), "name" : "Whale Shark", "character" : "Large", "__v" : 0 }
Cette sortie confirme que les données de votre application sont en cours de réplication entre les membres de votre jeu de réplicas.
Conclusion
Vous avez maintenant déployé une application d'informations de requin répliquée et hautement disponible sur un cluster Kubernetes à l'aide de diagrammes Helm. Cette application de démonstration et le flux de travail décrit dans ce didacticiel peuvent servir de point de départ lorsque vous créez des graphiques personnalisés pour votre application et tirez parti du référentielstable et desother chart repositories de Helm.
Lorsque vous vous dirigez vers la production, envisagez de mettre en œuvre les éléments suivants:
-
Centralized logging and monitoring. Veuillez consulter lesrelevant discussion dansModernizing Applications for Kubernetes pour un aperçu général. Vous pouvez également consulterHow To Set Up an Elasticsearch, Fluentd and Kibana (EFK) Logging Stack on Kubernetes pour savoir comment configurer une pile de journalisation avecElasticsearch,Fluentd etKibana. Consultez égalementAn Introduction to Service Meshes pour plus d'informations sur la façon dont les maillages de service tels queIstio implémentent cette fonctionnalité.
-
Ingress Resources to route traffic to your cluster. C'est une bonne alternative à LoadBalancer dans les cas où vous exécutez plusieurs services, chacun nécessitant son propre LoadBalancer, ou dans lesquels vous souhaitez implémenter des stratégies de routage au niveau de l'application (tests A / B et canary, par exemple). Pour plus d'informations, consultezHow to Set Up an Nginx Ingress with Cert-Manager on DigitalOcean Kubernetes et lesrelated discussion de routage dans le contexte de maillage de service dansAn Introduction to Service Meshes.
-
Backup strategies for your Kubernetes objects. Pour obtenir des conseils sur la mise en œuvre de sauvegardes avecVelero (anciennement Heptio Ark) avec le produit Kubernetes de DigitalOcean, veuillez consulterHow To Back Up and Restore a Kubernetes Cluster on DigitalOcean Using Heptio Ark.
Pour en savoir plus sur Helm, consultezAn Introduction to Helm, the Package Manager for Kubernetes,How To Install Software on Kubernetes Clusters with the Helm Package Manager et lesHelm documentation.