Безопасно ограничивая Анзибль сценарии для одной машины?
Я использую 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 ответов:
оказывается, можно ввести имя хоста непосредственно в 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
это работает, потому что инвентаризация скрипт создает группы по умолчанию.
начиная с версии 1.7 ansible имеет run_once. Раздел также содержит некоторые обсуждения различных других методов.
У нас есть некоторые общие 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)/ '