Le Labo #9 | Déploiement automatisé et surveillance de microservices

Introduction

Dans de précédents articles, nous avions abordé les technologies suivantes :

  • Docker
  • Weave
  • Consul
  • Ansible

Ces technologies permettent de créer des micro-services et de surveiller leur bon fonctionnement. Ceci s’inscit dans une démarche ‘DevOps’, lorsque du code permet, comme nous allons le démontrer, de créer toute une infrastructure fonctionnelle.

Nous allons effectuer les tâches suivantes :

  • Description des conteneurs à déployer dans un fichier utilisable par docker-compose,
  • Déploiement d’un réseau pour conteneurs Docker à l’aide de Weave,
  • Déploiement des conteneurs puis installation des paquets automatisée à l’aide d’Ansible,
  • Découverte et surveillance des services à l’aide de Consul

Avant d’aller plus loin…

Nous allons avoir besoin des éléments suivants :

  • 1 serveurs : mida-dockh1 - Ubuntu - (IP : 81.2.243.226)
  • Docker-Compose, Weave, Consul et Ansible installés sur le serveur mida-dockh1

Docker - Préparation et déploiement

L’image docker

Dans cet exercice, nous allons utiliser l’image docker rastasheep/ubuntu-ssh:14.04.
L’avantage de cette image est qu’un serveur SSH est préinstallé, ce qui se révèlera utile lors du déploiement des paquets à l’aide d’Ansible ainsi que lors du démarrage des services sur les conteneurs hadoop.

Docker Compose

Nous allons avoir besoin des éléments suivants pour mener à bien cet exercice :

  • Les ports 8300, 8301, 8302, 8400, 8500 et 8600 permettent à Consul de fonctionner (communication entre serveurs et interface web),
  • Le port 80 pour le conteneur serveur web,
  • Le port 3306 pour le conteneur serveur mysql,
  • les ports 50010, 50020, 50070, 50075, 50090, 19888, 8030, 8031, 8032, 8033, 8040, 8042, 8088 et 9000: Tous ces ports sont nécessaire au bon fonctionnement d’un serveur Hadoop, au déploiement de HDFS, de MapReduce et de Yarn.
  • Le port 22 pour SSH.

Si ces ports ne sont pas précisés dans le fichier docker-compose.yml lors du déploiement des conteneurs, les conteneurs ne disposeront pas de translation de ports vers les ports du serveur hôte. De plus, nous aurons besoin du dossier /root/.ssh contenant les clé SSH et des liens suivants entre les serveurs :

  • web -> db
  • hadoopnn -> hadoopdn

Enfin, lors du déploiement des namenode et datanode Hadoop, nous aurons aussi besoin des hostname des conteneurs.

Déploiement de l’infrastructure

Le déploiement se fait à l’aide de la commande docker-compose up -d
Pour afficher l’ensemble des conteneurs déployés, exécutons la commande docker-compose ps, ce qui permettra de connaître les ports ssh translatés de chaque conteneurs.

Ansible - Préparation et déploiement

Nous allons effectuer le déploiement des paquets, archives et fichiers de configuration nécessaires à l’aide d’Ansible, ce qui permettra d’automatiser cette étape et, par conséquent, de gagner du temps. Lors de cette étape, nous aurons obligatoirement besoin des deux éléments suivants :

  • Le fichier d’inventaire d’Ansible (hosts), il se trouve dans /etc/ansible.
  • Le playbook. Dans notre cas, nous allons créer plusieurs rôles puisque nous allons déployer quatres types de serveurs : Consul, Web, MySQL et Hadoop.

Le fichier d’inventaire

Le fichier d’inventaire Ansible doit contenir, au moins l’alias du serveur et son adresse IP.
Dans notre cas, le déploiement des paquets à l’aide d’Ansible se fera sur des conteneurs Docker reliés en réseau via Weave. En sachant que le serveur hôte dispose de l’adresse IP 172.17.0.1, les conteneurs obtiennent les IP qui suivent en fonction de leur ordre de création (et non suivant leur ordre de déclaration dans le fichier docker-compose.yml).

Il est d’ailleurs possible d’automatiser la création du fichier /etc/ansible/hosts nécessaire à l’aide de la commande suivante :
for x in $(docker ps --format "{{.Names}}" --filter name="root"); do echo "$x " | sed 's/^.....//' | sed 's/...$//' | sed 's/^/[/' | sed 's/$/]/' && docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $x ; done > /etc/ansible/hosts

Le playbook et les rôles

Notre fichier playbook devra contenir les paquets, archives et fichiers de configurations.
Chaque type de configuration sera organisée en rôle dans le playbook d’Ansible.

Nous allons créer 4 rôles : webserver, database, hadoop et consul. Notre fichier /etc/ansible/hosts contient les informations nécessaires au déploiement de paquets sur tous les conteneurs ainsi que sur le serveur hôte, dans le but de démarrer le déploiement des conteneurs directement à l’aide d’ansible.

Les rôles webserver et database ne nécessitent aucune intervention post-deploiment, contrairement aux autres rôles. Nous détaillerons plus tard les interventions à effectuer.

Le playbook

---
- hosts: web
  roles:
    - webserver
    - consul
- hosts: db
  roles:
    - database
    - consul
- hosts: hadoopnn
  roles:
    - hadoop
    - consul
  tasks: 
    - name: 1. Hadoop NameNode Config
      shell: echo hadoopdn > /root/hadoop/etc/hadoop/slaves
    - name: 2. Hadoop Namenode Config
      shell: echo localhost > /root/hadoop/etc/hadoop/masters
- hosts: hadoopdn
  roles:
    - hadoop
    - consul
  tasks: 
    - name: Hadoop DataNode Config
      shell: echo "localhost" > /root/hadoop/etc/hadoop/slaves

Concerant le rôle hadoop, nous avons deux situations différentes :

  • Un serveur hadoop NameNode sur lequel sera déployé le formattage HDFS, ainsi que les rôles dfs et yarn,
  • Un serveur hadoop DataNode sur lequel sera déployé le rôle datanode.

C’est pour cela que le playbook contient des tâches supplémentaires pour le conteneur hadoopnn relatives au fichier de configuration slaves (ainsi que le fichier /etc/hosts).

Le rôle Consul

---
- name: install wget
  apt: name=wget state=present
- name: Install unzip
  apt: name=unzip state=present
- name: Install Consul
  shell: cd /root && wget https://releases.hashicorp.com/consul/0.6.1/consul_0.6.1_linux_amd64.zip && unzip consul_0.6.1_linux_amd64.zip -d /usr/local/bin/consul
- name: 4. Add file to environment
  shell: echo "PATH=$PATH:/usr/local/bin/consul" >> /root/.bashrc

Le rôle webserver

---
- name: install Apache
  apt: name=apache2 state=present
- name: install PHP module for Apache
  apt: name=libapache2-mod-php5 state=present
- name: start Apache
  service: name=apache2 state=running enabled=yes
- name: install Hello World PHP script
  copy: src=index.php dest=/var/www/index.php mode=0664
- name: Check file directory
  shell: mkdir -p /home/consul/service
- name: File Consul checks
  copy: src=services.json dest=/home/consul/service/services.json mode=0664

Le rôle database

---
- name: Install mysql server package
  apt: name=mysql-server state=present
- name: Start Mysql Service
  service: name=mysql state=started enabled=true
- name: Install python Mysql package #required for mysql_db tasks
  apt: name=python-mysqldb state=present
- name: Check file directory
  shell: mkdir -p /home/consul/service
- name: File Consul checks
  copy: src=services.json dest=/home/consul/service/services.json mode=0664

Le rôle hadoop en lui même contient toutes les tâches relatives aux fichiers de configuration core-site, hdfs-site, mapred-site et yarn-site que vous devrez modifier par la suite.

Le rôle hadoop

---
- name: Install Java-jre
  apt: name=default-jre state=present
- name: Install Java-jdk
  apt: name=default-jdk state=present
- name: Install tar
  apt: name=tar state=present
- name: Download hadoop 
  shell: cd /root && wget http://mirrors.ircam.fr/pub/apache/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz && tar xzf /root/hadoop-2.7.1.tar.gz && mv /root/hadoop-2.7.1 /root/hadoop
- name: Environment file
  template: src=.bashrc dest=/root/.bashrc
- name: Check file directory
  shell: mkdir -p /home/consul/service
- name: File Consul checks
  copy: src=services.json dest=/home/consul/service/services.json mode=0664
- name: Hadoop Config files - core-site.xml
  copy: src=hadoop_config/core-site.xml dest=/root/hadoop/etc/hadoop/core-site.xml  
- name: Hadoop Config files - hdfs-site.xml
  copy: src=hadoop_config/hdfs-site.xml dest=/root/hadoop/etc/hadoop/hdfs-site.xml
- name: Hadoop Config files - mapred-site.xml
  copy: src=hadoop_config/mapred-site.xml dest=/root/hadoop/etc/hadoop/mapred-site.xml
- name: Hadoop Config files - yarn-site.xml
  copy: src=hadoop_config/yarn-site.xml dest=/root/hadoop/etc/hadoop/yarn-site.xml
- name: hadoop tmp directory
  shell: mkdir -p /root/hadoop/namenode && mkdir -p /root/hadoop/datanode
- name: Modify hadoop-env.sh
  shell: sed -i '/JAVA_HOME/d' /root/hadoop/etc/hadoop/hadoop-env.sh && echo 'export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64' >> /root/hadoop/etc/hadoop/hadoop-env.sh

Le déploiement

Pour déployer tout cela, nous allons employer la commande ansible-playbook playbook.yml.
Ce qui permettra d’automatiser l’installation des paquets et des archives nécessaires.

Une fois le déploiement terminé, le terminal affichera ce qui suit :

PLAY RECAP ********************************************************************
172.17.0.2                 : ok=10   changed=8    unreachable=0    failed=0
172.17.0.3                 : ok=21   changed=18   unreachable=0    failed=0
172.17.0.4                 : ok=10   changed=7    unreachable=0    failed=0
172.17.0.5                 : ok=19   changed=16   unreachable=0    failed=0

Signifiant que tout s’est bien passé et que notre infrastructure est fonctionnelle…ou presque. Il ne manque que quelques commandes à exécuter sur les conteneurs hadoopnn et hadoopdn.

Sur le Namenode Hadoop

Il faudra exécuter les commandes suivantes :

  • Démarrer le formattage en HDFS :
    hadoop/bin/hadoop namenode -format
  • Démarrage des services dfs et yarn :
    hadoop/sbin/start-dfs.sh
    hadoop/sbin/start-yarn.sh
  • Vérifier l’état des services à l’aide de la commande jps

    root@localhost:~# jps  
    7101 SecondaryNameNode
    7256 ResourceManager
    6928 NameNode
    7323 Jps
    

Sur le Datanode Hadoop

Si tout s’est bien passé sur le conteneur Namenode Hadoop, l’exécution de la commande jps devrait afficher le service Datanode, cependant il est toujours possible de le vérifier d’une autre manière grâce à la commande :
hadoop/sbin/hadoop-daemon.sh start datanode

Afin d’afficher ce qui suit dans le terminal :

datanode running as process 6764. Stop it first.

Consul

Dans notre cas, Consul va nous servir à surveiller le fonctionnement des conteneurs grâce aux fichiers de services copiés sur chacun d’eux lors du déploiement.
La première étape va consister à démarrer Consul et à servir l’interface web sur le serveur hôte à l’aide de la commande suivante : consul agent -data-dir consul -server -bootstrap -client 81.2.243.226 -advertise 172.17.0.1 -ui-dir /home/web_ui/ &

Ensuite, sur chaque conteneur, nous rejoindrons le service Consul démarré sur le serveur hôte à l’aide des commandes suivantes :

  • Sur webserver :
    consul agent -data-dir /root/consul -client 172.17.0.2 -advertise 172.17.0.2 -node webserver -config-dir /home/consul/service -join 172.17.0.1
  • Sur database :
    consul agent -data-dir /root/consul -client 172.17.0.4 -advertise 172.17.0.4 -node database -config-dir /home/consul/service -join 172.17.0.1
  • Sur hadoopnn :
    consul agent -data-dir /root/consul -client 172.17.0.3 -advertise 172.17.0.3 -node hadoopnn -config-dir /home/consul/service -join 172.17.0.1
  • Sur hadoopdn :
    consul agent -data-dir /root/consul -client 172.17.0.5 -advertise 172.17.0.5 -node hadoopdn -config-dir /home/consul/service -join 172.17.0.1

Une fois cette étape effectuée, nous allons pouvoir consulter l’interface web et vérifier que les quatre conteneurs y sont bien enregistrés.
Pour y accéder, il faudra ouvrir l’adresse IP du serveur, suivi du port 8500 et du dossier ui.

Conclusion

Nous vous avons présenté un exemple de Service Discovery à l’aide de Consul, Ansible et Docker.
Comme nous l’avions expliqué dans un précédent document, Consul est extensible et s’adapte à son environnement, il est tout à fait possible, dans l’état actuel de notre environnement de test, d’ajouter plusieurs service et de les faire reconnaître par Consul afin de surveiller leur bon fonctionnement.