Видео курс
Ansible На Русском Языке
https://www.youtube.com/playlist?list=PLg5SS_4L6LYufspdPupdynbMQTBnZd31N
Если на компьютере установлена утилита cowsay, то ансибл будет использовать ее для вывода заголовков тасок. Чтобы это отключить, нужно в конфиге (ansible.cfg) указать переменную nocows равной 0.
Inventory
[vandud@thinkpad ansible]$ cat hosts
[ru]
ru ansible_host=185.211.247.40 ansible_user=root
[test]
a ansible_host=185.176.25.118 ansible_user=root
b ansible_host=185.176.25.117 ansible_user=root
[vandud@thinkpad ansible]$ cat ansible.cfg
[defaults]
inventory = ./hosts
deprecation_warnings = False
В файле hosts перечисляются хосты и их параметры (например ключи для подключения, пользователи и прочее) [в нем можно не использовать группы, просто список хостов], по другому этот файл называется inventory.
Хосты без группы будут все равно входить в две группы: all и ungrouped.
При этом группа ungrouped входит в группу all.
То есть можно смешивать в одном файле и просто список хостов и хосты с группами.
В файле ansible.cfg перечисляются параметры. Такие же как и в /etc/ansible/ansible.cfg.
Нужно экспортировать переменную окружения, Иначе ансибл будет использовать /etc/ansible/ansible.cfg, а не тот что у тебя в текущей директории
export ANSIBLE_CONFIG=./ansible.cfg # что-то типа такого
Далее, имея два этих файла можно например пингануть все хосты:
$ ansible -m ping all
[WARNING]: Found both group and host with same name: ru
ru | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
b | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
a | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Но нужно чтобы был добавлен ключ, либо нужно указывать ансиблу, что не требуется проверять достоверность ключа и переданных ключей.
Можно в ansible.cfg это указать
host_key_checking = False
А можно передать в переменной окружения
export ANSIBLE_HOST_KEY_CHECKING=False;ansible -i hosters -m ping all
Запрашивать пароль при ad-hoc
$ export ANSIBLE_HOST_KEY_CHECKING=False;ansible -i hosters -u i.dudin_pro --ask-become-pass --ask-pass -m ping all
-
--ask-become-pass
- для судо -
--ask-pass
- для юзера
Можно вынести общие параметры в переменные. Например имя пользователя, ключ для подключения или что-то еще. Делается это так:
[test:vars]
ansible_user=root
То есть после объявления группы (так же как описано выше), можно ниже описать переменные для всей этой группы.
Также можно развертывать группы внутри групп:
[test:children]
a
b
[a]
a.vandud.ru ansible_host=185.176.25.118
[b]
b.vandud.ru ansible_host=185.176.25.117
[test:vars]
ansible_user=root
Имена групп могут быть в любом регистре.
Команда ansible-inventory --list позволяет вывести весь текущий inventory файл:
$ ansible-inventory --list
{
"_meta": {
"hostvars": {
"a.vandud.ru": {
"ansible_host": "185.176.25.118",
"ansible_user": "root"
},
"b.vandud.ru": {
"ansible_host": "185.176.25.117",
"ansible_user": "root"
},
"ru.vandud.ru": {
"ansible_host": "185.211.247.40",
"ansible_user": "root"
}
}
},
"a": {
"hosts": [
"a.vandud.ru"
]
},
"all": {
"children": [
"ru",
"test",
"ungrouped"
]
},
"b": {
"hosts": [
"b.vandud.ru"
]
},
"ru": {
"hosts": [
"ru.vandud.ru"
]
},
"test": {
"children": [
"a",
"b"
]
}
}
Еще есть ansible-inventory --graph:
$ ansible-inventory --graph
@all:
|--@ru:
| |--ru.vandud.ru
|--@test:
| |--@a:
| | |--a.vandud.ru
| |--@b:
| | |--b.vandud.ru
|--@ungrouped:
Ad-Hoc
Есть модуль setup, он позволяет узнать факты о хосте (как в puppet).
Можно выполнить команду ansible -m setup host
и увидеть большой список разных фактов.
По умолчанию факты собираются только для выполнения плейбука, их можно использовать для плейбуков (делать различные условия и прочее).
Модуль shell позволяет выполнить любую команду на удаленном хосте. С помощью ключа -a передаются аргументы в модуль, в нашем случае передается сама команда:
$ ansible -m shell -a 'uptime' test
b.vandud.ru | CHANGED | rc=0 >>
06:46:00 up 1:59, 1 user, load average: 0.00, 0.00, 0.00
a.vandud.ru | CHANGED | rc=0 >>
06:46:00 up 1:58, 1 user, load average: 0.00, 0.00, 0.00
Модуль command похож на shell, но в нем не видны шелловские штуки (переменные и прочие пайплайны).
С помощью модуля copy можно копировать файлы с локальной машины на удаленные:
$ ansible -m copy -a 'src=.vimrc dest=/tmp/.' test
Также можно указывать разные параметры для файлов (права, владельцев и тд)
Модуль file позволяет работать с файлами, например удалять файлы:
$ ansible -m file -a 'path=/tmp/.vimrc state=absent' test
- apt работает с пакетами (на чистой системе нужно не забывать обновлять кэш пакетов [apt update], иначе ничего нельзя будет установить)
- uri может дергать сайты
- service для управления сервисами (включение выключение и прочее)
Можно передавать ансиблу ключ -v для детализации (имеет четыре уровня: -v, -vv, -vvv, -vvvv)
ansible-doc документация по плагинам. Например:
$ ansible-doc -l | egrep '^postgres'
postgresql_copy Copy data between a file/program and a PostgreSQL table
postgresql_db Add or remove PostgreSQL databases from a remote host
postgresql_ext Add or remove PostgreSQL extensions from a database
postgresql_idx Create or drop indexes from a PostgreSQL database
postgresql_info Gather information about PostgreSQL servers
...
group_vars
Переменные можно вынести из файла hosts. Для этого нужно создать директорию group_vars и в ней в файлах с именами груп разместить переменные:
.
├── ansible.cfg
├── group_vars
│ ├── ru
│ └── test
└── hosts
В каждом файле group_vars/GROUPNAME нужно записывать параметры в формате YAML:
---
ansible_user: root
И теперь инвентарный файл содержит в себе только группы и адреса серверов:
[ru]
185.211.247.40
[test:children]
a
b
[a]
185.176.25.118
[b]
185.176.25.117
Опытным путем выявлено, что дефисы в именах переменных недопустимы.
Простой playbook
Плейбуки пишутся на YAML, вот простой пример:
---
- name: My first playbook
hosts: test
tasks:
- name: Ping host
ping:
И запускаются командой ansible-playbook PLAYBOOK_NAME:
$ ansible-playbook playbook.yaml
PLAY [My first playbook] ******************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************
ok: [185.176.25.117]
ok: [185.176.25.118]
TASK [Ping host] **************************************************************************************************************************************
ok: [185.176.25.118]
ok: [185.176.25.117]
PLAY RECAP ********************************************************************************************************************************************
185.176.25.117 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
185.176.25.118 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Параметры модулей (например var у debug или state у apt) можно записывать в плейбуке в стиле ad-hoc после названия модуля одной строкой через пробел, либо через двоеточие в yaml.
Вот например я добавил несуществующий хост в инвентарный файл, и вывод команды ansible-playbook показывает на какие хосты удалось зайти, а на какие нет:
В ansible можно использовать переменные. Делается это так:
В плейбуке нужно определить поле vars и в нужных местах вызывать переменные по имени внутри конструкции {{ NAME }}:
---
- name : vars and if's
hosts: test
vars :
src_file : file
dest_file: /tmp/file
tasks:
- name : copy file
copy : src={{ src_file }} dest={{ dest_file }} mode=0777
- name : print file
shell: cat {{ dest_file }}
- name : change dest file
shell: uname -a > {{ dest_file }}
- name : print changed file
shell: cat {{ dest_file }}
Также переменные можно обозначать в файле hosts, точно так же как и указываются переменные ansible_host и ansible_user.
Хэндлеры
Хэндлеры - нужны в для выполнения задачи при определнных условиях. Например нужно рестартануть веб-сервер при условии что файлы сайта изменились:
---
- name : vars and if's
hosts: test
vars :
src_file : file
dest_file: /tmp/file
tasks:
- name : change file
copy: src={{ src_file }} dest={{ dest_file }}
notify: handler
handlers:
- name: handler
service: name=nginx state=restarted
В данном плейбуке рестартуется nginx при условии что копируемый файл изменился.
В директиве notify вызывается хэндлер по имени в блоке name хэндлера. Вызывается он при условии что таска в которой он вызывается делает какие-либо изменения, то есть имеет статус CHANGED.
В выводе ниже видно что хэндлер запускается только в первый раз (когда файл не совпадал):
[vandud@thinkpad ansible]$ ansible-playbook playbook.yaml
PLAY [vars and if's] **********************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************
ok: [b.vandud.ru]
ok: [a.vandud.ru]
TASK [change file] ************************************************************************************************************************************
changed: [b.vandud.ru]
changed: [a.vandud.ru]
RUNNING HANDLER [handler] *****************************************************************************************************************************
changed: [b.vandud.ru]
changed: [a.vandud.ru]
PLAY RECAP ********************************************************************************************************************************************
a.vandud.ru : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
b.vandud.ru : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[vandud@thinkpad ansible]$ ansible-playbook playbook.yaml
PLAY [vars and if's] **********************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************
ok: [b.vandud.ru]
ok: [a.vandud.ru]
TASK [change file] ************************************************************************************************************************************
ok: [b.vandud.ru]
ok: [a.vandud.ru]
PLAY RECAP ********************************************************************************************************************************************
a.vandud.ru : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
b.vandud.ru : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
debug
Можно выводить факты о системе.
Выводить можно с помощью модуля debug, он имеет два параметра:
- var - получает на вход имя выводимой переменной
- msg - получает любой текст который нужно вывести
Вот плейбук и вывод:
---
- name : vars and if's
hosts: test
tasks:
- name: "print ansible_distribution with debug:msg"
debug:
msg: "{{ ansible_distribution }}"
- name: "print ansible_distribution with debug:var"
debug:
var: ansible_distribution
PLAY [vars and if's] **********************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************
ok: [b.vandud.ru]
ok: [a.vandud.ru]
TASK [print ansible_distribution with debug:msg] ******************************************************************************************************
ok: [a.vandud.ru] => {
"msg": "Ubuntu"
}
ok: [b.vandud.ru] => {
"msg": "Ubuntu"
}
TASK [print ansible_distribution with debug:var] ******************************************************************************************************
ok: [a.vandud.ru] => {
"ansible_distribution": "Ubuntu"
}
ok: [b.vandud.ru] => {
"ansible_distribution": "Ubuntu"
}
PLAY RECAP ********************************************************************************************************************************************
a.vandud.ru : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
b.vandud.ru : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Поле name можно и не использовать. Того вместо имени в выводе будет указываться название используемого модуля.
set_fact
Можно создать переменную в плейбуке без блока vars. Для этого используется модуль set_fact:
- set_fact: vandud_var="Server works at {{ ansible_distribution }}"
- debug:
msg: "{{ vandud_var }}"
И вывод:
TASK [set_fact] ***************************************************************************************************************************************
ok: [a.vandud.ru]
ok: [b.vandud.ru]
TASK [debug] ******************************************************************************************************************************************
ok: [a.vandud.ru] => {
"msg": "Server works at Ubuntu"
}
ok: [b.vandud.ru] => {
"msg": "Server works at Ubuntu"
}
register
Команда register помогает сохранить вывод таски. В ней указывается имя переменной по которой будет доступен вывод. Сама переменная содержит в себе json с множеством полей: начало выполнения таски, была ли ошибка, сам вывод и тд. И так как это json то можно через точку выбрать нужное поле как в примере ниже:
---
- name: vars and if's
hosts: test
tasks:
- set_fact: vandud_var="Server works at {{ ansible_distribution }}"
- debug:
msg: "{{ vandud_var }}"
- shell: uptime
register: uptime_out
- debug:
msg: "{{ uptime_out.stdout }}"
И вывод
TASK [debug] ******************************************************************************************************************************************
ok: [a.vandud.ru] => {
"msg": " 04:43:31 up 1 day, 21:08, 1 user, load average: 0.08, 0.02, 0.01"
}
ok: [b.vandud.ru] => {
"msg": " 04:43:31 up 1 day, 23:56, 1 user, load average: 0.08, 0.02, 0.01"
}
when
Чтобы указать условия при которых должна выполниться таска, нужно использовать директиву when. Она является свойством таски:
---
- name: vars and if's
hosts: test
tasks:
- service: name=nginx state=stopped
when: ansible_venet0_0.ipv4.address == '185.176.25.117'
Следующий плейбук отключает nginx на соответсвующем хосте.
Вывод предыдущего плейбука:
[vandud@thinkpad ansible]$ ansible-playbook playbook.yaml
PLAY [vars and if's] **********************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************
ok: [b.vandud.ru]
ok: [a.vandud.ru]
TASK [service] ****************************************************************************************************************************************
skipping: [a.vandud.ru]
changed: [b.vandud.ru]
PLAY RECAP ********************************************************************************************************************************************
a.vandud.ru : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
b.vandud.ru : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Как видно, он скипает неподходящий хост, и изменяет только подходящий под условие.
Блоки
С помощью блоков можно объединять таски в контейнеры (группы). И потом например применить к этой группе общее условие (when):
---
- name: when and block
hosts: all
tasks:
- block:
- service: name=nginx state=stopped
- service: name=apache2 state=started
when: ansible_venet0_0.ipv4.address == '185.176.25.117'
Циклы
Можно выполнять таску несколько раз проходя по какому-то списку аргументов.
Для этого можно использовать with_items и переменную item:
# playbook.yaml
---
- name: My Super Playbook
hosts: all
tasks:
- name: Say Hello to All
debug:
msg: "Hello {{ item }}!"
with_items:
- "Ivan"
- "Niga"
- "Mazafaka"
Переменная item зарезервирована и в своих целях (кроме циклов) ее использовать нельзя.
В примере выше можно заменить with_items на loop и плейбук отработает идентично.
Также есть оператор until, он позволяет повторять одно и то же действие пока не будет достигнуто какое-то условие:
---
- name: My Super Playbook
hosts: all
tasks:
- name: Loop Until
shell: echo -n Niga >> /tmp/myfile && cat /tmp/myfile
register: output
delay: 2
retries: 10
until: output.stdout.find("NigaNigaNiga") == false
В примере выше, в файл печатается слово и выводится на экран. Вывод записывается в переменную и это продолжается пока в переменной не накопится три таких слова.
retries по умолчанию имеет значение 3
Чтобы скопировать много файлов можно использовать with_fileglob. С его помощью можно указать паттерн ("*.txt"), а можно и не указывать
---
- name: My Super Playbook
hosts: all
tasks:
- name: Loop fileglob
copy: src={{ item }} dest=/var/www/html/
with_fileglob: "/tmp/test/*"
Как видно, все закопировалось.
[vandud@desktop ansible]$ ansible-playbook playbook.yaml
...
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/20.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/20.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/19.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/19.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/18.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/18.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/17.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/17.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/16.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/16.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/15.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/15.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/14.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/14.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/13.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/13.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/12.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/12.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/11.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/11.txt)
changed: [db.ru-ovz.vandud.ru] => (item=/tmp/test/10.txt)
changed: [back.ru-ovz.vandud.ru] => (item=/tmp/test/10.txt)
...
Для рекурсивного копирования подходит модуль copy
Jinja
Можно копировать файлы на сервер изменяя их на ходу. Для этого используется модуль template, он использует переменные, которые можно определить где угодно:
- hosts
- group_vars
- playbook
Также он может использовать переменные из фактов о системе (из модуля setup).
В файлах которые нужно изменять нужно указывать переменные в Jinja формате - {{ varname }}
Модуль template аналогичен модулю copy, только он еще и понимает вызовы переменных в копируемых файлах.
В файле group_vars/all определена переменная:
---
ansible_user: root
mycoolvar: nigamazafaka
Вот такой файл с шаблонами внутри:
Generated by ansible for {{ ansible_fqdn }}<br>
Virtualization type - {{ ansible_virtualization_type }}<br>
OS - {{ ansible_lsb.description }}<br>
User Var - {{ mycoolvar }}
И вот такой плейбук:
---
- name: My Super Playbook
hosts: db
tasks:
- name: Generate index.html
template: src=index.j2 dest=/var/www/html/index.html
Дают такой результат:
Роли
Нужны для упрощения плейбуков, а точнее для структурирования и разбиения на отдельные файлы.
Вместо одного длинного и сложного плейбука будет множество файлов и директорий.
С помощью команды ansible-galaxy init my-cool-role
внутри директории roles создается вот такая структура для роли my-cool-role:
└── my-cool-role
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
- files - файлы (в плейбуке файлы будут браться из этой папки)
- templates - тоже файлы, но они обрабатываются как шаблоны jinja, модулем template
- vars и defaults - для переменных
- handlers - для хэндлеров
- tasks - сам плейбук
- meta - описание зависимостей и прочие мета-данные типа автор и описание
Jinja-темплейт:
[vandud@desktop ansible]$ cat roles/my-cool-role/templates/index.j2
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ ansible_fqdn }}</title>
<style>
body {
background-image: url({{ ansible_nodename }}-bg.jpg);
}
</style>
</head>
<body>
System Info:<br>
Kernel: {{ ansible_kernel }}<br>
LSB: {{ ansible_lsb.description }}<br>
Hostname: {{ ansible_fqdn }}<br>
CPU: {{ ansible_processor[2] }}<br>
Update time: {{ ansible_date_time.time }} {{ ansible_date_time.date }}
</body>
</html>
Таски в роли:
[vandud@desktop ansible]$ cat roles/my-cool-role/tasks/main.yml
---
# tasks file for my-cool-role
- name: Copy picture to server
copy:
src: "{{ ansible_nodename }}-bg.jpg"
dest: "/var/www/html/{{ ansible_nodename }}-bg.jpg"
mode: 770
owner: www-data
group: www-data
- name: Copy index to server
template:
src: index.j2
dest: /var/www/html/index.html
mode: 770
owner: www-data
group: www-data
И сам плейбук:
---
- name: Picture and Sysinfo
hosts: all
roles:
- my-cool-role
Получается вот так:
extra-vars
Эта функция позволяет передавать переменные в плейбук при его вызове.
Плейбук который по-умолчанию исполняется для всех хостов, но так как поле hosts определено как переменная, то его можно переопределить при вызове плейбука:
[vandud@desktop ansible]$ cat playbook.yaml
---
- name: Picture and Sysinfo
vars:
node_to_exec: all
hosts: "{{ node_to_exec }}"
roles:
- my-cool-role
Вот так передаем переменную при вызове:
ansible-playbook playbook.yaml -e "node_to_exec=db ansible_kernel=test_kernel"
Несколько переменных можно перечислить через пробел.
extra_vars имеют наивысший приоритет
На скриншоте видно, что переменная ansible_kernel переопределилась в соответствии с extra_vars
import, include
Нужны для включения файла с инструкциями (плейбука) в другой файл (плейбук).
Импорты предобрабатываются, а инклуды обрабатываются по мере выполнения плейбука.
Отличаются они тем, что import сразу (перед выполнением) переопределяет все переменные из импортируемого файла, а include делает это только во время выполнения.
Я не понял в чем на самом деле разница (опытным путем тоже не смог понять). На первый взгляд разницы нет. Думаю пока в моих кейсах эта разница не имеет значения.
Автор курса использует везде include - думаю мне пока следует делать так же.
delegate_to
Нужно для выполнения таски на другом сервере.
Например когда после действий на одном сервере нужно сделать какие-то на другом:
---
- name: delegate_to
hosts: db
tasks:
- debug:
msg: reboot server
- copy:
dest: /tmp/delegate_to
content: delegated
delegate_to: back.ru-ovz.vandud.ru
Как видно в примере выше, сам плейбук выполняется для группы db, но одна маленькая таска в нем выполняется на сервере back.ru-ovz.vandud.ru
Проверяем что это работает
[vandud@desktop ansible]$ ansible -m shell -a "cat /tmp/delegate_to" back
back.ru-ovz.vandud.ru | CHANGED | rc=0 >>
delegated
Также таким образом можно писать локальные логи:
---
- name: delegate_to
hosts: all
tasks:
- debug:
msg: reboot server
- shell: echo {{ ansible_nodename }} was rebooted >> /tmp/delegate_to
delegate_to: localhost
Таска на запись в лог делегируется локальной машине и мы получаем вот такой файл:
]$ cat /tmp/delegate_to
db was rebooted
back was rebooted
И еще можно ждать пока перезагрузится сервер.
Например как-нибудь вот так:
---
- name: delegate_to
hosts: all
tasks:
- shell: sleep 3 && reboot now
async: 1 # чтобы продолжить выполнение следующих тасок без ожидания завершения этой
poll: 0 # не ходить за статусом выполнения команды
run_once: true
- name: wait
wait_for:
host: all
state: started
delay: 15
timeout: 30
delegate_to: localhost
- name: get uptime
shell: "uptime"
register: uptime
- debug:
var: uptime
run_once позволяет запустить таску только один раз на сервере который подошел первым (по очередности в hosts)
ignore_errors
Обычно, если одна из тасок зафейлилась, то все последующие таски выполняться не будут.
ignore_errors позволяет это обойти. Нужно в случаях, когда не важно выполнится таска или нет.
---
- name: delegate_to
hosts: all
tasks:
- apt:
name: treeee
state: present
ignore_errors: yes
- debug:
msg: Test
failed_when
Можно указывать условия при которых нужно завершить работу плейбука.
---
- name: delegate_to
hosts: all
tasks:
- apt:
name: treeee
state: present
ignore_errors: yes
- shell: echo niga # тут например результат работы какой-либо команды или скрипта
register: myvar
failed_when: "'iga' in myvar.stdout" # либо какая-то ansible-переменная, указывающая на определенное состояние
Еще пример
---
- name: delegate_to
hosts: all
tasks:
- apt:
name: treeee
state: present
ignore_errors: yes
- shell: uptime -p
register: uptime
failed_when: ansible_nodename == 'back'
- debug:
var: uptime
Остановить выполнение тасок на всех хостах при падении таски на одном из них поможет any_errors_fatal
---
- name: delegate_to
hosts: all
any_errors_fatal: yes
tasks:
- apt:
name: treeee
state: present
ignore_errors: yes
- shell: uptime -p
register: uptime
failed_when: ansible_nodename == 'back'
- debug:
var: uptime
Игнорируемые ошибки пройдут нормально. Но failed_when в этом примере остановит весь процесс (хотя он нацелен лишь на один хост
ansible-vault
-
ansible-vault encrypt playbook.yaml
- зашифровать плейбук (или любой другой файл) -
ansible-playbook playbook.yaml --ask-vault-pass
- запустить зашифрованный плейбук с ручным вводом пароля -
ansible-playbook playbook.yaml --vault-password-file pass
- пароль из файла -
ansible-vault decrypt playbook.yaml
- расшифровать -
ansible-vault rekey playbook.yaml
- изменить пароль -
ansible-vault edit playbook.yaml
- редактировать зашифрованный файл (откроется редактор) -
ansible-vault create test
- создать зашифрованный файл (откроется редактор) -
ansible-vault view test
- вывести содержимое файла (срабатывает как cat)
Можно зашифровать кусок плейбука или переменную или что-то другое:
-
ansible-vault encrypt_string
- полученный текст можно вставить в плейбук
[vandud@desktop ansible]$ echo -n 'nigamazafaka' | ansible-vault encrypt_string
New Vault password:
Confirm New Vault password:
Reading plaintext input from stdin. (ctrl-d to end input)
!vault |
$ANSIBLE_VAULT;1.1;AES256
65333931323136333731323934313439326664353934323034353964373731383931663731336561
3962646635656664643037643866656530383831633934340a656237363737653065643138616636
63663565376638646366313931396232316236643064396332393838633734343163613435613561
6537623536383639380a326265373936633866623832326437306139633665356635646538343732
3834
Encryption successful
Вставить в плейбук можно так
---
- name: vault
hosts: all
vars:
out_var: !vault |
$ANSIBLE_VAULT;1.1;AES256
65333931323136333731323934313439326664353934323034353964373731383931663731336561
3962646635656664643037643866656530383831633934340a656237363737653065643138616636
63663565376638646366313931396232316236643064396332393838633734343163613435613561
6537623536383639380a326265373936633866623832326437306139633665356635646538343732
3834
tasks:
- debug:
var: out_var
Но тогда запускать плейбук нужно с ключом для запроса пароля (либо через файл с паролем)
ansible-playbook playbook.yaml --ask-vault-pass
Важно шифровать данные одним паролем. Потому что при запуске плейбука можно указать только один пароль и если данные зашифрованы разными паролями, то какие-то данные расшифруются переданным паролем, а какие-то нет и будет ошибочка.
No Comments