Utilisation du module Service pour les tâches courantes d'administration système

Utilisez les commandes ad-hoc Ansible service pour démarrer, arrêter, redémarrer, recharger, activer et désactiver les services Linux en toute sécurité.

Utilisation du module Service pour les tâches courantes d'administration système

Ansible est utile même lorsque vous n'avez pas besoin d'un playbook complet. Si un service est arrêté sur quelques hôtes, ou si vous devez désactiver quelque chose de bruyant avant une fenêtre de maintenance, une commande ad-hoc peut être l'outil approprié. Elle offre le même ciblage d'inventaire et le même modèle d'élévation de privilèges sans vous obliger à créer un fichier YAML pour une opération ponctuelle.

Le module service intégré est l'un des outils les plus fréquemment utilisés dans la boîte à outils d'un administrateur système. Il fournit une interface standardisée et idempotente pour gérer les services sur diverses distributions Linux, en abstraisant les différences entre les systèmes d'initialisation comme Systemd, SysVinit et Upstart. Ce guide détaille comment exploiter le module service exclusivement via des commandes ad-hoc pour effectuer des opérations essentielles et courantes d'administration système.

Comprendre les commandes ad-hoc et le module service

Les commandes ad-hoc sont des exécutions sur une seule ligne qui utilisent la commande /usr/bin/ansible, en spécifiant un groupe cible (-i), un module (-m) et des arguments (-a). Elles sont non persistantes et ne reposent pas sur des fichiers YAML de playbook.

Le module service nécessite principalement deux paramètres :

  1. name : Le nom du service à gérer (par exemple, httpd, nginx, sshd).
  2. state : L'état opérationnel souhaité (started, stopped, restarted, reloaded).
  3. enabled (Optionnel) : Si le service doit démarrer au démarrage du système (yes ou no).

Syntaxe de base d'une commande ad-hoc

Tous les exemples ci-dessous utilisent la commande ansible. Étant donné que la gestion des services nécessite souvent des privilèges root, le drapeau -b (become/sudo) est presque toujours nécessaire.

ansible <motif_hôte> -m service -a "name=<nom_service> state=<action> enabled=<yes/no>" -b

Remarque : Remplacez <motif_hôte> par votre hôte ou groupe cible (par exemple, webservers, all).


1. S'assurer qu'un service est en cours d'exécution (démarrer un service)

L'une des tâches les plus courantes consiste à s'assurer qu'un service critique est actuellement actif. Le paramètre state=started garantit que si le service est arrêté, Ansible le démarre. S'il est déjà en cours d'exécution, Ansible ne fait rien (idempotence).

Exemple : S'assurer que le serveur web Nginx est en cours d'exécution sur tous les serveurs web

ansible webservers -m service -a "name=nginx state=started" -b

Si Ansible renvoie un message changed: true, le service était arrêté et vient d'être démarré. S'il renvoie changed: false, le service était déjà en cours d'exécution.

2. Arrêter un service

Pour arrêter immédiatement un service actif, utilisez state=stopped. Ceci est utile pour la maintenance, le nettoyage des dépendances ou les correctifs de sécurité immédiats.

Exemple : Arrêter la base de données PostgreSQL sur tous les serveurs de bases de données

ansible db_servers -m service -a "name=postgresql state=stopped" -b

Conseil : Lorsque vous arrêtez un service critique, assurez-vous d'exécuter une commande de vérification par la suite en utilisant un module différent, comme le module command, pour confirmer l'état si nécessaire (par exemple, ansible db_servers -a 'systemctl status postgresql').

3. Redémarrer et recharger les services

Lorsque les fichiers de configuration sont modifiés, les services doivent souvent être soit rechargés gracieusement, soit redémarrés de force. Le module service gère les deux actions.

Redémarrer (state=restarted)

Le redémarrage implique un arrêt complet suivi d'un démarrage du service. Ceci est nécessaire pour les modifications qui affectent le comportement sous-jacent du démon.

Exemple : Redémarrer le démon SSH sur tous les hôtes

ansible all -m service -a "name=sshd state=restarted" -b

Recharger (state=reloaded)

Le rechargement, lorsqu'il est pris en charge par le service (comme Nginx ou Apache), applique les modifications de configuration sans interrompre les connexions en cours. C'est la méthode préférée dans les environnements à haute disponibilité.

Exemple : Recharger gracieusement la configuration de Nginx

ansible webservers -m service -a "name=nginx state=reloaded" -b

Important : Si un service ne prend pas en charge reload, le résultat dépend du gestionnaire de services et de la définition de l'unité. Certaines unités échouent à la demande de rechargement, certaines mappent le rechargement à une autre action, et certaines ne font rien d'utile. Vérifiez la documentation du service avant de vous fier au rechargement pour les modifications en production.


4. Gérer la persistance des services (activer et désactiver)

Le paramètre state contrôle l'état d'exécution actuel. Le paramètre séparé enabled contrôle si le service démarrera automatiquement au démarrage du système d'exploitation.

S'assurer qu'un service démarre au démarrage (enabled=yes)

Ceci est crucial pour les services critiques qui doivent survivre à un redémarrage de l'hôte.

Exemple : S'assurer que le service Docker est activé et en cours d'exécution

ansible dockernodes -m service -a "name=docker state=started enabled=yes" -b

Empêcher un service de démarrer au démarrage (enabled=no)

Ceci est souvent utilisé pour sécuriser les systèmes ou désactiver les services par défaut inutiles (par exemple, désactiver le pare-feu intégré si vous utilisez un pare-feu basé sur le cloud).

Exemple : Désactiver le service Firewalld par défaut

ansible all -m service -a "name=firewalld state=stopped enabled=no" -b

Meilleure pratique de sécurité : Assurez-vous toujours que les services inutilisés sont à la fois stopped et enabled=no pour éviter un démarrage inattendu lors des mises à jour système ou des redémarrages.

5. Gérer les types de services avancés et les erreurs

Bien que le module service générique soit conçu pour fonctionner avec tous les principaux systèmes d'initialisation, il existe des scénarios où une gestion explicite est utile ou nécessaire.

Lorsque le module générique échoue

Dans de rares cas, en particulier sur des systèmes plus anciens ou des environnements hautement personnalisés, le module service générique peut ne pas détecter le système d'initialisation correct. Ansible fournit des modules spécifiques au système pour de tels cas :

  • systemd : Pour toutes les distributions modernes (CentOS 7+, Ubuntu 15+, Debian 8+).
  • sysvinit : Pour les systèmes plus anciens ou les distributions spécialisées.

Si vous savez que votre cible utilise Systemd, vous pouvez utiliser explicitement le module systemd, bien que sa syntaxe soit identique à celle du module service générique pour les opérations de base :

# Utilisation explicite du module systemd (fonctionnalité identique à 'service')
ansible servers -m systemd -a "name=chronyd state=started enabled=yes" -b

Gérer les services avec des scripts personnalisés

Si vous devez exécuter une commande de service non prise en charge nativement par le système d'initialisation (par exemple, des variables d'environnement personnalisées lors du démarrage), vous devrez peut-être combiner le module service avec d'autres tâches dans un playbook complet, ou utiliser le module shell pour une intervention ad-hoc, bien que cela réduise l'idempotence.

# Exemple de commande ad-hoc utilisant 'shell' pour des tâches de service complexes (à utiliser avec prudence)
ansible webservers -a "/usr/bin/my_custom_service_script restart" -b

Aide-mémoire des commandes ad-hoc du module Service

Tâche Arguments Exemple de commande
Assurer l'exécution state=started ansible all -m service -a "name=apache2 state=started" -b
Arrêter le service state=stopped ansible all -m service -a "name=fail2ban state=stopped" -b
Forcer le redémarrage state=restarted ansible servers -m service -a "name=postfix state=restarted" -b
Rechargement gracieux state=reloaded ansible webservers -m service -a "name=httpd state=reloaded" -b
Définir le démarrage automatique enabled=yes ansible all -m service -a "name=firewalld enabled=yes" -b
Désactiver le démarrage automatique enabled=no ansible all -m service -a "name=cups enabled=no" -b
Assurer l'exécution et l'activation state=started enabled=yes ansible control -m service -a "name=ansible_api state=started enabled=yes" -b

Un flux de travail sûr pour les incidents réels

Lorsque vous utilisez le module service Ansible lors d'un incident, la commande elle-même est généralement la partie facile. La partie la plus difficile est de s'assurer que vous ciblez les bons hôtes et que vous comprenez ce que le gestionnaire de services va faire.

Commencez par une inspection de l'inventaire. Si vous êtes sur le point de redémarrer Nginx sur webservers, vérifiez ce que ce groupe contient :

ansible-inventory -i inventory.ini --graph webservers

Si votre inventaire est dynamique, exécutez la même vérification sur la source dynamique. Il est courant que les tags cloud incluent des hôtes auxquels vous ne vous attendiez pas, surtout après des migrations ou des événements de mise à l'échelle temporaires. Un redémarrage de service qui est sûr sur cinq nœuds d'application peut être risqué sur tous les nœuds d'une région.

Ensuite, exécutez une commande en lecture seule sur la même cible :

ansible webservers -m command -a "systemctl is-active nginx" -b

Cela confirme l'utilisateur de connexion, l'élévation de privilèges, le motif d'hôte et le nom du service avant d'apporter une modification. Sur Debian et Ubuntu, le service web est généralement nginx ou apache2 ; sur de nombreux systèmes de la famille Red Hat, Apache est généralement httpd. Le module Ansible ne peut pas deviner la convention de nommage des paquets pour vous.

Pour les services à haut risque, utilisez d'abord --limit :

ansible webservers --limit web01.example.com -m service -a "name=nginx state=reloaded" -b

Si cela fonctionne, étendez à un petit groupe, puis au groupe complet. Les commandes ad-hoc n'ont pas la structure de déploiement intégrée d'un playbook avec serial, vous devez donc être délibéré. Pour un grand parc, un court playbook peut être plus sûr qu'une seule commande ad-hoc géante car vous pouvez définir serial, ajouter des vérifications de santé et vous arrêter en cas d'échec.

Soyez prudent avec state=restarted. Il demande toujours un redémarrage, donc il signale changed et interrompt le service même si rien d'autre n'a changé. C'est bien quand vous voulez vraiment un redémarrage. C'est un gaspillage lorsque vous l'utilisez comme un moyen paresseux de "vous assurer que tout va bien." Pour les vérifications de routine, préférez state=started ; il démarre un service arrêté mais laisse un service en cours d'exécution tranquille.

enabled=yes et enabled=no méritent la même attention. Ils modifient le comportement au démarrage, pas seulement le comportement d'exécution actuel. Si vous exécutez ceci pendant le dépannage :

ansible all -m service -a "name=firewalld state=stopped enabled=no" -b

vous n'avez pas seulement arrêté le pare-feu maintenant ; vous avez également dit au système de ne pas le démarrer après le redémarrage. Cela peut être correct dans un environnement cloud où les pare-feu hôtes sont intentionnellement désactivés, ou cela peut violer votre base de sécurité. Dans une équipe d'exploitation partagée, laissez une note de ticket ou validez une modification de playbook afin que la décision persistante soit visible.

Pour les services gérés par systemd, le module ansible.builtin.systemd_service vous offre des options spécifiques à systemd telles que daemon_reload, masked et les services au niveau utilisateur. Le module service générique est toujours pratique pour les bases portables, mais une fois que vous avez besoin d'un comportement spécifique à systemd, utilisez le module systemd directement :

ansible appservers -m ansible.builtin.systemd_service -a "name=myapp state=restarted daemon_reload=true" -b

Enfin, lisez toujours le résultat. changed=true signifie qu'Ansible a demandé au module de modifier quelque chose, pas que l'application est saine par la suite. Un service peut redémarrer proprement et toujours échouer à sa propre vérification de santé deux secondes plus tard. Suivez les modifications de service avec une vérification qui correspond à l'application :

ansible webservers -m uri -a "url=http://127.0.0.1/health status_code=200"

ou, si HTTP n'est pas disponible :

ansible webservers -m command -a "systemctl is-active nginx" -b

Les meilleures commandes de service ad-hoc sont ennuyeuses : cible étroite, état clair, élévation de privilèges incluse et une commande de vérification juste après. Cette habitude évite la plupart des erreurs qui surviennent lors de la gestion des services à grande vitesse.

Quand une commande ad-hoc doit devenir un playbook

Les commandes ad-hoc sont excellentes pour un travail rapide et à faible contexte. Elles ne remplacent pas les opérations reproductibles. Si vous vous surprenez à coller la même commande de service dans un chat, à ajouter une étape de vérification manuelle et à dire à quelqu'un "exécutez ceci sur les deux premiers hôtes, attendez, puis exécutez-le sur le reste", c'est déjà un playbook qui essaie d'exister.

Un playbook vous donne une intention révisable :

- name: Recharger nginx en toute sécurité
  hosts: webservers
  become: true
  serial: 5
  tasks:
    - name: Valider la configuration nginx
      ansible.builtin.command: nginx -t
      changed_when: false

    - name: Recharger nginx
      ansible.builtin.service:
        name: nginx
        state: reloaded

    - name: Vérifier le point de terminaison de santé local
      ansible.builtin.uri:
        url: http://127.0.0.1/health
        status_code: 200

La même opération est toujours simple, mais elle a maintenant un traitement par lots, une validation et une vérification de santé. Elle peut vivre dans Git. Quelqu'un peut la réviser avant la prochaine fenêtre de maintenance. Vous pouvez également ajouter any_errors_fatal: true ou ajuster le comportement en cas d'échec au lieu de regarder un terminal et de prendre des décisions sous pression.

Continuez à utiliser les commandes ad-hoc service pour les démarrages, arrêts et vérifications rapides. Optez pour un playbook lorsque l'opération modifie la disponibilité face aux clients, nécessite un ordre de déploiement ou doit être répétée par une autre personne. Cette limite n'est pas une question de cérémonie ; il s'agit de rendre visibles les parties risquées.