Déployer MeiliSearch avec Ansible et Docker

Je ne change pas toujours la configuration de mes serveurs mais quand je la change, je la change avec Ansible

Ansible en quelques mots

Ansible est une solution de provisionnement écrite en Python qui s’utilise avec des fichiers YAML. Ces fichiers sont organisés en respectant une certaine structure appelée playbook. Ça fait un peu plus de 5 ans que je m’en sers pour MD ou pour nos clients. Tout est versionné via Git. Ça requiert uniquement Python sur le serveur cible. Bref, ça fait le job et ça le fait bien.

Si vous voulez en savoir plus sur Ansible, je vous invite à lire cette présentation en français. Si vous n’avez pas le temps de la lire, les seuls concepts d’Ansible à comprendre pour continuer la lecture de cet article sont :

  • Un playbook peut avoir des rôles (par exemple : MySQL, Nginx, PHP).
  • Un playbook peut avoir des tâches (par exemple : créer un répertoire, créer un conteneur Docker).
  • Ansible met à disposition des modules pour exécuter des trucs sur le serveur cible (par exemple : installer un paquet, télécharger un fichier, gérer Docker).
  • Le comportement d’Ansible peut être étendu sur l’hôte qui lance le playbook en utilisant des plugins (par exemple : lire les fichiers, contacter des services).

Installation de MeiliSearch

Dans un avenir proche, je vais avoir besoin du moteur de recherche MeiliSearch sur un de mes serveurs (pour le blog de Maylis, ainsi que pour mon projet Stargazer — dont je parlais dans un précédent article).

Pour installer MeiliSearch, j’ai plusieurs possibilités :

  1. APT
  2. Télécharger le binaire
  3. Docker

Via APT, ça pose un problème de dépendances. N’ayant pas envie de creuser davantage j’ai laissé tomber cette solution. Le coup du binaire posé quelque part sur le serveur, c’est gérable facilement avec Ansible mais ça m’ennuie un peu de gérer ça comme ça. Après (cette super longue) réflexion, je vais donc partir sur Docker. En effet Docker n’est toujours pas installé sur mon serveur et j’ai plein d’autres services dockerizables à tester, donc ça m’arrange.

Créer un rôle Docker

Pour installer Docker, j’ai choisi d'écrire mon propre rôle plutôt que d’en utiliser un provenant d’Ansible Galaxy (le site de partage de rôles de la communauté Ansible). Comme tout paquet / librairie, dans certains cas il est intéressant d’en utiliser pour gagner du temps (tant que l’on fait confiance à l’auteur), tandis que dans d’autres cas il est préférable de faire le boulot soi-même. Donc sans plus attendre, le roles/docker/tasks/main.yml de mon rôle Docker, qui est une simple traduction en YAML de la documentation d’installation de Docker sur Ubuntu :

- name: Install Docker dependencies
  apt:
    state: latest
    update_cache: yes
    name: ['apt-transport-https', 'ca-certificates', 'curl', 'gnupg-agent', 'software-properties-common', 'python-pip']

- name: Add Docker's official GPG key
  apt_key:
    url: https://download.docker.com/linux/ubuntu/gpg
    state: present

- name: Add Docker Repository
  apt_repository:
    repo: deb https://download.docker.com/linux/ubuntu {{ ansible_distribution_release | lower }} stable
    state: present

- name: Install Docker Engine
  apt:
    state: latest
    name: ['docker-ce', 'docker-ce-cli']

- name: Install Docker Modules for Python
  pip:
    name: ['docker', 'docker-compose']

Mon rôle étant créé, je n’ai plus qu'à l’ajouter à la liste de rôles dans mon playbook :

roles:
  - {role: docker, tags: ['system', 'docker']}

Je peux maintenant exécuter mon rôle Docker via la commande suivante (et aller me prendre une petite 🍺 selon l’heure) :

ansible-playbook -i inventory playbook.yml --tags docker

Préparer le déploiement d’un conteneur pour MeiliSearch

Maintenant que j’ai Docker d’installé sur mon serveur, il ne me reste plus qu'à déployer un conteneur pour MeiliSearch. Pour cela, je vais utiliser le module Docker d’Ansible et créer le tasks/docker/meilisearch.yml de ma tâche Ansible :

- file: path=/var/apps/meilisearch state=directory
- name: Create MeiliSearch container
  docker_container:
    name: meilisearch
    state: started
    restart: yes
    image: getmeili/meilisearch
    ports:
      - 7700:7700
    volumes:
      - /var/apps/meilisearch/data.ms:/data.ms
    env:
      MEILI_ENV: production
      MEILI_MASTER_KEY: "{{ lookup('passwordstore', 'servers/wearemd/meilisearch-master-key') }}"

Plus d’infos à propos de la configuration de MeiliSearch

🔒 Prochainement, je vais devoir rendre disponible publiquement l’index de recherche de MeiliSearch en utilisant son API REST. J’ai donc besoin de limiter ce que l’on peut faire via cette API. Du coup, petite variable d’environnement MEILI_MASTER_KEY qui va bien.

🔑 Et comme il n’y a que moi qui gère les serveurs par chez nous, je gère mes mots de passe, mes tokens et autres trucs secrets avec pass. Ça s’utilise en CLI ou via une extension Firefox ou une GUI ou encore via un plugin Ansible, comme je l’ai fait plus haut :

lookup('passwordstore', 'servers/wearemd/meilisearch-master-key')

Le premier paramètre de la fonction (lookup) est le nom du plugin (passwordstore) pour accéder à pass et le second est le chemin de mon secret dans pass (servers/wearemd/meilisearch-master-key).

Pour finir, déployer le conteneur pour MeiliSearch

Maintenant je fourre ma tâche docker dans mon playbook :

tasks:
  tags: ['docker']

Et enfin, je crée mon conteneur avec la commande qui va bien :

ansible-playbook -i inventory playbook.yml --tags docker --skip-tags system

Et paf on a l’interface web de MeiliSearch disponible ici ! Pour le moment l’index de recherche est vide donc on ne peut pas tester plus loin, mais tout fonctionne comme attendu.

⚡ Petite parenthèse performances

Je maronne souvent sur le temps que met Ansible à faire son boulot. J’utilise beaucoup les tags afin de circonscrire l’exécution de mon playbook à une seule partie. Comme j’avais plein de notes sur le sujet et que je n’avais encore rien creusé, c'était un peu l’occasion ou jamais de voir comment accélérer l’exécution de mon playbook.

En résumé :

  • Installer Mitogen c’est la vie et c’est minimum 4x plus rapide (peu importe ce qu’on lance).
  • Quelques tweaks dans la configuration Ansible détaillés dans cet article (en anglais), avec des petits voire des gros gains de temps selon ce qui est exécuté.
David Authier

David Authier
Développeur freelance