До сих пор вы создавали сценарии Ansible для автоматизации определенной задачи на управляемых узлах. Существует огромная вероятность, что кто-то другой уже разработал Ansible-решение проблемы/задачи, которую вы пытаетесь решить, и именно в этом суть ролей Ansible.
В этом руководстве вы поймете, как структурированы роли в Ansible. Вы также научитесь использовать готовые роли из Ansible Galaxy.
Кроме того, вы научитесь создавать свои собственные роли Ansible.
Прежде чем приступить к изучению этой статьи, обратитесь к другим главам серии руководств по Ansible, чтобы лучше понять различные темы, упомянутые здесь.
Понимание ролей Ansible
Роль Ansible — это набор файлов, задач, шаблонов, переменных и обработчиков, которые вместе служат определенной цели, например, для настройки службы. Роли позволяют легко повторно использовать код и делиться решениями Ansible с другими пользователями, что делает работу с большими средами более управляемой.
Структура каталога ролей
Типичная роль Ansible следует определенной структуре каталогов, которая обычно состоит из следующих каталогов:
- defaults: содержит переменные по умолчанию для роли, которые должны быть легко перезаписаны.
- vars: содержит стандартные переменные для роли, которые не должны быть перезаписаны в вашей книге.
- tasks: содержит набор задач, которые должна выполнять роль.
- handlers: содержит набор обработчиков, которые будут использоваться в роли.
- templates: содержит шаблоны Jinja2, которые будут использоваться в роли.
- files: содержит статические файлы, необходимые из ролевых задач.
- tests: может содержать дополнительный файл инвентаря, а также playbook test.yml, который можно использовать для тестирования роли.
- meta: содержит метаданные роли, такие как информация об авторе, лицензия, зависимости и т. д.
Имейте в виду, что у роли могут быть все вышеупомянутые каталоги или только их часть. Фактически, вы можете определить пустую роль, у которой нет каталогов, но это бесполезно!
Хранение и расположение ролей
По умолчанию Ansible будет искать роли в двух местах:
- В каталоге role (тот же уровень каталога, что и ваш файл playbook).
- В каталоге /etc/ansible/roles.
Однако вы можете сохранить свои роли в другом месте; если вы решите это сделать, вы должны указать и установить параметр конфигурации roles_path в файле конфигурации Ansible ( ansible.cfg ).
Использование ролей Ansible в Playbooks
Есть два разных способа, которыми вы можете импортировать роли в пьесе Ansible :
- Использование ключевого слова roles для статического импорта ролей.
- Использование модуля include_role для динамического импорта ролей.
Например, чтобы статически импортировать роли в playbook, вы можете использовать ключевое слово роли в заголовке playbook следующим образом:
--- - name: Including roles statically hosts: all roles: - role1 - role2
Динамически импортировать роли; вы можете использовать модуль include_role следующим образом:
--- - name: Including roles dynamically hosts: all tasks: - name: import dbserver role include_role: name: db_role when: inventory_hostname in groups['dbservers']
Использование Ansible Galaxy для готовых ролей
Представьте себе место, где все нужные вам роли Ansible уже предоставляются бесплатно; Это место называется Ansible Galaxy и оно реально!
Ansible Galaxy — это общедоступный веб-сайт, на котором предлагаются роли, предоставленные сообществом. По сути, это публичный репозиторий, в котором размещается огромное количество ролей Ansible. Мы рекомендуем вам посетить сайт Ansible Galaxy galaxy.ansible.com и ознакомиться с его потрясающим контентом.
Поиск ролей
В Ansible Galaxy есть собственная утилита CLI (интерфейс командной строки), и вы можете использовать ее для выполнения операций, связанных с ролями.
Например, вы можете найти роль в репозитории Galaxy с помощью команды поиска ansible-galaxy следующим образом:
[destroyer@control plays]$ ansible-galaxy search mariadb Found 370 roles matching your search: Name Description ---- ----------- 0x_peace.mariadb Mariadb role 5003.mariadb SQL Server relational database > aalaesar.install_nextcloud Add a new Nextcloud instance in> aalaesar.upgrade-nextcloud Upgrade an Nextcloud instance i> aaronpederson.mariadb MariaDB - An enhanced, drop-in > acandid.mariadb Install and Configure MariaDB 1> acandid.mariadb_apache_wordpress Install and Configure MariaDB, > acandid.mariadb_galera_cluster Install and Configure MariaDB G> acandid.zabbix Install Zabbix 4.2 Server achaussier.mariadb-server Ansible role to install MariaDB> adfinis-sygroup.mariadb Install and manage mariadb/mysq> AdnanHodzic.containerized-wordpress Deploy & run Docker Compose pro> ajeeshbas.ansible_role_mariadb your description alainvanhoof.alpine_mariadb MariaDB for Alpine Linux alexandrem.mariadb MariaDB server role alexeymedvedchikov.galera An ansible role for Galera Mari> alexfeig.guacamole Ansible role for installing Apa> alikins.mysql MySQL server for RHEL/CentOS an> geerlingguy.mysql MySQL server for RHEL/CentOS an
Как вы видете; в нем перечислены все роли galaxy, связанные с моим поисковым запросом mariadb.
Получение информации о ролях
Вы можете использовать команду ansible-galaxy info для отображения информации о роли.
Например, на основе результатов поиска, которые вы получили ansible-galaxy search mariadb; вы можете получить дополнительную информацию о роли geerlingguy.mysql:
[destroyer@control ~]$ ansible-galaxy info geerlingguy.mysql Role: geerlingguy.mysql description: MySQL server for RHEL/CentOS and Debian/Ubuntu. active: True commit: 0a354d6ad1e4f466aad5f789ba414f31b97296fd commit_message: Switch to travis-ci.com. commit_url: https://api.github.com/repos/geerlingguy/ansible-role-mysql> company: Midwestern Mac, LLC created: 2014-03-01T03:32:33.675832Z download_count: 1104067 forks_count: 665 github_branch: master github_repo: ansible-role-mysql github_user: geerlingguy id: 435 imported: 2020-10-29T19:36:43.709197-04:00 is_valid: True issue_tracker_url: https://github.com/geerlingguy/ansible-role-mysql/is> license: license (BSD, MIT) min_ansible_version: 2.4 modified: 2020-10-29T23:36:43.716291Z open_issues_count: 24
Как вы видете; Он показал вам подробное описание роли geerlingguy.mysql.
Установка и использование ролей
Прежде чем я покажу вам, как установить роли Ansible Galaxy; Теперь создайте новый каталог ролей в каталоге вашего проекта (plays):
[destroyer@control plays]$ mkdir roles
Теперь вы можете использовать команду ansible-galaxy install для установки роли geerlingguy.mysql следующим образом:
[destroyer@control plays]$ ansible-galaxy install geerlingguy.mysql -p ./roles - downloading role 'mysql', owned by geerlingguy - downloading role from https://github.com/geerlingguy/ansible-role-mysql/archive/3.3.0.tar.gz - extracting geerlingguy.mysql to /home/destroyer/plays/roles/geerlingguy.mysql - geerlingguy.mysql (3.3.0) was installed successfully
Обратите внимание, что мы использовали параметр -p, чтобы указать путь, по которому мы хотим установить роль. По умолчанию Ansible Galaxy устанавливает роль в каталог ~/.ansible/roles.
Теперь перейдите в каталог ролей и перечислите содержимое каталога ролей geerlingguy.mysql:
[destroyer@control plays]$ cd roles/ [destroyer@control roles]$ ls geerlingguy.mysql [destroyer@control roles]$ tree geerlingguy.mysql/ geerlingguy.mysql/ ├── defaults │ └── main.yml ├── handlers │ └── main.yml ├── LICENSE ├── meta │ └── main.yml ├── README.md ├── tasks │ ├── configure.yml │ ├── databases.yml │ ├── main.yml │ ├── replication.yml │ ├── secure-installation.yml │ ├── setup-Debian.yml │ ├── setup-RedHat.yml │ ├── users.yml │ └── variables.yml ├── templates │ ├── my.cnf.j2 │ ├── root-my.cnf.j2 │ └── user-my.cnf.j2 └── vars ├── Archlinux.yml ├── Debian-10.yml ├── Debian.yml ├── RedHat-6.yml ├── RedHat-7.yml └── RedHat-8.yml 8 directories, 26 files
Как вы видете; geerlingguy.mysql роль следует стандартной структуре каталогов, что мы показали вам ранее.
Теперь давайте вернемся в каталог plays и создать новый PlayBook с именем MySQL-role.yml, который прикладывает роль geerlingguy.mysql на группу хоста dbservers:
[destroyer@control plays]$ cat mysql-role.yml --- - name: Applying geerlingguy.mysql role hosts: dbservers roles: - geerlingguy.mysql
Теперь запустите playbook:
[destroyer@control plays]$ ansible-playbook mysql-role.yml PLAY [Applying geerlingguy.mysql role] ***************************************** TASK [Gathering Facts] ********************************************************* ok: [node4] TASK [geerlingguy.mysql : include_tasks] *************************************** included: /home/destroyer/plays/roles/geerlingguy.mysql/tasks/variables.yml for node4 TASK [geerlingguy.mysql : Include OS-specific variables.] ********************** ok: [node4] => (item=/home/destroyer/plays/roles/geerlingguy.mysql/vars/Debian.yml) TASK [geerlingguy.mysql : Define mysql_packages.] ****************************** ok: [node4] TASK [geerlingguy.mysql : Define mysql_daemon.] . . . RUNNING HANDLER [geerlingguy.mysql : restart mysql] **************************** PLAY RECAP ********************************************************************* node4 : ok=32 changed=10 unreachable=0 failed=0 skipped=12
После того, как playbook будет запущен; mysql должен быть запущен на node4:
[destroyer@control plays]$ ansible node4 -m command -a "systemctl status mysql" node4 | CHANGED | rc=0 >> ● mysql.service - MySQL Community Server Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2020-11-10 23:31:51 UTC; 7min ago Process: 26544 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid (code=exited, status=0/SUCCESS) Process: 26524 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS) Main PID: 26546 (mysqld) Tasks: 28 (limit: 2265) CGroup: /system.slice/mysql.service └─26546 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid Nov 10 23:31:39 node4 systemd[1]: Starting MySQL Community Server... Nov 10 23:31:51 node4 systemd[1]: Started MySQL Community Server.
Если вам больше не нужна роль; вы можете удалить его с помощью команды ansible-galaxy remove следующим образом:
[destroyer@control plays]$ ansible-galaxy remove geerlingguy.mysql -p ./roles - successfully removed geerlingguy.mysql
Использование файла требований для установки нескольких ролей
Ansible galaxy может установить сразу несколько ролей, используя файл требований.
Каждая роль, которую вы определяете в своем файле требований, будет иметь еще один из следующих атрибутов:
- src: источник роли (обязательный атрибут).
- scm: если src является URL-адресом, укажите SCM. По умолчанию git; Поддерживаются только git и hg. (по желанию)
- имя: загрузка роли с определенным именем. По умолчанию используется имя Galaxy или имя репозитория при загрузке с git. (по желанию)
- версия: версия роли для загрузки. По умолчанию используется основная версия. (по желанию)
Чтобы продемонстрировать это, создайте файл requirements.yml со следующими тремя ролями:
[destroyer@control plays]$ cat requirements.yml # From Ansible Galaxy - src: geerlingguy.haproxy # From Github - src: https://github.com/bennojoy/nginx name: nginx_role version: master # From Ansible Galaxy - src: geerlingguy.jenkins name: jenkins_role
Теперь вы можете использовать команду установки ansible-galaxy вместе с параметром -r, чтобы установить три роли в вашем файле requirements.yml:
[destroyer@control plays]$ ansible-galaxy install -r requirements.yml -p ./roles - downloading role 'haproxy', owned by geerlingguy - downloading role from https://github.com/geerlingguy/ansible-role-haproxy/archive/1.1.2.tar.gz - extracting geerlingguy.haproxy to /home/destroyer/plays/roles/geerlingguy.haproxy - geerlingguy.haproxy (1.1.2) was installed successfully - extracting nginx_role to /home/destroyer/plays/roles/nginx_role - nginx_role (master) was installed successfully - downloading role 'jenkins', owned by geerlingguy - downloading role from https://github.com/geerlingguy/ansible-role-jenkins/archive/4.3.0.tar.gz - extracting jenkins_role to /home/destroyer/plays/roles/jenkins_role - jenkins_role (4.3.0) was installed successfully
Как вы видете; три роли, определенные в файле requirements.yml, успешно установлены. Вы также можете использовать список ansible-galaxy, чтобы перечислить установленные роли вместе с их версиями:
[destroyer@control plays]$ ansible-galaxy list -p ./roles # /home/destroyer/plays/roles - geerlingguy.haproxy, 1.1.2 - nginx_role, master - jenkins_role, 4.3.0
Создание пользовательских ролей
Вы также можете определить свои собственные роли. Для этого вы можете использовать команду ansible-galaxy init, чтобы определить структуру ролей.
Для демонстрации давайте создадим новую роль с именем httpd-role. Сначала перейдите в каталог ролей, а затем запустите команду ansible-galaxy init, за которой следует новое имя роли, как показано ниже:
[destroyer@control plays]$ cd roles/ [destroyer@control roles]$ ansible-galaxy init httpd-role - Role httpd-role was created successfully
Обратите внимание, что была создана новая роль с именем httpd-role, и в ней есть все типичные каталоги ролей.
[destroyer@control roles]$ tree httpd-role/ httpd-role/ ├── defaults │ └── main.yml ├── files ├── handlers │ └── main.yml ├── meta │ └── main.yml ├── README.md ├── tasks │ └── main.yml ├── templates ├── tests │ ├── inventory │ └── test.yml └── vars └── main.yml 8 directories, 8 files
Теперь начните определять задачи, шаблоны и переменные по умолчанию для новой роли httpd.
Во-первых, вы можете начать с определения задач, отредактировав файл tasks/main.yml так, чтобы он содержал следующее содержимое:
[destroyer@control httpd-role]$ cat tasks/main.yml --- # tasks file for httpd-role - name: Install httpd yum: name: httpd state: latest - name: Start and enable httpd service: name: httpd state: started enabled: true - name: Create index.html using Jinja2 template: src: index.j2 dest: /var/www/html/index.html
Затем вы можете создать файл шаблона Jinja2 index.j2 внутри каталога шаблонов роли:
[destroyer@control httpd-role]$ cat templates/index.j2 Welcome to {{ inventory_hostname }} This is an Apache Web Server. Please contact {{ sysadmin }} for any questions or concerns.
Наконец, вы можете определить и установить переменную sysadmin в defaults/main.yml:
[destroyer@control httpd-role]$ cat defaults/main.yml --- # defaults file for httpd-role sysadmin: destroyer@andreyex.ru
Хорошо! Теперь вы закончили создание роли. Давайте создадим сценарий, в котором используется httpd-role.
Вернитесь в каталог проекта и создайте playbook apache-role.yml со следующим содержимым:
[destroyer@control plays]$ cat apache-role.yml --- - name: Using httpd-role hosts: webservers roles: - role: httpd-role sysadmin: angela@andreyex.ru
Обратите внимание, что вы перезаписали переменную sysadmin в playbook. Идите вперед и запустите playbook:
[destroyer@control plays]$ ansible-playbook apache-role.yml PLAY [Using httpd-role] ****************************** TASK [Gathering Facts] ************************************** ok: [node2] ok: [node3] TASK [httpd-role : Install httpd] ********************* changed: [node2] changed: [node3] TASK [httpd-role : Start and enable httpd] ******************** changed: [node2] changed: [node3] TASK [httpd-role : Create index.html using Jinja2] **************** changed: [node2] changed: [node3] PLAY RECAP ****************** node2 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 node3 : ok=4 changed=3 unreachable=0 failed=0 skipped=0
Все выглядит хорошо. Давайте проверим, проверив ответ, который вы получаете на обоих веб-серверах ( node2 и node3 ):
[destroyer@control plays]$ curl node2 Welcome to node2 This is an Apache Web Server. Please contact angela@andreyex.ru for any questions or concerns. [destroyer@control plays]$ curl node3 Welcome to node3 This is an Apache Web Server. Please contact angela@andreyex.ru for any questions or concerns.
Отлично! Ваша заказная httpd-роль работала безупречно.
Если вы когда-нибудь создадите потрясающую роль Ansible, которая, по вашему мнению, принесет пользу многим; не забудьте опубликовать свою роль в Ansible Galaxy, чтобы поделиться ею со всем миром!
Управление порядком выполнения задач
Вы должны хорошо знать порядок выполнения задач в сценарии Ansible.
Если вы используете ключевую работу ролей для статического импорта роли; тогда все задачи в этой роли будут выполняться перед всеми другими задачами (включенными в раздел задач) в вашей игре.
Вы можете использовать ключевое слово pre_tasks, чтобы включить любые задачи, которые вы хотите запустить перед статически импортированными ролями. Вы также можете использовать ключевое слово post_tasks, чтобы включить любые задачи, которые вы хотите запустить после всех задач в разделе задач .
Таким образом, Ansible выполняет playbook в следующем порядке:
- pre_tasks будет запущен первым.
- обработчики, запускаемые pre_tasks, запускаются следующим образом.
- статически импортированные роли, перечисленные под ролями, будут выполняться.
- задачи, перечисленные в разделе задач.
- обработчики, запускаемые ролями или задачами.
- post_tasks будет выполняться последним.
- обработчики, запускаемые post_tasks, будут работать последними.
Для демонстрации взгляните на следующую книгу pre-post.yml, в которой используются pre_tasks, роли, задачи и post_tasks:
[destroyer@control plays]$ cat pre-post.yml --- - name: Understanding Order of Task Execution hosts: node1 tasks: - name: A regular task debug: msg: "I am just a regular task." post_tasks: - name: Runs last debug: msg: "I will run last (post_task)." pre_tasks: - name: Runs first debug: msg: "I will run first (pre_task)." roles: - role: myrole
В сборнике plays используется созданная мной роль myrole, которая выполняет две простые задачи:
[destroyer@control plays]$ tree roles/myrole roles/myrole └── tasks └── main.yml 1 directory, 1 file [destroyer@control plays]$ cat roles/myrole/tasks/main.yml - name: debug: msg: “I am the first task in myrole.” - name: debug: msg: “I am the second task in myrole.”
Теперь запустите playbook:
[destroyer@control plays]$ ansible-playbook pre-post.yml PLAY [Understanding Order of Task Execution] ************* TASK [Gathering Facts] ********************************* ok: [node1] TASK [Runs first] *************************** "msg": "I will run first (pre_tasks)." } TASK [myrole : debug] ******************************* ok: [node1] => { "msg": "I am the first task in myrole." } TASK [myrole : debug] ************************* ok: [node1] => { "msg": "I am the second task in myrole." } TASK [A regular task] *************************** ok: [node1] => { "msg": "I am just a regular task." } TASK [Runs last] ****************************** ok: [node1] => { "msg": "I will run last (post_tasks)." } PLAY RECAP ******************************* node1 : ok=6 changed=0 unreachable=0 failed=0 skipped=0
Как вы видите, сначала выполняется pre_tasks, затем две задачи в myrole, затем задачи и, наконец, последними запускаются post_tasks.
Надеюсь, вам понравилось узнавать, как использовать и создавать роли Ansible.