lid's Wiki

Introduction

L'an dernier, nous avons abordé différentes solutions de supervision (Nagios et Zabbix principalement), et nous avons mis en place une solution simple de supervision d'une petite infrastructure Web lors du TP.

Cette année, nous allons aller un peu plus loin, lors d'un TP nettement plus complet, qui nous permettra d'aborder différentes méthodes de collecte de métriques systèmes, réseau, mais aussi applicatives et "Business", tout en créant différents /dashboards/ adaptés à chaque type de métriques et surtout, adaptés aux besoins de l'utilisateur final.

En effet, un administrateur systèmes et réseaux, un développeur, ou un gestionnaire n'ont pas les mêmes besoins de visibilité sur l'ensemble du système d'information.

Dans le cadre d'un utilisateur "Business", par exemple, peu lui importe de savoir le temps CPU utilisé sur la 26è VM frontale de l'applicatif. Par contre, il sera sûrement intéressé par le nombre d'utilisateurs enregistrés de la plateforme, le nombre de clics sur tel article, le nombre de transactions, leur valeur moyenne, le temps de réponse de la plateforme, ou l'impact business d'une panne, etc...

Autant d'informations que nous pouvons collecter soit directement en base de données, soit via de l'analyse de logs, soit via des appels "internes" à l'API de notre applicatif, etc, et que bien évidemment nous pouvons stocker dans le temps afin d'obtenir un bon visuel de l'évolution des "affaires".

Comme vous effectuez en même temps votre TP de maintenance op', on va monitorer ces machines avec différents outils 😃

Indicateurs systèmes et réseaux

On va ici retrouver nos classiques métriques CPU, RAM, I/Os disques, espace disque, réseau, l'état de la réplication de nos données (DRBD ou autre), l'état de nos machines physiques, virtuelles, de notre équipement réseau (SNMP anyone? 😃), bref tous les indicateurs "proches" du matériel utilisé. Comme on l'a abordé l'année précédente, je ne vais pas m'attarder outre-mesure sur ces concepts 😃

Indicateurs applicatifs

État des services

Métriques des services

Indicateurs "Business"

Métriques métier

Exemple: call center

Exemple: Plateforme Web

Mise en place d'une solution d'analyse des logs

Graylog

Prérequis

Une VM avec 2Go ou plus de RAM, 10Go de disque, docker et docker-compose installés.

Stack Graylog

Aussi bon que soit ELK, il est quand même plutôt gourmand en ressources. On va donc utiliser une alternative plus légère afin que le TP puisse se dérouler sans faire exploser vos machines perso: Graylog. Et, oui, c'est de l'open-source pondu par... Oracle 😃

Graylog s'appuie sur MongoDB et ElasticSearch, dès lors on va aussi vouloir installer leurs images docker respectives. La recette est un poil plus compliquée que celle de portainer (notez qu'avec portainer, plus besoin des paramètres /network/ et /volumes/, c'est lui qui s'occupe de tout 😂)

(ici le hash du mot de passe est celui du super mot de passe bien balaise: "admin" :p)

Docker Compose: déployer rapidement Graylog

Votre VM doit impérativement disposer des instructions AVX2 (par exemple, dans la configuration matérielle de votre VM proxmox, choisissez le type de CPU x86-64-v2-AES au minimum). Dans le cas contraire, MongoDB (et donc, toute la stack qui en dépend) ne pourra pas se lancer.

Une fois cette vérification effectuée, il nous suffit d'utiliser cette stack docker compose:

services:
  mongodb:
    image: "mongo:7.0"
    restart: "on-failure"
    networks:
      - graylog
    volumes:
      - "mongodb_data:/data/db"
      - "mongodb_config:/data/configdb"  

  # For DataNode setup, graylog starts with a preflight UI, this is a change from just using OpenSearch/Elasticsearch.
  # Please take a look at the README at the top of this repo or the regular docs for more info.
  # Graylog Data Node: https://hub.docker.com/r/graylog/graylog-datanode

  # Make sure this is set on the host before starting:
  # echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
  # sudo sysctl -p
  datanode:
    image: "${DATANODE_IMAGE:-graylog/graylog-datanode:7.0}"
    hostname: "datanode"
    environment:
      GRAYLOG_DATANODE_NODE_ID_FILE: "/var/lib/graylog-datanode/node-id"
      # GRAYLOG_DATANODE_PASSWORD_SECRET and GRAYLOG_PASSWORD_SECRET MUST be the same value
      GRAYLOG_DATANODE_PASSWORD_SECRET: "somepasswordpeppersupersecret"
      GRAYLOG_DATANODE_MONGODB_URI: "mongodb://mongodb:27017/graylog"
    ulimits:
      memlock:
        hard: -1
        soft: -1
      nofile:
        soft: 65536
        hard: 65536
    ports:
      - "127.0.0.1:8999:8999/tcp"   # DataNode API
      - "127.0.0.1:9200:9200/tcp"
      - "127.0.0.1:9300:9300/tcp"
    networks:
      - graylog  
    volumes:
      - "graylog-datanode:/var/lib/graylog-datanode"
    restart: "on-failure"

  # Graylog: https://hub.docker.com/r/graylog/graylog-enterprise
  graylog:
    hostname: "server"
    image: graylog/graylog:7.0
    depends_on:
      mongodb:
        condition: "service_started"
      datanode:
        condition: "service_started"
    entrypoint: "/usr/bin/tini --  /docker-entrypoint.sh"
    environment:
      GRAYLOG_NODE_ID_FILE: "/usr/share/graylog/data/data/node-id"
      # GRAYLOG_DATANODE_PASSWORD_SECRET and GRAYLOG_PASSWORD_SECRET MUST be the same value
      GRAYLOG_PASSWORD_SECRET: "somepasswordpeppersupersecret"
      GRAYLOG_ROOT_PASSWORD_SHA2: "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"
      GRAYLOG_HTTP_BIND_ADDRESS: "0.0.0.0:9000"
      GRAYLOG_HTTP_EXTERNAL_URI: "http://192.168.1.191:9000/"
      GRAYLOG_MONGODB_URI: "mongodb://mongodb:27017/graylog"
    ports:
    - "5044:5044/tcp"   # Beats
    - "1514:1514/udp"   # Syslog
    - "1514:1514/tcp"   # Syslog
    - "5140:5140/udp"   # Syslog
    - "5140:5140/tcp"   # Syslog
    - "5555:5555/tcp"   # RAW TCP
    - "5555:5555/udp"   # RAW UDP
    - "9000:9000/tcp"   # Server API
    - "12201:12201/tcp" # GELF TCP
    - "12201:12201/udp" # GELF UDP
    #- "127.0.0.1:10000:10000/tcp" # Custom TCP port
    #- "127.0.0.1:10000:10000/udp" # Custom UDP port
    - "13301:13301/tcp" # Forwarder data
    - "13302:13302/tcp" # Forwarder config
    networks:
      - graylog
    volumes:
      - "graylog_data:/usr/share/graylog/data/data"
    restart: "on-failure"

networks:
  graylog:
    driver: "bridge"

volumes:
  mongodb_data:
  mongodb_config:
  graylog-datanode:
  graylog_data:

Bien sûr, il faut maintenant alimenter Graylog. Pour celà, on peut utiliser /rsyslog/, HAProxy permet aussi de directement envoyer ses logs à un syslog distant (log IP:port local0 par exemple dans la configuration globale d'HAProxy), de même, on peut aussi utiliser une /Input/ Graylog de type Raw Text (TCP) et y envoyer les résultats de nos scripts (cronnés par exemple) d'extraction de statistiques de base de données, et ainsi de suite, par exemple en pipant le résultat d'une requête SQL dans netcat, qui lui même envoie le résultat en TCP à l'input Graylog voulue.

Il faut ensuite configurer (System/Inputs) une Input de type RawPlaintext/UDP, en mode global, sur le port 1514, écoutant sur 0.0.0.0

Sur notre haproxy, on va modifier sa configuration pour lui faire envoyer ses logs à Graylog:

global
   log /dev/log    local0
   log /dev/log    local1 notice
   log 192.168.1.191:1514 local0

Où 192.168.1.191 est l'IP de notre VM Graylog.

Pour finir, au niveau de notre input Graylog, on va cliquer sur 'Manage Extractors' pour pouvoir configurer notre premier extracteur de logs. Le but est d'extraire, via un Grok Pattern ou une Regex, les informations voulues des lignes de log envoyées par Haproxy à Graylog. Dans notre exemple, l'adresse IP pour laquelle nous utiliserons le Grok Pattern % puis ensuite, via une expression régulière, un autre extracteur pour extraire le code de retour HTTP (200, 404, 503...), et enfin, créer un dashboard nous permettant d'afficher les données extraites (grokées) via de beaux graphes 😃