Ansible вводная инструкция по началу работы. Devops инструменты Часть 1.
Ansible – Введение
Ansible – это простой ИТ-движок с открытым исходным кодом, который автоматизирует развертывание приложений, внутрисервисную оркестровку, облачную подготовку и многие другие ИТ-инструменты.
Ansible прост в развертывании, поскольку он не использует агентов или пользовательскую инфраструктуру безопасности.
Ansible использует playbook для описания заданий автоматизации, а playbook использует очень простой язык, то есть YAML (это читаемый человеком язык сериализации данных и обычно используется для файлов конфигурации, но может использоваться во многих приложениях, где хранятся данные), что очень легко для людей, чтобы понять, читать и писать. Следовательно, преимущество заключается в том, что даже ребята из службы поддержки ИТ-инфраструктуры могут читать и понимать игровую книгу и отлаживать ее при необходимости (YAML – она в удобочитаемой форме).
Ansible предназначен для многоуровневого развертывания. Ansible не управляет одной системой одновременно, он моделирует ИТ-инфраструктуру, описывая все ваши системы взаимосвязанными. Ansible полностью без агента, что означает, что Ansible работает, подключая ваши узлы через ssh (по умолчанию). Но если вам нужен другой способ подключения, например Kerberos, Ansible предоставит вам такую возможность.
После подключения к вашим узлам Ansible запускает небольшие программы, называемые «Ansible Modules». Ansible запускает эти модули на ваших узлах и удаляет их по завершении. Ansible управляет вашим инвентарем в простых текстовых файлах (это файл hosts). Ansible использует файл hosts, в котором можно сгруппировать хосты и управлять действиями над определенной группой в книгах воспроизведения.
@DevOPSitsec – бесплатное обучение DevOps в нашем канале.
Образец файла 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. Все, что вам нужно сделать, это перечислить IP-адреса ваших узлов в инвентаре и написать книгу для установки WebLogic / WebSphere. Запустите playbook со своего компьютера управления, и он будет установлен на всех ваших узлах.
Как работает Ansible?
На рисунке ниже показана работа Ansible.
Ansible работает , подключаясь к вашим узлам и выдвигая к ним небольшие программы, называемые « Ansible modules». Затем Ansible выполняет эти модули (по умолчанию через SSH) и удаляет их после завершения. Ваша библиотека модулей может находиться на любом компьютере, и для нее не требуются серверы, демоны или базы данных.
Узел управления на приведенном выше изображении является управляющим узлом (управляющим узлом), который управляет всем исполнением книги воспроизведения. Это узел, с которого вы запускаете установку. Файл инвентаризации содержит список хостов, на которых необходимо запустить модули Ansible, а узел управления устанавливает соединение SSH, выполняет небольшие модули на хост-машине и устанавливает продукт / программное обеспечение.
Прелесть Ansible в том, что он удаляет модули после того, как они установлены, настолько эффективно, что он подключается к хост-машине, выполняет инструкции и, если он успешно установлен, удаляет код, который был скопирован на хост-машине, которая была выполнена.
Ansible – Настройка среды
В этой главе мы узнаем о настройке среды Ansible.
Процесс установки
В основном, есть два типа машин, когда мы говорим о развертывании –
- Управление машиной – Машина, с которой мы можем управлять другими машинами.
- Дистанционная машина – машины, которые управляются / контролируются управляющей машиной.
Управление машиной – Машина, с которой мы можем управлять другими машинами.
Дистанционная машина – машины, которые управляются / контролируются управляющей машиной.
Может быть несколько удаленных машин, которые обрабатываются одной управляющей машиной. Итак, для управления удаленными машинами мы должны установить Ansible на управляющей машине.
Требования к контрольной машине
Ansible может быть запущен с любой машины с установленным Python 2 (версии 2.6 или 2.7) или Python 3 (версии 3.5 и выше).
Примечание. Windows не поддерживает управление машиной.
По умолчанию Ansible использует ssh для управления удаленным компьютером.
Ansible не добавляет ни одной базы данных. Это не требует каких-либо демонов, чтобы запустить или поддерживать его. При управлении удаленными машинами Ansible не оставляет на них установленного или запущенного программного обеспечения. Следовательно, нет вопроса о том, как обновить его при переходе на новую версию.
Ansible может быть установлен на управляющей машине, которая имеет вышеупомянутые требования по-разному. Вы можете установить последнюю версию через Apt, yum, pkg, pip, OpenCSW, pacman и т. Д.
Установка через Apt на Ubuntu Machine
Для установки 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 – version, чтобы проверить версию и просто проверить, правильно ли был установлен Ansible.
Ansible – Основы YAML
Ansible использует синтаксис YAML для выражения Ansible playbooks. В этой главе представлен обзор YAML. Ansible использует YAML, потому что людям очень легко понимать, читать и писать по сравнению с другими форматами данных, такими как XML и JSON.
Каждый файл YAML может начинаться с «—» и заканчиваться на «…».
Понимание YAML
В этом разделе мы изучим различные способы представления данных YAML.
пара ключ-значение
YAML использует простую пару ключ-значение для представления данных. Словарь представлен в паре ключ: значение.
Примечание. Между: и значением должен быть пробел.
Пример: запись студента
--- #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 использует «|» для включения новых строк при отображении нескольких строк и «>» для подавления новых строк при отображении нескольких строк. Благодаря этому мы можем читать и редактировать большие строки. В обоих случаях намерения будут игнорироваться.
Мы также можем представлять логические (True / false) значения в YAML. где логические значения могут быть без учета регистра.
пример
--- - 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.
Сервис / Сервер – процесс на компьютере, который предоставляет сервис.
Машина – физический сервер, виртуальная машина или контейнер.
Целевая машина – машина, которую мы собираемся настроить с помощью Ansible.
Задача – действие (запустить, удалить это) и т. Д., Управляемое Ansible.
Playbook – файл yml, в котором записываются команды Ansible и на компьютере выполняется yml.
Сервис / Сервер – процесс на компьютере, который предоставляет сервис.
Машина – физический сервер, виртуальная машина или контейнер.
Целевая машина – машина, которую мы собираемся настроить с помощью Ansible.
Задача – действие (запустить, удалить это) и т. Д., Управляемое Ansible.
Playbook – файл yml, в котором записываются команды Ansible и на компьютере выполняется yml.
Инвентори: ansible_host vs FQDN
В этой части мы хорошо разбираемся с тем, что такое inventory_hostname
, что такое ansible_host
, с понятием транспорта.
При том, что транспорт уже не совсем “инвентори”, к содержимому инвентори он относится наипрямейшим образом, потому что смена транспорта внутри play — это уже экстремальный спорт, на который не распространяется ваша медстраховка.
Что такое “транспорт”? Это результат использования “connection plugin” Ансибла, через который модуль копируется в целевую систему (или, в ряде случаев, не копируется, но получает доступ к целевой системе). Какой-то транспорт используется всегда. Самый популярный транспорт ssh (используется по-умолчанию), но их на самом деле много. Каждый плагин может использовать набор переменных, выделенных для подключения: ansible_host
, ansible_user
, ansible_port
и т. д. А может и не использовать. Например, если транспорт lxc (который выполняет код через lxc-execute
), то зачем ему порт?
Если же ansible_host
не задан, то используется inventory_hostname
. Это — имя хоста в инвентори.
Вот пример:
---
somegroup:
hosts:
somehost:
ansible_host: 254.12.11.10
Вот somehost
тут — это inventory_hostname
. Если нет ansible_host
, то используется inventory_hostname
. И всё было бы понятно, если бы не следующий уровень преобразований, который не имеет никакого отношения к Ансибл, но может попортить много нервов.
Внутри как inventory_hostname
, так и ansible_host
может быть либо адрес, либо имя. С адресом всё понятно, а вот с именем уже интереснее. Оно передаётся “как есть” в нижележащий исполнитель. Интерпретация имени оставляется на усмотрение транспорта. Например, lxc использует его для выбора контейнера. А вот ssh (самый распространённый транспорт, напоминаю) использует кое-что более сложное.
Во-первых, он смотрит в конфиг ~/.ssh/ssh_config
(или другой, заданный через переменные окружения). Если кто пропустил, напоминаю, что конфиг ssh тьюринг-полный и может делать странное через комбинацию регэкспов и сниппетов для исполнения баша. Т.е. переданное имя становится (в общем случае) аргументом к частично-рекурсивной функции, которая (может быть) выдаёт реальные параметры соеднения на выходе. Может быть, соединение пойдёт через цепочку jump-хостов, редиректов портов и прочего ssh-цирка. А может быть, такого хоста не найдётся. Если же из ssh_config
выползает другое имя (или искомого нет в ssh_config
), то ssh делает gethostbyname()
. Это вызов libc, который получает адрес по имени. Который, в свою очередь, руководствуется пачкой конфигурационных файлов (/etc/nsswitch.conf
, /etc/hosts
) и ответами DNS-ресолвера (если конфигурационные файлы это разрешают). Который, в свою очередь, может дописывать к имени домен, смотреть на разные рекурсивные DNS-сервера, которые могут отвечать разное, а могут посмотреть на ресурсную запись CNAME пойти куда сказано… Просто волшебная простыня возможностей того, что может пойти не так.
Из этого вытекает моё, выстраданное, мнение: при работе с SSH, всегда (кроме спецслучаев) использовать ansible_host
внутри которого IP-адрес.
Я пробовал другой путь, и он мне местами аукается до сих пор. Давайте разберём этот вопрос подробно.
Если вы используете любое вне-ансибловое, но host-local определение имени (ssh_config
, /etc/hosts
), то ваши плейбуки перестают быть портабельными между машинами. Вы ссылаетесь на что-то, что существует только у вас в голове и с вами разговаривает только в конфигурации вашего компьютера. Вы не можете перетащить эти плейбуки на CI, на машину коллеги или даже на вторую вашу машину. Точнее, можете, но для этого нужно что-то (что?) прописать в конфигурацию, которой не видно в репозитории. Опечатки трудно отлаживать (у меня всё работает), изменения почти невозможно распространять. НЕ ДЕЛАЙТЕ ТАК.
Хотя, разумеется, есть исключения. Например, моя маленькая уютная оверлейная сеточка для домашних нужд живёт с именами из /etc/hosts и все плейбуки полагаются на эти имена. Но это моё осознанное решение, которое к индустриальному продакшену никакого отношения иметь не должно.
Если вы используете DNS, то вы получаете себе регэксп ещё одну проблему. Когда изменения в DNS дойдут до вашей машины? Негативное/позитивное кеширование, всё такое. А даже если оно дошло до вас, то когда оно дойдёт до резолвера, которым пользуется ваш динамический слейв CI? Слейв-то помер, а DNS-ресолвер — нет. Удачи в отладке. НЕ ДЕЛАЙТЕ ТАК.
Второй момент, куда более тонкий. Надо ли всегда указывать ansible_host
или inventory_hostname
достаточно?
В плейбуках рано или поздно возникает потребность указать “адрес соседа”. В самых трудных случаях этот процесс требует модуля setup
и выполнения головоломного кода:
- name: Ping neighbor
command: ping -c 1 {{ neighbor_ip }} -w 1
changed_when: false
vars:
neighbor_ip: '{{ (hostvars[item].ansible_all_ipv4_addresses|ipaddr(public_network))[0] }}'
with_items: '{{ groups[target_group] }}'
(имея на руках public_network
мы проверяем, что хосты могут общаться со всеми серверами в группе target_group
).
Но, это трудный случай, поскольку у серверов несколько интерфейсов. В 99% случаев вам нужен просто “адрес соседа”. Если вы договорились, что у каждого хоста есть ansible_host
и внутри там обязательно IP-адрес, то вот он. Никакого setup
. Бери и используй. Прелесть ansible_host
с IP-адресом трудно переоценить, потому что, помимо “какого-то IP соседа”, этот адрес ещё неявно (явно!) отвечает вам на вопрос, какой из IP-адресов сервера является его “access address” при наложении всяких файрвольных правил, конфигурации доступов и т.д. Делайте так. Это хорошо и удобно.
… Но тут может возникнуть вопрос: а если у нас сервера появляются на свет динамически, или у нас внешная система оркестрации (а-ля докер) у которой точно есть хороший DNS? Ну, тогда используйте их. А, заодно, страдайте, если вам понадобились IP. Разумеется, к любой общей рекомендации всегда можно найти частные исключения.
Инвентори: ansible_user
Следующая интереснейшая проблема: надо ли в инвентори хранить имя пользователя? Это важный вопрос, но у него нет однозначного ответа. Вот набор моментов, о которых надо подумать перед выбором.
- Есть ли доступ к этому хосту из-под “спецаккаунта” у других пользователей? Если есть, то
ansible_user
в инвентори разумно. - Есть ли доступ к серверу под “своими” аккаунтами у других пользователей? Если есть, то
ansible_user
в инвентори создаёт проблемы. - Если вы не указываете пользователя в инвентори, то опция
-u
уansible-playbook
позволяет пользователя задать, причём так, что его можно переопределить из любого места в инвентори или плейбуке для необычных видов коннектов. Это удобно. Каждый под своим пользователем, CI использует-u
(или тоже под своим пользователем), все счастливы. - Но тогда абстракция протекает. Например, ваш сосед может быть залогинен на своём ноутбуке под именем ‘me’. Это ж его ноутбук. А на сервере он — m.gavriilicheynko. Неудобненько.
- В то же самое время, использование опции
ansible-playbook -e ansible_user=ci
(для CI, например) с одной стороны позволяет использовать правильное имя вне зависимости от содержимого инвентори, с другой стороны ломает все нестандартные подключения (к коммутаторам, например). - Если у вас стоит проблема “первого логина” (плейбука создаёт всех пользователей, но только после первого запуска), то первый запуск можно сделать и с опцией
-u
, и никто не помрёт.
В моей практике (и обстоятельствах, в которых я работаю), мне удобно указывать ansible_user
для “себя” (т.е. инвентори, к которыми работаю только я). Если инвентори используется более одним человеком — ansible_user используется только для специальных случаев (например, доступ к коммутаторам при первом провизе и т.д.), а обычные хосты ansible_user
не используют.
Ansible – специальные команды
Специальные команды – это команды, которые можно запускать индивидуально для выполнения быстрых функций. Эти команды не должны быть выполнены позже.
Например, вам нужно перезагрузить все серверы вашей компании. Для этого вы запустите команды Adhoc из / usr / bin / ansible .
Эти специальные команды не используются для управления конфигурацией и развертывания, потому что эти команды используются один раз.
ansible-playbook используется для управления конфигурацией и развертывания.
Параллелизм и Команды Shell
Перезагрузите сервер своей компании в 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 (Secure Copy Protocol) на нескольких компьютерах.
Передача файла на многие серверы / машины
$ 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"
Управление пакетами
Специальные команды доступны для 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
Ansible – Playbooks
В этой главе мы узнаем о Playbooks в Ansible.
Названия
Главная ошибка пользователя Ansible — это не знать как что называется. Если вы не знаете названий, вы не можете понимать то, что написано в документации. Живой пример: на собеседовании, человек, вроде бы заявлявший, что он много писал на Ансибле, не смог ответить на вопрос “из каких элементов состоит playbook’а?”. А когда я подсказал, что “ожидался ответ, что playbook состоит из play”, то последовал убийственный комментарий “мы этого не используем”. Люди пишут на Ансибле за деньги и не используют play. На самом деле используют, но не знают, что это такое.
Так что начнём с простого: как что называется. Может быть вы это знаете, а может и нет, потому что не обратили внимания, когда читали документацию.
ansible-playbook исполняет playbook. Playbook — это файл с расширением yml/yaml, внутри которого что-то такое:
---
- hosts: group1
roles:
- role1
- hosts: group2,group3
tasks:
- debug:
Мы уже поняли, что весь этот файл — плейбука. Мы можем показать где тут роли (roles), где таски (tasks). Но где тут play? И чем отличается play от role или playbook?
В документации это всё есть. И это пропускают. Начинающие — потому что там слишком много и всё сразу не запомнишь. Опытные — потому что “тривиальные вещи”. Если вы опытный — перечитывайте эти страницы хотя бы раз в полгода, и ваш код станет классом лучше.
Итак, запоминайте: Playbook — это список, состоящий из play и import_playbook
.
Вот это — одна play:
- hosts: group1
roles:
- role1
и вот это тоже ещё одна play:
- hosts: group2,group3
tasks:
- debug:
Что же такое play? Зачем она?
Play — это ключевой элемент для playbook, потому что play и только play связывает список ролей и/или тасок с списком хостов, на которых их надо выполнять. В глубоких недрах документации можно найти упоминание про delegate_to
, локальные lookup-плагины, network-cli-специфичные настройки, jump-хосты и т.д. Они позволяют слегка поменять место исполнения тасок. Но, забудьте про это. У каждой из этих хитрых опций есть очень специальные применения, и они точно не являются универсальными. А мы говорим про базовые вещи, которые должны знать и использовать все.
Если вы хотите “что-то” исполнить “где-то” — вы пишете play. Не роль. Не роль с модулями и делегейтами. Вы берёте и пишете play. В которой, в поле hosts вы перечисляете где исполнять, а в roles/tasks — что исполнять.
Просто же, да? А как может быть иначе?
Одним из характерных моментов, когда у людей возникает желание сделать это не через play, это “роль, которая всё настраивает”. Хочется иметь роль, которая настраивает и сервера первого типа, и сервера второго типа.
Архетипичным примером является мониторинг. Хочется иметь роль monitoring, которая настроит мониторинг. Роль monitoring назначается на хосты мониторинга (в соотв. play). Но, выясняется, что для мониторинга нам надо поставить пакеты на хосты, которые мы мониторим. Почему бы не использовать delegate? А ещё надо настроить iptables. delegate? А ещё надо написать/поправить конфиг для СУБД, чтобы мониторинг пускала. delegate! А если креатив попёр, то можно сделать делегацию include_role
во вложенном цикле по хитрому фильтру на список групп, а внутри include_role
можно ещё делать delegate_to
снова. И понеслось…
Благое пожелание — иметь одну-единственную роль monitoring, которая “всё делает” — ведёт нас в кромешный ад из которого чаще всего один выход: всё переписать с нуля.
Где тут случилась ошибка? В тот момент, когда вы обнаружили, что для выполнения задачи “x” на хосте X вам надо пойти на хост Y и сделать там “y”, вы должны были выполнить простое упражнение: пойти и написать play, которая на хосте Y делает y. Не дописывать что-то в “x”, а написать с нуля. Пусть даже с захардкоженными переменными.
Вроде бы, в абзацах выше всё сказано правильно. Но это же не ваш случай! Потому что вы хотите написать переиспользуемый код, который DRY и похож на библиотеку, и нужно искать метод как это сделать.
Вот тут вот притаилась ещё одна грубая ошибка. Ошибка, которая превратила множество проектов из терпимо написанных (можно лучше, но всё работает и легко дописать) в совершенный ужас, в котором даже автор не может разобраться. Оно работает, но упаси боже что-то поменять.
Эта ошибка звучит так: роль — это библиотечная функция. Эта аналогия сгубила столько хороших начинаний, что просто грустно смотреть. Роль — не библиотечная функция. Она не может делать вычисления и она не может принимать решения уровня play. Напомните мне, какие решения принимает play?
Спасибо, вы правы. Play принимает решение (точнее, содержит в себе информацию) о том, какие таски и роли на каких хостах выполнять.
Если вы делегируете это решение на роль, да ещё и с вычислениями, вы обрекаете себя (и того, кто ваш код будет пытаться разобрать) на жалкое существование. Роль не решает где ей выполняться. Это решение принимает play. Роль делает то, что ей сказали, там, где ей сказали.
Почему заниматься программированием на Ансибле опасно и чем COBOL лучше Ансибла мы поговорим в главе про переменные и jinja. Пока что скажем одно — каждое ваше вычисление оставляет за собой нестираемый след из изменения глобальных переменных, и вы ничего с этим не можете сделать. Как только два “следа” пересеклись — всё пропало.
Замечание для въедливых: роль, безусловно, может влиять на control flow. Есть delegate_to
и у него есть разумные применения. Есть meta: end host/play
. Но! Помните, мы учим основы? Забыли про delegate_to
. Мы говорим про самый простой и самый красивый код на Ансибл. Который легко читать, легко писать, легко отлаживать, легко тестировать и легко дописывать. Так что, ещё раз:
play и только play решает на каких хостах что исполняется.
В этом разделе мы разобрались с противостоянием play и role. Теперь поговорим про отношения tasks vs role.
Playbooks – это файлы, в которых написан код Ansible. Сборники написаны в формате YAML. YAML означает еще один язык разметки. Playbooks являются одной из основных функций Ansible и говорят Ansible, что выполнять. Они похожи на список дел для Ansible, который содержит список задач.
Playbooks содержат шаги, которые пользователь хочет выполнить на определенной машине. Playbooks запускаются последовательно. Playbooks являются строительными блоками для всех случаев использования Ansible.
Структура Playbook
Каждая пьеса представляет собой совокупность одной или нескольких пьес в ней. Playbooks структурированы с использованием Plays. В сборнике пьес может быть несколько пьес.
Функция игры состоит в том, чтобы отобразить набор инструкций, определенных для определенного хоста.
YAML – строго типизированный язык; поэтому при записи файлов YAML необходимо соблюдать особую осторожность. Существуют разные редакторы YAML, но мы предпочитаем использовать простой редактор, такой как notepad ++. Просто откройте notepad ++, скопируйте и вставьте нижеследующий yaml и измените язык на YAML (Язык → YAML).
YAML начинается с — (3 дефиса)
Создать Playbook
Давайте начнем с написания примера файла 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. Как в том, что будет делать этот playbook. Любое логическое имя может быть дано пьесе.
хостов
Этот тег определяет списки хостов или группы хостов, для которых мы хотим запустить задачу. Поле / тег hosts является обязательным. Он сообщает Ansible, на каких хостах запускать перечисленные задачи. Задачи могут быть запущены на той же машине или на удаленной машине. Можно запускать задачи на нескольких машинах, и, следовательно, тег hosts может содержать также запись группы узлов.
вары
Тег Vars позволяет вам определять переменные, которые вы можете использовать в своей книге игр. Использование аналогично переменным в любом языке программирования.
задачи
Все пьесы должны содержать задачи или список задач для выполнения. Задачи – это список действий, которые нужно выполнить. Поле задач содержит название задачи. Это работает как текст справки для пользователя. Это не обязательно, но оказывается полезным при отладке playbook. Каждая задача внутренне связана с частью кода, называемой модулем. Модуль, который должен быть выполнен, и аргументы, необходимые для модуля, который вы хотите выполнить.
Ansible – Роли
Роли обеспечивают основу для полностью независимых или взаимозависимых наборов переменных, задач, файлов, шаблонов и модулей.
В Ansible эта роль является основным механизмом разбиения книги воспроизведения на несколько файлов. Это упрощает написание сложных сборников и облегчает их повторное использование. Взлом playbook позволяет вам логически разбить playbook на компоненты многократного использования.
Каждая роль в основном ограничена определенной функциональностью или желаемым результатом со всеми необходимыми шагами для обеспечения этого результата либо внутри самой роли, либо в других ролях, перечисленных как зависимости.
Роли не являются пьесами. Роли – это небольшая функциональность, которую можно использовать независимо, но ее нужно использовать в книгах. Нет способа напрямую выполнить роль. Роли не имеют явного параметра, для которого будет применяться роль.
Playbook верхнего уровня – это мост, удерживающий хосты из файла инвентаризации для ролей, которые должны применяться к этим хостам.
Создание новой роли
Структура каталогов для ролей необходима для создания новой роли.
Ролевая структура
Роли имеют структурированный макет в файловой системе. Структура по умолчанию может быть изменена, но пока давайте придерживаться значений по умолчанию.
Каждая роль представляет собой дерево каталогов само по себе. Имя роли – это имя каталога в каталоге / role.
$ ansible-galaxy -h
использование
ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...
Опции
- -h, –help – показать это справочное сообщение и выйти.
- -v, –verbose – подробный режим (-vvv для большего, -vvvv для включения отладки соединения)
- –version – Показать номер версии программы и выйти.
-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
Это код пьесы, которую мы написали для демонстрации. Этот код из сборника пьес 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. Основным содержимым 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 начального tomcat –
#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.
Разбивая Playbook на роль
Если не для ролей, содержимое main.yml соответствующей роли может быть скопировано в yml- файл playbook. Но чтобы иметь модульность, роли были созданы.
Любая логическая сущность, которая может быть повторно использована как функция многократного использования, эта сущность может быть перемещена в роль. Пример для этого показан выше
Запустил команду для запуска 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
Ansible – переменные
Переменные в playbooks очень похожи на использование переменных в любом языке программирования. Это поможет вам использовать и назначить значение переменной и использовать ее в любом месте книги. Можно поставить условия вокруг значения переменных и соответственно использовать их в сборнике игр.
пример
- 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 – код рядом с тегом action – это задача, которая должна быть выполнена. Действие снова является ключевым словом Ansible, используемым в yaml.
- register – Выходные данные действия регистрируются с использованием ключевого слова register, а Output – это имя переменной, которая содержит выходные данные действия.
- always – снова ключевое слово Ansible, оно указывает, что ниже всегда будет выполняться
- msg – отображает сообщение
block – Доступный синтаксис для выполнения данного блока.
name – Соответствующее имя блока – это используется при ведении журнала и помогает в отладке того, все блоки которого были успешно выполнены.
action – код рядом с тегом 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"
Ниже приводится синтаксис для обработки исключений.
- спасение и всегда являются ключевыми словами, специфичными для обработки исключений.
- Блок – это место, где написан код (все, что должно быть выполнено на Unix-машине).
- Если команда, записанная внутри функции блока, не выполняется, то выполнение достигает блока спасения, и оно выполняется. В случае отсутствия ошибки в команде в функции блокировки, восстановление не будет выполнено.
- Всегда исполняется во всех случаях.
- Так что если мы сравниваем то же самое с Java, то это похоже на попытку, поймать и, наконец, блокировать.
- Здесь Block аналогичен блоку try, в котором вы пишете код для выполнения, а функция спасения аналогична блоку catch и всегда похожа на finally .
спасение и всегда являются ключевыми словами, специфичными для обработки исключений.
Блок – это место, где написан код (все, что должно быть выполнено на Unix-машине).
Если команда, записанная внутри функции блока, не выполняется, то выполнение достигает блока спасения, и оно выполняется. В случае отсутствия ошибки в команде в функции блокировки, восстановление не будет выполнено.
Всегда исполняется во всех случаях.
Так что если мы сравниваем то же самое с Java, то это похоже на попытку, поймать и, наконец, блокировать.
Здесь Block аналогичен блоку try, в котором вы пишете код для выполнения, а функция спасения аналогична блоку catch и всегда похожа на finally .
Loops
Ниже приведен пример, демонстрирующий использование Loops в 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}}"
Блоки
Сборник пьес в целом разбит на блоки. Наименьшая часть шагов для выполнения записана в блоке. Написание конкретной инструкции в блоках помогает разделить функциональность и обрабатывать ее с обработкой исключений, если это необходимо.
Пример блоков описан выше в использовании переменных, обработке исключений и циклах.
Conditionals
Условные выражения используются там, где необходимо выполнить определенный шаг на основе условия.
--- #Tsting - hosts: all vars: test1: "Hello Vivek" tasks: - name: Testing Ansible variable debug: msg: "Equals" when: test1 == "Hello Vivek"
В этом случае Equals будет напечатан, поскольку переменная test1 равна, как указано в условии when. когда можно использовать с логическим ИЛИ и логическим условием И, как во всех языках программирования.
Просто измените значение переменной test1 с Hello Vivek на Hello World и посмотрите результат.
Ansible – Расширенное исполнение
В этой главе мы узнаем, что такое расширенное выполнение с Ansible.
Как ограничить выполнение задач
Это очень важная стратегия исполнения, когда нужно выполнить только одно исполнение, а не всю книгу. Например , предположим, что вы хотите только остановить сервер (в случае возникновения производственной проблемы), а затем опубликовать исправление, которое вы хотели бы только запустить сервер.
Здесь в оригинальной пьесе «Остановка и запуск» были частью разных ролей в одной и той же пьесе, но это можно сделать с помощью тегов. Мы можем предоставить разные теги для разных ролей (которые, в свою очередь, будут иметь задачи), и, следовательно, на основе тегов, предоставленных исполнителем, выполняется только указанная роль / задача. Поэтому для приведенного выше примера мы можем добавить теги, подобные следующим:
- {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}} не определен, книга воспроизведения ничего не делает. Группа из файла hosts также может быть пропущена, если это необходимо. Это не вредит, если дополнительные переменные не предоставляются.
Playbook ориентирован на одного хоста
$ ansible-playbook user.yml --extra-vars "target = <your hosts variable>" --listhosts
Ansible – Устранение неполадок
Наиболее распространенные стратегии отладки PlaySbooks 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
В этом разделе мы узнаем о нескольких распространенных проблемах Playbook. Проблемы –
- квотирование
- вдавливание
Playbook написан в формате yaml, и две вышеупомянутые проблемы являются наиболее распространенными в yaml / playbook.
Yaml не поддерживает отступы на основе табуляции и поддерживает отступы на основе пробелов, поэтому нужно быть осторожным с этим.
Примечание. Как только вы закончите писать yaml, откройте этот сайт ( https://editor.swagger.io/ ) и скопируйте и вставьте ваш yaml с левой стороны, чтобы обеспечить правильную компиляцию yaml. Это всего лишь совет.
Swagger квалифицирует как ошибки, так и ошибки.