Ansible - Краткое руководство

Ansible - это простой ИТ-движок с открытым исходным кодом, который автоматизирует развертывание приложений, оркестровку внутри служб, выделение облачных ресурсов и многие другие ИТ-инструменты.

Ansible легко развернуть, так как не использует агентов или настраиваемую инфраструктуру безопасности.

Ansible использует playbook для описания задач автоматизации, а playbook использует очень простой язык, т.е. YAML(Это удобочитаемый язык сериализации данных и обычно используется для файлов конфигурации, но может использоваться во многих приложениях, где хранятся данные), который людям очень легко понять, прочитать и написать. Следовательно, преимущество состоит в том, что даже специалисты службы поддержки ИТ-инфраструктуры могут читать и понимать playbook и отлаживать при необходимости (YAML - это в удобочитаемой форме).

Ansible разработан для многоуровневого развертывания. Ansible не управляет одной системой за раз, он моделирует ИТ-инфраструктуру, описывая, что все ваши системы взаимосвязаны. Ansible полностью безагентный, что означает, что Ansible работает, подключая ваши узлы через ssh (по умолчанию). Но если вам нужен другой метод подключения, такой как Kerberos, Ansible предоставит вам эту возможность.

После подключения к вашим узлам Ansible запускает небольшие программы, называемые «Ansible Modules». Ansible запускает эти модули на ваших узлах и удаляет их по завершении. Ansible управляет вашим инвентарем в простых текстовых файлах (это файл hosts). Ansible использует файл hosts, в котором можно сгруппировать хосты и управлять действиями в определенной группе в playbooks.

Образец файла Hosts

Это содержимое файла hosts -

#File name: hosts
#Description: Inventory file for your application. Defines machine type abc
node to deploy specific artifacts
# Defines machine type def node to upload
metadata.

[abc-node]
#server1 ansible_host = <target machine for DU deployment> ansible_user = <Ansible
user> ansible_connection = ssh
server1 ansible_host = <your host name> ansible_user = <your unix user>
ansible_connection = ssh

[def-node]
#server2 ansible_host = <target machine for artifact upload>
ansible_user = <Ansible user> ansible_connection = ssh
server2 ansible_host = <host> ansible_user = <user> ansible_connection = ssh

Что такое управление конфигурацией

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

Такая информация обычно включает точные версии и обновления, которые были применены к установленным программным пакетам, а также расположение и сетевые адреса аппаратных устройств. Например, если вы хотите установить новую версиюWebLogic/WebSphere сервер на всех машинах, имеющихся на вашем предприятии, вам нецелесообразно вручную обновлять каждую машину.

Вы можете установить WebLogic / WebSphere за один раз на всех своих машинах с помощью Ansible playbooks и инвентаря, написанных самым простым способом. Все, что вам нужно сделать, это перечислить IP-адреса ваших узлов в инвентаризации и написать сценарий для установки WebLogic / WebSphere. Запустите playbook с вашего управляющего компьютера, и он будет установлен на всех ваших узлах.

Как работает Ansible?

На приведенном ниже рисунке показана работа Ansible.

Ansible works подключившись к вашим узлам и запустив небольшие программы, называемые "Ansible модули »им. Ansibleзатем выполняет эти модули (по умолчанию через SSH) и удаляет их по завершении. Ваша библиотека модулей может находиться на любом компьютере, и для этого не требуются серверы, демоны или базы данных.

Узел управления на изображении выше - это управляющий узел (управляющий узел), который контролирует все выполнение playbook. Это узел, с которого вы запускаете установку. Файл инвентаризации предоставляет список хостов, на которых должны быть запущены модули Ansible, а узел управления устанавливает SSH-соединение, выполняет небольшие модули на хост-машине и устанавливает продукт / программное обеспечение.

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

В этой главе мы узнаем о настройке среды Ansible.

Процесс установки

В основном, когда мы говорим о развертывании, есть два типа машин:

  • Control machine - Машина, с которой мы можем управлять другими машинами.

  • Remote machine - Машины, которые управляются / управляются машиной управления.

Может быть несколько удаленных машин, которые обслуживаются одной управляющей машиной. Итак, для управления удаленными машинами нам нужно установить Ansible на управляющую машину.

Требования к управляющей машине

Ansible можно запускать с любого компьютера с установленным Python 2 (версии 2.6 или 2.7) или Python 3 (версии 3.5 и выше).

Note - Windows не поддерживает управляющую машину.

По умолчанию Ansible использует ssh для управления удаленной машиной.

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

Ansible может быть установлен на управляющую машину, у которой есть указанные выше требования, различными способами. Вы можете установить последнюю версию через Apt, yum, pkg, pip, OpenCSW, pacman и т. Д.

Установка через Apt на машине Ubuntu

Для установки Ansible вам необходимо настроить PPA на вашем компьютере. Для этого вам нужно запустить следующую строку кода -

$ sudo apt-get update $ sudo apt-get install software-properties-common 
$ sudo apt-add-repository ppa:ansible/ansible $ sudo apt-get update 
$ sudo apt-get install ansible

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

Ansible использует синтаксис YAML для представления сценариев Ansible. В этой главе представлен обзор YAML. Ansible использует YAML, потому что людям очень легко понимать, читать и писать по сравнению с другими форматами данных, такими как XML и JSON.

Каждые YAML файл необязательно начинается с «---» и заканчивается «...».

Понимание YAML

В этом разделе мы изучим различные способы представления данных YAML.

пара "ключ-значение"

YAML использует простую пару ключ-значение для представления данных. Словарь представлен парой ключ: значение.

Note - Между: и значением должен быть пробел.

Пример: студенческая запись

--- #Optional YAML start syntax 
james: 
   name: james john 
   rollNo: 34 
   div: B 
   sex: male 
… #Optional YAML end syntax

Сокращение

Вы также можете использовать сокращения для обозначения словарей.

пример

James: {name: james john, rollNo: 34, div: B, sex: male}

Представляющий список

Мы также можем представить список в YAML. Каждый элемент (член) списка должен быть записан с новой строки с таким же отступом, начиная с «-» (- и пробела).

пример

---
countries:  
   - America 
   - China 
   - Canada 
   - Iceland 
…

Сокращение

Вы также можете использовать аббревиатуры для обозначения списков.

пример

Countries: [‘America’, ‘China’, ‘Canada’, ‘Iceland’]

Список внутри словарей

Мы можем использовать список внутри словарей, т.е. значение ключа - это список.

пример

---  
james: 
   name: james john 
   rollNo: 34 
   div: B 
   sex: male 
   likes: 
      - maths 
      - physics 
      - english 
…

Список словарей

Также мы можем составить список словарей.

пример

---  
- james: 
   name: james john 
   rollNo: 34 
      div: B 
   sex: male 
   likes: 
      - maths 
      - physics 
      - english 

- robert: 
      name: robert richardson 
      rollNo: 53 
      div: B 
      sex: male 
   likes: 
      - biology 
      - chemistry 
…

YAML использует «|» для включения новых строк при отображении нескольких строк и «>» для подавления новых строк при отображении нескольких строк. Благодаря этому мы можем читать и редактировать большие строки. В обоих случаях интенденция будет проигнорирована.

Мы также можем представить Boolean(True / false) значения в YAML. гдеboolean значения могут быть нечувствительными к регистру.

пример

---  
- james: 
   name: james john 
   rollNo: 34 
   div: B 
   sex: male 
   likes: 
      - maths 
      - physics 
      - english 
   
   result: 
      maths: 87 
      chemistry: 45 
      biology: 56 
      physics: 70 
      english: 80 
   
   passed: TRUE 
   
   messageIncludeNewLines: | 
      Congratulation!! 
      You passed with 79% 
   
   messageExcludeNewLines: > 
      Congratulation!! 
      You passed with 79%

Несколько общих слов, связанных с Ansible.

Service/Server - Процесс на машине, предоставляющей услугу.

Machine - Физический сервер, vm (виртуальная машина) или контейнер.

Target machine - Машина, которую мы собираемся настроить с помощью Ansible.

Task - Действие (запустить, удалить) и т. Д., Управляемое Ansible.

Playbook - Файл yml, в котором записываются команды Ansible и выполняется yml на машине.

Специальные команды - это команды, которые можно запускать индивидуально для выполнения быстрых функций. Эти команды не нужно выполнять позже.

Например, вам необходимо перезагрузить все серверы вашей компании. Для этого вы запустите специальные команды из '/usr/bin/ansible'.

Эти специальные команды не используются для управления конфигурацией и развертывания, поскольку эти команды используются один раз.

ansible-playbook используется для управления конфигурацией и развертывания.

Параллелизм и команды оболочки

Перезагружайте сервер вашей компании в 12 параллельных форках за раз. Для этого нам нужно настроить SSHagent для подключения.

$ ssh-agent bash 
$ ssh-add ~/.ssh/id_rsa

Чтобы выполнить перезагрузку для всех серверов вашей компании в группе, abc, в 12 параллельных форках -

$ Ansible abc -a "/sbin/reboot" -f 12

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

$ Ansible abc -a "/sbin/reboot" -f 12 -u username

Передача файла

Вы можете использовать специальные команды для выполнения SCP (Протокол безопасного копирования) множество файлов параллельно на нескольких машинах.

Передача файла на множество серверов / машин

$ Ansible abc -m copy -a "src = /etc/yum.conf dest = /tmp/yum.conf"

Создание нового каталога

$ Ansible abc -m file -a "dest = /path/user1/new mode = 777 owner = user1 group = user1 state = directory"

Удаление всего каталога и файлов

$ Ansible abc -m file -a "dest = /path/user1/new state = absent"

Управление пакетами

Команды Ad-hoc доступны для yum и apt. Ниже приведены некоторые специальные команды, использующие yum.

Следующая команда проверяет, установлен ли пакет yum, но не обновляет его.

$ Ansible abc -m yum -a "name = demo-tomcat-1 state = present"

Следующая команда проверяет, что пакет не установлен.

$ Ansible abc -m yum -a "name = demo-tomcat-1 state = absent"

Следующая команда проверяет, установлена ​​ли последняя версия пакета.

$ Ansible abc -m yum -a "name = demo-tomcat-1 state = latest"

Сбор фактов

Факты можно использовать для реализации условных операторов в playbook. Вы можете найти специальную информацию обо всех ваших фактах с помощью следующей специальной команды -

$ Ansible all -m setup

В этой главе мы узнаем о Playbooks в Ansible.

Плейбуки - это файлы, в которых написан код Ansible. Плейбуки написаны в формате YAML. YAML означает еще один язык разметки.Playbooksявляются одной из основных функций Ansible и сообщают Ansible, что нужно выполнить. Они похожи на список дел для Ansible, который содержит список задач.

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

Структура учебника

Каждая игра представляет собой совокупность одной или нескольких пьес в ней. Пособия структурированы с использованием пьес. Внутри сборника пьес может быть несколько пьес.

Функция игры заключается в отображении набора инструкций, определенных для конкретного хоста.

YAML - это язык со строгой типизацией; поэтому при записи файлов YAML необходимо проявлять особую осторожность. Существуют разные редакторы YAML, но мы предпочтем использовать простой редактор, например notepad ++. Просто откройте блокнот ++, скопируйте и вставьте приведенный ниже yaml и измените язык на YAML (Language → YAML).

YAML начинается с --- (3 дефиса)

Создать учебник

Давайте начнем с написания образца файла YAML. Мы пройдемся по каждому разделу, написанному в файле yaml.

--- 
   name: install and configure DB
   hosts: testServer
   become: yes

   vars: 
      oracle_db_port_value : 1521
   
   tasks:
   -name: Install the Oracle DB
      yum: <code to install the DB>
    
   -name: Ensure the installed service is enabled and running
   service:
      name: <your service name>

Выше приведен пример Playbook, в котором мы пытаемся охватить базовый синтаксис playbook. Сохраните указанное выше содержимое в файле какtest.yml. Синтаксис YAML должен соответствовать правильному отступу, и нужно быть немного осторожным при написании синтаксиса.

Различные теги YAML

Давайте теперь рассмотрим различные теги YAML. Различные теги описаны ниже -

имя

Этот тег определяет имя сборника пьес Ansible. Что касается того, что будет делать этот сценарий. Плейбуку можно дать любое логическое имя.

хозяева

Этот тег определяет списки хостов или группы хостов, для которых мы хотим запустить задачу. Поле / тег хостов является обязательным. Он сообщает Ansible, на каких хостах запускать перечисленные задачи. Задачи можно запускать на одной или удаленной машине. Можно запускать задачи на нескольких машинах, и, следовательно, тег hosts также может иметь запись группы хостов.

варс

Тег Vars позволяет вам определять переменные, которые вы можете использовать в своей книге. Использование аналогично переменным в любом языке программирования.

задания

Все playbooks должны содержать задачи или список задач, которые нужно выполнить. Задачи - это список действий, которые необходимо выполнить. Поле задач содержит название задачи. Это работает как текст справки для пользователя. Это не обязательно, но полезно при отладке playbook. Каждая задача внутренне связана с фрагментом кода, который называется модулем. Модуль, который должен быть выполнен, и аргументы, необходимые для модуля, который вы хотите выполнить.

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

В Ansible роль является основным механизмом для разбиения playbook на несколько файлов. Это упрощает написаниеcomplex playbooks, и это упрощает их повторное использование. Разрушение playbook позволяет логически разбить playbook на повторно используемые компоненты.

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

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

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

Создание новой роли

Структура каталогов для ролей важна для создания новой роли.

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

Роли имеют структурированный макет в файловой системе. Структуру по умолчанию можно изменить, но пока оставим значения по умолчанию.

Каждая роль сама по себе является деревом каталогов. Имя роли - это имя каталога в каталоге / roles.

$ ansible-galaxy -h

Применение

ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...

Параметры

  • -h, --help - Показать это справочное сообщение и выйти.

  • -v, --verbose - Подробный режим (-vvv для получения дополнительной информации, -vvvv для включения отладки соединения)

  • --version - Показать номер версии программы и выйти.

Создание каталога ролей

Приведенная выше команда создала каталоги ролей.

$ ansible-galaxy init vivekrole 
ERROR! The API server (https://galaxy.ansible.com/api/) is not responding, please try again later. 

$ ansible-galaxy init --force --offline vivekrole - vivekrole was created successfully $ tree vivekrole/ 
vivekrole/ 
├── 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

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

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

Это код учебника, который мы написали для демонстрационных целей. Это код из playbook vivek_orchestrate.yml. Мы определили хосты:tomcat-node и назвал две роли - install-tomcat и start-tomcat.

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

--- 
- hosts: tomcat-node 
roles: 
   - {role: install-tomcat} 
   - {role: start-tomcat}

Содержимое нашей структуры каталогов, из которой мы запускаем playbook.

$ ls 
ansible.cfg  hosts  roles  vivek_orchestrate.retry vivek_orchestrate.yml

В каждом каталоге есть каталог задач, содержащий файл main.yml. Содержимое main.yml install-tomcat:

--- 
#Install vivek artifacts 
-  
   block: 
      - name: Install Tomcat artifacts
         action: > 
            yum name = "demo-tomcat-1" state = present 
         register: Output 
          
   always: 
      - debug: 
         msg: 
            - "Install Tomcat artifacts task ended with message: {{Output}}" 
            - "Installed Tomcat artifacts - {{Output.changed}}"

Содержимое main.yml начального кота:

#Start Tomcat          
-  
   block: 
      - name: Start Tomcat 
      command: <path of tomcat>/bin/startup.sh" 
      register: output 
      become: true 
   
   always: 
      - debug: 
         msg: 
            - "Start Tomcat task ended with message: {{output}}" 
            - "Tomcat started - {{output.changed}}"

Преимущество разделения сценария на роли состоит в том, что любой, кто хочет использовать функцию Install Tomcat, может вызвать роль Install Tomcat.

Преобразование учебника в роль

Если не для ролей, содержимое main.yml соответствующей роли можно скопировать в playbook. ymlфайл. Но чтобы иметь модульность, были созданы роли.

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

Выполните команду, чтобы запустить playbook.

-vvv option for verbose output – verbose output 
$ cd vivek-playbook/

Это команда для запуска playbook

$ sudo ansible-playbook -i hosts vivek_orchestrate.yml –vvv 
-----------------------------------------------------------------
-----------------------------------------------------------------------

Вывод

Сгенерированный результат показан на экране -

С помощью /users/demo/vivek-playbook/ansible.cfg как файл конфигурации.

PLAYBOOK: vivek_orchestrate.yml *********************************************************
*********************************************************** 
1 plays in vivek_orchestrate.yml 

PLAY [tomcat-node] **********************************************************************
******** ************************************************* 
 
TASK [Gathering Facts] *************************************************
****************************** ********************************************* 
Tuesday 21 November 2017  13:02:05 +0530 (0:00:00.056) 0:00:00.056 ****** 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/system/setup.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249525.88-259535494116870 `" && 
   echo ansible-tmp-1511249525.88-259535494116870="` 
   echo /root/.ansible/tmp/ansibletmp-1511249525.88-259535494116870 `" ) && sleep 0' 
<localhost> PUT /tmp/tmpPEPrkd TO 
   /root/.ansible/tmp/ansible-tmp-1511249525.88259535494116870/setup.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/ 
   /root/.ansible/tmp/ansible-tmp-1511249525.88259535494116870/setup.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/setup.py; rm -rf 
   "/root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/" > /dev/null 2>&1 && sleep 0' 
ok: [server1] 
META: ran handlers 
 
TASK [install-tomcat : Install Tomcat artifacts] ***********************************
*************************************************************** 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:5 
Tuesday 21 November 2017  13:02:07 +0530 (0:00:01.515)       0:00:01.572 ****** 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/packaging/os/yum.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249527.34-40247177825302 `" && echo 
   ansibletmp-1511249527.34-40247177825302="` echo 
   /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302 `" ) && sleep 0' 
<localhost> PUT /tmp/tmpu83chg TO 
   /root/.ansible/tmp/ansible-tmp-1511249527.3440247177825302/yum.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/ 
   /root/.ansible/tmp/ansible-tmp-1511249527.3440247177825302/yum.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/yum.py; rm -rf 
   "/root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/" > /dev/null 2>
   &1 && sleep 0' 
changed: [server1] => { 
   "changed": true, 
   "invocation": { 
      "module_args": { 
         "conf_file": null, 
         "disable_gpg_check": false, 
         "disablerepo": null, 
         "enablerepo": null, 
         "exclude": null, 
         "install_repoquery": true, 
         "installroot": "/", 
         "list": null, 
         "name": ["demo-tomcat-1"], 
         "skip_broken": false, 
         "state": "present", 
         "update_cache": false, 
         "validate_certs": true 
      } 
   }, 
   "msg": "", 
   "rc": 0, 
   "results": [ 
      "Loaded plugins: product-id, 
      search-disabled-repos, 
      subscriptionmanager\nThis system is not registered to Red Hat Subscription Management. 
      You can use subscription-manager to register.\nResolving Dependencies\n--> 
      Running transaction check\n---> 
      Package demo-tomcat-1.noarch 0:SNAPSHOT-1 will be installed\n--> Finished Dependency 
      Resolution\n\nDependencies Resolved\n
      \n================================================================================\n 
      Package Arch Version Repository         
      Size\n==================================================================\nInstalling:\n 
      demo-tomcat-1 noarch SNAPSHOT-1 demo-repo1 7.1 M\n\nTransaction 
      Summary\n==================================================================\nInstall  1 
      Package\n\nTotal download size: 7.1 M\nInstalled size: 7.9 M\nDownloading 
         packages:\nRunning transaction 
      check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : 
      demotomcat-1-SNAPSHOT-1.noarch 1/1 \n  Verifying  : 
      demo-tomcat-1-SNAPSHOT-1.noarch 1/1 \n\nInstalled:\n  
      demo-tomcat-1.noarch 0:SNAPSHOT-1 \n\nComplete!\n" 
   ] 
} 
 
TASK [install-tomcat : debug] **********************************************************
*************************************************************************** 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:11 
Tuesday 21 November 2017  13:02:13 +0530 (0:00:06.757) 0:00:08.329 ****** 
ok: [server1] => { 
   "changed": false, 
   "msg": [ 
      "Install Tomcat artifacts task ended with message: {
         u'msg': u'', u'changed': True, u'results': 
         [u'Loaded plugins: product-id, 
         search-disabledrepos, 
         subscription-manager\\nThis system is not registered to Red Hat Subscription Management. 
         You can use subscription-manager to register.\\nResolving Dependencies\\n--> 
         Running transaction check\\n---> 
         Package demo-tomcat-1.noarch 0:SNAPSHOT-1 will be installed\\n--> 
         Finished Dependency Resolution\\n
         \\nDependencies 
         Resolved\\n\\n==================================================================\\n 
         Package Arch Version Repository         
         Size\\n======================================================================== 
         =====\\nInstalling:\\n demo-tomcat-1 noarch SNAPSHOT-1 demo-repo1 7.1 M\\n\\nTransaction 
         Summary\\n=========================================================\\nInstall  1 
         Package\\n\\nTotal download size: 7.1 M\\nInstalled size: 7.9 M\\nDownloading 
            packages:\\nRunning 
         transaction check\\nRunning transaction test\\nTransaction test succeeded\\nRunning 
            transaction\\n  
         Installing : demo-tomcat-1-SNAPSHOT-1.noarch 1/1 \\n  Verifying  : 
         demo-tomcat-1-SNAPSHOT-1.noarch
         1/1 \\n\\nInstalled:\\n  demo-tomcat-1.noarch 0:SNAPSHOT-1  \\n\\nComplete!\\n'], u'rc': 0
      }", 
      "Installed Tomcat artifacts - True" 
   ] 
} 
 
TASK [install-tomcat : Clean DEMO environment] ****************************************
************************************************************ 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:19 
Tuesday 21 November 2017  13:02:13 +0530 (0:00:00.057) 0:00:08.387 ****** 
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or 
   {% %}. Found: {{installationOutput.changed}} 
 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/files/file.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249534.13-128345805983963 `" && echo 
   ansible-tmp-1511249534.13-128345805983963="` echo 
   /root/.ansible/tmp/ansibletmp-1511249534.13-128345805983963 `" ) && sleep 0' 
<localhost> PUT /tmp/tmp0aXel7 TO 
   /root/.ansible/tmp/ansible-tmp-1511249534.13128345805983963/file.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/ 
   /root/.ansible/tmp/ansible-tmp-1511249534.13128345805983963/file.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/file.py; rm -rf 
   "/root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/" > /dev/null 2>&1 
   && sleep 0' 
changed: [server1] => { 
   "changed": true, 
      "diff": { 
         "after": { 
            "path": "/users/demo/DEMO", 
            "state": "absent" 
      }, 
      "before": { 
         "path": "/users/demo/DEMO", 
         "state": "directory" 
      } 
   },

   "invocation": { 
      "module_args": { 
         "attributes": null, 
         "backup": null, 
         "content": null, 
         "delimiter": null, 
         "diff_peek": null, 
         "directory_mode": null, 
         "follow": false, 
         "force": false, 
         "group": null, 
         "mode": null, 
         "original_basename": null, 
         "owner": null, 
         "path": "/users/demo/DEMO", 
         "recurse": false, 
         "regexp": null, 
         "remote_src": null, 
         "selevel": null, 
         "serole": null, 
         "setype": null, 
         "seuser": null, 
         "src": null, 
         "state": "absent", 
         "unsafe_writes": null, 
         "validate": null 
      } 
   }, 
   "path": "/users/demo/DEMO", 
   "state": "absent" 
} 
 
TASK [install-tomcat : debug] ********************************************************
************************************************************* 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:29 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.257)       0:00:08.645 ****** 
ok: [server1] => {
   "changed": false, 
   "msg": [ 
      "Clean DEMO environment task ended with message:{u'diff': {u'after': {u'path': 
         u'/users/demo/DEMO', u'state': u'absent'}, 
      u'before': {u'path': u'/users/demo/DEMO', u'state': u'directory'}}, u'state': u'absent', 
         u'changed': True, u'path': u'/users/demo/DEMO'}", 
      "check value  :True" 
   ] 
} 
 
TASK [install-tomcat : Copy Tomcat to user home] *************************************
******************************************************** 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:37 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.055)       0:00:08.701 ****** 
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or 
   {% %}. Found: {{installationOutput.changed}} 
 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/commands/command.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249534.43-41077200718443 `" && echo 
   ansibletmp-1511249534.43-41077200718443="` echo 
   /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443 `" ) && sleep 0' 
<localhost> PUT /tmp/tmp25deWs TO 
   /root/.ansible/tmp/ansible-tmp-1511249534.4341077200718443/command.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443/ 
   /root/.ansible/tmp/ansible-tmp-1511249534.4341077200718443/command.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443/command.py; rm -rf 
   "/root/.ansible/tmp/ansibletmp-1511249534.43-41077200718443/" > /dev/null 2>&1 
   && sleep 0' 
changed: [server1] => { 
   "changed": true, 
   "cmd": [ 
      "cp", 
      "-r", 
      "/opt/ansible/tomcat/demo", 
      "/users/demo/DEMO/" 
   ],
   "delta": "0:00:00.017923", 
   "end": "2017-11-21 13:02:14.547633", 
   "invocation": { 
      "module_args": { 
         "_raw_params": "cp -r /opt/ansible/tomcat/demo /users/demo/DEMO/", 
         "_uses_shell": false, 
         "chdir": null, 
         "creates": null, 
         "executable": null, 
         "removes": null, 
         "warn": true 
      } 
   }, 
   "rc": 0, 
   "start": "2017-11-21 13:02:14.529710", 
   "stderr": "", 
   "stderr_lines": [], 
   "stdout": "", 
   "stdout_lines": [] 
} 
 
TASK [install-tomcat : debug] ********************************************************
********************************************************** 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:47 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.260)       0:00:08.961 ****** 
ok: [server1] => { 
   "changed": false, 
   "msg": "Copy Tomcat to user home task ended with message {
      'stderr_lines': [], u'changed': True, u'end': u'2017-11-21 13:02:14.547633', u'stdout': 
      u'', u'cmd': [u'cp', u'-r', u'/opt/ansible/tomcat/demo', u'/users/demo/DEMO/'], u'rc': 0, 
      u'start': u'2017-11-21 13:02:14.529710', u'stderr': u'', u'delta': u'0:00:00.017923', 
      'stdout_lines': []}" 
} 
 
TASK [start-tomcat : Start Tomcat] **************************************************
********************************************************** 
task path: /users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:5 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.044)       0:00:09.006 ****** 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/commands/command.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249534.63-46501211251197 `" && echo 
   ansibletmp-1511249534.63-46501211251197="` echo 
   /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197 `" ) && sleep 0' 
<localhost> PUT /tmp/tmp9f06MQ TO 
   /root/.ansible/tmp/ansible-tmp-1511249534.6346501211251197/command.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197/ 
   /root/.ansible/tmp/ansible-tmp-1511249534.6346501211251197/command.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197/command.py; rm -rf 
   "/root/.ansible/tmp/ansibletmp-1511249534.63-46501211251197/" > /dev/null 2>&1 
   && sleep 0' 
changed: [server1] => { 
   "changed": true, 
   "cmd": [ "/users/demo/DEMO/bin/startup.sh" ], 
   "delta": "0:00:00.020024", 
   "end": "2017-11-21 13:02:14.741649", 
   "invocation": { 
      "module_args": { 
         "_raw_params": "/users/demo/DEMO/bin/startup.sh", 
         "_uses_shell": false, 
         "chdir": null, 
         "creates": null, 
         "executable": null, 
         "removes": null, 
         "warn": true 
      } 
   }, 
   "rc": 0, 
   "start": "2017-11-21 13:02:14.721625", 
   "stderr": "", 
   "stderr_lines": [], 
   "stdout": "Tomcat started.", 
   "stdout_lines": [ "Tomcat started." ] 
} 
 
TASK [start-tomcat : debug] *************************************************
********************************************************************** 
task path: /users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:10 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.150)       0:00:09.156 ****** 
ok: [server1] => { 
   "changed": false, 
   "msg": [ 
      "Start Tomcat task ended with message: {'
         stderr_lines': [], u'changed': True, u'end': u'2017-11-21 13:02:14.741649', u'stdout': 
         u'Tomcat started.', u'cmd': [u'/users/demo/DEMO/bin/startup.sh'], u'rc': 0, u'start': 
         u'2017-11-21 13:02:14.721625', u'stderr': u'', u'delta': u'0:00:00.020024', 
         'stdout_lines': [u'Tomcat started.']}", 
      "Tomcat started - True" 
   ] 
} 
META: ran handlers 
META: ran handlers 
 
PLAY RECAP ******************************************************************************* 
********************************************************* 
server1  : ok = 9    changed = 4    unreachable = 0    failed = 0 
 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.042)       0:00:09.198 ****** 
=============================================================================== 
install-tomcat : Install Tomcat artifacts ------------------------------- 6.76s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:5 -------------- 
Gathering Facts --------------------------------------------------------- 1.52s 
 ------------------------------------------------------------------------------ 
install-tomcat : Copy Tomcat to user home ------------------------------- 0.26s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:37 ------------- 

install-tomcat : Clean DEMO environment --------------------------------- 0.26s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:19 ------------- 

start-tomcat : Start Tomcat --------------------------------------------- 0.15s 
/users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:5 ----------------

install-tomcat : debug -------------------------------------------------- 0.06s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:11 ------------- 

install-tomcat : debug -------------------------------------------------- 0.06s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:29 ------------- 

install-tomcat : debug -------------------------------------------------- 0.04s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:47 ------------- 

start-tomcat : debug ---------------------------------------------------- 0.04s 
/users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:10 ---------------

Нажмите следующий URL-адрес, и вы будете перенаправлены на страницу, как показано ниже - http://10.76.0.134:11677/HelloWorld/HelloWorld

У развернутой войны есть только сервлет, который отображает «Hello World». Подробный вывод показывает время, затраченное на каждую задачу из-за записи, добавленной в файл ansible.cfg -

[defaults] 
callback_whitelist = profile_tasks

Переменные в playbooks very similarиспользовать переменные на любом языке программирования. Это помогает вам использовать и присваивать значение переменной и использовать его в любом месте учебника. Можно поставить условия вокруг значения переменных и, соответственно, использовать их в playbook.

пример

- hosts : <your hosts> 
vars:
tomcat_port : 8080

В приведенном выше примере мы определили имя переменной tomcat_port и присвоил этой переменной значение 8080 и может использовать это в своей книге где угодно.

Теперь возьмем ссылку из приведенного примера. Следующий код взят из одной из ролей (install-tomcat) -

block: 
   - name: Install Tomcat artifacts 
      action: > 
      yum name = "demo-tomcat-1" state = present 
      register: Output 
          
   always: 
      - debug: 
         msg: 
            - "Install Tomcat artifacts task ended with message: {{Output}}" 
            - "Installed Tomcat artifacts - {{Output.changed}}"

Здесь вывод - это используемая переменная.

Давайте пройдемся по всем ключевым словам, использованным в приведенном выше коде -

  • block - Ответственный синтаксис для выполнения заданного блока.

  • name - Соответствующее имя блока - используется в журнале и помогает в отладке того, все блоки которого были успешно выполнены.

  • action- Код рядом с тегом действия - это задача, которую нужно выполнить. Действие снова является ключевым словом Ansible, используемым в yaml.

  • register - Вывод действия регистрируется с помощью ключевого слова register, а Output - это имя переменной, которая содержит вывод действия.

  • always - Опять ключевое слово Ansible, в нем указано, что ниже всегда будет выполняться.

  • msg - Отображает сообщение.

Использование переменной - {{Output}} ->

Это прочитает значение переменной Output. Также, поскольку он используется на вкладке msg, он будет печатать значение выходной переменной.

Кроме того, вы также можете использовать дополнительные свойства переменной. Как и в случае с проверкой {{Output.changed}}, изменился ли вывод, и соответственно использовать его.

Обработка исключений в Playbooks

Обработка исключений в Ansible аналогична обработке исключений в любом языке программирования. Пример обработки исключений в playbook показан ниже.

tasks: 
   - name: Name of the task to be executed 
      block: 
         - debug: msg = 'Just a debug message , relevant for logging' 
         - command: <the command to execute> 
      
      rescue: 
         - debug: msg = 'There was an exception.. ' 
         - command: <Rescue mechanism for the above exception occurred) 
      
      always: 
         - debug: msg = "this will execute in all scenarios. Always will get logged"

Ниже приводится синтаксис обработки исключений.

  • rescue и always - ключевые слова, относящиеся к обработке исключений.

  • Блок - это место, где написан код (все, что должно выполняться на машине Unix).

  • Если команда, записанная внутри функции блока, не выполняется, выполнение достигает блока восстановления и выполняется. Если в команде в блокировке нет ошибки, то восстановление не будет выполнено.

  • Always выполняется во всех случаях.

  • Итак, если мы сравним то же самое с java, то это похоже на попытку, поймать и, наконец, заблокировать.

  • Вот, Block похож на try block где вы пишете код для выполнения и rescue похож на catch block и always похож на finally.

Петли

Ниже приведен пример, демонстрирующий использование циклов в Ansible.

Задача состоит в том, чтобы скопировать набор всех файлов war из одного каталога в папку tomcat webapps.

Большинство команд, используемых в приведенном ниже примере, уже рассматривались ранее. Здесь мы сосредоточимся на использовании петель.

Изначально в команде shell мы сделали ls * .war. Таким образом, он перечислит все файлы войны в каталоге.

Вывод этой команды сохраняется в переменной с именем output.

Для цикла используется синтаксис with_items.

with_items: "{{output.stdout_lines}}" -> output.stdout_lines дает нам построчный вывод, а затем мы перебираем вывод с помощью команды with_items из Ansible.

Прилагаем пример вывода, чтобы вы поняли, как мы использовали stdout_lines в команде with_items.

--- 
#Tsting 
- hosts: tomcat-node 
   tasks: 
      - name: Install Apache 
      shell: "ls *.war" 
      register: output 
      args: 
         chdir: /opt/ansible/tomcat/demo/webapps 
      
      - file: 
         src: '/opt/ansible/tomcat/demo/webapps/{{ item }}' 
         dest: '/users/demo/vivek/{{ item }}' 
         state: link 
      with_items: "{{output.stdout_lines}}"

                

Блоки

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

Примеры блоков описаны выше в использовании переменных, обработке исключений и циклах.

Условные

Условные выражения используются там, где нужно выполнить определенный шаг на основе условия.

--- 
#Tsting 
- hosts: all 
   vars: 
      test1: "Hello Vivek" 
   tasks: 
      - name: Testing Ansible variable 
      debug: 
         msg: "Equals" 
         when: test1 == "Hello Vivek"

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

Просто измените значение переменной test1 из Hello Vivek, чтобы сказать Hello World и посмотреть результат.

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

Как ограничить выполнение задачами

Это очень важная стратегия выполнения, когда нужно выполнять только одно выполнение, а не всю книгу воспроизведения. For example, предположим, вы хотите только остановить сервер (в случае возникновения производственной проблемы), а затем опубликовать патч, который вы хотите только запустить.

Здесь, в оригинальной playbook, остановка и запуск были частью разных ролей в одной playbook, но с этим можно справиться с помощью тегов. Мы можем предоставить разные теги для разных ролей (которые, в свою очередь, будут иметь задачи), и, следовательно, на основе тегов, предоставленных исполнителем, выполняется только указанная роль / задача. Итак, для приведенного выше примера мы можем добавить следующие теги:

- {role: start-tomcat, tags: ['install']}}

Следующая команда помогает в использовании тегов -

ansible-playbook -i hosts <your yaml> --tags "install" -vvv

С помощью приведенной выше команды будет вызываться только роль start-tomcat. Предоставляемый тег чувствителен к регистру. Убедитесь, что команде передается точное совпадение.

Как ограничить выполнение хостами

Есть два способа добиться выполнения определенных шагов на определенных хостах. Для конкретной роли определяются хосты - на каких именно хостах должна выполняться эта конкретная роль.

пример

- hosts: <A> 
   environment: "{{your env}}" 
   pre_tasks: 
      - debug: msg = "Started deployment. 
      Current time is {{ansible_date_time.date}} {{ansible_date_time.time}} " 
     
   roles: 
      - {role: <your role>, tags: ['<respective tag>']} 
   post_tasks: 
      - debug: msg = "Completed deployment. 
      Current time is {{ansible_date_time.date}} {{ansible_date_time.time}}" 
 
- hosts: <B> 
   pre_tasks: 
      - debug: msg = "started.... 
      Current time is {{ansible_date_time.date}} {{ansible_date_time.time}} " 
        
   roles: 
      - {role: <your role>, tags: ['<respective tag>']} 
   post_tasks: 
      - debug: msg = "Completed the task.. 
      Current time is {{ansible_date_time.date}} {{ansible_date_time.time}}"

Согласно приведенному выше примеру, в зависимости от предоставленных хостов, будут вызываться только соответствующие роли. Теперь мои хосты A и B определены в хостах (файл инвентаризации).

Альтернативное решение

Другое решение может заключаться в определении хостов playbook с помощью переменной с последующей передачей конкретного адреса хоста через --extra-vars -

# file: user.yml  (playbook) 
--- 
- hosts: '{{ target }}' 
   user: ... 
playbook contd….

Запуск Playbook

ansible-playbook user.yml --extra-vars "target = "<your host variable>"

Если {{target}} не определен, playbook ничего не делает. При необходимости также можно передать группу из файла hosts. Это не повредит, если не предусмотрены дополнительные переменные.

Пособие для одного хоста

$ ansible-playbook user.yml --extra-vars "target = <your hosts variable>" --listhosts

Наиболее распространенные стратегии для отладки сборников пьес Ansible используют модули, приведенные ниже:

Отладка и регистрация

Эти два модуля доступны в Ansible. Для целей отладки нам нужно разумно использовать два модуля. Примеры показаны ниже.

Используйте многословие

С помощью команды Ansible можно обеспечить уровень детализации. Вы можете запускать команды с уровнем детализации один (-v) или два (-vv).

Важные точки

В этом разделе мы рассмотрим несколько примеров, чтобы понять некоторые концепции.

Если вы не цитируете аргумент, который начинается с переменной. Например,

vars: 
   age_path: {{vivek.name}}/demo/ 
   
{{vivek.name}}

Это вызовет ошибку.

Решение

vars: 
   age_path: "{{vivek.name}}/demo/" – marked in yellow is the fix. 
 
How to use register -> Copy this code into a yml file say test.yml and run it  
--- 
#Tsting 
- hosts: tomcat-node 
   tasks: 
 
   - shell: /usr/bin/uptime 
      register: myvar 
      - name: Just debugging usage 
         debug: var = myvar

Когда я запускаю этот код с помощью команды Ansible-playbook -i hosts test.yml, я получаю результат, как показано ниже.

Если вы видите yaml, мы зарегистрировали вывод команды в переменной - myvar и просто распечатал результат.

Текст, помеченный желтым, сообщает нам о свойстве переменной –myvar, которое можно использовать для дальнейшего управления потоком. Таким образом, мы можем узнать о свойствах конкретной переменной. В этом помогает следующая команда отладки.

$ ansible-playbook -i hosts test.yml 

PLAY [tomcat-node] ***************************************************************
**************** ****************************************************************
*************** ****************************** 
 
TASK [Gathering Facts] *****************************************************************
************** *****************************************************************
************** ************************** 
Monday 05 February 2018  17:33:14 +0530 (0:00:00.051) 0:00:00.051 ******* 
ok: [server1] 
 
TASK [command] ******************************************************************
************* ******************************************************************
************* ********************************** 
Monday 05 February 2018  17:33:16 +0530 (0:00:01.697) 0:00:01.748 ******* 
changed: [server1] 
 
TASK [Just debugging usage] ******************************************************************
************* ******************************************************************
************* ********************* 
Monday 05 February 2018  17:33:16 +0530 (0:00:00.226) 0:00:01.974 ******* 
ok: [server1] => { 
   "myvar": { 
      "changed": true, 
      "cmd": "/usr/bin/uptime", 
      "delta": "0:00:00.011306", 
      "end": "2018-02-05 17:33:16.424647", 
      "rc": 0, 
      "start": "2018-02-05 17:33:16.413341", 
      "stderr": "", 
      "stderr_lines": [], 
      "stdout": " 17:33:16 up 7 days, 35 min,  1 user,  load average: 0.18, 0.15, 0.14", 
      "stdout_lines": [ 
         " 17:33:16 up 7 days, 35 min,  1 user,  load average: 0.18, 0.15, 0.14" 
      ] 
   } 
} 
 
PLAY RECAP ****************************************************************************
**********************************************************************************
 ************************************** 
server1 : ok = 3    changed = 1    unreachable = 0    failed = 0

Распространенные проблемы с Playbook

В этом разделе мы узнаем о нескольких распространенных проблемах с учебником. Проблемы -

  • Quoting
  • Indentation

Playbook написан в формате yaml, и два указанных выше являются наиболее распространенными проблемами в yaml / playbook.

Yaml не поддерживает отступы на основе табуляции и поддерживает отступы на основе пробелов, поэтому с этим нужно быть осторожным.

Note - как только вы закончите писать ямл, откройте этот сайт (https://editor.swagger.io/) и скопируйте и вставьте свой yaml с левой стороны, чтобы убедиться, что yaml компилируется правильно. Это всего лишь подсказка.

Swagger квалифицирует ошибки как предупреждение, а также как ошибку.