banner cross

En naviguant sur notre site, vous acceptez l’utilisation de cookies qui nous permettront de réaliser des analyses et de vous proposer des contenus
et des annonces les plus adaptés à vos centres d’intérêts.
En savoir plus / Gérez votre consentement à l’utilisation des cookies.

Comment automatiser le monitoring de nos 200 stacks clients en un déploiement ?

Au commencement…

Chez Toucan Toco, chaque client dispose de son instance dédiée, et donc de sa propre stack: MongoDB dédié, Redis dédié, pools de process gunicorn / celery dédiés. À chaque nouveau projet ou pilote, on est amené à déployer une nouvelle instance.

Architecture typique

Très vite pour déployer une nouvelle stack, nous avons fait une suite de playbooks Ansible. Ceux-ci sont en charge de provisionner la machine cible avec la stack et toutes ses dépendances, d’ajuster l’environnement (comme les règles fail2ban, etc…), mais rien n’était géré pour notre supervision.

Plutôt que de gérer le monitoring des différentes briques de chaque instance avec un outil agent-based comme Nagios (à déployer, configurer et mettre à jour sur chaque serveur), la première version de notre monitoring était réalisée à l’aide du free trial proposé par StatusCake. Ce service permet de pinger à intervalle régulier une URL donnée, et de remonter des alertes via Slack ou mail.

Le problème : tout faire manuellement

Comme cette partie n’était pas automatisée, la création des tests StatusCake était faite manuellement en allant sur l’interface web comme le décrivait notre documentation pour l’initialisation d’une nouvelle stack. La création de checks sur l’interface de StatusCake est relativement simple mais reste fastidieuse avec la multiplication des projets. A chaque fois il faut se connecter à l’interface, retrouver les credentials, être certain qu’on crée le test avec les bonnes options comme les autres tests, cliquer, cliquer et encore cliquer… Du coup personne ne veut le faire et on s’expose à des erreurs.

Charlie Chaplin - Modern Times

La peine est la même lorsqu’on doit mettre à jour les tests (par exemple pour ajouter des conditions ou des paramètres). On comprend vite que le passage à l’échelle va vite être compromis.

La solution avec Ansible !

Avec la multiplication des clients et des projets, le besoin d’automatiser la création et la mise à jour du monitoring s’est donc rapidement fait sentir. Sachant que le deploiement et la mise à jour de nos stacks sont déjà automatisés par nos scripts Ansible… Pourquoi ne pas y déléguer la création de ces checks directement ?

Dans notre cas, on souhaite disposer de différents types de checks concernant la santé de nos services :

Ces deux points correspondent à la distinction entre liveness et readiness, bien décrite dans un article d’Octo: Liveness et readiness probes: Mettez de l’intelligence dans vos clusters:

L’implémentation de ces checks passe par la mise à disposition de 2 routes dédiées, sur notre service :

@app.route('/liveness')
def liveness():
    return "OK", 200

@app.route('/readiness')
def readiness():
    try:
        g.redis_connection.ping()
        g.mongo_connection.server_info()
    except (pymongo.errors.ConnectionFailure, redis.ConnectionError):
        return "KO", 500
    return "OK", 200

Côté scripts Ansible, nous avons créé un module custom en python ansible-statuscake (forké à partir de p404/ansible-statuscake qui n’est aujourd’hui plus maintenu). Ce module s’utilise de cette façon:

- name: Create StatusCake test
  local_action:
    module:        status_cake_test
    username:      "my-user"
    api_key:       "my-api-key"
    name:          "My service check"
    url:           "https://myservice.example.com"
    state:         "present"
    test_type:     "HTTP"
    check_rate:    60  # on check toutes les minutes

Afin qu’Ansible puisse trouver ce module custom, il faut placer le script python status_cake_test.py dans le dossier library à la racine du playbook.

Note technique : ici, puisqu’on utilise une local_action, l’exécution a lieu sur la machine qui lance le déploiement, pas sur la machine cible. Dans un tel contexte, on peut donc bénéficier de l’interpréteur python et des packages pip de notre choix, sans dépendre de la machine cible. Cela nous a été utile pour réaliser un autre module ansible en python 3 / asyncio, qui nous a permis de réécrire certaines tâches en utilisant un modèle concurrent et ainsi nous faire gagner en vélocité de déploiement.

Quelques stats pour finir…

Aujourd’hui grâce à cette approche :