Безопасное ограничение Ansible playbooks одной машиной?

я использую Ansible для некоторых простых задач управления пользователями с небольшой группой компьютеров. В настоящее время у меня есть сценарии для hosts: all и мой файл hosts-это всего лишь одна группа со всеми перечисленными машинами:

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

я обнаружил, что мне часто приходится нацеливаться на одну машину. The ansible-playbook команда может ограничить такие игры:

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

но это кажется довольно хрупким, особенно для потенциально разрушительной пьесы. Опуская limit флаг это значит, что сценарий будет везде. Поскольку эти инструменты используются только изредка, кажется, стоит предпринять шаги для надежного воспроизведения, чтобы мы случайно не взорвали что-то через несколько месяцев.

есть ли лучшая практика для ограничения playbook работает на одной машине? В идеале playbooks должны быть безвредны, если какая-то важная деталь была опущена.

10 ответов


оказывается, можно ввести имя хоста непосредственно в playbook, поэтому запуск playbook с hosts: imac-2.local будет работать нормально. Но он довольно неуклюжий.

лучшим решением может быть определение хостов playbook с помощью переменной, а затем передача определенного адреса хоста через --extra-vars:

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

запуск playbook:

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

если {{ target }} не определено, playbook ничего не делает. Группа из файла hosts также может быть передана, если нужно. В целом, это кажется гораздо более безопасным способом создания потенциально разрушительной книги.

Playbook таргетинг на один хост:

$ 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 с группой хостов:

$ 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

забыв определить хосты безопасно!

$ ansible-playbook user.yml --list-hosts

playbook: user.yml

  play #1 ({{target}}): host count=0

есть также милый маленький трюк, который позволяет указать один хост в командной строке (или несколько хостов, я думаю), без промежуточного инвентаря:

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

обратите внимание на запятую (,) в конце; это означает, что это список, а не файл.

теперь это не защитит вас, если вы случайно передадите реальный файл инвентаризации, поэтому это может не быть хорошим решением этой конкретной проблемы. Но это удобный трюк, чтобы знать!


этот подход выйдет, если более одного хоста предоставляется путем проверки play_hosts переменной. The сбой модуля используется для выхода, если условие одного хоста не выполняется. В приведенных ниже примерах используется файл hosts с двумя хостами alice и bob.

пользователей.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!'

запустить playbook без фильтров хоста

$ 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

запустить playbook на одном хозяин

$ 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!"
}

чтобы расширить ответ joemailer, если вы хотите иметь возможность сопоставления шаблонов для соответствия любому подмножеству удаленных машин (так же, как ansible команда делает), но все же хочет, чтобы было очень сложно случайно запустить playbook на всех машинах, вот что я придумал:

тот же playbook, что и в другом ответе:

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

давайте иметь следующие хосты:

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

теперь, чтобы запустить команду на всех устройствах, вы должны explicty установите целевую переменную в "all"

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

и чтобы ограничить его до определенного шаблона, вы можете установить target=pattern_here

или, в качестве альтернативы, вы можете оставить target=all и добавить


есть ИМХО более удобный способ. Вы действительно можете интерактивно запрашивать пользователя для машины(ов), которую он хочет применить к playbook благодаря vars_prompt:

---

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

пользователи AWS, использующие сценарий внешнего инвентаризации EC2, могут просто фильтровать по идентификатору экземпляра:

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

это работает, потому что инвентаризация скрипт создает группы по умолчанию.



У нас есть некоторые общие playbooks, которые могут использоваться большим количеством команд. У нас также есть файлы инвентаризации среды, содержащие несколько объявлений групп.

чтобы заставить кого-то, вызывающего playbook, указать группу для запуска, мы помещаем фиктивную запись в верхней части playbook:

[ansible-dummy-group]
dummy-server

затем мы включаем следующую проверку в качестве первого шага в общий playbook:

- 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'

Если фиктивный сервер отображается в списке хостов этот playbook планируется запустить против (ansible_play_batch), затем вызывающий не указал группу, и выполнение playbook завершится ошибкой.


У меня есть сценарий оболочки под названием provision заставляет вас выбирать цель, поэтому мне не нужно обрабатывать ее в другом месте.

для тех, кто любопытен, я использую ENV vars для опций, которые использует мой vagrantfile (добавляя соответствующий ansible arg для облачных систем), и пусть остальные ansible args проходят. Где я создаю и предоставляю более 10 серверов одновременно, я включаю автоматическую повторную попытку на неудачных серверах (пока выполняется прогресс - я нашел при создании 100 или около того серверов в то время, часто некоторые из них потерпят неудачу в первый раз).

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)/
'

Я действительно не понимаю, как все ответы настолько сложны, сделать это просто:

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

режим проверки позволяет работать в режиме сухого запуска без каких-либо изменений.