Используемые термины: Ansible.
Инструкция представляет из себя шпаргалку по работе с Ansible. У автора не стоит задачи подробного пояснения всех операций — только описание задачи и пример того, как ее можно решить с помощью ansible. Для более подробного описания я постараюсь указать ссылки на официальную документацию. Также в данную шпаргалку не войдут все возможные действия, которые можно выполнить с помощью данной системы — только популярные и те, с которыми приходилось сталкиваться самому автору. По мере возможности, их список будет пополняться.
Для удобства, мы попробуем разбить примеры на операции, которые логически можно объединить в одну группу.
Сюда войдут примеры, которые позволят собирать информацию, выводить ее на экран, помогать в отладке и всякое такое.
1. Показать информацию об удаленной системе, на которой запускается ansible.
Выполняется с помощью модуля debug, который должен показать содержимое ansible_facts:
— name: Print all available facts ansible.builtin.debug: var: ansible_facts
* ansible_facts содержит массив данных с информацией о системе. Однако, функция сборки информации может быть отключена (так как на ее работу тратится, относительно, много времени) в настройках плейбука с помощью опции gather_facts: false — в этом случае, значение нужно изменить на true.
Также мы можем обратиться к конкретному элементу массива ansible_facts, получив информацию о конкретной настройке или опции:
… ansible_facts.hostname
* например, имя компьютера.
Ссылка на документацию: https://docs.ansible.com/ansible/latest/user_guide/playbooks_vars_facts.html.
2. Отображение на экран переменной.
Выше мы уже использовали debug для отображения переменной — принцип тот же:
— name: Show Value of Variable debug: msg: «{{ variable }}»
* при выполнении задачи на экране мы увидим значение переменной variable. Обратите внимание, что запись ansible.builtin.debug и debug — это одно и то же, то есть, ansible.builtin можно не писать.
О debug: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/debug_module.html.
3. Сохранение результата в переменную.
Результат выполняется команды может быть сохранен с помощью register:
— name: Run a shell command and register its output as a variable shell: command register: command_result
* в данном примере мы запишем в переменную command_result все то, что мы получили с помощью команды command.
Также нам может понадобиться сохранить в переменную результат обработки строки или другой переменной:
— name: Set variable set_fact: my_hosts: «{{ command_result.stdout.split(‘:’) | replace(‘ ‘, ») }}»
* в данном случае мы взяли переменную, которую получили в примере выше и разбили строку по знаку «:». Таким образом, мы получим массив данных, который будет сохранен в переменную my_hosts.
Вывести на экран содержимое можно с помощью debug:
— name: Show Value of Variable debug: var: command_result.stdout
* обратите внимание, что мы выводим не все содержимое, а только stdout, то есть то, что должна была вывести в консоль команда.
4. Получить список сервисов.
Для этого существует service_facts:
— name: Populate service facts ansible.builtin.service_facts:
— name: Print all available facts ansible.builtin.debug: var: ansible_facts.services
* цель достигается двумя задачами. В первой мы собираем информацию о сервисах с помощью service_facts, второй — выводим на экран содержимое.
О service_facts: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/service_facts_module.html.
В данную группу войдут действия, которые помогут нам ограничить выполнение задач.
1. Проверка на пустую папку.
Задачи сводится к двум операциям:
Пример будет таким:
— name: Register Contents of PGDATA Folder shell: ls /var/lib/postgresql/11/main register: pg_contents
— name: Init PostgreSQL DB shell: /opt/pgpro/std-11/bin/pg-setup initdb environment: PGDATA: «/var/lib/postgresql/11/main» when: pg_contents[«stdout_lines»] | length == 0
* в данном примере мы в первой задаче выводим содержимое каталога /var/lib/postgresql/11/main и помещаем его в переменную pg_contents. Во второй задаче мы уже проверяем с помощью when количество строк — если их 0, то тогда выполняем команду initdb. На практике, это важно, так как инициализация базы PostgreSQL при непустом каталоге выводит сообщение об ошибке.
О when: https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html.
2. Проверить, определена ли переменная.
Для этого используется опция is defined (определена) или is not defined (не определена):
when: pgpro is defined
when: pgpro is not defined
* в данном примере мы проверим наличие переменной pgpro. На практике такая проверка имеет значение, так как если мы попробуем выполнить действия с несуществующей переменной, Ansible нам вернет ошибку.
В официальной документации про это сказано в статье о when (ссылка выше).
3. Выполнение команды, если сервис в рабочем состоянии.
Нам необходимо получить информацию о службах с помощью service_facts, после чего можно уже делать проверку с помощью when:
— name: Stop Service If Running One shell: systemctl stop apache2 when: ansible_facts.services[«apache2.service»] is defined and ansible_facts.services[«apache2.service»].state == «running»
* в данном примере мы проверим, есть ли служба apache2 и запущена ли она. Если это так, то мы ее останавливаем.
Подробнее о service_facts можно прочитать в документации (ссылка выше в разделе 4. Получить список сервисов).
В данном разделе мы коснемся всего, что приводит к установке чего бы то ни было. А именно:
Рассмотрим это подробнее.
1. Установка пакетов в систему.
Выполняется с помощью модуля package:
— name: Install NTP-client package: name: chrony state: present
* по данной инструкции в нашей системе должен присутствовать пакет chrony.
О package: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/package_module.html.
2. Установка модуля в nodejs.
Установка модулей в nodejs выполняется с помощью npm. Для него в ansible есть отдельная функция:
— name: Install nodejs modules. npm: name: newman global: yes
* в данном примере будет выполнена установка newman, которая будет доступна всем проектам (опция global).
О nodejs npm: https://docs.ansible.com/ansible/latest/collections/community/general/npm_module.html.
3. Загрузка из GIT.
Выполняется с помощью модуля git:
— name: Clone docker-compose git: repo: «https://github.com/docker/compose.git» dest: /tmp/docker-compose
* в данном примере мы сделаем клон репозитория в каталог /tmp/docker-compose.
О Git: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/git_module.html.
4. Распаковка архива.
Выполняется с помощью unarchive:
— name: Unpacking Nginx Source unarchive: src: «http://nginx.org/download/nginx-{{ nginx_ver }}.tar.gz» dest: /tmp/ remote_src: yes creates: /tmp/nginx-{{ nginx_ver }}.tar.gz
* в данном примере мы распакуем исходник для nginx в каталог /tmp. Обратите внимание на две вещи:
Об unarchive: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/unarchive_module.html.
В данном разделе мы рассмотрим процессы, которые больше подходят для категории настройки системы.
1. Добавить задание в cron.
Выполняется с помощью модуля cron:
— name: Add Job for Run Command cron: name: Start Script job: «/scripts/command.sh» user: root minute: «0» hour: «*/6» day: «*» month: «*» weekday: «*»
* в данном примере мы создадим задание для запуска команды /scripts/command.sh каждый день, каждые 6 часов.
О cron: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/cron_module.html.
2. Добавить публичный ключ хоста в known_hosts.
Делается с помощью known_hosts. Пример из официальной документации:
— name: Tell the host about our servers it might want to ssh to known_hosts: path: /etc/ssh/ssh_known_hosts name: foo.com.invalid key: «{{ lookup(‘file’, ‘pubkeys/foo.com.invalid’) }}»
* в данном примере мы добавим ключ из файла pubkeys/foo.com.invalid в /etc/ssh/ssh_known_hosts.
О known_hosts: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/known_hosts_module.html.
3. Создание новых SSH-ключей для сервера.
Создание ключей реализуется с помощью модуля openssh_keypair:
— name: Generate New SSH Host Keys openssh_keypair: path: «/etc/ssh/ssh_host_{{ item.type }}_key» owner: root state: present type: «{{ item.type }}» size: «{{ item.size }}» force: yes loop: — { type: dsa, size: 1024 } — { type: ecdsa, size: 521 } — { type: ed25519, size: 2048 } — { type: rsa, size: 2048 }
* в данном примере мы создадим 4 ключа разных типов: dsa, ecdsa, ed25519, rsa. Так как у каждого из них свои требования к размеру, перечень представлен в виде двумерного массива. Ключи будут созданы в каталоге /etc/ssh/.
О openssh_keypair: https://docs.ansible.com/ansible/latest/collections/community/crypto/openssh_keypair_module.html.
4. Создание системной учетной записи.
Для этого есть модуль user. У него много опций, но для создания системной учетной записи нам достаточно:
— name: Create User Consul user: name: consul system: yes comment: «Consul Agent»
* в данном примере будет создана учетная запись consul.
О user: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html.
5. Работа с systemd.
Для данной настройки есть одноименный модуль systemd. Рассмотрим варианты его использования.
а) перечитать конфигурацию (необходимо делать каждый раз, когда мы меняем настройки юнита):
— name: systemd reload systemd: daemon_reload: yes
б) разрешить сервис (автозапуск):
— name: mysql enable systemd: name: mysql enabled: yes
* для сервиса mysql.
в) перезапустить сервис:
— name: mysql reload systemd: name: mysql state: restarted
О systemd: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/systemd_module.html.
6. Настройка брандмауэра.
Выполняется разными модулями в зависимости от используемой системы управления netfilter:
Рассмотрим небольшие примеры.
а) firewalld:
— name: permit traffic in default zone for https service firewalld: service: https permanent: yes state: enabled
Подробнее: https://docs.ansible.com/ansible/latest/collections/ansible/posix/firewalld_module.html.
б) iptables:
— name: Block specific IP iptables: chain: INPUT source: 8.8.8.8 jump: DROP
Подробнее: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/iptables_module.html.
в) UFW.
Добавить 80 порт:
— name: Allow all access to tcp port 80 ufw: rule: allow port: ’80’ proto: tcp
Добавить порты с циклом:
— name: Allow Ports in Firewall ufw: rule: allow port: «{{ item.port }}» proto: «{{ item.proto }}» comment: «{{ item.comment }}» loop: — { port: 5432, proto: tcp, comment: ‘PostgreSQL’ }
Подробнее: https://docs.ansible.com/ansible/latest/collections/community/general/ufw_module.html.
Рассмотрим задачи, которые помогут нам создавать, копировать и работать с файлами.
1. Создание каталогов и файлов.
Создание файлов и каталогов выполняется с помощью модуля file.
а) для каталога в качестве state указываем directory:
— name: Create Directories file: path: «{{ item }}» state: directory owner: www-data group: www-data mode: 0755 loop: — ‘/var/www/site1’ — ‘/var/www/site2’
* в данном примере мы создадим 2 каталога: site1 и site2 в каталоге /var/www.
б) для создания файла указываем убираем опцию state (или даем ей значение file):
— name: Create File file: path: «/var/www/site1/index.php» owner: www-data group: www-data mode: 0644
* в данном примере мы созданим файл index.php в каталоге /var/www/site1.
О file: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html.
2. Копирование файлов из каталога.
Для копирования данных мы используем модуль copy:
— name: Copy Cert File If Different copy: src: «{{ item }}» dest: /etc/ssl/admins24 remote_src: no mode: 0644 owner: root group: root with_fileglob: — files/*
* в данном примере мы прочитаем все содержимое каталога files на компьютере с ansible, и скопируем его в каталог /etc/ssl/admins24 на целевом компьютере.
О copy: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html.
3. Используем шаблон.
Копирование из шаблона отличается от копирования из файла тем, что в шаблоне могут использоваться переменные, которые будет заменяться их значениями в момент копирования. Для самого процесса копирования из шаблона используется модуль template:
— name: Create Config for Consul Agent template: src: templates/consul/config.json.j2 dest: /etc/consul.d/config.json
* в данном примере мы возьмом шаблон templates/consul/config.json.j2 на компьютере ansible и разместим его в по пути /etc/consul.d/config.json на целевом компьютере.
Мы можем вывести в консоль результат обработки шаблона следующим образом:
— name: Show Templating Results debug: msg: «{{ lookup(‘template’, ‘./config.json.j2’) }}»
О template: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/template_module.html.
4. Удалить последние 30 файлов.
Задача решается в два этапа:
Поиск выполняем с помощью модуля find, удаление — file:
— name: «Get list of backup files» find: paths: «/backup» file_type: file register: founds
— name: «Delete last 30 Copies» file: path: «{{ item }}» state: absent loop: «{{ (founds.files | sort(attribute=’mtime’, reverse=True) | map(attribute=’path’) | list )[30:] }}»
* в данном примере мы ищем файлы в каталоге /backup, после чего сортируем найденное и удаляем по списку все файлы, которые идут после 30-го.
О find: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/find_module.html.
5. Скачать файл с помощью curl.
Для этого используется модуль uri. Простой пример:
— name: CURL simple download file uri: url: https://admins24.com/files/winsetupfromusb.zip dest: /tmp
* в данном примере мы загрузим файл https://admins24.com/files/winsetupfromusb.zip в каталог /tmp.
Пример посложнее:
— name: CURL download file with token auth uri: url: https://gitlab.admins24.ru/api/v4/projects/555/repository/files/folder%2Fpath%2Fdata.sql/raw?ref=master dest: /tmp/data.sql owner: admins24 group: admins24 mode: 640 headers: PRIVATE-TOKEN: access-token
* в данном примере мы скачаем файл с ресурса, где требуется аутентификация по токену, который передается в заголовке. Заголовки мы передаем с помощью параметра headers. Также мы задаем права на загруженный файл и делаем в качестве владельца пользователя и группу admins24.
Об uri: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/uri_module.html.
С помощью Ansible мы можем менять содержимое строк как в файлах — вставлять, удалять и редактировать, так и полученных результатах. Рассмотрим несколько примеров.
1. Замены строки в файлах.
Замены выполняются с помощью модуля replace:
— name: Check configs (comment server address 127.0.0.1) replace: path: «/etc/nginx/nginx.conf» regexp: ‘^server.address=127.0.0.1$’ replace: ‘#server.address=127.0.0.1’
* в данном примере мы добавляем комментарий к строке server.address=127.0.0.1.
О replace: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/replace_module.html.
2. Добавление и удаление строк в файле.
Мы можем менять содержимое файла с помощью модуля lineinfile. Рассмотрим некоторые примеры работы с ним.
а) Удалить строку:
— name: Remove server strings lineinfile: path: «/etc/chrony.conf» regexp: ‘^server .*’ state: absent
* в данном примере мы удалим все строки из файла /etc/chrony.conf, которые начинаются на server.
б) Добавить строку:
— name: Add server strings lineinfile: path: «/etc/chrony.conf» line: ‘server ntp.server.local’
* в данном примере мы добавим строку server ntp.server.local в файл /etc/chrony.conf. Если данная запись уже есть в файле, ansible ничего не станет менять.
О lineinfile: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html.
3. Разбить строку.
Выполняется с помощью метода split. Рассмотрим пример, когда мы регистрируем результат при выполнении команды, после чего мы разобьем его по предложениям:
— name: Parse string for dot and show results ansible.builtin.debug: var: command_result.stdout.split(«.»)
* в данном примере мы получим массив данных из предложений.
Работа с виртуальными машинами на платформе VMware выполняется с помощью модуля vmware_guest.
Подробнее о vmware_guest: https://docs.ansible.com/ansible/latest/collections/community/vmware/vmware_guest_module.html.
Мы рассмотрим несколько примеров.
1. Базовое подключение.
Для выполнения действий над виртуальными машинами мы должны подключиться к хосту VMware. Для этого используем данные строки:
— name: Connect to ESX Host vmware_guest: hostname: «{{ vcenter_hostname }}» username: «{{ vcenter_username }}» password: «{{ vcenter_password }}» validate_certs: no
* параметр validate_certs, выставленный в no, позволит избежать ошибки, если у нас на хосте используется самоподписанный сертификат (как правило, так и есть).
2. Переименовать виртуальную машину.
Для выполнения действия нам нужно знать идентификатор виртуальной машины:
— name: Rename a virtual machine vmware_guest: hostname: «{{ vcenter_hostname }}» username: «{{ vcenter_username }}» password: «{{ vcenter_password }}» validate_certs: no uuid: «{{ hw_product_uuid }}» name: «Template-{{ vm_name }}» state: present
* где uuid — идентификатор виртуальной машины; name — новое имя виртуальной машины.
3. Конвертировать виртуальную машину в шаблон.
Для этого нужно просто задать признак is_template:
— name: Convert virtual machine to Template vmware_guest: hostname: «{{ vcenter_hostname }}» username: «{{ vcenter_username }}» password: «{{ vcenter_password }}» validate_certs: no uuid: «{{ vm_info.instance.hw_product_uuid }}» is_template: true state: present
В данном разделе будет рассказано о дополнительных опциях, которые позволяют менять поведение выполнения задач, добавляет функциональности или все то, для чего не найдена отдельная подходящая категория.
1. Шифрование строки.
С помощью ansible-vault мы можем шифровать файлы и папки. Это позволит нам хранить секреты не в открытом виде. Данные расшифровываются в момент выполнения задач.
Данной командой мы получаем шифрованную строку:
ansible-vault encrypt_string
Система запросит ввести дважды пароль и предложит ввести строку, которую нужно зашифровать. После мы должны нажать 2 раза Ctrl + D — мы получим строку, которая начинается с !Vault и различные символы.
Для того, чтобы в момент выполнения задачи ansible расшифровал данные, при запуске плейбука мы должны указать ключ —ask-vault-pass:
ansible-playbook … —ask-vault-pass
Об ansible-vault: https://docs.ansible.com/ansible/latest/user_guide/vault.html.
2. Игнорировать ошибки.
Если ansible столкнется с ошибкой при выполнении задачи, работа плейбука будет завершена. Иногда, нужно пропустить ошибку при выполнении определенной задачи, чтобы выполнение было продолжено. Для этого существует опция ignore.
а) чтобы пропустить ошибки выполнения, в настройка задачи используем:
— name: Bad Task … ignore_errors: yes
б чтобы игнорировать ошибки при подключении к хосту:
— name: Bad Task … ignore_unreachable: yes
3. Начинать выполнение с определенной задачи.
При выполнении отладки, полезно запустить плейбук, но начать выполнение с определенной задачи. Остальные пропустить.
Это можно сделать с помощью опции —start-at-task:
ansible-playbook … —start-at-task=»Start Job»
* в данном примере плейбук начнет выполнять задания с задачи Start Job.
4. Завершить выполнение плейбука после определенной задачи.
С помощью данной конструкции:
— meta: end_play
5. Зависимые роли.
С помощью файла meta/main.yml в роли мы можем определить пред-роль, от которой зависит выполнение текущей роли. Для этого настраивается опция dependencies:
dependencies: — role: pred
6. Вставка роли и ее задач.
Позволяет в процессе выполнения задачи подключить роль. Делается при помощи include_role:
— name: «Include Other Role» include_role: name: other_role
А это пример, как подключить роль и сделать так, чтобы все ее задачи выполнились на определенном хосте:
— name: «Include Other Role» include_role: name: other_role apply: delegate_to: «{{ deploy_vm.instance.ipv4 }}»
7. Повторы при выполнении задачи.
Мы можем управлять цикличностью выполнения задач с помощью retries (количиство повторов), delay (задержка в секундах).
Рассмотрим пример повтора выполнения задачи при возникновении ошибки:
— name: Run anything command command: /foo/bar/cmd register: result retries: 3 delay: 60 until: result is not failed
* в данном примере мы будем выполнять команду /foo/bar/cmd пока ее выполнение не закончится без ошибок. Количество повторов будет равен 3 с интервалом в 60 секунд.
Небольшой пример на странице https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#retrying-a-task-until-a-condition-is-met.
8. Резервное копирование базы данных MySQL/MariaDB.
Работа с базой данных возможно с помощью коллекции mysql.mysql_db. Она не идет в комплекте к ansible и нам необходимо ее установить командой:
ansible-galaxy collection install community.mysql
Резервное копирование можно выполнить так:
— name: Dump mysql databases community.mysql.mysql_db: state: dump name: — db1 — db2 target: /tmp/dump.sql
* в данном примере мы создадим 2 дампа из баз db1 и db2 и сохраним результат в файл /tmp/dump.sql.
О mysql_db: https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_db_module.html.
9. Объединение задач в блоки.
Это позволит установить общие свойства и условие для нескольких задач. Такая форма записи уменьшит количиство строк и упростит восприятие.
Синтаксис записи:
— name: Block Name block: — name: Task 1 …
— name: Task 2 …
— name: Task 3 … when: ansible_facts[‘distribution’] == ‘CentOS’ become: true become_user: root ignore_errors: yes
* в данном примере будет выполнены 3 задачи, если выполнится одно условие, которое описывается не для задач, а для блока.
О block: https://docs.ansible.com/ansible/latest/user_guide/playbooks_blocks.html.
10. Перебор массива.
Предположим, нам нужно перебрать все элементы массива в шаблоне. Это можно сделать конструкцией:
{% for host in my_hosts %}server «{{ host }}»{% endfor %}
* в данном примере мы сделаем перебор по переменной my_hosts. Для каждого элемента массива будет создана строка со значением server <значение переменной>.
Другая информация по Ansible:
1. Инструкция по установке и запуску Ansible на Linux.
2. Примеры ролей Ansible для установки сервисов и настройки системы.
Продолжая использовать данный сайт вы принимаете политику конфиденциальности и cookies