DEV Community

Cover image for Docker swarm & Portainer UI
DUVAL Olivier
DUVAL Olivier

Posted on • Updated on

Docker swarm & Portainer UI

Sommaire

Introduction

De nos jours, il est courant et fortement recommandé de mettre en place de la "conteneurisation", souvent au travers de la technologie Docker qui a accéléré la tendance depuis 10 ans :

Dans une équipe de développements applicatifs, sur l'environnement de développement :

  • avoir des images prêtes à l'emploi : par exemple une image du serveur d'applications, que toute l'équipe utilise, sur la même base de modules et versions, annuaire LDAP, base de données, etc
  • facilité de mise en place d'images, facilement déployables sur chaque station de travail : une image est légère et son exécution sera rapide, pour tester ou effectuer des POC, cela s'avère plus accessible
  • une gestion des dépendances (versions des packages, modules, ...) nettement améliorée et contrôlée

Dans un environnements de tests ou de production

Ces images pourront être packagées pour une utilisation sur une plateforme de tests et / ou la plateforme de prod, de façon rapide et efficace : déploiements facilités et mise en production efficiente.

Sur un environnement de production, il y aura régulièrement plusieurs instances d'applications sur plusieurs VM / serveurs, afin d'absorber la charge des accès utilisateurs, il va donc falloir déployer toutes ces images applicatives sous forme de conteneurs légers vers ces différentes instances de machines, et ensuite, s'assurer d'orienter tel flux (https, accès base, etc) vers tels conteneurs : cette façon de faire se nomme de l'orchestration de conteneurs, qui va également gérer le cycle de vie des conteneurs : scaling, création, déploiement / rechargement pour aller vers du Zero downtime deployment, load-balancing, la communcation entre les containers etc

Docker propose un orchestrateur natif à leur technologie, dans le moteur de conteneurs : Docker Swarm, où l'on va retrouver nos habitudes :

Docker swarm & Portainer

Vocabulaire

Worker = un noeud du cluster Swarm, une VM ou une machine physique

Manager = un noeud spécial du cluster Swarm qui aura pour charge d'orchestrer les services / containers du cluster (flux, déploiements, load balancing et haute disponibilité des services exposés), tel un chef d'orchestre ! Un manager peut aussi jouer le rôle de worker

Stack = un "fichier" docker-compose dans lequel ait décrit les services avec les règles associées : d'images sources à utiliser, de déploiement, de ressources (volumes, networks, ...voire CPU & co)

Service = un élément d'une stack à déployer selon des règles

Task = un container déployé sur un / des noeuds

Registry docker

Dans un écosystème où l'orchestration demande des images pour les transformer en conteneurs ("instances" d'une image), il est nécessaire d'avoir un registry docker qui permettra de stocker ces images à déployer :

  • le Docker Hub en est un

ou avoir une machine registry dédiée à cela :

  • via une solution légère de type registry développé par Docker et disponible sur le Hub
  • via une solution avec une interface Web de type harbor / github

Docker swarm

Docker swarm est inclus dans le moteur docker, c'est un orchestrateur de containers, qui permettra de gérer sur un ensemble de machines / VM, les containers sur chacune de ces instances (flux, déploiement, cycle de vie, répartitions et disponibilité), et, avouons-le, la mise en place reste accessible et rapide, une fois les concepts appréhendés.

Un cluster Swarm a plusieurs nœuds avec au moins 2 nœuds :

  • de type manager : aura la mission de diriger les flux entrants vers les nœuds et la gestion de l'orchestration des conteneurs : réplication dans le cluster, déploiement / rechargement des services, load-balancing. Il est conseillé d'avoir un nombre de manager impairs et au moins 3, selon l'algorithme Raft. Un manager peut aussi jouter le rôle de worker
  • de type worker, on pourra avoir plusieurs nœuds de ce type, afin de répartir la charge, un noeud à différents état : Active, Drain et Pause. Le mode Drain permettra de dire au manager de ne plus déployer vers les noeuds worker les services et donc d'arrêter les flux vers celui-ci. Le Pause, que j'utilise rarement, permet de suspendre tous les processus dans les containers contenus sur le noeud, en revanche, les flux continuent à être dirigés vers ce dernier.

Schématiquement, un cluster composé de managers et de workers se représentera ainsi :

swarm-diagram

Source : https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/

Le cluster swarm se gère avec la commande docker (CLI), tout comme on le ferait habituellement avec des images / containers /... en local d'une machine, c'est le gros avantage, on ne perd pas ses habitudes :)

Quelques commande avec le docker CLI

Les commandes ont le plus souvent une aide, il suffit d'utiliser l'option --help pour avoir la liste des arguments possible.

Le docker CLI permet de gérer un cluster swarm, quelques commandes que j'utilise régulièrement, hormis l'initialisation :

Swarm

  • initialisation d'un cluster swarm


$ docker swarm init --advertise-addr IP_MANAGER:2377


Enter fullscreen mode Exit fullscreen mode
  • informations sur le cluster


$ docker info


Enter fullscreen mode Exit fullscreen mode
  • obtenir un TOKEN worker / node à partir du manager


$ docker swarm join-token worker
docker swarm join --token SWMTKN-1-id1-id2 IP_MANAGER:2377


Enter fullscreen mode Exit fullscreen mode
  • faire rejoindre une machine sur le cluster en tant que worker

A partir de la commande donnée précédemment, il suffit de la recopier à partir d'une machine cluster



$ docker swarm join --token SWMTKN-1-id1-id2 IP_MANAGER:2377


Enter fullscreen mode Exit fullscreen mode
  • worker / noeud : faire quitter un noeud du cluster, à partir d'un noeud :


* docker swarm leave


Enter fullscreen mode Exit fullscreen mode

Noeud(s)

  • liste des noeuds


$ docker node ls


Enter fullscreen mode Exit fullscreen mode
  • liste des containers / tâches des noeuds ou d'un noeud


$ docker node ps
$ docker node ps <NODE_NAME>


Enter fullscreen mode Exit fullscreen mode
  • modifier l'état d'un noeud


$ docker node <ID_NODE> --availability "drain"
$ docker node <ID_NODE> --availability "active"


Enter fullscreen mode Exit fullscreen mode

Stack(s)

  • liste des stacks du cluster contenant, pour chacun, des services


$ docker stack ls 
NAME                SERVICES            ORCHESTRATOR
api-XYZ             7                   Swarm
ws                  1                   Swarm
fluend              3                   Swarm
ABC                 7                   Swarm
loki-grafana        3                   Swarm
portainer           2                   Swarm
prometheus          8                   Swarm



Enter fullscreen mode Exit fullscreen mode
  • liste des containers / tâches d'une stack


$  docker stack ps <STACK_NAME>


Enter fullscreen mode Exit fullscreen mode
  • liste des services d'une stack (un service correspond à une section du docker compose)


$ docker stack services fluend


Enter fullscreen mode Exit fullscreen mode

Service(s)

  • liste des services d'un noeud


$ docker service ls


Enter fullscreen mode Exit fullscreen mode
  • informations d'un service


$ docker service inspect --pretty <SERVICE_NAME>


Enter fullscreen mode Exit fullscreen mode
  • liste des containers d'un service avec répartition sur les noeuds


$ docker service ps <SERVICE_NAME>
$ # ou enlever le troncage du log de démarrage et la résolution DNS
$ docker service ps <SERVICE_NAME> --no-resolve --no-trunc


Enter fullscreen mode Exit fullscreen mode
  • rechargement d'un service


# forcer le redéploiement d'un service
$ docker service update --force <SERVICE_NAME>


Enter fullscreen mode Exit fullscreen mode
  • réplication d'un service


# réplication à 2 d'un service
$ docker service scale <SERVICE_NAME>=2


Enter fullscreen mode Exit fullscreen mode
  • logs d'un service


$ docker service logs <SERVICE_NAME> -f


Enter fullscreen mode Exit fullscreen mode
  • liste des configurations du cluster


$ docker config ls 


Enter fullscreen mode Exit fullscreen mode

Config(s)

  • lire une config


$ docker config inspect <CONFIG_NAME> --pretty


Enter fullscreen mode Exit fullscreen mode

Portainer

Introduction

Portainer propose une interface Web qui vous aidera à gérer votre cluster, à la place de la ligne de commande qui peut s'avérer rébarbative ou tout simplement pour simplifier la connaissance de toutes les options possible du CLI docker pour gérer le cluster ou tout simplement pour avoir une meilleure "vue" du cluster.

Comme vous avez pu le voir sur le docker CLI, il y a beaucoup d'options ou d'arguments à connaitre pour gérer son cluster, même s'il est bien de les savoir au cas où portainer venait à ne plus fonctionner.

La version présentée est la version 1.2x qui ne prend en compte que Docker ou Docker swarm. La version 2.x a grandement évolué pour gérer en plus un cluster de type Kubernetes, K8s de son petit nom qui est un autre orchestrateur de containers.

Portainer est livré sous forme d'images, soit à utiliser en "local" pour gérer votre écosystème docker, soit à déployer en tant que stack dans le cluster (ie : fichier docker-compose YAML) qui contiendra le service portainer ("serveur") et agent ("client" pour portainer), ce dernier sera déployé sur l'ensemble des workers / noeuds, manager compris.

Avec un fichier compose docker-compose.yml contenant



version: '3'

services:
  agent:
    image: portainer/agent:1.3.0
    environment:
      # REQUIRED: Should be equal to the service name prefixed by "tasks." when
      # deployed inside an overlay network
      AGENT_CLUSTER_ADDR: tasks.agent
      # AGENT_PORT: 9001
      LOG_LEVEL: debug
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    networks:
      - agent_network
    deploy:
      mode: global

  portainer:
    image: portainer/portainer:1.21.0
    command: -H tcp://tasks.agent:9001 --tlsskipverify
    ports:
      - "9000:9000"
    volumes:
      - portainer_data:/data
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    networks:
      - agent_network
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]

networks:
  agent_network:
    driver: overlay

volumes:
  portainer_data:



Enter fullscreen mode Exit fullscreen mode

Pour rappel : le mode global déploie le service (ici agent) sur tous les noeuds du cluster, pour le serveur portainer, il ne déploiera le service uniquement sur le manager swarm. Le type / driver docker utilisé est overlay, qui permet d'avoir un réseau "virtuel" entre les machines du cluster docker swarm.

Il suffit, sur notre cluster prêt (un manager / un worker) de déployer portainer avec un deploy, cela va créer la stack portainer en déploiement l'agent et le manager.



$ docker stack deploy -c docker-compose.yml portainer


Enter fullscreen mode Exit fullscreen mode

Les services de la stack portainer ont bien été déployés :



$ docker stack services portainer
ID                  NAME                  MODE                REPLICAS            IMAGE                        PORTS
65trhtm7ei17        portainer_agent       global              1/1               portainer/agent:latest
l4ucvho6ms2m        portainer_portainer   replicated          1/1                 portainer/portainer:latest   *:9000->9000/tcp


Enter fullscreen mode Exit fullscreen mode

Vous pouvez alors accéder à l'interface Portainer (certainement sur le port 9000 ou via un reverse proxy devant le cas échéant) pour initialiser le compte admin

Alt Text

Fonctionnalités utiles

Portainer propose un ensemble de fonctionnalités qui va nous soulager dans la gestion de notre cluster swarm, parmi lesquelles :

2021-09-26_12h09_29

1 : tableau de bord synthétique des stacks, images, volumes, containers, etc, avec la possibilité d'avoir une vue sur des containers actifs sur chacun des noeuds du cluster

2021-09-29_14h04_35

2021-09-29_14h05_05

2 : vous accéderez à l'ensemble de vos stacks afin d'en créer, en supprimer ou voir le détail des services déployés (containers / tasks) de la stack : redéployer une stack (pour une mise en production par exemple avec de nouvelles images), modifier le docker-compose associé qui décrit la stack avec, en plus du compose habituel docker, ses règles de déploiements, de loggin, etc

2021-10-02_13h35_52

Par exemple, sur la stack prometheus, a 4 services, décrit dans le compose (cf. Editor) : prometheus_alertmanager, prometheus_caddy, prometheus_cadvisor, prometheus_dockerd-exporter, ...

Les noms des services sont nommés selon le motif : nom_de_la_stack_nom_du_service

Nous aurons 2 onglets :

  • un général pour recharger / mettre à jour, entrer en mode console dans un container, avoir des logs ou l'information (inspect) d'un container, l'état des containers / tasks, le scaling / réplication opérées, et un onglet
  • pour éditer le docker-compose de cette stack.

2021-10-02_15h46_11

Sur une stack

1- onglet Stack :

3- : pouvoir filtrer les containers / tasks sur un service
4- : permet d'avoir dans l'ordre des icones : les logs du container (stdout / stderr des process du container, par ex. les logs nginx), les infos (inspect docker) de celui-ci : cela peut être utile pour avoir de l'informations sur d'éventuelles erreurs d'un container qui ne voudrait pas se lancer (en failed / shutdown), des stats (mémoire, CPU, flux réseau et les process lancés dans le container), accéder à la console du container
5- : permet de recharger les services de la stack, en cochant ceux souhaités : soit en recharge simple vers les noeuds (reploiement des services de la stack), soit en forçant le pull des images du compose (cf. Editor) pour redéploiement.

2021-10-03_11h52_51

1- onglet "Editor" : permet d'écrire un compose (lors d'une création d'une stack ou sa mise à jour), en Yaml, qui reprend la syntaxe du docker-compose avec en plus des sections propres à Swarm (section deploy qui donnera les règles de déploiement /réplication / contraintes, ressources, section *configs les configurations à monter lorsqu'il y en a besoin)

2021-10-03_12h37_26

2021-10-03_12h38_58

2021-10-03_12h39_10

Le bouton "Update the stack" permet de déployer toute la stack sur le cluster et ses services décrits dans le compose une fois modifié le compose

3 : les services déployés sur les nœuds du cluster et les containers / tasks associés et leur état, des actions seront possible : rechargement, suppression voire création de service (mais on passera plus volontiers par de la gestion de stack via un compose), indications de la répartition des containers (replicas)

2021-10-02_13h37_18

4 : liste des containers du cluster swarm avec la possibilité de les filtrer selon leur état ("running", "stopped", "created", "healthy") et d'opération une action dessus : en supprimer (très utile pour effectuer un ménage de temps en temps), en relancer, voire en créer ou d'entrer en mode console dans un container

2021-10-02_13h40_44

2021-10-02_13h42_11

2021-10-02_13h42_24

2021-10-02_13h42_31

5 : liste des images du cluster : vous permettra de faire un peu le ménage de temps en temps afin de supprimer les images inutilisées

2021-09-29_14h10_45

6 : volumes : les volumes dockers utilisés ou non sur les différents nœuds : cela peut être pratique de repérer les volumes inutilisés à supprimer. On peut aussi en créer mais je passe la plupart par les stacks et un docker-compose. Les volumes sont soient locaux à un noeud (par exemple, le volume portainer de portainer déployé uniquement sur un noeud manager, ou via des partages réseaux de NFS, Longhorn, ... qui permettra un accès de plusieurs noeuds sur ces partages)

2021-10-02_13h52_50

2021-10-02_13h53_05

2021-10-02_13h53_32

7 : les configurations docker qui seront utilisées dans les services, où l'on peut en créer ou en cloner (à la place d'une modification qui n'est pas possible en état). Sur une instance isolée, nous utilisons les volumes pour monter un répertoire, un fichier dans le container. Dans un environnement distribué, un cluster de machines, ces fichiers doivent être centralisé (sur le manager) afin de le distribuer sur chacun des noeuds, ce à quoi servent les configurations sauf à les inclure lors de la création de l'image, mais cela rendra moins souple leur gestion, cela dépend.

2021-09-29_17h31_54

Par exemple, la configuration fluen-elasticsearch-conf.v2 aura ce type de contenu



<source>
  @type  forward
  @id    input1
  @label @mainstream
  port  24224
</source>

<filter **>
  @type stdout
</filter>

<label @mainstream>
  <match api-prod>
    @type copy
    <store>
        @type file
        @id   output_docker1
        path         /fluentd/log/api-prod.*.log
        symlink_path /fluentd/log/api-prod.log
        append       true
        time_slice_format %Y%m%d
        time_slice_wait   1m
        time_format       %Y%m%dT%H%M%S%z
        compress gzip
        utc
       format json
    </store>
    </match>
</label>


Enter fullscreen mode Exit fullscreen mode

La config fluent-elasticsearch-conf.v2 pour être utilisée dans une stack comme suit, grâce à la section configs :



version: "3.6"
configs: # déclaration de la config à prendre
  fluent-elasticsearch-conf.v2:
    external: true

services:
  fluentd:
    image: fluend:latest
    volumes:
      - /home/root/data/logs:/fluentd/log
    ports:
      - "24224:24224"
      - "24224:24224/udp"
    networks:
      - net
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.labels.type == fluent]
    configs: # montage de la config vers la target
      - source: fluent-elasticsearch-conf.v2
        target: /fluentd/etc/fluent.conf


Enter fullscreen mode Exit fullscreen mode

8 : vue synthétique des nœuds du cluster et de leur état, permettra de changer leur état ("Active" => "Drain" notamment) ou d'ajouter / modifier des labels sur les nœuds, ces labels pourront servir pour les règles de déploiement d'un service , sur ses contraintes (cf. deploy d'un service dans le compose)

2021-09-29_14h27_10

2021-09-29_14h30_59

Par exemple, le label nginx avec une valeur true pourra être une contrainte pour un service nginx pour son déploiement : déploie l'image nginx sur 3 noeuds ayant un label nginx avec une valeur à true

2021-10-03_17h00_00

9 : gestion des dépôts d'images docker : soit DockerHub, soit le registry de votre écosystème : les images des stacks pourront alors être prise du registry paramétré

2021-09-29_17h29_49

Conclusion

Docker swarm peut être mis en place relativement rapidement, bien entendu, charge à vous de construire vos images et les VM qui hébergeront manager et workers.

Pour sa gestion, portainer permet de gérer votre cluster directement en ligne, pour la majeure partie des fonctionnalités de swarm, et...c'est très appréciable.

Katacoda propose d'essayer Portainer directement en ligne, avec les VM provisionnées, un bac à sable pour découvrir ces technologies : https://www.katacoda.com/portainer/scenarios/deploying-to-swarm

Top comments (6)

Collapse
 
deviantony profile image
Anthony Lapenna

Super article, très détaillé, bravo! Je peux te demander pourquoi tu as préférer faire cette présentation avec une version plutôt ancienne de Portainer (1.21) ?

La version 2.x n'apporte pas simplement des changements pour supporter Kubernetes mais aussi pas mal de features (en autre la possibilité pour Portainer de déployer une application "synchronisée" directement depuis Git) et de bugfix pour Docker/Swarm.

Top en tout cas :)

Collapse
 
zorky profile image
DUVAL Olivier • Edited

Merci, me suis appliqué pour ce billet :)

J'ai axé sur la 1.2x car "je" ne suis pas passé à la 2.x et donc je voulais rester sur ce que je connaissais, proche de la réalité.

C'est prévu de passer à la 2.x, chantier à programmer (upgrade des machines, docker, ....et de portainer), pas mal de choses à faire en amont avant.

Merci de ton retour concernant la version 2, intéressant oui

Collapse
 
deviantony profile image
Anthony Lapenna

Cool, hésites pas à m'envoyer un email si tu as des questions!

Thread Thread
 
zorky profile image
DUVAL Olivier

Oui, et je vois que j'ai à faire à la bonne personne en voyant ton profil LinkedIn :)

Beau produit Portainer ! ça nous facilite grandement la vie

Thread Thread
 
zorky profile image
DUVAL Olivier

@deviantony je peux te contacter sur quel email ou via LinkedIn ?

J'ai une interrogation sur l'alignement des versions entre le portainer "manager" et ses agents :)

Thread Thread
 
deviantony profile image
Anthony Lapenna

Woops j'ai raté cette notification, tu peux me contacter sur mon LinkedIn et je te partagerai mon email.