Пособие по Ansible / Хабр

Пособие по Ansible / Хабр Сертификаты

Почему Ansible лучше других подобных программ?

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

Преимущества Ansible по сравнению с другими аналогичными решениями (здесь в первую очередь следует назвать такие продукты, как Puppet, Chef и Salt) заключаются в следующем:

  • на управляемые узлы не нужно устанавливать никакого дополнительного программного оборудования, всё работает через SSH (в случае необходимости дополнительные модули можно взять из официального репозитория);
  • код программы, написанный на Python, очень прост;
  • при необходимости написание дополнительных модулей не составляет особого труда;
  • язык, на котором пишутся сценарии, также предельно прост;
  • низкий порог вхождения: обучиться работе с Ansible можно за очень короткое время;
  • документация к продукту написана очень подробно и вместе с тем — просто и понятно;
  • документация регулярно обновляется;
  • Ansible работает не только в режиме push, но и pull, как это делают большинство систем управления (Puppet, Chef);
  • имеется возможность последовательного обновления состояния узлов (rolling update).

Самостоятельно ознакомиться с Puppet вы можете по моим инструкциям на этом же сайте:

Ссылка:«Puppet — система управления конфигурацией».

Начало. vagrant

Задача: не делаю новый хост, потому что хочу сохранить ip. То есть, очищу дроплет через контрольную панель, затем инициализирую с помощью Ansible. План: написать playbook и отладить его на Vagrant.

Начать очень сложно. Все учебники по Ansible начинаются с описания inventory, куда нужно прописывать адрес сервера. Но какой ip у вагранта? Чёрт его знает. В документации по Ansible есть инструкция, как запустить playbook в Vagrant; в документации по Vagrant есть инструкция по подключению Ansible, и они не то чтобы идентичны. В итоге, забил на поиск ip и взял общее: минимальный Vagrantfile, который запускает playbook.

Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/xenial64"
  config.vm.network "forwarded_port", guest: 80, host: 8080
  # так и не знаю, зачем это:
  config.ssh.insert_key = false

  config.vm.provision "ansible" do |ansible|
    ansible.verbose = "v"
    ansible.playbook = "playbook.yml"
  end
end


Набросал черновик playbook-а, создал заготовки ролей и запустил

vagrant up

. Не взлетело. Поскольку официальный образ xenial — только для VirtualBox, а в Fedora Linux виртуализация через libvirt. Долго вспоминал правильную команду:

vagrant up --provider virtualbox

. Затем правил синтаксические ошибки в yaml (зачем там в начале обязательные три дефиса?). Помним, что после запуска коробки для перезапуска Ansible пишем

vagrant provision

И первый сюрприз: в коробке Ubuntu 16.04 нет python по умолчанию! Дикость для федоры, где пакетный менеджер написан на питоне. Ansible, как я узнал, загружает свои модули на сервер и выполняет их там. Идём на StackOverflow, находим волшебный таск (точнее, десять вариаций одного таска и непонятно, как лучше):

- name: Install python for Ansible 
  become: yes
  raw: test -e /usr/bin/python || (apt -qy update && apt install -y python-minimal)
  register: output
  changed_when: output.stdout

Что такое Ansible?

Ansible — программное решение для удаленного управления конфигурациями, разработанное Майклом Де Хаанном в 2021 году. Название продукта взято из научно-фантастической литературы: в романах американской писательницы Урсулы Ле Гуин была такая штука, как Ansible — это устройство для оперативной космической связи.

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

Машина управления, где установлен Ansible и Узлы, управляемая этой машиной по SSH. Местоположение узлов определяется управляющей машиной через её инструментарий. Ansible не требует установки клиентской части или приложения, что означает отсутствие необходимости какой-либо установки агента на удаленных узлах, так что это означает, что нет каких-либо фоновых демонов или программ, выполняемых для Ansible, когда он не управляет узлами.

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

Ansible берет на себя всю работу по приведению удаленных серверов в необходимое состояние. Администратору необходимо лишь описать, как достичь этого состояния с помощью так называемых сценариев — специальных файлов «playbook».

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

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

Пример плейбука:

Введение.

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

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

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

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

Предлагается все эти операции автоматизировать и внедрить систему удаленного управления конфигурациями.

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

Ссылка:«Ansible: Часть 2. Примеры простых задач.»

Рассмотрим структуру и правила написания таких сценариев более подробно.

Ссылка:«Ansible: Часть 3. Сценарии (плейбуки) — Playbooks.»

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

Ссылка:«Ansible: Часть 4. Практические примеры плейбуков.»

Как настраивать защищенные плейбуки описано в этом разделе.

Ссылка:«Ansible: Часть 5. Настройка защищенных плейбуков.»

. Файл конфигурации ansible.cfg.

По умолчанию список хостов/групп, к которым применяются команды содержится в файле /etc/ansible/hosts:

# grep -E ‘^#inventory’ /etc/ansible/ansible.cfg

Ответ:

При необходимости его можно переопределить с помощью опции

--inventory-file(-i)

Пример создания кастомного файла конфигурации.

Подключитесь по SSH к созданному управляющему серверу с установленным Ansible.

Создайте директорию для экспериментов ‘ansible‘ в своём домашнем каталоге и перейдите в него:

# mkdir ~/ansible# cd ~/ansible

Также создайте каталог для хранения модулей Ansible и каталог для хранения логов:

# mkdir ~/ansible/modules# mkdir ~/ansible/logs

Создайте файл ansible.cfg со следующим содержимым:

. Переменные.

Во время работы, как правило, требуется не только установить какое-либо приложение, но и настроить его в соответствии с определенными параметрами на основании принадлежности к группе серверов или индивидуально (например, IP-адресBGP-соседа и номер его AS или параметры для базы данных).

Как уже было сказано, загромождать файл hosts будет не очень красиво, поэтому разработчики Ansible пошли следующим путём:

  • файлы с переменными групп хранятся в каталоге ../group_vars/имя_группы;
  • файлы с переменными хостов в каталоге ../hosts_vars/имя_хоста;
  • файлы с переменными роли (о них речь пойдет ниже) в директории ../имя_роли/vars/имя_задачи.yml.

Помимо пользовательских переменных можно и даже нужно использовать факты, собранные Ansible перед выполнением сценариев и отдельных задач.

. Модули Ansible.

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

  • облачные ресурсы и виртуализация (Openstack, libvirt);
  • базы данных (MySQL, Postgresql, Redis, Riak);
  • файлы (шаблонизация, регулярные выражения, права доступа);
  • мониторинг (Nagios, monit);
  • оповещения о ходе выполнения сценария (Jabber, Irc, почта, MQTT, Hipchat);
  • сеть и сетевая инфраструктура (Openstack, Arista);
  • управление пакетами (apt, yum, rhn-channel, npm, pacman, pip, gem);
  • система (LVM, Selinux, ZFS, cron, файловые системы, сервисы, модули ядра);
  • работа с различными утилитами (git, hg).
Про сертификаты:  Средство для мытья посуды Химитек Кухмастер-Гель 5 л (концентрат) – выгодная цена – купить товар Средство для мытья посуды Химитек Кухмастер-Гель 5 л (концентрат) в интернет-магазине Комус

О том, с чем умеет работать Ansible, можно прочитать в официальной документации. Список действительно впечатляет.

. Организация RSA-ключей между серверами.

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

Как это сделать подробно описывается в инструкции: «CentOS 7: Настройка и использование SSH — Secure Shell».

В данном руководстве я приведу краткий способ организации коммуникации между хостами.

Создаём пару RSA-ключей.

# ssh-keygen

На все вопросы жмём Enter. Нам не нужны никакие пароли и генерируем ключи мы в каталог по умолчанию.

Ответ:

Копируем открытые ключи на сервера, которыми планируем управлять.

У нас их 3 штуки, поэтому копируем на каждый:

# ssh-copy-id root@192.168.0.39# ssh-copy-id root@192.168.0.30# ssh-copy-id root@192.168.0.31

Ответы:

Либо средствами самого Ansible через модуль authorized_key.

Раскатаем пользователя root на все виртуальные машины, до которых может дотянуться Ansible:

. Проверка подключения к узлам.

Чтобы убедиться, что Ansible может подключаться к узлам и запускать команды и плейбуки, вы можете использовать следующую команду:

# ansible all -m ‘ping’

или, встроенной в Ansible, одноименной утилитой:

# ansible all -m ping

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

Ответ pong означает, что Ansible готов запускать команды и плейбуки на этом узле.

Ответ:

Проверять с целевыми узлами можно и поштучно через их алиасы:

# ansible server1 -m ping# ansible server2 -m ping# ansible server3 -m ping

Ответ:

И еще одну команду:

# ansible all -a ‘uptime’

Ответ:

. Сценарии — Playbooks.

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

Рассмотрим структуру и правила написания таких сценариев более подробно.

Ссылка:«Ansible: Часть 3. Сценарии (плейбуки) — Playbooks.»

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

Ссылка:«Ansible: Часть 4. Практические примеры плейбуков.»

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

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

Ссылка:«Ansible: Часть 5. Настройка защищенных плейбуков.»

. Файл инвентаря.

21.1. Пользовательский файл инвентаря.

Файл инвентаря по умолчанию обычно находится в /etc/ansible/hosts, но вы можете использовать опцию -i для указания пользовательских файлов при запуске команд и плейбуковAnsible.

Это удобный способ настройки индивидуального инвентаря для каждого проекта, который можно включить в системы контроля версий, такие как Git:

# ansible all -m ping -i my_custom_inventory

Такая опция действительна и для ansible-playbook:

# ansible-playbook myplaybook.yml -i my_custom_inventory

21.2. Динамический файл инвентаря.

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

Вы можете найти ряд скриптов с открытым исходным кодом в официальном репозитории Ansible GitHub. После загрузки требуемого сценария на Ansible Control Machine и настройки необходимых параметров (например, учетных данных API) вы можете запустить исполняемый файл в качестве пользовательского инвентаря с любой командой Ansible, которая поддерживает эту опцию.

Следующая команда использует скрипт инвентаря my_inventory.py с командой ping для проверки подключения ко всем текущим активным серверам:

# ansible all -m ping -i my_inventory.py

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

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

Основная идея Ansible – наличие одного или нескольких управляющих серверов, из которых вы можете отправлять команды или наборы последовательных инструкций (playbooks) на удаленные сервера, подключаясь к ним по SSH.

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

Наборы инструкций (playbooks) состоят из одной или более задач, которые описываются с помощью функциональность модуля ядра Ansible или сторонних модулей, которые могут потребоваться в специфических ситуациях. Сами по себе наборы инструкций — последовательные наборы команд, в которых могут быть проверки условий: если условие не выполняется, определенные команды могут пропускаться.

Также вы можете использовать Ansible API для запуска скриптов. Если скрипту-обертке (wrapper) может потребоваться запуск playbook, это можно сделать через API. Сами playbooks описываются декларативно в формате YAML.

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

Краткий словарь терминов Ansible.

В этом этой инструкции широко используются такие термины Ansible:

  • Control Machine или Node — ведущая система, в которой установлен Ansible и откуда он может подключаться к нодам и выполнять на них команды.
  • Хост — в Ansible хост — это удаленный компьютер, которому назначены отдельные переменные, и они далее группируются вместе. У каждого хоста есть выделенное имя или уникальный IP-адрес, чтобы сделать его идентификацию легкой и быстрой. Им также может быть присвоен простой номер порта, если вам не нужно обращаться к ним через соединение ssh.
  • Нода или Узел — сервер, управляемый Ansible.
  • Файл инвентаря — файл, который содержит информацию о серверах, которыми управляет Ansible, обычно находится в /etc/ansible/hosts.
  • Playbooks — они написаны на языке программирования YAML с минимальным синтаксисом и обычно используются для автоматизации задач при необходимости.
  • Роль — коллекция плейбуков и других файлов, которые имеют отношение к цели. Например, к установке web-сервера.
  • Play — полный набор инструкций Ansible. В play может быть несколько плейбуков и ролей, включенных в один плейбук, который служит точкой входа.
  • Задача — каждая инструкция, определенная в книге игр, называется задачей, которая будет выполняться в дальнейшем для выполнения действия.
  • Факты — они выводятся из удаленных узлов автоматически при выполнении модулей на удаленных узлах.
  • Группа — это комбинация хостов, которые назначены пулу, и переменные также могут совместно использоваться.
  • Инвентаризация — инвентаризация является важным компонентом ANSI удаленного механизма, который описывает хосты, группы и так далее. С помощью IP-адреса или номера порта и так далее. Таким образом, вы можете определить все хосты в одном файле для быстрого доступа.
  • API — это транспортная среда для различных облачных сервисов, как частных, так и общедоступных.
  • Модули — с помощью playbook модули могут быть выполнены на удаленных узлах напрямую. Кроме того, его можно использовать для управления службами, ресурсами, пакетами, файлами или командами и так далее. Модули являются основными компонентами, которые помогают устанавливать пакеты, позволяют API-интерфейсам взаимодействовать друг с другом и планировать действия для системных файлов. В Ansible есть множество модулей, которые запрограммированы для автоматизации практически всего внутри инструмента.
  • Плагины — это специальные части кода, которые помогают быстро писать код. Плагины автоматизируют задачи разработки и помогают максимально ускорить работу по развертыванию. Ansible оснащен различными удобными плагинами, которые можно использовать при необходимости, чтобы упростить вам задачу.
  • Оркестровка — это общий термин, который часто используется в техническом мире. Почему это важно и в Ansible? Для разных программных продуктов значение оркестровки может быть различным. Ansible использует его в качестве дирижера для управления оркестром.

Ansible documentation — ansible documentation

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

Ansible’s main goals are simplicity and ease-of-use. It also has a strong focus on security and reliability, featuring a minimum of moving parts, usage of OpenSSH for transport (with other transports and pull modes as alternatives), and a language that is designed around auditability by humans–even those not familiar with the program.

We believe simplicity is relevant to all sizes of environments, so we design for busy users of all types: developers, sysadmins, release engineers, IT managers, and everyone in between. Ansible is appropriate for managing all environments, from small setups with a handful of instances to enterprise environments with many thousands of instances.

You can learn more at AnsibleFest, the annual event for all Ansible contributors, users, and customers hosted by Red Hat. AnsibleFest is the place to connect with others, learn new skills, and find a new friend to automate with.

Ansible manages machines in an agent-less manner. There is never a question of how to upgrade remote daemons or the problem of not being able to manage systems because daemons are uninstalled. Because OpenSSH is one of the most peer-reviewed open source components, security exposure is greatly reduced. Ansible is decentralized–it relies on your existing OS credentials to control access to remote machines. If needed, Ansible can easily connect with Kerberos, LDAP, and other centralized authentication management systems.

Про сертификаты:  Индивидуальная настройка Internet Explorer | КомпьютерПресс

This documentation covers the version of Ansible noted in the upper left corner of this page. We maintain multiple versions of Ansible and of the documentation, so please be sure you are using the version of the documentation that covers the version of Ansible you’re using. For recent features, we note the version of Ansible where the feature was added.

Ansible releases a new major release approximately twice a year. The core application evolves somewhat conservatively, valuing simplicity in language design and setup. Contributors develop and change modules and plugins, hosted in collections since version 2.10, much more quickly.

Ansible: create a self-signed ssl certificate and key

I want to create a self signed certificate to use it with stunnel, in order to securely tunnel my redis traffic between the redis server and client. I’m using this command to generate the certificate and it works fine.

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/stunnel/redis-server.key -out /etc/stunnel/redis-server.crt

Since I’m using Ansible for provisioning, I would like to know how I can convert this into a more Ansible way of doing, using a module. There actually is a module called the openssl_certificate Ansible module and it states “This module allows one to (re)generate OpenSSL certificates.”. I tried to use the module to generate the certificate, but I couldn’t get it to work.

- name: Generate a Self Signed OpenSSL certificate
  openssl_certificate:
    path: /etc/stunnel/redis-server.crt
    privatekey_path: /etc/stunnel/redis-server.key
    csr_path: /etc/stunnel/redis-server.csr
    provider: selfsigned

From a look at the documentation, I can’t specify the following arguments -x509 -nodes -days 3650 -newkey rsa:2048. Of course, I could also split the key and cert generation, but that still wouldn’t allow me to use the Ansible module, correct?

Example given:

openssl genrsa -out /etc/stunnel/key.pem 4096

openssl req -new -x509 -key /etc/stunnel/key.pem -out /etc/stunnel/cert.pem -days 1826

I would like to know the following things:

  • a) How can I get the same result from the original command, but using an Ansible module?
  • b) Is there a better way to manage self signed certificates using Ansible?

Cценарии (playbooks)

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

Чтобы выполнить сценарий используется команда ansible-playbook со следующим сиснтаксисом:

ansible-playbook <имя_файла_сценария.yml> ... [другие параметры]


В начале сценария обязательно должна присутствовать последовательность символов «–––» (так в YAML обозначается начало документа). Перед каждым новым разделом списка ставится дефис ( — ):

---
- hosts: webservers

Основными параметрами/группами простого сценария являются:

Также в сценарии перед непосредственным описанием задач могут быть указаны следующие параметры или группы параметров:

Haproxy playbook

Самое сложное позади. Написать плейбук для устновки и конфигурации HAproxy очень легко:

Выглядит знакомо, правда? Новый модуль тут только один: template. У него такие же аргументы, как у copy. А еще мы ограничили этот плейбук группой haproxy.

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

$ ansible-playbook -i step-10/hosts step-10/apache.yml step-10/haproxy.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]
ok: [host2.example.org]

TASK: [Updates apt cache] *********************
ok: [host1.example.org]
ok: [host2.example.org]

TASK: [Installs necessary packages] *********************
ok: [host1.example.org] => (item=apache2,libapache2-mod-php5,git)
ok: [host2.example.org] => (item=apache2,libapache2-mod-php5,git)

TASK: [Push future default virtual host configuration] *********************
ok: [host2.example.org]
ok: [host1.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host1.example.org]
changed: [host2.example.org]

TASK: [Check that our config is valid] *********************
changed: [host1.example.org]
changed: [host2.example.org]

TASK: [Rolling back - Restoring old default virtualhost] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Rolling back - Removing out virtualhost] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Rolling back - Ending playbook] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Deploy our awesome application] *********************
ok: [host2.example.org]
ok: [host1.example.org]

TASK: [Deactivates the default virtualhost] *********************
changed: [host1.example.org]
changed: [host2.example.org]

TASK: [Deactivates the default ssl virtualhost] *********************
changed: [host2.example.org]
changed: [host1.example.org]

NOTIFIED: [restart apache] *********************
changed: [host2.example.org]
changed: [host1.example.org]

PLAY RECAP *********************
host1.example.org              : ok=10   changed=5    unreachable=0    failed=0    
host2.example.org              : ok=10   changed=5    unreachable=0    failed=0    

PLAY [haproxy] *********************

GATHERING FACTS *********************
ok: [host0.example.org]

TASK: [Installs haproxy load balancer] *********************
changed: [host0.example.org]

TASK: [Pushes configuration] *********************
changed: [host0.example.org]

TASK: [Sets default starting flag to 1] *********************
changed: [host0.example.org]

NOTIFIED: [restart haproxy] *********************
changed: [host0.example.org]

PLAY RECAP *********************
host0.example.org              : ok=5    changed=4    unreachable=0    failed=0    

Больше фактов

Легко и просто. Однако, если нам нужно больше информации (IP-адреса, размеры ОЗУ, и пр.), такой подход может быстро оказаться неудобным. Решение – использовать модуль setup. Он специализируется на сборе фактов с узлов.

Попробуйте:

ansible -i step-02/hosts -m setup host0.example.org

ответ:

"ansible_facts": {
    "ansible_all_ipv4_addresses": [
        "192.168.0.60"
    ],
    "ansible_all_ipv6_addresses": [],
    "ansible_architecture": "x86_64",
    "ansible_bios_date": "01/01/2007",
    "ansible_bios_version": "Bochs"
    },
    ---snip---
    "ansible_virtualization_role": "guest",
    "ansible_virtualization_type": "kvm"
},
"changed": false,
"verbose_override": true

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

Например, вам нужно узнать, сколько памяти доступно на всех хостах. Это легко: запустите ansible -i step-02/hosts -m setup -a ‘filter=ansible_memtotal_mb’ all:

host2.example.org | success >> {
    "ansible_facts": {
        "ansible_memtotal_mb": 187
    },
    "changed": false,
    "verbose_override": true
}

host1.example.org | success >> {
    "ansible_facts": {
        "ansible_memtotal_mb": 187
    },
    "changed": false,
    "verbose_override": true
}

host0.example.org | success >> {
    "ansible_facts": {
        "ansible_memtotal_mb": 187
    },
    "changed": false,
    "verbose_override": true
}

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

Кстати, при использовании модуля setup можно указывать * в выражении filter=. Как в shell.

Группы серверов

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

  • из специального текстового файла (далее этот вариант будет рассмотрен более подробно);
  • с помощью внешнего скрипта, возвращающего нужный нам список серверов, например из MongoDB. В официальном github-репозитории есть готовые скрипты для получения списка из Cobbler, Digital Ocean, EC2, Linode, OpenStack Nova, Openshift, Spacewalk, Vagrant, Zabbix.

Модуль copy

Модуль copy позволяет копировать файл из управляющей машины на удаленный узел. Представим, что нам нужно скопировать наш /etc/motd в /tmp узла:

Вывод:

host0.example.org | success >> {
    "changed": true,
    "dest": "/tmp/motd",
    "group": "root",
    "md5sum": "d41d8cd98f00b204e9800998ecf8427e",
    "mode": "0644",
    "owner": "root",
    "size": 0,
    "src": "/root/.ansible/tmp/ansible-1362910475.9-246937081757218/motd",
    "state": "file"
}

Ansible (точнее, модуль copy, запущенный на узле) ответил кучей полезной информации в формате JSON. Позже мы увидим, как это можно использовать.

У Ansible есть огромныйсписок модулей, который покрывает практически все, что можно делать в системе. Если вы не нашли подходящего модуля, то написание своего модуля – довольно простая задача (и не обязательно писать его на Python, главное, чтобы он понимал JSON).

Модуль git

Ну, честно говоря, тут все будет просто, ничего нового. Модуль git это просто еще один модуль. Но давайте попробуем что-нибудь интересное. А позже это пригодится, когда мы будем работать с ansible-pull.

Виртуальный хост задан, но нам нужно внести пару изменений чтобы закончить деплой. Мы деплоим приложение на PHP, так что нужно установить пакет libapache2-mod-php5. Также нужно установить сам git, так как, очевидно, модуль git требует его наличия.

Можно сделать так:

    ...
    - name: Installs apache web server
      apt: pkg=apache2 state=installed update_cache=true

    - name: Installs php5 module
      apt: pkg=libapache2-mod-php5 state=installed

    - name: Installs git
      apt: pkg=git state=installed
    ...

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

Полезные штуки

Во время написания playbook-ов находишь или нагугливаешь много полезных мелочей. Какие-то описаны в документации, какие-то — в статьях (поищите «Ansible» на хабре). Вот несколько из них.

Для выполнения команд — только модули command или shell. Последний, как пишет документация, только в крайних случаях, поэтому забудьте про перенаправление вывода и &&. Результат всегда «changed», что плохо.

Управляйте результатом либо параметром creates (удобнее — в блоке args, вместе с chdir), либо register и changed_when. Полезно проверить условия перед выполнением: сначала рекогносцировка command register changed_when: False, а затем с помощью when проверяем сохранённый stdout на необходимость запуска команды.

Пример сценария

Чтобы понять, как это все работает, рассмотрим практический пример: простой сценарий развёртывания новой версии PostgreSQL 9.3 на debian-based ОС. Роли в этом примере не используются.

текст плэйбука
---
- name: install postgresql 9.3 # имя playbook'a
  # секция, описывающая параметры, которые нужно уточнить у пользователя в начале запуска
  vars_prompt:
    hosts: "Please enter hosts group name" # спрашиваем имя группы серверов в инвентаре (в нашем случае файл $ANSIBLE_HOSTS)
    username: "Please enter username for auth" # спрашиваем имя пользователя для подключения к серверам
  hosts: $hosts # 
  user: $username
  sudo: True
  accelerate: true
  vars:
    app_username: 'app_user'     # имя пользователя мифического приложения, которое работать с базой данных
    app_host_ip: '192.168.0.100' # ip-адрес хоста с запущенным приложением, с него будут поступать запросы в базу данных
    app_database_name: 'appdb'   # имя базы данных приложения

  tasks:
      # Проверяем установлен ли и устанавливаем пакет python-software-properties
      # для обеспечения работы модуля apt. Параметры модуля:
      # pkg - имя пакета для установки
      # state - устанавливаем последнюю версию пакета, 
      # update_cache - обновляем список доступных пакетов перед установкой
    - name: check add-apt-repository 
      apt: pkg=python-software-properties state=latest update_cache=yes

      # добавляем ключ официального apt-репозитория проекта postgresql
      # Параметры модуля:
      # url - URL до файла с ключём
      # state - добавить ключ
    - name: add apt key
      apt_key: url=http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc state=present

      # добавляем репозиторий, адрес формируется на основе имени релиза установленной ОС
    - name: add apt repo
      apt_repository: repo='deb http://apt.postgresql.org/pub/repos/apt/ ${ansible_lsb.codename}-pgdg main'

      # устанавливаем пакет с ключём для последующего возможного автоматического обновления
    - name: install pgdg-key
      apt: pkg=pgdg-keyring state=latest update_cache=yes

      # устанавливаем пакеты postgresql-9.3 (непосредственно сам сервер баз данных)
      # и python-psycopg2 - для работы модулей postgresql_user, postgresql_db, postgresql_privs
    - name: install packages
      apt: pkg=$item state=latest
      with_items:
        - postgresql-9.3
        - python-psycopg2
        - python-keyczar

      # создаём пользователя для работы нашего мифического приложения c атрибутом LOGIN
      # сгенерированный пароль будет сохранён в credentials/имя_хоста/postgres/имя_пользователя
    - name: create postresql user for some app
      # выполнение задачи будем производить с правами пользователя postgres (создаётся при установке postgresql)
      sudo: yes
      sudo_user: postgres 
      postgresql_user:
          user=${app_username}
          password="{{ lookup('password','example/credentials/'   inventory_hostname   '/postgres/'   app_username, length=15) }}"
          role_attr_flags=LOGIN

      # создаём базу данных для мифического приложения с говорящими за себя параметрами
    - name: create db for our app
      sudo: yes
      sudo_user: postgres
      action: postgresql_db name=${app_database_name} owner=${app_username} encoding='UTF8' lc_collate='en_US.UTF-8' lc_ctype='en_US.UTF-8' template='template0' state=present

      # Следующая задача будет выполнена хосте приложения, а не на текущем настраиваемом хосте
    - name: add app_user password to .pg_pass file on server with our app
      sudo: yes
      sudo_user: ${app_username}
      delegate_to: ${app_host_ip}
      lineinfile:
          dest=/home/${app_username}/.pgpass
          regexp='^{{ inventory_hostname }}:*:${app_database_name}:${app_username}'
          line='{{ inventory_hostname }}:*:${app_database_name}:${app_username}:{{ lookup('password','example/credentials/'   inventory_hostname   '/postgres/'   app_username, length=15) }}'
          create=yes
          state=present
          backup=yes

      # добавляем в pg_hba.conf строчку, описываюшую разрешение подключение с ip-адреса приложения для ранее созданной базы и пользователя
    - name: add entry to pg_hba.conf
      lineinfile:
          dest=/etc/postgresql/9.3/main/pg_hba.conf
          regexp='host ${app_database_name} ${app_username} ${app_host_ip}/32 md5'
          line='host ${app_database_name} ${app_username} ${app_host_ip}/32 md5' state=present
      # если файл изменился, то вызовем задачу по перечитыванию конфига postgresql
      # напоминаем что модули ansible возвращают состояние "изменилось/не изменилось" после выполнения,
      # хэндлеры описываются либо в конце playbook'a или в отдельном файле
      notify:
        - reload postgres

      # по умолчанию postgresql слушает только localhost
      # изменияем соответствующий параметр в postgresql.conf на ip-адрес сервера
    - name: add entry to postgresql
      lineinfile:
          dest=/etc/postgresql/9.3/main/postgresql.conf
          regexp='^listen_addresses'
          line="listen_addresses = '${ansible_default_ipv4.address}'"
          state=present
      # если файл изменился, то вызовем задачу по перезапуску postgresql, т.к.
      # параметр listen_addresses можно изменить только перезагрузкой сервера postgresql
      notify:
        - restart postgres

  # описание хэндлеров
  handlers:
      # перечитываем конфигурацию postgresql
    - name: reload postgres
      sudo: yes
      action: service name=postgresql state=reloaded

      # перезагружаем postgresql
    - name: restart postgres
      sudo: yes
      action: service name=postgresql state=restarted

Про сертификаты:  Установка сертификата ЭЦП стала автоматической — Удостоверяющий центр — СКБ Контур

Сборка второго веб-сервера

Мы не зря напрягались перед этим. Деплой второго сервера очень прост:

$ ansible-playbook -i step-09/hosts step-09/apache.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host2.example.org]
ok: [host1.example.org]

TASK: [Updates apt cache] *********************
ok: [host1.example.org]
ok: [host2.example.org]

TASK: [Installs necessary packages] *********************
ok: [host1.example.org] => (item=apache2,libapache2-mod-php5,git)
changed: [host2.example.org] => (item=apache2,libapache2-mod-php5,git)

TASK: [Push future default virtual host configuration] *********************
ok: [host1.example.org]
changed: [host2.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host2.example.org]
changed: [host1.example.org]

TASK: [Check that our config is valid] *********************
changed: [host2.example.org]
changed: [host1.example.org]

TASK: [Rolling back - Restoring old default virtualhost] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Rolling back - Removing out virtualhost] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Rolling back - Ending playbook] *********************
skipping: [host1.example.org]
skipping: [host2.example.org]

TASK: [Deploy our awesome application] *********************
ok: [host1.example.org]
changed: [host2.example.org]

TASK: [Deactivates the default virtualhost] *********************
changed: [host1.example.org]
changed: [host2.example.org]

TASK: [Deactivates the default ssl virtualhost] *********************
changed: [host2.example.org]
changed: [host1.example.org]

NOTIFIED: [restart apache] *********************
changed: [host1.example.org]
changed: [host2.example.org]

PLAY RECAP *********************
host1.example.org              : ok=10   changed=5    unreachable=0    failed=0    
host2.example.org              : ok=10   changed=8    unreachable=0    failed=0    

Все, что нужно, это удалить -l host1.example.org из командной строки. Помните, -l позволяет ограничить хосты для запуска. Теперь ограничения не требуется, и запуск произойдет на всех машинах группы web.

Если бы в группе web были другие машины, и нам нужно было бы запустить плейбук только на некоторых из них, можно было бы использовать, например, такое: -l firsthost:secondhost:….

Теперь у нас есть чудесная ферма веб-серверов, давайте превратим ее в кластер с помощью балансировщика нагрузок.

Создаем плейбук роли

Давайте создадим плейбук верхнего уровня для связывания хостов и групп хостов с ролями. Назовем файл site.yml, так как нам нужна общая конфигурация сайта. Заодно добавим туда haproxy:

- hosts: web
  roles:
    - { role: apache }

- hosts: haproxy
  roles:
    - { role: haproxy }

Совсем не сложно. Теперь давайте создадим роль haproxy:

mkdir -p step-12/roles/haproxy/{tasks,handlers,templates}
cp step-11/templates/haproxy.cfg.j2 step-12/roles/haproxy/templates/

потом извлечем хэндлер и удалим упоминание templates/.

Попробуем?:

ansible-playbook -i step-12/hosts step-12/site.yml

Если все хорошо, то мы увидим “PLAY RECAP”:

host0.example.org          : ok=5    changed=2    unreachable=0 failed=0
host1.example.org          : ok=10   changed=5    unreachable=0 failed=0
host2.example.org          : ok=10   changed=5    unreachable=0 failed=0

Вы наверное заметили, что запуск всех ролей в site.yml занимает много времени. Что если нужно сделать изменения только для веб-серверов? Легко! Используем limit-флаг:

ansible-playbook -i step-12/hosts -l web step-12/site.yml

На этом миграция на роли закончена.

(От переводчика: в оригинальном пособии в будущем появится еще как минимум одна глава. Я добавлю ее в эту публикацию или создам новую).

Структура проекта

├── production                # инвентарный файл для продакшн-серверов
├── stage                     # инвентарный файл для stage-окружения
│
├── group_vars/
│   ├── group1                # здесь назначаются переменные для
│   └── group2                # конкретных групп
├── host_vars/
│   ├── hostname1             # специфические переменные для хостов в
│   └── hostname2             # случае необходимости прописываются здесь
│
├── site.yml                  # основной сценарий
├── webservers.yml            # сценарий для веб-сервера
├── dbservers.yml             # сценарий для сервера базы данных
│
└── roles/
    ├── common/               # здесь описываются роли
    │   ├── tasks/            #
    │   │   └── main.yml      # - файл задач роли, может включать файлы
    │   │                     #   меньшего размера
    │   ├── handlers/         #
    │   │   └── main.yml      # - файл с обработчиками (handlers)
    │   ├── templates/        # - директория для шаблонов, в данном
    │   │   └── ntp.conf.j2   #   случае - для конфига ntp
    │   ├── files/            #
    │   │   ├── bar.txt       # - файл-ресурс для копирования на хост
    │   │   └── foo.sh        # - скрипт для выполнения на удалённом хосте
    │   └── vars/             #
    │       └── main.yml      # - ассоциированные с ролью переменные
    │
    ├── pgsql/                # такая же структура, как выше, для роли pgsql
    └── fooapp/               # такая же структура, как выше, для роли fooapp

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

Роли добавляют немного «магии» в Ansible: они предполагают особую организацию файлов. Роли полагается структурировать определенным образом, хотя вы можете делать это как угодно вам. Тем не менее, если придерживаться соглашений, вам будет гораздо легче создавать модульные плейбуки. Содержать код в порядке будет гораздо легче. Рубисты называют это “convention over configuration”.

Структура файлов для ролей такая:

roles
  |
  |_some_role
       |
       |_files
       |   |
       |   |_file1
       |   |_...
       |
       |_templates
       |   |
       |   |_template1.j2
       |   |_...
       |
       |_tasks
       |   |
       |   |_main.yml
       |   |_some_other_file.yml
       |   |_ ...
       |
       |_handlers
       |    |
       |    |_main.yml
       |    |_some_other_file.yml
       |    |_ ...
       |
       |_vars
       |    |
       |    |_main.yml
       |    |_some_other_file.yml
       |    |_ ...
       |
       |_meta
            |
            |_main.yml
            |_some_other_file.yml
            |_ ...

Довольно просто.

Файлы main.yml не обязательны. Но если они присутствуют, то роли добавят их к отработке автоматически. Эти файлы можно использовать для добавления других тасков и хэндлеров.

Обратите внимание на директории vars и meta. vars нужна для случаев, когда есть куча переменных, связанных с ролью. Но мне лично не нравится задавать переменные в ролях и сценариях напрямую. Я считаю, что переменные должны быть частью конфигурации, а сценарии — это структура.

Иными словами, я считаю сценарии фабриками, а данные — параметрами для фабрик. Поэтому я предпочитаю видеть «данные» (например, переменные) вне ролей и сценариев. Тогда мне легче шарить роли и не раскрывать слишком много информации о внутренностях серверов. Но это дело личных предпочтений. Ansible предоставляет вам выбор.

В директории meta находятся зависимости, но об этом поговорим в следующий раз. Сценарии лежат в директории roles.

Улучшение плейбука

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

Давайте создадим директиорию под названием files и добавим нашу конфигурацию для host1.example.org, назовем ее awesome-app:

Теперь небольшое обнуление плейбука и все готово:

Поехали:

$ ansible-playbook -i step-05/hosts -l host1.example.org step-05/apache.yml

PLAY [web] *********************

GATHERING FACTS *********************
ok: [host1.example.org]

TASK: [Installs apache web server] *********************
ok: [host1.example.org]

TASK: [Push default virtual host configuration] *********************
changed: [host1.example.org]

TASK: [Deactivates the default virtualhost] *********************
changed: [host1.example.org]

TASK: [Deactivates the default ssl virtualhost] *********************
changed: [host1.example.org]

TASK: [Activates our virtualhost] *********************
changed: [host1.example.org]

NOTIFIED: [restart apache] *********************
changed: [host1.example.org]

PLAY RECAP *********************
host1.example.org              : ok=7    changed=5    unreachable=0    failed=0    

Круто! Ну, если задуматься, мы немного опережаем события. Не нужно ли проверить корректность конфигурации перед тем, как перезапускать apache? Чтобы не нарушать работоспособность сервиса в случае если конфигурация содержит ошибку.

Установка

Требования для установки Ansible минимальны. На машине с которой производится управление должен быть установлен Python 2.6 или выше. На управляемых узлах должен быть установлен только Python версии не ниже 2.4, но он, как правило, по умолчанию включен в состав большинства дистрибутивов linux-систем. MS Windows не поддерживается.

Вам также могут потребоваться следующие модули Python, устанавливаемые через pip или пакетный менеджер вашей операционной системы:

В Ubuntu установка самого Ansible и зависимостей осуществляется добавлением репозитория и установкой пакета:

sudo add-apt-repository -y ppa:rquillo/ansible
sudo apt-get update
sudo apt-get install ansible -y


О процедуре установки в других ОС можно прочитать в

Оцените статью
Мой сертификат
Добавить комментарий