introduction
Kubernetes est un outil d’orchestration de conteneur open source pour la gestion des applications conteneurisées. Dans le didacticiel précédent de cette série, A regarder de plus près à Kubernetes, vous avez appris les fondements de Kubernetes.
Dans ce didacticiel, vous allez appliquer les concepts des didacticiels précédents pour créer, déployer et gérer une application de microservices de bout en bout dans Kubernetes. L’exemple d’application Web que vous utiliserez dans ce didacticiel est une application «liste de tâches» écrite dans Node.js, qui utilise MongoDB comme base de données. C’est la même application que nous avons utilisée dans le tutoriel Construire des applications conteneurisées.
Vous allez créer une image de conteneur pour cette application à partir d’un fichier Docker, la transmettre à Docker Hub, puis la déployer sur votre cluster. Ensuite, vous allez adapter l’application pour répondre à la demande croissante.
Conditions préalables
Pour compléter ce tutoriel, vous aurez besoin de:
-
Un cluster Kubernetes, que vous pouvez configurer dans la troisième partie de cette série de didacticiels, est De base de Kubernetes.
-
Un compte actif Docker Hub pour stocker l’image.
-
Git installé sur votre machine locale. Vous pouvez suivre le tutoriel Contributing to Open Source: Premiers pas avec Git pour installer et configurer Git sur ton ordinateur.
Étape 1 - Construire une image avec Dockerfile
Nous allons commencer par conteneuriser l’application Web en l’intégrant dans une image Docker.
Commencez par accéder à votre répertoire personnel, puis utilisez Git pour cloner l’exemple d’application Web de ce didacticiel à partir de son référentiel officiel sur GitHub.
cd ~
git clone https://github.com/janakiramm/todo-app.git
Construisez l’image de conteneur à partir du fichier Dockerfile. Utilisez le commutateur -t pour baliser l’image avec le nom d’utilisateur du registre, le nom de l’image et une balise facultative.
docker build -t sammy/todo .
La sortie confirme que l’image a été construite et étiquetée correctement.
OutputSending build context to Docker daemon 8.238MB
Step 1/7 : FROM node:slim
---> 286b1e0e7d3f
Step 2/7 : LABEL maintainer = "[email protected]"
---> Using cache
---> ab0e049cf6f8
Step 3/7 : RUN mkdir -p /usr/src/app
---> Using cache
---> 897176832f4d
Step 4/7 : WORKDIR /usr/src/app
---> Using cache
---> 3670f0147bed
Step 5/7 : COPY ./app/ ./
---> Using cache
---> e28c7c1be1a0
Step 6/7 : RUN npm install
---> Using cache
---> 7ce5b1d0aa65
Step 7/7 : CMD node app.js
---> Using cache
---> 2cef2238de24
Successfully built 2cef2238de24
Successfully tagged sammy/todo-app:latest
Vérifiez que l’image est créée en exécutant la commande docker images.
docker images
Vous pouvez voir la taille de l’image avec le temps écoulé depuis sa création.
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
sammy/todo-app latest 81f5f605d1ca 9 minutes ago 236MB
Ensuite, placez votre image dans le registre public sur Docker Hub. Pour ce faire, connectez-vous à votre compte Docker Hub:
docker login
Une fois que vous avez fourni vos informations d’identification, marquez votre image en utilisant votre nom d’utilisateur Docker Hub:
docker tag /todo-app
Poussez ensuite votre image sur Docker Hub:
docker push
Vous pouvez vérifier que la nouvelle image est disponible en effectuant une recherche dans Docker Hub dans votre navigateur Web.
Avec l’image Docker transmise au registre, emballons l’application pour Kubernetes.
Étape 2 - Déployer le pod MongoDB dans Kubernetes
L’application utilise MongoDB pour stocker les listes de tâches créées via l’application Web. Pour exécuter MongoDB dans Kubernetes, nous devons le conditionner en tant que pod. Lorsque nous lancerons ce pod, une seule instance de MongoDB sera exécutée.
Créez un nouveau fichier YAML appelé db-pod.yaml:
nano db-pod.yaml
Ajoutez le code suivant qui définit un pod avec un conteneur basé sur MongoDB. Nous exposons le port + 27017 +
, le port standard utilisé par MongoDB. Notez que la définition contient les étiquettes + name
et` + app`. Nous utiliserons ces étiquettes pour identifier et configurer des pods spécifiques.
db-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: db
labels:
name: mongo
app: todoapp
spec:
containers:
- image: mongo
name: mongo
ports:
- name: mongo
containerPort: 27017
volumeMounts:
- name: mongo-storage
mountPath: /data/db
volumes:
- name: mongo-storage
hostPath:
path: /data/db
Les données sont stockées dans le volume appelé + mongo-storage +
qui est mappé sur l’emplacement + / data / db +
du noeud. Pour plus d’informations sur les volumes, reportez-vous à la documentation officielle des Kubernetes.
Exécutez la commande suivante pour créer un pod.
kubectl create -f db-pod.yml
Vous verrez cette sortie:
Outputpod "db" created
Maintenant, vérifiez la création du pod.
kubectl get pods
La sortie affiche le pod et indique qu’il est en cours d’exécution:
OutputNAME READY STATUS RESTARTS AGE
db 1/1 0 2m
Faisons en sorte que ce pod soit accessible aux utilisateurs internes du cluster.
Créez un nouveau fichier appelé + db-service.yaml +
qui contient ce code qui définit le service pour MongoDB:
db-service.yaml
apiVersion: v1
kind: Service
metadata:
name: db
labels:
name: mongo
app:
spec:
selector:
name: mongo
type: ClusterIP
ports:
- name: db
port: 27017
targetPort: 27017
Le service découvre tous les pods dans le même espace de noms qui correspondent à l’étiquette avec + name: db +
. La section + selector +
du fichier YAML définit explicitement cette association.
Nous spécifions que le service est visible dans le cluster via la déclaration + type: ClusterIP +
.
Enregistrez le fichier et quittez l’éditeur. Ensuite, utilisez + kubectl +
pour le soumettre au cluster.
kubectl create -f db-service.yml
Cette sortie indique que le service a été créé avec succès:
Outputservice "db" created
Voyons le port sur lequel le pod est disponible.
kubectl get services
Vous verrez cette sortie:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db ClusterIP 10.109.114.243 <none> 14s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47m
À partir de cette sortie, vous pouvez voir que le service est disponible sur le port + 27017 +
. L’application Web peut atteindre MongoDB via ce service. Lorsqu’il utilise le nom d’hôte + db +
, le service DNS exécuté dans Kubernetes résoudra l’adresse en ClusterIP associé au service. Ce mécanisme permet aux pods de se découvrir et de communiquer les uns avec les autres.
Avec le pod et le service de base de données en place, créons un pod pour l’application Web.
Étape 3 - Déployer l’application Web Node.JS en tant que pod
Composons l’image Docker que vous avez créée à la première étape de ce didacticiel en tant que pod et déployez-la sur le cluster. Cela servira de couche d’application Web frontale accessible aux utilisateurs finaux.
Créez un nouveau fichier YAML nommé + web-pod.yaml +
:
nano web-pod.yaml
Ajoutez le code suivant qui définit un pod avec un conteneur basé sur l’image Docker + sammy / todo-app +
. Il est exposé sur le port + 3000 +
via le protocole TCP.
web-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
name: web
app:
spec:
containers:
- image: sammy/todo-app
name: myweb
ports:
- containerPort: 3000
Notez que la définition contient les étiquettes + name
et` + app`. Un service utilisera ces étiquettes pour acheminer le trafic entrant vers les ports appropriés.
Exécutez la commande suivante pour créer le pod:
kubectl create -f web-pod.yaml
Outputpod "web" created
Vérifions la création du pod:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
1/1 Running 0 8m
1/1 Running 0 9s
Notez que la base de données MongoDB et l’application Web s’exécutent en tant que pods.
Nous allons maintenant rendre le pod + web +
accessible au public sur Internet.
Les services exposent un ensemble de pods de manière interne ou externe. Définissons un service qui rend public le pod + web +
. Nous l’exposerons via un NodePort, un schéma rendant le pod accessible via un port arbitraire ouvert sur chaque nœud du cluster.
Créez un nouveau fichier nommé + web-service.yaml +
contenant ce code qui définit le service de l’application:
apiVersion: v1
kind: Service
metadata:
name: web
labels:
name: web
app:
spec:
selector:
name: web
type: NodePort
ports:
- name: http
port: 3000
targetPort: 3000
protocol: TCP
Le service découvre tous les pods dans le même espace de noms qui correspondent à l’étiquette avec le nom + web +
. La section de sélection du fichier YAML définit explicitement cette association.
Nous spécifions que le service est de type + NodePort +
via la déclaration + type: NodePort +
.
Utilisez + kubectl +
pour soumettre cela au cluster.
kubectl create -f web-service.yml
Cette sortie indique que le service a été créé avec succès:
Outputservice "web" created
Voyons le port sur lequel le pod est disponible.
kubectl get services
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db ClusterIP 10.109.114.243 <none> 27017/TCP 12m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 59m
web NodePort 10.107.206.92 <none> 3000: 12s
À partir de cette sortie, nous voyons que le service est disponible sur le port + 30770 +
. Essayons de nous connecter à l’un des nœuds de travail.
Obtenez l’adresse IP publique de l’un des nœuds de travail associés à votre cluster Kubernetes à l’aide de la console DigitalOcean.
image: https: //assets.digitalocean.com/articles/webinar_3_kubernetes_stackpoint/w9acP7y.png [Console DigitalOcean montrant les nœuds de travail]
Une fois que vous avez obtenu l’adresse IP, utilisez la commande + curl +
pour envoyer une requête HTTP à l’un des nœuds situés sur le port + 30770 +
:
curl http://:30770
Vous verrez une sortie semblable à celle-ci:
Output<!DOCTYPE html>
<html>
<head>
<title>Containers Todo Example</title>
<link rel='stylesheet' href='/stylesheets/screen.css' />
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div id="layout">
<h1 id="page-title">Containers Todo Example</h1>
<div id="list">
<form action="/create" method="post" accept-charset="utf-8">
<div class="item-new">
<input class="input" type="text" name="content" />
</div>
</form>
</div>
<div id="layout-footer"></div>
</div>
<script src="/javascripts/ga.js"></script>
</body>
</html>
Vous avez défini le Web Pod et un service. Voyons maintenant comment le redimensionner avec les jeux de réplicas.
Étape 5 - Mise à l’échelle de l’application Web
Un jeu de répliques garantit qu’un nombre minimal de pods sont en cours d’exécution dans le cluster à tout moment. Lorsqu’un pod est packagé en tant que jeu de répliques, Kubernetes exécutera toujours le nombre minimal de pods définis dans la spécification.
Supprimons le pod actuel et recréons deux pods à travers le jeu de répliques. Si nous laissons le pod en marche, il ne fera pas partie du jeu de répliques. Par conséquent, c’est une bonne idée de lancer les pods à travers un jeu de réplicas, même si le nombre n’est que de un.
Tout d’abord, supprimez le pod existant.
kubectl delete pod web
Outputpod "web" deleted
Créez maintenant une nouvelle déclaration de jeu de réplicas. La définition du jeu de répliques est identique à celle d’un pod. La principale différence réside dans le fait qu’il contient l’élément + réplica +
qui définit le nombre de pods à exécuter. Comme un pod, il contient également des étiquettes en tant que métadonnées qui aident à la découverte de services.
Créez le fichier + web-rs.yaml +
et ajoutez ce code au fichier:
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: web
labels:
name: web
app: todoapp
spec:
replicas: 2
template:
metadata:
labels:
name: web
spec:
containers:
- name: web
image: sammy/todo-app
ports:
- containerPort: 3000
Enregistrez et fermez le fichier.
Maintenant, créez le jeu de répliques:
kubectl create -f web-rs.yaml
Outputreplicaset "web" created
Puis vérifiez le nombre de pods:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 18m
web-n5l5h 1/1 Running 0 25s
web-wh6nf 1/1 Running 0 25s
Lorsque nous accédons au service via NodePort, la demande sera envoyée à l’un des pods gérés par l’ensemble de répliques.
Testons la fonctionnalité d’un jeu de répliques en supprimant l’un des pods et en observant ce qui se passe:
kubectl delete pod web-wh6nf
Outputpod "web-wh6nf" deleted
Regardez à nouveau les pods:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 19m
web-n5l5h 1/1 Running 0 1m
web-wh6nf 1/1 Terminating 0 1m
web-ws59m 0/1 ContainerCreating 0 2s
Dès que le pod est supprimé, Kubernetes en a créé un autre pour garantir le maintien du nombre souhaité.
Nous pouvons adapter le jeu de répliques à l’exécution de pods Web supplémentaires.
Exécutez la commande suivante pour adapter l’application Web à 10 pods.
kubectl scale rs/web --replicas=
Outputreplicaset "web" scaled
Vérifiez le nombre de pods:
kubectl get pods
Vous verrez cette sortie:
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 22m
web-4nh4g 1/1 Running 0 21s
web-7vbb5 1/1 Running 0 21s
web-8zd55 1/1 Running 0 21s
web-f8hvq 0/1 ContainerCreating 0 21s
web-ffrt6 1/1 Running 0 21s
web-k6zv7 0/1 ContainerCreating 0 21s
web-n5l5h 1/1 Running 0 3m
web-qmdxn 1/1 Running 0 21s
web-vc45m 1/1 Running 0 21s
web-ws59m 1/1 Running 0 2m
Kubernetes a lancé le processus de mise à l’échelle du pod + web +
. Lorsque la demande parvient au service via NodePort, elle est acheminée vers l’un des pods du jeu de réplicas.
Lorsque le trafic et la charge diminuent, nous pouvons revenir à la configuration d’origine de deux pods.
kubectl scale rs/web --replicas=
Outputreplicaset "web" scaled
Cette commande termine tous les pods sauf deux.
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 24m
web-4nh4g 1/1 Terminating 0 2m
web-7vbb5 1/1 Terminating 0 2m
web-8zd55 1/1 Terminating 0 2m
web-f8hvq 1/1 Terminating 0 2m
web-ffrt6 1/1 Terminating 0 2m
web-k6zv7 1/1 Terminating 0 2m
web-n5l5h 1/1 Running 0 5m
web-qmdxn 1/1 Terminating 0 2m
web-vc45m 1/1 Terminating 0 2m
web-ws59m 1/1 Running 0 4m
Pour vérifier la disponibilité du jeu de réplicas, essayez de supprimer l’un des pods et vérifiez le nombre.
kubectl delete pod web-ws59m
Outputpod "web-ws59m" deleted
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
db 1/1 Running 0 25m
web-n5l5h 1/1 Running 0 7m
web-ws59m 1/1 Terminating 0 5m
web-z6r2g 0/1 ContainerCreating 0 5s
Dès que le nombre de pod change, Kubernetes l’ajuste pour correspondre au nombre défini dans le fichier YAML. Lorsque l’un des pods Web du jeu de répliques est supprimé, un autre pod est immédiatement créé pour conserver le nombre souhaité. Cela garantit une haute disponibilité de l’application en veillant à ce que le nombre minimal de pods s’exécute en permanence.
Vous pouvez supprimer tous les objets créés au cours de ce tutoriel avec la commande suivante:
kubectl delete -f db-pod.yaml -f db-service.yaml -f web-rs.yaml -f web-service.yaml
Outputpod "db" deleted
service "db" deleted
replicaset "web" deleted
service "web" deleted
Conclusion
Dans ce didacticiel, vous avez appliqué tous les concepts abordés dans la série pour empaqueter, déployer et mettre à l’échelle des applications de microservices.
Dans la prochaine partie de cette série, vous apprendrez à rendre MongoDB hautement disponible en l’exécutant en tant que StatefulSet.