Безопасно ограничивая Анзибль сценарии для одной машины?


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

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

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

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

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

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

10 164

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.

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 переменной. Элемент сбой модуля используется для выхода, если одно условие хоста не выполняется. В приведенных ниже примерах используется файл 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!'

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

$ 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 ARG проходят. Где я создаю и подготавливаю более 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

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