Найти в Дзене

Ansible – система управления конфигурациями: знакомство

Исходный сайт представленного материала: r4ven.me В этой заметке мы с вами познакомимся с популярной open source системой управления конфигурациями с говорящим названием – Ansible🎻. Выполним установку и настройку🛠, составим инвентаризацию📋, научимся запускать плейбуки🚀, поговорим про Ansible facts🗂, узнаем, что такое Ansible console🖥 и напишем playbook📝 который правит конфиг sshd и копирует файлы на сервер. Будет познавательно😉! Присоединяйтесь к нашему каналу в телеграм: t.me/r4ven_me, уведомления о новых постах приходят туда в день публикации. А если у вас есть вопросы или просто желание пообщаться по тематике – заглядывайте в чат: t.me/r4ven_me_chat. Чтобы чуть лучше понимать суть происходящего, рекомендую прочитать мою теоретическую заметку📝 про системы управления конфигурациями (Cofiguration Management, CM). В ней дано описание термина, какие виды существуют, а также коротко рассказано про популярные реализации подобных систем и их отличия. Возвращаясь к Ansible, с его
Оглавление
Ansible – система управления конфигурациями: знакомство
Ansible – система управления конфигурациями: знакомство
Исходный сайт представленного материала: r4ven.me

Приветствую!

В этой заметке мы с вами познакомимся с популярной open source системой управления конфигурациями с говорящим названием – Ansible🎻. Выполним установку и настройку🛠, составим инвентаризацию📋, научимся запускать плейбуки🚀, поговорим про Ansible facts🗂, узнаем, что такое Ansible console🖥 и напишем playbook📝 который правит конфиг sshd и копирует файлы на сервер. Будет познавательно😉!

Присоединяйтесь к нашему каналу в телеграм: t.me/r4ven_me, уведомления о новых постах приходят туда в день публикации. А если у вас есть вопросы или просто желание пообщаться по тематике – заглядывайте в чат: t.me/r4ven_me_chat.
-2

Предисловие

Чтобы чуть лучше понимать суть происходящего, рекомендую прочитать мою теоретическую заметку📝 про системы управления конфигурациями (Cofiguration Management, CM). В ней дано описание термина, какие виды существуют, а также коротко рассказано про популярные реализации подобных систем и их отличия.

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

Ну и прежде, чем мы продолжим углубляться перечислю основные сущности данной CM📒:

  • Control node — управляющий сервер, на котором установлен Ansible и с которого запускаются команды и Playbooks с помощью SSH;
  • Managed nodes — управляемые серверы, на которых Ansible выполняет задачи, не требуют установки Ansible на них;
  • Inventory file — файл(ы) (обычно inventory.yml), содержащий список управляемых узлов и их групп для логического объединения. В нем указываются IP-адреса, DNS имена, порты и пользовательские переменные;
  • Configuration file — файл конфигурации Ansible (по умолчанию ansible.cfg), где задаются настройки, например, путь к файлу инвентаря, параметры SSH и другие параметры, позволяющие настроить поведение Ansible под конкретные нужды;
  • Variables — переменные, которые можно использовать для гибкой настройки задач и параметров. Переменные могут определяться на разных уровнях: в файле инвентаризации, плейбуке, ролях, командах и динамически собираться;
  • Playbook — файл сценария в формате YAML, описывающий, какие задачи нужно выполнить на каких узлах;
  • Facts (факты) — информация об управляемом сервере в виде системных переменных (например, тип и версия ОС, IP-адрес, версии пакетов и пр.), автоматически собираемая Ansible. Часто используются для описания условий выполнения задач (tasks);
  • Task — отдельное задание, выполняемое на управляемом узле. Это атомарная инструкция (например, установка пакета), описанная с помощью Ansible module;
  • Module — готовый модуль из библиотеки Ansible для выполнения конкретной задачи, например, копирование файла, управление сервисами, установка пакетов и пр.;
  • Handler (обработчик) — задача, которая запускается только при изменении состояния (например, перезапуск сервиса), вызывается из задачи через параметр notify;
  • Template — файл шаблона (в формате Jinja2), который позволяет, например, создавать динамические файлы конфигурации с использованием переменных и конструкций, свойственным языкам программирования (фильтры, циклы, условные выражения и т.д.), тут можно утонуть;
  • Role — структура файлов и директорий для удобной организации задач, шаблонов, файлов переменных для Playbook. По сути, это плейбук, раздробленный на отдельные файлы/папки для большего удобства и наглядности;
  • Plugins – дополнения Ansible, расширяющие его функционал.

Установка Ansible в Debian / Ubuntu / Linux mint

Пример установки я буду показывать в среде дистрибутива Debian 12😎:

-3

Т.к. Ansible работает по push принципу (т.е. все управление происходит с административного сервера), то и устанавливать его необходимо только на одной машине. На управляемых серверах понадобится установленный Python🐍 и доступ по SSH.

Подробнее про использование и настройку SSH в Linux, в т.ч. и работу с ключами, читайте в отдельной инструкции: SSH – Безопасное подключение к удалённым хостам: введение.

Все необходимые пакеты Ansible есть в стандартных репозиториях🗄. Поэтому просто открываем терминал и вводим команду:

sudo apt update && sudo apt install -y ansible sshpass

-4

Также мы устанавливаем утилиту sshpass, которая понадобится для передачи пароля при соответствующей SSH аутентификации, а также получение полномочий через sudo💪.

Зависимостей много, поэтому установка займет некоторое время⏳.

Настройка Ansible – файл ansible.cfg

Переходим к начальной настройке. Для этого создаем необходимые директории и файл конфигурации. Открываем его любым текстовым редактором (я предпочитаю vim/neovim)🧑‍💻:

mkdir -p ~/ansible/{playbooks,roles,tmp}

nvim ~/ansible/ansible.cfg

-5

И наполняем его:

Файл ansible.cfg на GitHub

-6
Понравился мой конфиг Neovim? Можете с легкостью создать аналогичный по статье: Neovim – Установка и настройка редактора кода с элементами IDE всего в несколько команд.
-7

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

Если есть потребность изучить все доступные параметры файла конфигурации🤓, то его можно сгенерировать такой командой:

ansible-config init --disabled > ~/ansible/ansible.cfg.example

Файл хорошо прокомментирован🧐.

Подробнее про процесс конфигурации смотрите на оф. сайте: Ansible Configuration Settings.

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

export ANSIBLE_CONFIG="$HOME/ansible/ansible.cfg"

# для создания переменной при входе в систему
echo 'export ANSIBLE_CONFIG="$HOME/ansible/ansible.cfg"' >> ~/.profile

-8
Замените ~/.profile на файл загрузки окружения вашей оболочки. В моем случае используется интерактивная оболочка ZSH.

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

Полный список доступных переменных окружения также смотрите в оф. доке: Environment Variables.

Инвентаризация – файл inventory.yml

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

nvim ~/ansible/inventory.yml

-9

И добавляем в него список наших серверов📋, которыми будем управлять. В моем примере 5 Linux серверов (3 – Debian, 2 – Ubuntu):

Файл inventory.yml на GitHub

Не забудьте заменить параметры на свои 😉

-10

Сохраняем, закрываем.

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

Коротко опишу содержимое на примере сервера debian12-vpn:

  • debian12-vpn – произвольное имя хоста в файле инвентаризации;
  • ansible_host: 192.168.122.93 – адрес хоста (IP или DNS);
  • ansible_port: 22 – порт подключения SSH;
  • ansible_user: ivan – пользователь SSH, с помощью которого выполняется подключение;
  • ansible_ssh_private_key_file: ~/.ssh/id_ed25519 – путь до приватного SSH ключа (переопределяет значение из ansible.cfg);
  • Нежелательная альтернатива: ansible_password – пароль подключения по SSH;
  • project: vpn – пользовательская переменная для данного хоста.

Также обратите внимание, что после списка хостов идет список групп🖥🖥:

  • debian
  • ubuntu

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

Весь список доступных параметров подключения для файла inventory смотрите тут: Connecting to hosts: behavioral inventory parameters.

Наш файл инвентаря составлен, давайте посмотрим на его структуру такой командой:

ansible-inventory --graph

-11

Эта визуализация особенно полезна, если у вас большая инфраструктура из сотен серверов, разбитых на группы📊.

Пишем первый плейбук: проверка доступности серверов с помощью модуля ping

В контексте Ansible модуль ping не выполняет ping сервера в классическом понимании🤷‍♂️. Его задача произвести подключение к серверу по SSH, выполнить некоторые проверки (например наличие интерпретатора Python) и вернуть сообщение об успехе/ошибке👀.

Создаем файл плейбука в директории, которую мы обозначили в файле конфигурации:

nvim ~/ansible/playbooks/ping.yml

-12

В самом простом виде плейбук выглядит так:

Файл ping.yml на GitHub

-13

Где:

  • hosts: all – список хостов, на которых требуется выполнить плейбук (в данном примере на всех);
  • gather_facts: false – отключает сбор фактов (про них будет ниже);
  • tasks – блок со списком задач, выполняемых на управляемых хостах, в данном случае одна задача: ping.

Сохраняем файл и запускаем плейбук:

ansible-playbook ./ansible/playbooks/ping.yml

-14
При использовании команды ansible-playbook путь до плейбуков нужно указывать явно. Чтобы не делать этого каждый раз, для удобства можно создать короткую функцию и вызывать ее в консоли (смотрите далее в статье).

В моем примере доступ до серверов настроен по ключам SSH. Поэтому проверка доступности выполнена успешно😎.

-15

Если вы используете пароль (что не рекомендуется)😳 можете задать его в файле ansible.cfg (параметр ansible_password) или передать интерактивно с помощью ключа --ask-pass (для этого мы устанавливали пакет sshpass):

ansible-playbook ./ansible/playbooks/ping.yml --ask-pass

В случае каких-либо ошибок, Ansible выведет страшного вида красные сообщения⛔️. Например, при недоступности хоста по SSH такое:

-16

Чтобы запустить плейбук на указанной группе серверов, можно их явно указать в команде через параметр -l (limit):

ansible-playbook ./ansible/playbooks/ping.yml -l ubuntu

-17
-18

Для запуска плейбука от имени привилегированного пользователя💪 добавьте ключ -b (become). В моем примере модуль ping запуститься от имени root:

ansible-playbook ./ansible/playbooks/ping.yml -b

-19

В моей конфигурации серверов настроен беспарольный доступ к root через sudo (т.к. у меня тестовый стенд🛠), поэтому все отработало корректно. Но если у вас доступ по паролю, его можно передать в файле ansible.cfg (параметр ansible_become_password, не рекомендуется) или ввести интерактивно, с помощью ключа --ask-become-pass:

ansible-playbook ./ansible/playbooks/ping.yml -b --ask-become-pass

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

-20
Если что, вот документация по модулю ping.

Ansible facts – модули setup и debug

Как уже ранее говорилось, факты Ansible (facts) – это информация об управляемом сервере в виде системных переменных, таких как тип и версия ОС, IP-адрес, версии пакетов и пр., автоматически собираемая Ansible во время выполнения плейбуков (если активирован флаг gather_facts) и команд🤯.

Давайте теперь соберем эти факты, чтобы понять, как они выглядят👨‍🏭. Для этого используется стандартный модуль setup. Выполняем:

ansible all -m setup

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

В зависимости от количества хостов, сбор фактов может занять какое-то время. В выводе команды вы увидите все собранные факты в формате json:

-21

Факты можно фильтровать, например так:

ansible debian12-vpn -m setup -a 'filter=os_family,distribution_version'

Ранее в файле ansible.cfg мы настроили кэширование фактов с помощью fact_caching☝️.

Это значит, что собранные факты будут сохранятся в виде json файлов во временной директории ~/ansible/tmp, которую мы также обозначили в файле конфига:

ls -l ./ansible/tmp/

-22

Часто необходимо получить значения только конкретных фактов или переменных. Это можно сделать с помощью модуля debug🔨 в плейбуках или прямо в терминале.

Вот пример получения информации об OS, объеме диска /dev/sda1, переменной project и выводе shell команды на сервере debian12-vpn в playbook:

nvim ./ansible/playbooks/debug.yml

Файл debug.yml на GitHub

И запускаем:

nvim ./ansible/playbooks/debug.yml

-23

Просмотр фактов с помощью команд в терминале:

В этом случае факты будут взяты из кэша.

ansible debian12-vpn -m debug -a 'var=ansible_facts.os_family,ansible_facts.distribution_version'

ansible debian12-vpn -m debug -a 'var=ansible_facts.devices.keys()'

ansible debian12-vpn -m debug -a 'var=ansible_facts.devices.sda.partitions.sda1.size'

-24

Можно было заметить, что обращение к фактам происходит с помощью синтаксиса точки, как в Python (ansible написан на этом языке👌).

Подборную инфу по сбору фактов также смотрите на оф сайте: Discovering variables: facts and magic variables. Инфа по модулю debug тут.

Выполнение shell команд в терминале на нескольких серверах одновременно

С помощью Ansible и стандартного модуля shell можно выполнять удаленные команды сразу на множестве серверов🧑‍💻💻💻💻. Это очень удобно для дебага или выполнения простых операций.

Удаленная команда передается в кавычках с помощью ключа -a. Например, вывести список сетевых интерфейсов их IP адресов:

ansible all -m shell -a 'ip -br a'

-25

Или выполнить команду из нашей Linux викторины🧐, которая выводит uptime сервера в формате Unix time:

ansible debian12-vpn,ubuntu22-storage -m shell -a 'date -d "$(uptime -s)" +%s'

-26

Для запуска команд от имени привилегированного пользователя также используется -b:

ansible all -m shell -a 'whoami' -b

-27

Что такое Ansible console

В комплекте с Ansible идет такой полезные инструмент, как ansible-console😏. Это интерактивная оболочка для выполнения команд на нескольких серверах. Похоже на команды модуля shell, которые мы выполняли ранее, но способ взаимодействия немного другой:

ansible-console

whoami

-28
Для выхода введите exit или нажмите сочетание клавиш Ctrl+d.

Пример использования модуля ping группы debian:

ansible-console debian

ping

-29

Просмотр фактов Ansible:

setup filter=ansible_hostname

-30

Для выполнения привилегированных команды, добавьте ключ -b (но будьте осторожны!):

ansible-console debian -b

whoami

-31

При выполнении удаленных команд ansible-console по умолчанию используется модуль command❗️. Он вызывает команды напрямую, поэтому некоторые shell механизмы тут работать не будут. Для задействования shell укажите его явно:

shell echo $HOME

-32

Документация Ansible прямо в терминале

У Ansible очень хорошая документация (правда на английском🙄) и она доступна даже из консоли с помощью утилиты ansible-doc. Например, чтобы посмотреть описание и примеры использования модуля systemd выполните:

ansible-doc systemd

-33

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

-34

Как по мне, это очень удобно!

Пример ansible playbook: правка конфига sshd и копирование SSH ключа

В качестве практики напишем плейбук📝, который:

на всех серверах:

  • изменит номер порта подключения SSH;
  • отключит доступ по паролю на сервер по SSH;
  • создаст директорию ~/.ssh, если она не существует;
  • добавить новый публичный ssh ключ для авторизации по ключу.

на серверах, у которых переменная “project” равна “vpn”:

  • скопирует файл приватного ключа SSH с локальной машины в директорию пользователя на удаленных серверах.

Генерируем новый ключ:

ssh-keygen -t ed25519 -f ~/ansible/id_ed25519_new

-35

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

nvim ./ansible/playbooks/sshd_config.yml

-36

Наполняем его:

Файл sshd_config.yml на GitHub

И запускаем:

-37

ВНИМАНИЕ❗️ Данный playbook меняет номер порта демона sshd и отключает парольный доступ к серверу по SSH. Крайне рекомендуется запускать необкатанные плейбуки в тестовых средах. Все действия вы выполняете на свой страх и ответственность. Я вас предупредил)

ansible-playbook ./ansible/playbooks/sshd_config.yml

-38

Если все отработало корректно, то порт доступа SSH на удаленных серверах будет изменен. Не забудьте скорректировать номер порта в файле инвентаризации. Или верните старый номер порта подобной командой:

ansible-playbook ./ansible/playbooks/sshd_config.yml -e 'ansible_port=4444' -e 'new_ssh_port=22'

В ней переопределены переменная ansible_port (из конфига ansible.cfg), используемая для подключения к хостам, и кастомная переменная new_ssh_port (из плейбука sshd_config.yml), определяющая новый номер порта в плейбуке😶‍🌫️.

На всякий случай повторю, что плейбук также добавляет наш новый публичный (~/ansible/id_ed25519_new.pub) ключ на сервера.

Возможно вы обратили внимание🧐, что в плейбуке используются теги🔖. С их помощью можно осуществлять выборочный запуск. Например, выполнить только те задачи, которых есть тег ssh_client (ключ -t или --tags):

ansible-playbook ./ansible/playbooks/sshd_config.yml -t ssh_client

-39

Или наоборот, игнорировать задачи (--skip-tags):

ansible-playbook ./ansible/playbooks/sshd_config.yml --skip-tags ssh_server

Коротко про Ansible roles

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

ansible-galaxy init ./ansible/roles/base-config

-40

Краткое описание структуры:

./ansible/roles/base-config/
├── README.md # документация роли
├── defaults/ # значения переменных по умолчанию (main.yml)
├── files/ # файлы, которые будут копироваться на целевые хосты
├── handlers/ # обработчики для уведомлений (main.yml)
├── meta/ # метаданные роли, включая зависимости (main.yml)
├── tasks/ # основные задачи роли (main.yml)
├── templates/ # шаблоны Jinja2, которые будут рендериться
├── tests/ # тесты для роли (inventory, test.yml)
└── vars/ # переменные роли с более высоким приоритетом (main.yml)

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

-41

Но и это уже совсем другая история)

Создаем функцию для удобного запуска плейбуков

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

echo 'ap() {ansible-playbook ~/ansible/playbooks/"$@"}' >> ~/.profile

source ~/.profile

which ap

Описания команд выше:

  • echo – выводит строку (подробнее про вывод текста тут);
  • 'ap() {ansible-playbook ~/ansible/playbooks/"$@"}' – строка, которая определяет функцию ap:
  • ap() — объявление функции с именем ap (имя произвольное);
  • {ansible-playbook ~/ansible/playbooks/"$@"} – тело функции, которая запускает ansible-playbook, передавая ей все аргументы ("$@"), например, ap playbook.yml --become;
  • >> ~/.profile – добавляет строку в конец файла ~/.profile, чтобы функция автоматически загружалась при входе в систему (подробнее про перенаправление потоков тут).
  • source ~/.profile – загружает изменения из ~/.profile, активируя функцию ap в текущей сессии;
  • which ap – если функция определена успешно, это отобразит её как часть текущей оболочки.
-42

Проверяем работу:

ap ping.yml

-43

Отлично!

Послесловие

Вот мы с вами и познакомились с таким крутым и полезным инструментом управления конфигурациями под названием Ansible😎. Базовые знания у нас есть, теперь осталось применить их на практике для решения рутинных задач😌. В планах написать плейбук по базовой настройке сервера Linux, установке и запуску различных сервисов, установке Arch linux на шифрованные разделы и много чего другого🤯.

Спасибо, что уделили время 😊. Если появились вопросы – приглашаю в наш дружелюбный Вороний чат 🚶‍♀️🐧🚶🐧🚶‍♂️🐧 в телеге 😅. Также обязательно подписывайтесь на основной телеграм канал: @r4ven_me, уведомления о новых материалах на сайте приходят туда в день публикации.

Удачи!

Полезные источники