ИТ Блог. Администрирование серверов на основе Linux (Ubuntu, Debian, CentOS, openSUSE)

Ansible. Роли в Ansible

Начало работы с Ansible

До сих пор вы создавали сценарии Ansible для автоматизации определенной задачи на управляемых узлах. Существует огромная вероятность, что кто-то другой уже разработал Ansible-решение проблемы/задачи, которую вы пытаетесь решить, и именно в этом суть ролей Ansible.

В этом руководстве вы поймете, как структурированы роли в Ansible. Вы также научитесь использовать готовые роли из Ansible Galaxy.

Кроме того, вы научитесь создавать свои собственные роли Ansible.

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

 

Понимание ролей Ansible

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

 

Структура каталога ролей

Типичная роль Ansible следует определенной структуре каталогов, которая обычно состоит из следующих каталогов:

  1. defaults: содержит переменные по умолчанию для роли, которые должны быть легко перезаписаны.
  2. vars: содержит стандартные переменные для роли, которые не должны быть перезаписаны в вашей книге.
  3. tasks: содержит набор задач, которые должна выполнять роль.
  4. handlers: содержит набор обработчиков, которые будут использоваться в роли.
  5. templates: содержит шаблоны Jinja2, которые будут использоваться в роли.
  6. files: содержит статические файлы, необходимые из ролевых задач.
  7. tests: может содержать дополнительный файл инвентаря, а также playbook test.yml, который можно использовать для тестирования роли.
  8. meta: содержит метаданные роли, такие как информация об авторе, лицензия, зависимости и т. д.

Имейте в виду, что у роли могут быть все вышеупомянутые каталоги или только их часть. Фактически, вы можете определить пустую роль, у которой нет каталогов, но это бесполезно!

 

Хранение и расположение ролей

По умолчанию Ansible будет искать роли в двух местах:

  1. В каталоге role (тот же уровень каталога, что и ваш файл playbook).
  2. В каталоге /etc/ansible/roles.

Однако вы можете сохранить свои роли в другом месте; если вы решите это сделать, вы должны указать и установить параметр конфигурации roles_path в файле конфигурации Ansible ( ansible.cfg ).

 

Использование ролей Ansible в Playbooks

Есть два разных способа, которыми вы можете импортировать роли в пьесе Ansible :

  1. Использование ключевого слова roles для статического импорта ролей.
  2. Использование модуля 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 может установить сразу несколько ролей, используя файл требований.

Каждая роль, которую вы определяете в своем файле требований, будет иметь еще один из следующих атрибутов:

Чтобы продемонстрировать это, создайте файл 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 в следующем порядке:

  1. pre_tasks будет запущен первым.
  2. обработчики, запускаемые pre_tasks, запускаются следующим образом.
  3. статически импортированные роли, перечисленные под ролями, будут выполняться.
  4. задачи, перечисленные в разделе задач.
  5. обработчики, запускаемые ролями или задачами.
  6. post_tasks будет выполняться последним.
  7. обработчики, запускаемые 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.

Exit mobile version