Limiter en toute sécurité les playbooks Ansible à une seule machine?

J’utilise Ansible pour certaines tâches simples de gestion des utilisateurs avec un petit groupe d’ordinateurs. Actuellement, mes livres de lecture sont configurés sur des hosts: all et mon fichier hosts ne sont qu’un seul groupe avec toutes les machines répertoriées:

 # file: hosts [office] imac-1.local imac-2.local imac-3.local 

J’ai souvent dû cibler une seule machine. La commande ansible-playbook peut limiter les jeux comme ceci:

 ansible-playbook --limit imac-2.local user.yml 

Mais cela semble un peu fragile, surtout pour un playbook potentiellement destructeur. Quitter le drapeau limit signifie que le playbook sera exécuté partout. Étant donné que ces outils ne sont utilisés que de temps en temps, il semble utile de prendre des mesures pour une lecture infaillible afin que nous ne touchions pas accidentellement quelque chose dans quelques mois.

Existe-t-il une meilleure pratique pour limiter les exécutions de playbook à une seule machine? Idéalement, les playbooks devraient être inoffensifs si des détails importants étaient omis.

Il apparaît qu’il est possible d’entrer un nom d’hôte directement dans le playbook, de sorte que l’exécution du playbook avec les hosts: imac-2.local fonctionnera hosts: imac-2.local . Mais c’est un peu maladroit.

Une meilleure solution pourrait être de définir les hôtes du playbook à l’aide d’une variable, puis de transmettre une adresse d’hôte spécifique via --extra-vars :

 # file: user.yml (playbook) --- - hosts: '{{ target }}' user: ... 

Lancer le playbook:

 ansible-playbook user.yml --extra-vars "target=imac-2.local" 

Si {{ target }} n’est pas défini, le playbook ne fait rien. Un groupe du fichier hosts peut également être transmis si nécessaire. Dans l’ensemble, cela semble être un moyen beaucoup plus sûr de construire un playbook potentiellement destructeur.

Playbook ciblant un seul hôte:

 $ ansible-playbook user.yml --extra-vars "target=imac-2.local" --list-hosts playbook: user.yml play #1 (imac-2.local): host count=1 imac-2.local 

Playbook avec un groupe d’hôtes:

 $ ansible-playbook user.yml --extra-vars "target=office" --list-hosts playbook: user.yml play #1 (office): host count=3 imac-1.local imac-2.local imac-3.local 

Oublier de définir des hôtes est sûr!

 $ ansible-playbook user.yml --list-hosts playbook: user.yml play #1 ({{target}}): host count=0 

Il y a aussi un petit truc mignon qui vous permet de spécifier un seul hôte sur la ligne de commande (ou plusieurs hôtes, je suppose), sans inventaire intermédiaire:

 ansible-playbook -i "imac1-local," user.yml 

Notez la virgule ( , ) à la fin; cela signale que c’est une liste, pas un fichier.

Maintenant, cela ne vous protégera pas si vous transmettez accidentellement un fichier d’inventaire réel, ce qui peut ne pas être une bonne solution à ce problème spécifique. Mais c’est un truc pratique à savoir!

Cette approche se terminera si plusieurs hôtes sont fournis en vérifiant la variable play_hosts . Le module Fail est utilisé pour quitter si la condition d’hôte unique n’est pas remplie. Les exemples ci-dessous utilisent un fichier hosts avec deux hôtes, alice et bob.

user.yml (playbook)

 --- - hosts: all tasks: - name: Check for single host fail: msg="Single host check failed." when: "{{ play_hosts|length }} != 1" - debug: msg='I got executed!' 

Exécuter un livret sans filtre hôte

 $ ansible-playbook user.yml PLAY [all] **************************************************************** TASK: [Check for single host] ********************************************* failed: [alice] => {"failed": true} msg: Single host check failed. failed: [bob] => {"failed": true} msg: Single host check failed. FATAL: all hosts have already failed -- aborting 

Exécuter un playbook sur un hôte unique

 $ ansible-playbook user.yml --limit=alice PLAY [all] **************************************************************** TASK: [Check for single host] ********************************************* skipping: [alice] TASK: [debug msg='I got executed!'] *************************************** ok: [alice] => { "msg": "I got executed!" } 

Pour étendre la réponse de joemailer, si vous voulez avoir la capacité de faire correspondre un modèle à un sous-ensemble de machines distantes (comme le ansible commande ansible ), mais que vous voulez toujours exécuter accidentellement le playbook sur toutes les machines, est ce que j’ai imaginé:

Même playbook que dans l’autre réponse:

 # file: user.yml (playbook) --- - hosts: '{{ target }}' user: ... 

Avons les hôtes suivants:

 imac-10.local imac-11.local imac-22.local 

Maintenant, pour exécuter la commande sur tous les périphériques, vous devez définir explicitement la variable cible sur “all”

 ansible-playbook user.yml --extra-vars "target=all" 

Et pour le limiter à un modèle spécifique, vous pouvez définir target=pattern_here

ou, alternativement, vous pouvez laisser target=all et append l’argument --limit , par exemple:

 --limit imac-1* 

c’est à dire. ansible-playbook user.yml --extra-vars "target=all" --limit imac-1* --list-hosts

qui se traduit par:

 playbook: user.yml play #1 (office): host count=2 imac-10.local imac-11.local 

Il y a IMHO un moyen plus pratique. Vous pouvez en effet inviter l’utilisateur à indiquer la ou les machines vars_prompt il souhaite appliquer le playbook grâce à vars_prompt :

 --- - hosts: "{{ hosts }}" vars_prompt: - name: "hosts" prompt: "Which hosts would you like to setup?" private: no tasks: […] 

Les utilisateurs AWS utilisant le script d’inventaire externe EC2 peuvent simplement filtrer par ID d’instance:

 ansible-playbook sample-playbook.yml --limit i-c98d5a71 --list-hosts 

Cela fonctionne car le script d’inventaire crée des groupes par défaut .

Depuis la version 1.7, ansible a l’option run_once . La section contient également des discussions sur diverses autres techniques.

Nous avons des playbooks génériques utilisables par un grand nombre d’équipes. Nous avons également des fichiers d’inventaire spécifiques à l’environnement, contenant plusieurs déclarations de groupe.

Pour forcer une personne à appeler un livre de jeu à spécifier un groupe sur lequel exécuter, nous introduisons une entrée factice en haut du livre:

 [ansible-dummy-group] dummy-server 

Nous incluons ensuite la vérification suivante comme première étape dans le playbook partagé:

 - hosts: all gather_facts: False run_once: true tasks: - fail: msg: "Please specify a group to run this playbook against" when: '"dummy-server" in ansible_play_batch' 

Si le serveur factice apparaît dans la liste des hôtes sur lesquels ce répertoire est programmé pour s’exécuter (ansible_play_batch), l’appelant n’a pas spécifié de groupe et l’exécution du guide échouera.

J’ai un script wrapper appelé provision qui vous oblige à choisir la cible, donc je n’ai pas à la gérer ailleurs.

Pour ceux qui sont curieux, j’utilise ENV vars pour les options utilisées par mon vaguelfile (en ajoutant l’argument ansible correspondant pour les systèmes cloud) et laisser passer le rest des arguments ansible. Où je crée et approvisionne plus de 10 serveurs à la fois J’inclus une nouvelle tentative automatique sur les serveurs défaillants (tant que des progrès sont réalisés – j’ai trouvé que lors de la création d’une centaine de serveurs plusieurs ).

 echo 'Usage: [VAR=value] bin/provision [options] dev|all|TARGET|vagrant' echo ' bootstrap - Bootstrap servers ssh port and initial security provisioning' echo ' dev - Provision localhost for development and control' echo ' TARGET - specify specific host or group of hosts' echo ' all - provision all servers' echo ' vagrant - Provision local vagrant machine (environment vars only)' echo echo 'Environment VARS' echo ' BOOTSTRAP - use cloud providers default user settings if set' echo ' TAGS - if TAGS env variable is set, then only tasks with these tags are run' echo ' SKIP_TAGS - only run plays and tasks whose tags do not match these values' echo ' START_AT_TASK - start the playbook at the task matching this name' echo ansible-playbook --help | sed -e '1d s#=/etc/ansible/hosts# set by bin/provision argument# /-k/s/$/ (use for fresh systems)/ /--tags/s/$/ (use TAGS var instead)/ /--skip-tags/s/$/ (use SKIP_TAGS var instead)/ /--start-at-task/s/$/ (use START_AT_TASK var instead)/ ' 

Je ne comprends vraiment pas comment toutes les réponses sont si compliquées, la façon de le faire est simplement:

 ansible-playbook user.yml -i hosts/hosts --limit imac-2.local --check 

Le mode de vérification vous permet de fonctionner en mode de fonctionnement à sec, sans rien changer.