Série de séminaires Web: Déploiement et mise à l’échelle de microservices dans Kubernetes

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:

É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.

Related