Используете Red Hat Satellite и Red Hat Ansible Automation Platform? Начиная с Satellite 6.3, их можно интегрировать друг с другом, чтобы Dynamic Inventory в Ansible Tower подтягивал списки хостов из Satellite. Кроме того, если хосты RHEL инициализируются средствами Satellite (имеется в виду provisioning), то в этот процесс можно встроить Ansible Tower, чтобы он автоматически запускал на новых хостах сценарии конфигурирования.



В этом посте мы рассмотрим, как настроить Dynamic Inventory в Ansible Tower, чтобы он подтягивал хосты из Satellite, и на примерах покажем, как этим пользоваться. Кроме того, расскажем, как организовать автоматический вызов Ansible Tower после инициализации нового хоста из Satellite.

Часть 1. Интеграция на уровне Inventory. Настраиваем Satellite, чтобы его можно было использовать как Dynamic Inventory в Ansible Tower


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

В Satellite 6.6 и выше для этого уже есть готовая роль Ansible Tower Inventory Reader, поэтому приведенные ниже шаги по созданию роли можно пропустить.

В Satellite 6.3-6.5 роль придется создать руками. Для этого заходим в веб-интерфейс Satellite, идем на экран Administer, выбираем Roles и щелкаем Create Role.

Назовем эту роль ansible_tower_integration_role и зададим для нее Locations и Organizations:



Щелкаем Submit, чтобы создать роль. После этого кликаем на ее имя и переходим на вкладку Filters. Жмем зеленую кнопку New Filter и добавляем следующие фильтры, по одному за раз:

Resource Type: Host, Permission: view_hosts
Resource Type: Host Group, Permission: view_hostgroups
Resource Type: Fact value, Permission: view_facts

В итоге роль должна иметь следующие фильтры:



Итак, мы создали роль. Теперь заведем нового пользователя в Satellite, для чего идем в меню Administer, выбираем Users и щелкаем Create User. Называем этого пользователя ansible_integration, меняем параметр Authorized by на INTERNAL и задаем пароль. Затем на вкладках Locations и Organizations выбираем соответствующие локации/организации. Наконец переходим на вкладку Roles и назначаем этому пользователю только что созданную роль ansible_tower_integration_role (если у вас Satellite 6.3 – 6.5) или встроенную роль Ansible Tower Inventory Reader (Satellite 6.6 и выше). В завершение щелкаем Submit, чтобы создать для этого пользователя учетную запись.

Настраиваем Ansible Tower


Теперь заходим в веб-интерфейс Ansible Tower и переходим на экран Credentials. Жмем зеленую кнопку + (Add), чтобы создать новую запись Credential. Назовем ее satellite_integration, а в Credential Type укажем Red Hat Satellite 6. Затем вводим URL-адрес (в нашем случае Satellite 6), а также имя пользователя (в нашем случае ansible_integration), и пароль – тот, что мы выше задали в Satellite:



После чего щелкаем Save.

Теперь переходим на экран Inventories, щелкаем зеленую кнопку + (Add) и выбираем Inventory. В качестве имени указываем satellite_inventory и жмем Save, чтобы создать inventory. После чего переходим на вкладку Sources только что созданного inventory и жмем зеленую кнопку + (Add). В качестве имени источника используем satellite, а тип источника указываем как Red Hat Satellite 6. В поле Credential указываем satellite_integration, который создали на предыдущем шаге. Включаем галочки Overwrite, Overwrite Variables и Update on Launch в группе элементов управления Update Options (подробнее узнать об этих опциях можно с помощью знаков вопроса справа). Кроме того, в поле Cache Timeout (Seconds) вводим 90 и щелкаем Save.



Теперь, не покидая вкладку Sources, щелкаем значок Start sync process:



Ждем, пока значок позеленеет – это сигнализирует об успешном завершении синхронизации.

Теперь можно перейти на вкладку Hosts и посмотреть данные, которые были подтянуты из Satellite:



Еще можно глянуть вкладку Groups:



Как видим, синхронизация не только подтянула списки хостов из Satellite, но и разбила их на группы по соответствующим контент-представлениям (content views) в Satellite, группам хостов, средам жизненного цикла (lifecycle environments), локациям и организациям. Эту группировку можно использовать для таргетированного запуска сценариев Ansible на целевых хостах, и это очень мощная штука.

Если выбрать какой-нибудь хост на вкладке Hosts, то мы увидим, что между Satellite и Ansible Tower синхронизируется масса вспомогательных сведений о хосте, которые представлены в виде переменных. Эти переменные затем можно использовать в сценариях Ansible:



Используем Dynamic Inventory, привязанные к Satellite


Итак, мы синхронизировали Satellite и Ansible Tower.Теперь рассмотрим, как этим пользоваться на практике.

Самый простой способ – использовать satellite_inventory в качестве источника Inventory в шаблоне Ansible Tower Template. Если в сценарии задана опция hosts: all, то сценарий будет запущен на всех хостах Satellite.

Более продвинутый вариант – использовать в сценариях автоматически созданные inventory-группы (как они создаются – см. выше), иначе говоря, указывать нужную группу хостов в строке hosts. Например, как в этом сценарии, где выполняется установка пакета screen:

---
- name: Install screen package
  hosts: "foreman_hostgroup_rhel6"
  tasks:
  - yum:
      name: screen
      state: installed

Здесь мы прописали hosts: foreman_hostgroup_rhel6, указав тем самым список хостов, образующих в Satellite группу хостов rhel6. Соответственно, сценарий будет выполняться только на этих хостах.

Кроме того, в сценарии можно указывать в строке hosts те переменные, которые Ansible Tower получает в ходе синхронизации с Satellite. Например, можно сделать вот так:

---
- name: Install screen package
  hosts: "{{ hosts_var }}"
  tasks:
  - yum:
      name: screen
      state: installed

В результате мы сможем на лету менять job template в Ansible Tower, указывая одну из inventory-групп через внешнюю переменную.



В этом примере шаблон будет запускаться только на тех хостах, которые входят в группу rhel7 в Satellite.

Более того, job template можно настроить так, что при запуске он будет запрашивать у пользователя значение переменной hosts_var (и при этом выводить на экран имеющиеся inventory-группы в виде комментариев):



Скрин выше иллюстрирует ситуацию, когда при запуске шаблона пользователю предлагается ввести имя inventory-группы Satellite, на хостах которой нужно запустить сценарий.

Кроме того, можно использовать переменные хоста, подтянутые из Satellite при синхронизации. Например, вот как выглядит сценарий, показывающий, как ссылаться на эти переменные:

---
- name: Show Satellite variables
  hosts: all
  tasks:
  - name: Show subscription_status
    debug:
      msg: >
        Subscription Status: {{ foreman.subscription_status_label }}
  - name: Show Errata Counts
    debug:
      msg: >
        Bug fixes: {{ foreman.content_facet_attributes.errata_counts.bugfix }},
        Security: {{ foreman.content_facet_attributes.errata_counts.security }},
        Enhancement: {{ foreman.content_facet_attributes.errata_counts.enhancement }},
        Total: {{ foreman.content_facet_attributes.errata_counts.total }}

Если запустить этот сценарий в Ansible Tower, он покажет значения переменных:



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

Подводим итоги


Red Hat Satellite и Red Hat Ansible сами по себе являются очень мощными инструментами, а их интеграция дает ощутимую синергетику. Выше мы показали, как сделать Satellite источником данных для Dynamic Inventory в Ansible и пользоваться этим на практике.
?

Часть 2. Автонастройка новых хостов через provisioning callback


Помимо массы прочих возможностей, Satellite также умеет инициализировать хосты, иначе говоря, выполнять provisioning. В свою очередь Ansible Tower предназначен для того, чтобы хосты конфигурировать. Интеграция позволяет сделать так, что после инициализации нового хоста RHEL средствами Satellite к этому хосту будет автоматически подключаться Ansible Tower и запускать на нем соответствующий сценарий конфигурирования. Очевидным образом, такая схема экономит уйму времени системным администраторам, помогая им быстрее реагировать на потребности организации.

Надо заметить, что эта схема работает только при соблюдении нескольких условий. Во-первых, Satellite должен использоваться в качестве источника данных Dynamic Inventory в Ansible Tower (мы рассмотрели этот вопрос в предыдущей части). Во-вторых, инициализации хостов должна не только выполняться через Satellite, но и работать через механизм групп хостов (подробнее об этом можно прочитать в руководстве Provisioning Guide).

Ниже мы покажем, как настроить Satellite и Ansible Tower так, чтобы после инициализации хоста на нем автоматически запускался сценарий конфигурирования Ansible.

Обзор


Средства ИТ-автоматизации, такие как Ansible Tower, обычно относятся к одной из двух категорий: одни работают по методу push, другие – по методу pull. В push-системах, к которым принадлежит Ansible Tower, соединение с хостом инициирует сервер автоматизации. В pull-системах инициатором выступает хост, который сам связывается сервером автоматизации.

В нашем случае с автоматическим запуском сценариев на новых хостах используется смешанная схема. Только что инициализированный хост обращается к серверу автоматизации с просьбой «перезвонить» ему и провести настройку. После чего сервер автоматизации подключается к этому хосту и запускает на нем запрошенный хостом сценарий конфигурирования. Поэтому в Ansible Tower данный механизм называется provisioning callback, что можно перевести как «инициализационный обратный вызов».

Чтобы показать, зачем вообще нужен provisioning callback, рассмотрим следующую ситуацию: у нас есть некий сценарий конфигурирования хостов, который ежедневно запускается в полночь. Допустим, в 8 утра мы выполняем инициализацию сразу нескольких новых серверов через Satellite. При этом Satellite используется как источник данных Dynamic Inventory в Ansible Tower, поэтому созданные хосты автоматом попадают в Ansible. Однако следующий запуск сценария автоматизации состоится лишь в полночь, то есть через 16 часов. Очевидно, это далеко не идеальный вариант, и хотелось бы, чтобы сценарий запускался сразу после инициализации нового хоста. Именно для этого и придуман provisioning callback.

В общих чертах provisioning callback настраивается и работает следующим образом:

  1. На сервере Ansible Tower создаем запись credential и прописываем в ней учетные данные пользователя root, которые Satellite использует при инициализации новых хостов в той или иной своей группе. Tower будет использовать эту запись, чтобы логиниться на только что созданные хосты и запускать на них сценарии.
  2. В настройках шаблона Job Template в Ansible Tower разрешаем запросы provisioning callback. Эти запросы должны поступать на соответствующий URL и содержать некий ключ Host Config Key, который задается в настройках этого же шаблона Ansible.
  3. В Satellite для группы хостов задаем параметры того, как клиент будет формировать свой запрос provisioning callback к серверу Ansible Tower, а именно: URL-адрес сервера Ansible Tower, ключ Host Config Key и идентификатор шаблона Ansible.
  4. При инициализации нового хоста шаблоны инициализации Satellite создают на нем файл /etc/systemd/system/ansible-callback.service (на серверах RHEL 7 и 8; на машинах RHEL 6 используются скрипты). При первой загрузке хоста этот файл инициирует запрос provisioning callback к серверу Ansible Tower, используя параметры, заданные в предыдущем пункте (URL-адрес, Host Config Key и идентификатор шаблона).
  5. Ansible Tower получает этот запрос и проверяет ключ Host Config Key. Если ключ верен, Tower инициирует запуск на вызывающем хосте запрошенного шаблона, используя для авторизации учетные данные root, прописанные в шаблоне Job Template. Если все нормально, то шаблон запускается и конфигурирует хост.

Настраиваем Ansible Tower для Provisioning Callback


Начнем с создания на сервере Ansible Tower некий сценарий конфигурирования, который меняет содержимое/etc/motd, создает какого-то пользователя и устанавливает определенный пакет. Затем мы будет использовать этот сценарий для настройки новых хостов сразу после их инициализации.

В реальной жизни сценарии автоматизации, скорее всего, хранятся в какой-то системе управления версиями, но для простоты изложения будем считать, что они лежат прямо на сервере Ansible Tower. Поэтому входим на сервер Ansible Tower по SSH и создаем для них каталог /var/lib/awx/projects/provision, выполнив следующую команду:

# mkdir /var/lib/awx/projects/provision

Затем создаем в этом каталоге наш сценарий, называем его provision.yaml и прописываем в нем следующее содержимое:

---

- name: Provision new host

  hosts: all

  tasks:

  - name: Set content in /etc/motd 

    copy:

      content: Authorized use only!

      dest: /etc/motd

      mode: 644

      owner: root

      group: root


  - name: Create brian user account

    user:

      name: brian

      uid: 10000

      state: present


  - name: Install tmux package

    yum:

      name: tmux

      state: present


Теперь заходим в веб-интерфейс Tower и идем на экран Credentials. Щелкаем кнопку с зеленым плюсиком, чтобы создать новую запись credential, даем ей имя provisioning_root, а также задаем Credential Type как Machine. В поле Username пишем root, а в поле Password указываем тот пароль, который задан в Satellite для использования на новых хостах соответствующей группы хостов в Satellite (ее название его можно посмотреть в веб-интерфейсе Satellite на вкладке Operating System). Используя эту запись, Ansible Tower сможет авторизоваться на новых хостах, созданных при инициализации через Satellite.



После этого в интерфейсе Ansible Tower идем на экран Projects и щелкаем зеленый плюсик, чтобы создать новый проект. Назовем его provision, изменим SCM Type на Manual, а в качестве каталога Playbook Directory укажем provision:



Затем в интерфейсе Ansible Tower переходим на экран Templates, щелкаем зеленый плюсик, чтобы создать новый Job Template. Назовем его provision, в поле Inventory пишем Satellite, в поле Project – provision, в поле Playbook – provision.yaml, а в поле Credential – provisioning_root. Кроме того, надо включить галочку Allow Provisioning Callbacks и щелкнуть значок с волшебной палочкой справа от поля Host Config Key, чтобы сгенерировать секретный ключ. Этот ключ нужен для того, чтобы запрашивать provisioning callback мог не кто угодно, а только тот, кто знает Host Config Key. Без указания верного ключа сервер Ansible Tower просто не будет реагировать на запрос.



Теперь нам надо запомнить на будущее значение ключа Host Config Key, а также Template ID, который можно узнать из URL-адреса этого шаблона Job Template:

https://tower.example.com/#/templates/job_template/11

В этом примере ID равен 11.

Настраиваем Satellite для Provisioning Callback


Теперь заходим в веб-интерфейс Satellite, идем на экран Configure и щелкаем Host Groups. Выбираем существующую группу хостов, которая используется при инициализации новых хостов, в нашем примере это группа RHEL 8.

На экране редактирования группы хостов переходим на вкладку Parameters и создаем 4 новых параметра:

ansible_host_config_key – здесь прописываем Host Config Key из нашего шаблона Ansible Tower Template.
ansible_job_template_id – здесь пишем Template ID, которые мы ранее выяснили из URL шаблона.
ansible_tower_fqdn – полное доменное имя сервера Ansible Tower.
ansible_tower_provisioning – прописываем true.



Проверяем, как всё работает


Теперь инициализируем новый хост из Satellite и проверим, что provisioning callback работает и автоматически запускает наш сценарий на этом хосте.

В веб-интерфейсе Satellite идем на экран Hosts, щелкаем Create Host и проверяем, что используется именно та группа, для которой мы только что создали 4 новых параметра, то есть группа RHEL 8.



После того, как инициализация хоста выполнена, нам надо удостовериться, что шаблон на нем был успешно запущен. Для этого в веб-интерфейсе Ansible Tower идем на экран Templates, ищем наш шаблон в списке и смотрим, позеленел ли самый левый квадратик его индикатора:



Щелкаем этот зеленый квадратик, чтобы посмотреть детали запуска, который в нашем случае был успешным. Обратите внимание, что у этого задания есть ограничение (Limit) – запуск только новых хостах, которые создаются в ходе инициализации. Что ж, это неудивительно, поскольку механизм provisioning callback запускает шаблон только на тех хостах, которые этого просят.



Теперь зайдем на только что созданный хост и проверим, соответствует ли он тому, что прописано в сценарии:

[root@provision-test-rhel8 ~]# rpm -qa | grep tmux
tmux-2.7-1.el8.x86_64

[root@provision-test-rhel8 ~]# id brian
uid=10000(brian) gid=10000(brian) groups=10000(brian)

[root@provision-test-rhel8 ~]# cat /etc/motd
Authorized use only!

Устранение неполадок


Если шаблон Ansible Tower не запускается автоматически на новом, инициализированном через Satellite, хосте, надо проверить несколько вещей.

Первым делом надо выяснить, получал ли Ansible Tower запрос на provisioning callback, как прошел запуск сценария и запускался ли он вообще. Для этого в интерфейсе Tower идем на экран Templates и смотрим цвет индикатора рядом с именем шаблона: зеленый – запуск прошел успешно, красный – неудачный запуск.



Если квадратик красный, то щелкаем его и смотрим дополнительные сведения, чтобы понять почему запуск сорвался (это могут быть как синтаксические ошибки в сценарии, так и другие проблемы).

Если квадратик зеленый, то все равно щелкаем и смотрим, поскольку задание могло рапортовать об успешном выполнении, но на самом деле не запускалось на нашем хосте. Например, если строка hosts в сценарии указывает конкретные хосты и группы, но не включает хосты, создаваемые в ходе инициализации, то задание будет рапортовать об успешном выполнении, но в дополнительных сведениях будет написано «skipping: no hosts matched».

Если же квадратик индикатора ни зеленый, ни красный, то начать надо с проверки параметров группы хостов в Satellite. Убедитесь, что там верно указаны URL сервера Ansible Tower, ключ Host Config Key и идентификатор шаблона.

Далее зайдите на только что инициализированный хост и проверьте, что там есть файл /etc/systemd/system/ansible-callback.service (на системах RHEL 7 или 8) или файл /root/ansible_provisioning_call.sh (RHEL 6).

Если файла нет, проверьте, что для этой группы хостов параметр ansible_tower_provisioning задан как true, а шаблоны инициализации на сервере Satellite не были изменены.
Если файл /etc/systemd/system/ansible-callback.service на хосте присутствует, то открываем его и ищем URL, по которому отправляется запрос provisioning callback:

[root@provision-test-rhel8 ~]# cat /etc/systemd/system/ansible-callback.service
[Unit]
Description=Provisioning callback to Ansible Tower
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/curl -k -s --data "host_config_key=aa5ebe82-491c-4fbb-bd36-a6657549451e" https://tower.example.com/api/v2/job_templates/11/callback/
ExecStartPost=/usr/bin/systemctl disable ansible-callback

[Install]
WantedBy=multi-user.target

Можно запустить curl и вручную продублировать указанные в этом файле команды, чтобы руками инициировать provisioning callback:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=aa5ebe82-491c-4fbb-bd36-a6657549451e" https://tower.example.com/api/v2/job_templates/11/callback/

Если указан неверный Host Config Key, мы получим следующее сообщение об ошибке:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=wrong-key-here" https://tower.example.com/api/v2/job_templates/11/callback/

{"detail":"You do not have permission to perform this action."}

Если неправильно указан Template ID (здесь – 43 вместо 11), то ответ будет следующий:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=wrong-key-here" https://tower.example.com/api/v2/job_templates/43/callback/

{"detail":"Not found."}

Также можно отключить режим silent (-s) в команде curl, чтобы она выводила на экран ошибки, связанные с разрешением имени хоста, как в примере ниже, где мы заменили верное имя ansible.example.com на неверное ansible-tower.example.com:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k  --data "host_config_key=wrong-key-here" https://ansible-tower.example.com/api/v2/job_templates/11/callback/

curl: (6) Could not resolve host: ansible-tower.example.com

Кроме того, при выяснении причин ошибки может пригодиться файл /var/log/tower/tower.log на сервере Ansible Tower.
Например, в этом файле фиксируется использование неверного ключа Host Config Key:

2019-11-19 23:19:17,371 WARNING  awx.api.generics status 403 received by user AnonymousUser attempting to access /api/v2/job_templates/11/callback/ from 192.168.0.138

Здесь же фиксируется использование неверного Template ID:

2019-11-19 23:19:49,093 WARNING  awx.api.generics status 404 received by user AnonymousUser attempting to access /api/v2/job_templates/43/callback/ from 192.168.0.138

2019-11-19 23:19:49,095 WARNING  django.request Not Found: /api/v2/job_templates/43/callback/

Подводим итоги


Интеграция Satellite и Ansible Tower позволяет сильно оптимизировать процессы инициализации и конфигурирования новых хостов, что экономит уйму времени системным администраторам, помогая им быстрее реагировать на потребности организации.

24 марта с 11:00 до 12:30 Red Hat проведет вебинар «Что нужно знать про автоматизацию: Базовые навыки работы с Ansible»

Автоматизация – тема, приближающаяся по популярности и количеству запросов к цифровой трансформации. Мы расскажем вам про наш взгляд на автоматизацию – вместе с Ansible и Ansible Tower – и это будет та базовая информация, которая откроет вам двери в дивный новый мир декларативных средств автоматизации.
После этого вебинара вам станут понятны базовые сущности Ansible, такие как playbook, inventory, module. Вместе с вами мы освоим основной синтаксис YAML, чтобы вы смогли писать ваши собственные сценарии. Также будет рассмотрен вопрос запуска на исполнение сценариев и эскалации привилегий.

В результате вы получите базовый набор навыков, который позволит вам успешно изучать документацию и другую литературу без постоянного чувства, что вы что-то упускаете из виду. Регистрируйтесь и приходите!