Catégories
Application Paramétrage Uncategorized

Surveillance des services avec prometheus et blackbox

La mise en place du node exporter pour apache me permet de surveiller mon reverse proxy. Je peux ainsi m’assurer que mon infra est bien accesssible.

Cela ne m’assure pas que les services qui sont derrière le reverse proxy sont bien accessibles.

Définition de l’accessibilité

Que le reverse proxy fonctionne est une condition nécessaire, que le processus du service backend fonctionne est une nécessité également mais si par exemple le DNS ne fonctionne pas, le service n’est plus accessible. Plus généralement un service est accessible si il l’est pour son utilisateur. La métriques doit donc utiliser une sonde qui se place comme un utilisateur.

Diagnostique de non accessibilité

Cela consistera pour moi à vérifier que les url des services sont bien accessibles au travers la brique la plus externe de mon architecture. Cela revient à passer par l’IP publique de ma box soit l’url publique de mes services. Pour cela un blackbox sur l’hôte permettra de verifier les url publiques des services. De manière générale, un blackbox sera installé sur chaque neoud de l’infrastructure: l’hôte principal et les 2 VM à conteneurs.

En cas d’échec la cause du problème restera encore à chercher. Elle peut provenir de n’importe quelle brique des couches sous-jacentes: box, reverse proxy, VM, service, base de données ?

Un blackbox par hôte

Le rapidite du diagnostique de la non accessibilité demande des métriques sur les briques profondes. La box ne peut pas vraiment être testée car toute l’architecture est derrière celle-ci. Le reverse proxy est déjà testé par l’exporter apache. Pour les VM on pourra utiliser le ping de blackbox depuis la machine hôte. Un test via la blackbox de l’hôte vers l’url local des services (comme utilisé dans le reverse proxy) pourra vérifier la liaison entre le reverse proxy et les services. Enfin les blackbox sur les VM pourra vérifier l’ accessibilité des services en local. Pour ce qui est du diagnostique des bases de données, comme celles-ci ne sont pas exposées vers l’exterieur, je ne peux pas les tester depuis les blackbox de l’hôte.

Un blackbox par nœud

Mise en place des blackbox

L’opération est des plus simples. Il suffit d’ajouter le service prom/blackbox-exporter dans mon application prom-node qui regroupe tous les services distanciés sur chacun de mes noeuds.

version: "3.7"
services:
  blackbox_exporter:
    image: 'prom/blackbox-exporter'
    restart: always
    ports:
      - '9115:9115'
    volumes:
      - blackbox_conf:/etc/blackbox_exporter
....
volumes:
  blackbox_conf: {}

Je mets en volume le repertoire de configuration du conteneur blackbox-exporter car cdans mon cas j’ai dû forcer l’ipv4. Oui v4 !

Forcage IPv4

En faisant un test depuis l’hôte et en passant l’argument debug=true je voyais une erreur remontée par un composant Go qui n’arrivait pas à acceder aux urls de mes services car il prenait systématiquement l’IPv6 associé. Malheureusement cela ne marche pas même après avoir activé l’IPv6 dans le démon docker. Pour faire simple j’ai choisi de forcer l’IPv4. Comme j’ai monté la configuration en volume il suffit d’aller modifier sur l’hôte le fichier /var/lib/docker/volumes/prom-node_blackbox_conf/_data/config.yml

modules:
  http_2xx:
    prober: http
    http:
       preferred_ip_protocol: ip4

Configuration de prometheus

Pour configurer prometheus il suffit de suivre à lettre la documentation de blackbox. Remarquons la subtilité qui consiste à changer le point d’appel par l’adresse du blackbox et passer le point d’appel en paramètre car au final c’est le blackbox qui interroge le point d’appel.

- job_name: 'services depuis internet'
  metrics_path: /probe
  params:
     module: [http_2xx] # Look for a HTTP 200 response.
  static_configs:
  - targets:
    # - http://prometheus.io # Target to probe with http.
    # - https://prometheus.io # Target to probe with https.
    # - http://example.com:8080 # Target to probe with http on port 8080.
     - https://blog.bressure.net
     - https://kitejust4fun.bressure.net
     - https://mattermost.bressure.net
     - https://www.kitejust4fun.fr
     - https://owncloud.bressure.net
     - https://bikejust4fun.bressure.net
     - https://www.cramayailes.fr
     - https://matomo.bressure.net
     - https://gitlab.bressure.net
     - https://registry.bressure.net
     - https://prometheus.bressure.net
     - https://grafana.bressure.net
  relabel_configs:
     - source_labels: [__address__]
       target_label: __param_target
     - source_labels: [__param_target]
       target_label: instance
     - target_label: __address__
       replacement: 192.168.0.12:9115

Lorsque je veux vérifier que la liaison avec les backend est fonctionnelle, j’utilise directement les adresses IP dans un autre job et cela donne:

- job_name: 'services depuis infra'
  metrics_path: /probe
  params:
     module: [http_2xx] # Look for a HTTP 200 response.
  static_configs:
  - targets:
    # - http://prometheus.io # Target to probe with http.
    # - https://prometheus.io # Target to probe with https.
    # - http://example.com:8080 # Target to probe with http on port 8080.
    # blackbox infra
     - http://192.168.0.12:9115
    # blackbox production
     - http://192.168.122.30:9115
    # blog pro
     - http://192.168.122.30:8081
    # bikejust4fun
     - http://192.168.122.30:8082
    # kitejust4fun blog
     - http://192.168.122.30:8083
    # kitejust4fun asso
     - http://192.168.122.30:8084
    # matomo
     - http://192.168.122.30:8085
    # cramayailes
     - http://192.168.122.30:8086
    # owncloud
     - http://192.168.122.30:8087
    # mattermost
     - http://192.168.122.30:8088
    # gitlab, registry
     - http://192.168.0.12:8080
    # prometheus
     - http://192.168.0.12:9090
    # grafana
     - http://192.168.0.12:3000


  relabel_configs:
     - source_labels: [__address__]
       target_label: __param_target
     - source_labels: [__param_target]
       target_label: instance
     - target_label: __address__
       replacement: 192.168.0.12:9115

Comme les instances qui sont relatives au même service, par exemple ce blo sont référencées par des url différentes https://blog.bressure.net ou http://192.168.122.30:8081, il faudra faire une gymnastique dans la tableau de bord. Pour simplifier l’utilisation des métriques, je préfère ajouter un label spéciale que j’appelle service et qui me permettra de regrouper les métriques d’un même service. Pour cela j’utilise la fonction de modification des label déjà vu pour l’astuce du blackbox. Ainsi pour que mon blog j’ajoute le label service=blog par la configuration:

relabel_configs:
     - source_labels: [__address__]
       target_label: __param_target
     - source_labels: [__param_target]
       target_label: instance
     - target_label: __address__
       replacement: 192.168.0.12:9115 # The blackbox ex
     - source_labels: [instance]
       regex: 'http\:\/\/192\.168\.122\.30\:8081'
       replacement: 'blog'
       target_label: service

Test de connectivité

Le test HTTP est parfois non pertinent quand on veux juste vérifier que quelques chose répond. Il est alors suffisant de tester qu’une connexion TCP est possible. Je fais alors un job dans Prométheus:

 job_name: 'connection depuis infra'
  metrics_path: /probe
  params:
     module: [tcp_connect]
  static_configs:
  - targets:
    # - http://prometheus.io # Target to probe with http.
    # - https://prometheus.io # Target to probe with https.
    # - http://example.com:8080 # Target to probe with http on port 8080.
    # blackbox infra
     - 192.168.0.12:9115
    # blackbox production
     - 192.168.122.30:9115
    # blog pro
     - 192.168.122.30:8081
    # bikejust4fun
     - 192.168.122.30:8082
    # kitejust4fun blog
     - 192.168.122.30:8083

La prochaine étape sera de mettre en place des alertes quand les services ne sont plus disponibles.

Catégories
Application Paramétrage

Surveillance apache avec Prometheus

Dans le remplacement de Munin par Prometheus, les indicateurs systèmes (OS et docker) sont en place. Avant de supprimer munin de mes machines, il reste encore quelques éléments à reprendre commme les métriques de:

  • Apache (frontal et reverse proxy)
  • KVM
  • Mail
  • Fail2ban
  • Queue d’impression (utile ?)

Commençons par la surveillance de apache

Apache exporter

Sur le site de Prometheus on trouve une liste de logiciels complementaires poir exporter des métriques des composants connus tels que apache. De nombreuses version de cet exporter pour apache sont disponibles, sur github notament, mais je retiendrais les 3 versions suivantes:

  • httpd_exporter de https://github.com/kelein/httpd_exporter
  • apache_exporter de https://github.com/Lusitaniae/apache_exporter
  • prometheus-apache-exporter en paquet debian

Compiler avant d’utiliser…. pas user-friendly

En tant qu’informaticien et développeur à la base la compilation est une étape qui ne devrait pas effrayer. Cela tombe bien car la version de kelein est un exporter dockerisé et demande à faire une compilation avant se pouvoir etre utilisée.

Compiler en docker c’est quoi ?

Dans les projet docker, la phase build consiste à fabriquer l’image avant de pouvoir l’exécuter. Cette phase est normale lors du développement du logiciel mais ne devrait pas être imposée à l’utilisateur du logiciel.

Quand je vais acheter une voiture, elle n’est pas fournie en kit que je dois monter

Differentes stratégies de constructions

Comme l’informaticien est un utilisateur que la compilation n’effrait pas, un petit docker build . ne va pas nous gêner. Si le httpd_exporter de kelein se construit parfaitement du premier coût c’est parce qu’il embarque dans son Dockerfile tout ce qu’il faut: compilation du source en langage Go dans une image intermediaire et création de l’image finale.

httpd_exporter pas compatible avec les tableaux de bord Grafana

Le test de l’image obtenue est concluant pour peu que l’indique bien l’url cible du serveur apache accessible depuis le conteneur via l’argument

--scrape_uri="https://perso.bressure.net/server-status"

Malheureusement les métriques sont exportées sous des noms qui ne ne sont pas ceux attendus par les tableaux de bord Grafana disponibles en libre service. Ces derniers se basent sur l’exportation faite par apache_exporter de Lusitaniae.

Lusitaniae

Cette autre version semble être la plus ancienne dans la sphère Docker. De plus elle est reprise dans le paquet prometheus-apache-exporter de Debian. C’est un signe de qualité et utiliser un exporteur à la fois disponible en version conteneurisés et native permettrait de passer de l’un à l’autre plus simplement.

Autre stratégie de construction

Comme pour httpd_exporter il faut faire un buils avant d’utiliser. Je me sens comme revenu dans en 1998 où pour utiliser le mode graphique sous Linux il fallait parfois encore compiler et jouer du makefile… Cette fois-ci je déchante car le Dockefile attend un binaire dont on a bien le source Go mais pas les instructions de build…. sauf dans la documentation. Il eu été préférable de les avoir dans le source du projet même et idéalement dans un Dockerfile.

On est informaticien ? Alors on compile via les instructions données dans la documentation. Je choisi donc une version de Go un peu récente et lance la compilation via une image docker de Go. La déception ne tarda pas à venir. La construction échoue sur un problème de dépendance dans la définition du projet.

Docker c’est un peu la création de paquet

Cette mésaventure soulève un aspect non négligeable de docker. Contrairement à l’écosystème Java où un seule langage et une seule méthode (si on se réfère au temps glorieux de J2EE) permettent de construire, d’empaqueter et déployer une application, docker offre certe de repondre au problème des dépendances et d’intégration mais il ressemble sur bien des aspects à un mécanisme de paquet des distribution Linux.

Compétences multi-langage requise

En effet le mainteneur d’un paquet doit savoir compiler le logiciel à partir de son source. Cela necessite donc de connaître les mecanismes de constructions propres au langage dans lequel est écrit l’application. Dans le cas des exporter pour appache c’est le langage Go. Pour pouvoir construire l’image il ne suffit pas juste connaitre Docker mais il faut également connaitre Go. J’ai egalement expérimenté le même soucis avec un projet Rails dont l’écosystème avec les Gemfiles m’est totalement étranger.

Fournir des images au lieu des sources

Comme je vois Docker comme une couche au dessus de l’application permettant à celle-ci de s’exécuter sans que l’utilisateur ait à se soucier des dependances où autres plomberie d’intègration, cela me conforte dans l’idée de la nécessité de fournir des images à l’utilisateur et non des souces pour la commande docker build.

Paquet debian prometheus-apache-exporter

Heureusement que d’autres savent mieux que moi comment compiler des sources Go. Debian fournit d’ailleurs un paquet binaire de l’exporter apache basé sur Lusitaniae.

Cherchant la simplicité et puisque mon apache n’est de toute façon pas encore dockerisé, je me suis rabattu sur cette version native de l’exporter. Cela n’est pas sans conséquence car étant installé en service systemd le paramètrage de l’url nécessite de s’accomoder d’un paramétrage propre à l’OS. On fait du système.

Paramètrage de l’exporter apache en service

En allant consulter la documentation Debian, j’apprends que le fichier définition du service installé par le paquet est dans /lib/systemd/system/prometheus-apache-exporter.service et non pas dans /etc/systemd/system/

En allant voir ce fichier on découvre qu’un fichier de variable est utilisé et que la variable ARGS permettra de paramétrer notre exporter.

EnvironmentFile=/etc/default/prometheus-apache-exporter ExecStart=/usr/bin/prometheus-apache-exporter $ARGS

Il ne reste plus qu’à aller ajouter dans /etc/default/prometheus-apache-exporter le paramètre

ARGS='-scrape_uri https://perso.bressure.net/server-status/?auto'

Notez que l’argument ne contient qu’un seul tiret dans le service et deux en ligne de commande docker. Je passe sous silence la sécurisation qui rend l’url du status de apache accessible seulement en local.

Tableau de bord grafana

A ce stade les métriques suivantes sur apache peuvent être disponibles dans Prometheus. Il suffit de déclarer un nouveau job pointant sur le endpoint offert par l’exporter. Par exemple dans le fichier prometheus.yml:

- job_name: apache
honor_timestamps: true
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- 192.168.0.12:9117

On peut alors avoir ce genre de graphique:

Graphique prometheus d’une métrique apache

En utilisant un tableau de bord en libre service sur le site de grafana, on peut avoir ce genre de graphiques sans aucune configuration supplémentaire:

Tableau de bord Grafana pour apache

On a réussi facilement à remplacer Munin par Prometheus pour surveiller apache. La prochaine étape sera de passer sous Prometheus la surveillance des VM. La suite au prochain billet.

Catégories
Application Paramétrage

Les alertes avec Prometheus

Remplacer munin par Prometheus se serait complet sans la partie envoi des alertes. Dans mon cas un simple mail suffira.

Alertmanager

Comme tout est dockerisé chez moi, je vais donc ajouter dans mon application de monitoring le service alertmanager. Le rôle de l’alertmanager est de recevoir les demandes de notification quand une métrique a une valeur donnée. Les fonctions de l’alertmanager sont entre autres de temporiser, relayer ou inhiber les notifications.

Grafana peut également envoyer des notifications mais comme je l’ai déjà mentionné, je ne vais l’utiliser que pour sa fonction de tableau de bord. Par ailleurs Grafana peut envoyer des alertes vers l’alertmanager donc ce dernier jouera parfaitement son rôle en recevant les demandes de notification de la part de Promethéus ou Grafana.

Alertes

Créer des alerte est relativement simple. Si munin est fournit avec beaucoup de plugin déjà éprouvés, il va falloir ajouter les alertes de bases comme: la saturation cpu, mémoire ou disque.

Paramétrage d’une destination mail dans l’alertmanager

Comme je définis un volume pour le conteneur alertmanager via mon fichier docker-compose.yml de l’appication de monitoring

   alertmanager:
      image: 'prom/alertmanager'
      restart: always 
      volumes:
        - alertmanager_conf:/etc/alertmanager

Il suffit depuis l’hôte docker de modifier le fichier /var/lib/docker/volumes/monitoring_alertmanager_conf/_data/alertmanager.yml

Voici le contenu qui permet de configurer l’envoi de mail, à modifier pour adapter à votre configuration de mail !

global:
  resolve_timeout: 5m
  smtp_smarthost: 'mon.serveur.smtp.com:587'
  smtp_from: 'monadresse@mail.com'
route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'mail_to_admin'
receivers:
- name: 'web.hook'
  webhook_configs:
  - url: 'http://127.0.0.1:5001/'
- name: 'mail_to_admin'
  email_configs:
  - to: destinataire@mail.com
inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'instance']

Configuration de prometheus pour utiliser l’alertmanager

L’application de monitoring utilise une image personnalisée de prométheus dont le seul but est de fournir une configuration de base visible dans le fichier prometheus.yml.

La partie importante est celle-ci:

rule_files:
  - '/etc/prometheus/rules/*'
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['alertmanager:9093']
    scheme: http
    timeout: 10s
    api_version: v1

Ajout d’un alerte d’occupation disque

Dans le fichier de configuration prometheus.yml on a indiqué de prendre tous les fichiers du répertoire /etc/prometheus comme règles. Il suffit alors d’ajouter dans ce répertoire les fichiers de règles des alertes. Comme prométheus est dans un conteneur, il faudra aller sur machine hôte dans le répertoire /var/lib/docker/volumes/monitoring_prometheus_conf/_data/rules/

Voici par exemple le contenu d’un fichier qui donne l’alerte quand l’occupation disque dépasse 80%

groups:
- name: disk
  rules:
  - alert: diskUsage
    expr: 1 - node_filesystem_free_bytes / node_filesystem_size_bytes > 0.8
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: consommation disque eleve

Règles enregistrées

On pourra factorisé les calculs de métriques qui peuvent être coûteux et partager le résultat dans des définitions d’alerte. Ainsi dans l’exemple suivant on calcul un seul fois l’occupation d’overcommit et 2 alertes réutilisent le résultat:

groups:
- name: memoire
  rules:
  - record: memoire:overcommit
    expr: node_memory_Committed_AS_bytes / (node_memory_MemTotal_bytes + node_memory_SwapTotal_bytes) 
  - alert: overcommit
    expr: memoire:overcommit > 0.9
    for: 10m
    labels:
      severity: critical
    annotations:
      summary: surconsommation memoire
  - alert: overcommit
    expr: memoire:overcommit > 0.8 and memoire:overcommit <= 0.9
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: surconsommation memoire

L’étape suivante sera la surveillance de l’espace disque occupé par docker. Il peut être intéressant de suivre l’évolution de cette métrique et se sera l’occasion d’apprendre à étendre le node-exporter de prométheus. La suite au prochain billet…

Catégories
Application Paramétrage

Docker sur VM et réseau

J’ai eu surprise de voir que ma surveillance ne fonctionnait plus avant hier. Pourtant d’après la capture prise vendredi soir tout semblait fonctionner.

Il y a 2 jours la connexion entre mon conteneur Prometheus et les conteneurs prom-node et cAdvisor situés sur des VM étaient devenu impossible. Toute la configuration reseau est du standard à savoir:

  • conteneur avec reseau bridge dédié par défaut avec docker-compose
  • VM avec reseau NAT par défaut avec virsh/KVM
connexion conteneur sur hôte vers conteneur sur VM impossible

Un test avec telnet m’a alors montré que depuis la machine hôte on pouvait joindre les conteneurs sur VM avec l’IP des VM gérée par KVM. Cependant depuis le conteneur sur l’hôte si l’accès à l’hôte lui-même était possible, un telnet vers les IP des VM échouait

Il faut dire que tout le paramètrage réseau mis en place par KVM et docker est un peu mystèrieux pour moi et je fais confiance à ceux qui savent plus que moi paramétrer le réseau…

Solution rapide

Comme depuis l’hôte la connexion vers les conteneurs sur VM NAT est possible alors une solution rapide est d’indiquer à Docker de mettre le conteneur Prometheus dans un réseau de type hôte. Dans le fichier docker-compose.yml au même niveau que image ajouter:

network_mode: "host"
Solution rapide, passer par l’hôte

Solution pérenne : le réseau overlay

La solution précédente enlève l’isolation reseau du conteneur Prometheus avec l’hôte et cela me gêne. De plus le conteneur grafana ne pouvait plus accéder à prometheus par son nom. Il fallait le faire passer par l’IP de l’hôte.

Une autre solution serait de mettre le conteneur prometheus dans une VM, car les VM se voient entre-elles par défaut. Un test telnet m’avait montré que les conteneurs d’une VM pouvait via l’IP des autres VM accéder aux conteneurs de ces VM.

Cette autre solution me gêne également car elle fait reposer la connectivité sur un paramétrage réseau géré par virsh/KVM. Idealement on voit aisément que les conteneurs dévolus au monitoring doivent être dans le même réseau et ce réseau doit chevaucher plusieurs démons docker sur des hôtes différents. C’est un réseau overlay !

Solution idéale : le reseau overlay

La mise en place du reseau overlay est une opération un peu complexe car il faut initialiser un neoud swarm maître sur l’hôte de prometheus, créer un réseau overlay dédié au monitoring, sur les hôtes de cAdvisor/prom-node il faut déclarer docker comme membre du swarm et enfin indiquer des les fichiers docker-compose que tous les conteneurs doivent utiliser le reseau overlay précédemment créé. Ici on avait créé un réseau appelé monitoring-net

networks:
  default:
    external:
       name: monitoring-net

Je ne suis pas allé au bout de la solution idéale de l’overlay car en créant seulement le reseau overlay et en y mettant prometheus, tout est retombé en marche. Je suis alors revenu en arrière et tout continue de fonctionner comme vendredi soir…. Je n’aime pas quand les choses tombent en marche. Affaire à suivre en gardant ce billet sous le coude.

Catégories
Application Paramétrage

Monitorer ses applications (docker) avec Prometheus et Grafana

Après avoir réglé mes soucis de mise à jour de Owncloud, je me suis remis à mes aventures avec Prometheus et Grafana.

Config de Prometheus embarquée

Comme mon infrastructure ne change pas entre mes environnements, j’ai tout d’abord pensé mettre le fichier de configuragion /etc/prometheus/prometheus.yml dans l’image docker de prometheus. Le code source final de cette petite manipulation se trouve ici https://gitlab.bressure.net/docker/services/prometheus

Enrichissement de la couche infra

Puis il suffit de construire l’application monitoring avec docker-compose en ajoutant le service grafana. Le tout devra s’executer sur mon instance docker que je qualifie d’infrastructure car sémantiquement ce n’est ni un poste de développement (bien qu’il ait aussi ce rôle dans les faits), ni de la production.

Nous obtenons alors une application de monitoring dont la seule source de métrique est l’instance de prometheus elle-même qui expose ses propres valeurs. Quand à grafana il faudra lui ajouter une source de données de type prometheus qui sera désignée par son url http://prometheus:9090/. La résolution du nom prometheus sera faite par le DNS de docker au sein du réseau construit par ses soin grâce au docker-compose.yml.

Mon objectif est de faire de prometheus le centralisateur de toutes les métriques et grafana sera le traceur de graphique avec comme unique source de données prometheus.

Ajout des sources à monitorer

Il faut donc ajouter des sources de données dans prometheus. C’est ce qui s’appelle dans la terminologie de prometheus des job avec pour chacun d’eux des endpoints c’est-à-dire des adresses exposant au bon format les valeurs des métriques. Ainsi prometheus lui-même est un endpoint comme vu plus haut.

Gitlab

Mon conteneur GitLab est capable d’exposer des métrique applicative (données métiers) au format prometheus. Cela sans grand effort. Il suffit d’activer prometheus dans GitLab…. même pas c’est sans déjà la cas ! Il ne faut même pas chercher à modifier la configuration dz Gitlab pour rendre le endpoint visible de l’exterieur du conteneur, GitLab fournit déjà une url avec un token secret pour accéder aux metriques. La contrepartie de cette facilité est que le endpoint prometheus du GitLab sera accédé via une url externe ie celle du gitlab !

Voilà pourquoi ma configuration de Prometheus ne peut pas être entièrement dans l’image Prometheus car le token secret dépend de l’instance GitLab c’est donc applicatif et pas structurel. De plus ce secret ne doit pas aller dans le code source que je veux public !

Métriques systèmes

Sur le schéma précédent on voit en vers Prometheus servant à lui lui-même de endpoint et en bleu la liaison avec GitLab.

Une fonction de munin, qui est sans doute la première, est le monitoring des constantes du système (mémoire, cpu, disque ….). Avec prometheus, ce sont les node exporter installé sur chaque machine qui vont exposer ses métriques sous forme de endpoint Prometheus. J’installe donc ces node exporter sur chacune de mes VM, bien entendu dans leur version dockerisée what else ? Le source trivial de cette manipulation se trouve ici https://gitlab.bressure.net/docker/applications/prom-node

Métriques docker

L’application docker, le démon docker, est elle-même une application intéressante à surveiller. Avec munin j’utilisais une sonde qui remontait l’utilisation cpu et mémoire de chaque conteneur. Pour Prometheus j’ai testé 2 solutions.

Le démon docker lui-même peut exporter des métriques prometheus. Il faut activer cette fonction expérimentale dans le fichier /etc/docker/daemon.json

{
"metrics-addr" : "IP_HOTE:9323", "experimental" : true
}

L’autre solution s’appelle cAdvisor une image docker dont google est à l’origine et qui expose un plus grand nombre de métrique que celles exposées par le démon docker lui-même. Comment ce fait-il ? En montant les répertoires systèmes de l’hôte dans le conteneur cAdvisor:

sudo docker run \ --volume=/:/rootfs:ro \ --volume=/var/run:/var/run:ro \ --volume=/sys:/sys:ro \ --volume=/var/lib/docker/:/var/lib/docker:ro \ --volume=/dev/disk/:/dev/disk:ro \ --publish=8080:8080 \ --detach=true \ --name=cadvisor \ gcr.io/google-containers/cadvisor:latest

Node exporter, cAdvisor, démon docker

Le trio gagnant des outils d’export de métriques semble être:

  • Le démon docker lui-même mais exporte seulement les données essentielles et ce n’est pas une fonctionnalité pérenne
  • cAdvisor qui est beaucoup plus complet mais demande un accès également complet au système de fichiers hôte en lecture certes mais….
  • Le node exporter de prometheus moins riche que cAdvisor mais avec une possibilité d’extension
Trio gagnant des sondes à métriques

On voit que les sondes node exporter de prometheus et cAdvisor de google, sont des composants réutilisables et installables en bloc sur mes différents environnements: infra, staging et production. Je vais donc avantageusement les regrouper dans un projet docker compose prom-node. Finalement l’architecture de monitoring devient la suivante:

Bilan

Avec quelque configuration qui se résument à assembler des conteneurs entre eux, j’arrive à avoir une solution uniquement visuelle pour l’instant, de surveillance de mon infra. Je m’appuie pour cela sur:

  1. une image de Prométheus avec une configuration taillée sur mesure. Ce point est facultatif et je pouvais me contenter de l’image originale https://gitlab.bressure.net/docker/services/prometheus
  2. une application combinant Prometheus pour la collecte et Grafana pour la restitution https://gitlab.bressure.net/docker/applications/monitoring
  3. Des sondes sous forme de conteneur qui expose les métriques pour Prometheus https://gitlab.bressure.net/docker/applications/monitoring
  4. Un configuration des démons docker pour exposer des métriques Prometheus. Attention fonctionnalité expérimentale selon docker.

La prochaine étape sera d’ajouter des alertes afin de reproduire toutes les fonctions de munin.

Catégories
Application Paramétrage

Mise à jour owncloud dockerisé et plugin non supporté

J’ai voulu mettre à jour mon instance de owncloud dockerisée pour utiliser la derniere version. Pour cela il me suffit de changer la version qui se trouve dans un fichier .env comme on le voit ici https://gitlab.bressure.net/docker/applications/owncloud

N’ayant pas lu les instructions concernant les plugins (appelés application dans Owncloud), certains ne pouvaient pas être mis à jour lors du démarrage de la nouvelle version de Owncloud.

Log du conteneur owncloud

docker logs owncloud_owncloud_1

Ce dernier restait alors en mode maintenance et du point de vue de docker le conteneur restait dans l’état en démarrage rendant impossible toute connexion via un docker exec -it owncloud_owncloud_1 /bin/bash. Il est alors impossible d’utiliser la commande occ pour administrer owncloud en commande php.

Comme le service (conteneur) de base de données fonctionnait bien, j’ai dû passer par des requêtes SQL pour désactiver les applications (plugin) problématiques.

Connexion au conteneur de base de données

docker exec -it owncloud_db_1 /bin/bash

Connexion au service de base de données

mysql -u root -p

Modification de la configuration Owncloud par SQL

update oc_appconfig set configvalue="no" where appid="files_videoplayer" and configkey="enabled";
update oc_appconfig set configvalue="no" where appid="drawio" and configkey="enabled";

Reinstallation de drawio

Ce plugin m’est utile pour faire des diagramme par le web sur mon cloud privé. Comme la version de owncloud est maintrnant 10.3.2.2 il faut modifier les specfication du plugin drawio pour pouvoir l’activer. Il « suffit » de modifier le fichier appinfo/info.xml mais la signature du plugin n’alors plus vérifié. Il faudra attendre que le mainteneur du plugin drawio fasse une livraison officielle.

Catégories
Uncategorized

Monitorer ses applications avec Prometheus et Grafana

Jusque là j’utilisais le bien connu munin pour suivre l’état de mes serveurs et services. Cet outil assez ancien se positionne bien en tant que surveillance système et pour des alertes en cas de détection de valeurs anormales. Étant depuis plusieurs mois passé à une infra dockerisé, mon outils de monitoring était encore en natif. De plus son ihm n’était plus dans l’air du temps et il ne permet pas de faire des requêtes arbitraires sur l’historique des valeurs voire de d’agréger des indicateurs comme ce que ElasticSearch/Logstash/Kibana, ELK le poids lourd de la catégorie, permet.

Alternative légère

Avant de se lancer dans ELK plus fait pour de l’analyse de log que le suivi d’indicateur métriques, je souhaitais me limiter à une solution plus moderne que munin mais également peu gourmande en ressources tout en offrant la monitoring système de base de munin: les indicateurs mémoire, cpu, système de fichiers etc.

Prometheus est la solution mise en avant dans GitLab pour surveiller les performances des applications dans leurs environnement d’exécution. Un tour sur le site de Prometheus permet de voir que son architecture est bien au goût du jour c’est-à-dire à la sauce épicée des conteneurs:

On remarque le brique Grafana qui permet d’ajouter des capacités de visualisation et d’export des données en plus de l’interface web basique de Prometheus. Je vais également l’utiliser pour avoir de jolis graphiques dans l’air du temps.

Prometheus, Grafana, Docker

Comme je suis dans un univers dockerisé maintenant, je vais donc installer le couple Prometheus et Grafana en version conteneurisée. Dans un premier temps pour me familiariser avec ces outils, je vais installer la solution pour monitorer mes démons docker et les indicateurs systèmes de mes machines.

Mais avant tout, fidèle au principe de s’appliquer à soit même ses précepte, je commence par créer un projet dans mon GitLab et sera destiné à mettre en place mon application de monitoring. Ainsi toute ma phase de mise au point sera sous IC/DC comme dans un monde idéal.

https://gitlab.bressure.net/docker/applications/monitoring

La suite de mes aventures avec Prometheus, Grafana et docker dans le prochain billet… pour très bientôt.

Catégories
Uncategorized

Docker – VM modèle ou installation automatique

Je voulais initialement mettre au point une VM modèle que je pourrais cloner pour servir de base à une machine paramétrable avec Ansible. La mise au point de la VM passse par l’installation de l’OS et cette phase vait aussi pour une machine physique. Comme l’informatique est la science de ceux qui n’aiment pas se répéter, je me lance donc sur le sujet d’automatisation d’une installation.

Preseed

Le processus d’installation d’un système Debian peut peut-être automatisé par un fichier preseed.cfg qui contient les réponses aux questions de l’installateur. La mise au point de ce fichier merite l’utilisation de l’intégration continue qui consistera à :

  1. rappatrier une ISO de debian en version stable
  2. extraire l’ISO
  3. ajouter le preseed
  4. recréer l’ISO
  5. demarrer une VM sur l’ISO
  6. vérifier que le système installé répond à l’attente
  7. déployer l’ISO pour utilisation future.

Gitlab-runner et libvirt

Le principe est séduisant mais il faut que je trouve comment depuis un gitlab-runner lancer une VM. Cette VM devra être créée from scrach pour bien reproduire le cas d’utilisation de l’ISO custom. J’entrevois déjà des questions nouvelles dans la coneption de la solution: idealement le test devrait se faire dans un conteneur mais la mise sous docker sera impossible car le conteneur partage les librairies systèmes (noyau) de l’hôte. Donc le seul moyen d’isoler le test création/installation de VM serait de le faire sur un hôte dédié: une VM avec gitlab-runner et libvirt afin de créer des VM !

Affaire à suivre….

Catégories
Uncategorized

Docker – vers la scalabilité

Feuille de route du 26/05/2019

La migration a pour objectif de:

  • Réduire le nombre de VM (moins d’administration etc)
  • Réduire l’empreinte mémoire des services (blog divers, owncloud etc)
  • Répondre au besoin de sauvegarde comme à l’heure actuel
  • Répondre au besoin de monitoring comme à l’heure actuel
  • Ajouter la possibilité d’avoir une préproduction complète

En option:

  • Permettre la scalabilité des services
  • L’exécution des services dans le cloud

Objectifs atteints

Si j’ai atteints facilement les objectifs principaux, la mis à l’échelle et la capacité à mettre mes services dans le cloud c’est-à-dire de faire héberger ou bien mes conteneurs ou bien la VM hôte dans le cloud, sont encore à faire.

Scalabilité

J’ai commencé avec une VM de 4 Go pour progressivement monter à 7 Go. Cela se fait en modifiant la VM et ajouter du swap pour les raisons que j’évoquais dans le billet sur l’over-commit. L’objectif était de voir combien de RAM je pouvais économiser c’est-à-dire combien j’en avais gaspillé avec le modèle tout VM où un service c’est une VM.

Rappel de mon infra sur serveur mutalisé de VM à conteneur

Cette méthode nécessite de l’administration de la VM et atteindra sa limite de toute façon avec le nombre maximum de processus par OS et la résistance à la panne. Si la VM plante alors tous les services sont impactés. C’est le Single Point Of Failure (SPOF) à éviter.

Augmentation de l’enveloppe dal VM pour s’adapter au nombre de conteneur

Outils possibles

Le principe est d’avoir plusieurs dockers sur des machines différente (physique ou VM) afin de répartir les conteneurs. C’est ce que swarm semble promettre. Un autre outil serait le bazooka Kubernetes. Le choix de l’outil dépendra des bénéfices apportés par rapport au temps de mise en œuvre.

Solution cible

Quelle que soit la solution technique qui permettra de panacher les conteneurs sur différents docker, il faudra que je revoie le reverse proxy apache pour l’instant natif sur l’hôte. Je pense à le dockeriser ou à utiliser une solution comme traefik.

Automatisation de la création de l’hôte

Dans mon infra j’ai réussi à rendre transparent le déploiement des conteneurs via le processus d’intégration continue. Cela nécessite la création préalable de l’hôte du moteur docker et du gitlab-runner natif. Si docker s’exécute dans une VM comme dans mon cas il faut encore avoir créer la VM et donc installer un OS. Tout cela est encore manuel chez moi même si cela reste simple: une débian minimaliste, docker, docker-compose et gitlab-runner natif.

Clonage de VM

Afin d’avoir une préprod et une prod identique au niveau OS/Docker, j’ai procédé par clonage de VM. Une fois la VM de préprod prête, j’ai cloné celle-ci. Ce mécanisme permet d’ajouter autant de VM que voulu à partir d’une image creuse prête à l’emploi ne contenant que l’OS, le moteur docker et le gitlab-runner natif. Cependant comment ajouter une machine physique à mon infra ? Il faut être capable de créer et configurer une machine physique également:

  • Aussi bien pour accueillir un moteur docker directement
  • Que pour accueillir des VM à conteneurs

Outils de configuration

La création de machine physique prête à rentrer dans mon cluster de moteur docker peut se faire avec un outils de configuration comme Ansible. Le principe est d’appliquer une configuration (installation, paramétrage) sur une machine disposant d’un accès SSH. Dès lors il me suffit d’être capable d’installer rapidement une machine physique avec les caractéristiques suivantes:

  • Débian minimale
  • Accès SSH pour Ansible

Dans le cas d’un machine virtuelle, il me suffira d’avoir une VM modèle avec ces mêmes caractéristiques minimales afin de pouvoir utiliser Ansible pour la configurer plus en avant. Cette configuration consistera à:

  • mettre à jours le système
  • installer le moteur docker
  • installer docker compose
  • installer le gitlab-runner natif ?

Gitlab-runner

J’utilise jusque là l’intégration continue pour faire les déploiements via gitlab-runner. Cette façon de faire m’évite d’avoir à mettre à jours une copie locale des fichiers de configuration des application par un git pull, le runner faisant tout ça automatiquement. Dans le cadre des conteneurs en cluster gérés par swarm ou kubernetes, le gitlab-runnner sera peut-être remis en cause.

La prochaine étape sera la création d’une VM modèle. La suite au prochain billet !

Catégories
Application Paramétrage

Docker – conteneuriser c’est mutualiser efficacement

Le chantier de passage de mes VM en conteneur docker commencé en mai touche à sa fin. Il ne me reste qu’une seule VM à migrer. Pour rappel, je me contrains à réellement migrer en conteneur et je n’utilise pas d’outils de conversion VM vers conteneur afin d’avoir réellement des images minimales offrant uniquement le service attendu. Le résultat obtenu début juillet était déjà probant. Dans ce billet j’enfonce le clou graphique munin à l’appui.

Réduction de l’enveloppe mémoire de VM et de la mémoire alloué sur l’hôte

La ligne bleu montre l’enveloppe mémoire des VM de ma machine hôye

Les 15 VM occupaient initialement 18-19 Go de RAM avant que ne me lance dans la migration avec uniquement un production. Au début de la migration en conteneur docker, l’enveloppe mémoire avait fait un bon puisque j’ajoutais 2 VM : une production et un pré-production puis au fil des migrations l’enveloppe mémoire sur l’hôte s’était mise à chuter rapidement. Actuellement j’ai doublé le nombre de services (une prod et une pré-prod) et réduit l’enveloppe mémoire à 15 Go. 30 Services pour 15 Go là où la virtualisation prenait 18-19 Go pour 15 services !

La ligne verte montre la mémoire commitée

Mutualisation efficace par over-commit

Du point de vu de l’hôte la mémoire alloué à sensiblement diminuée passant de 45 Go à 33 Go. Tout cela doit être vu avec la perspective du doublement du nombre de service. Cela est rendu possible par la mutualisation au sein d’une même VM (un seul OS) de tous les services. L’OS a alors le choix d’allouer intelligemment les ressources limitées par l’enveloppe de la VM. Dans mon cas ma VM de prod occupe 7 Go de RAM. Idem pour la pré-pod. Pour ce faire le noyaux linux à recours à la surréservation (over-commit). Ici la machine de production:

La ligne verte montre la réservation mémoire : on est bien en over-commit

La machine de pré-production certes moins sollicitée est également en over-commit:

Bien que la sur-réservation mémoire est normale car par empirisme les applications allouent la mémoire sans vraiment en avoir besoin tout le temps ce qui a conduit Linux à prendre en comportement par défaut l’over-commit. Cependant si jamais toutes les applications veulent accéder en même temps à la mémoire qui leur avait été promise, le système va planter sauf si on met suffisamment de fichier d’échange pour amortir le choc. Dans mon cas je me fixe comme limite de commit la quantité de mémoire virtuelle disponible (RAM 7 Go + SWAP 7 Go = 14 Go). Quand l’over-commit s’approche de cette limite, une alerte munin est rémontée !

Je ne triche pas avec le Swap

On pourrait croire que le swap est un moyen de tricher. Et non, il n’est là que pour amortir le cas improbable où tous les services voudraient leur mémoire promise. D’ailleurs on voit bien sur les graphiques que les VM ne « swappent » pas.

Overcommit sans swap = jusque là tout va bien

Et l’usage disque supplémentaire pour le swap ? C’était déjà la cas avec chacune des 15 VM du départ. Chacune ayant entre 1 Go et 4 Go de swap. Avec docker j’ai 15 services qui tiennent avec 7 Go de swap.

Docker (ou une solution de conteneurisation) est vraiment une avancée dans l’usage raisonné des ressources. Il offre en plus l’avantage de garantie d’une exécution dans des environnements à l’identique en terme de dépendance. Ces 2 points me permettent d’avoir une pré-prod représentative de ma prod aussi bien en terme d’installation (dépendances) et de taille (sans que cela ne coûte trop cher)