Нахуя ansible
Давайте сразу определимся, я буду рассказывать про Ансибл в рамках Пайтон разработчика. Может немного бОльше, но всё же буду рассматривать то, как он нам поможет в разворачивании наших поделок на сервера.
В этой статье будет вводная информация про Ансибл. Не ждите реальный проект, тема слишком обширна и конкретная статья призвана только заинтересовать.
До того как мы начнём, поставь ансибл, братиш! pip install --user ansible
Для чего?
Очень часто мы руками раскатываем наши сервисы на сервера. Как это обычно происходит?
- Влезть за сервер по ssh
- Скопировать туда код
- Запустить какие-то действия
- миграция
- сборка контейнера Докер
- обновление конфигов
- поставить новые пакеты\софт
- etc
- Остановить старую версию сервиса
- Запустить новую
- Убедиться что все конфиги поднялись.
Где тут проблема?
Проблема в куче ручных шагов, на которых можно ошибиться, тупануть, вставить не то, обрушить всё к хуям собачьим. Да и не удобно это всё. Точнее оно может и удобно до какой-то стадии повышения сложности, но потом точно не удобно.
Именно для этого и нужен Ансибл. Он позволяет всё это автоматизировать. Надёжно и просто(если понимаешь что делаешь).
Как это работает?
У ансибл есть два режима работы:
- Работа с модулями Ансибл напрямую
- Работа в режиме плейбуки
Работа напрямую
Это как разовый вызов модуля в пайтоне, а ля python -m pip install aiohttp.
Лично я это использую для разовой операции на куче серверов (да хоть на одном), чтоб что-то мелкое выполнить.
Например узнать uptime всех серверов:ansible all -i inventory.yaml -m shell -a "uptime"
Работа в режиме плейбуки
Это более серьёзный режим. Playbook - это список правил, действий, по которым ваш сервер приводится к нужному состоянию.
Стоит упомянуть, что Ansible именно приводит к нужному состоянию.
Например у вас в плейбуке написано, чтоб ансибл установил nginx.
1. Ансибл лезет на первый сервер, собирает кучу инфы о сервере и пакетах, установленных там. Устанавливает nginx.
2. Ансибл лезет на второй сервер, собирает кучу инфы... смотрит, nginx уже стоит и ничего не делает вообще.
На выходе серверов может быть 10000 и на всех по итогу будет установлен nginx. Можно поставить тригер, чтоб nginx был установлен именно последней доступной в репозитории версии или определённой версии, тогда ансибл везде сделает nginx именно нужной версии.
Круто? Круто!
Немножко практики и ещё чуть теории
На данный момент нам важно узнать про две вещи.
inventory
inventory - это список серверов\машин\компьютеров с которым ansible работает.
inventory может быть в формате ini, в формате yaml (мой любимчик) и динамический.
Формат ini я не буду рассматривать, если интересно, найдёте в документации. А вот yaml я покажу.
Динамический inventory нигде не хранится кроме оперативной памяти. Чаще всего используется, когда вы автоматически листите какие-то ваши сервера в датацентре и\или создаёте сервер с нуля тем же ansible. Тобишь послали запрос на создание сервера, дождались статуса создания, записали в inventory его параметры.
Давайте напишем свой inventory.
Например у меня есть 2 машины, я назвал их raspi_four
и raspi_zero
.
Для интереса, я настрою всё так, чтоб ssh вход на raspi_four
был по ssh ключу, а на raspi_zero
по паролю.
Доступ по ключу на raspi_four
настраиваем заранее. (прописываем ваш публичный ключ в authorized_keys
на raspi_four
, в интернете куча инструкций).
Дальше пишем в файле inventory.yaml
all: hosts: raspi_four: ansible_ssh_host: 192.168.0.119 ansible_user: pi raspi_lite: ansible_connection: ssh ansible_ssh_host: 192.168.0.115 ansible_user: pi ansible_ssh_pass: raspberry
Вместо имён, например raspi_four
, можно написать доменное имя и не указывать ip. Ансибл сам разберётся.
Теперь команда ansible all -i inventory.yaml -m shell -a "uptime"
будет работать.
Плейбука!
Давайте напишем простую плейбуку.
Рассмотрим два простых действия:
1. Установить какой-нибудь софт на сервер.
2. Скопировать файл с хоста (на котором запущена плейбука) на сервер.
3. Выполнить это на всех машинах в inventory
Приступим. Создаём файл test_playbook.yaml
и пишем там это
- name: my tasks hosts: all tasks: - name: install nmap apt: name: ["nmap"] become: True - name: copy file copy: src: "{{ playbook_dir }}/some_file.txt" dest: /tmp/tempConfig.txt
Давайте разберёмся что тут происходит.
Если вы знакомы со структурой yaml, вы сразу видите список, а именно список из одного элемента, в котором лежит всё написанное. Этих элементов может быть несколько и все будут выполняться последовательно. Конкретно этот элемент отвечает за исполнение наших, так называемых tasks
и называется my tasks. Это будет фигурировать в логах исполнения и весьма полезно давать осмысленные названия.
Далее мы указываем hosts: all
. Помните инвентори, там в основе всего была группа all
(да, там разделение по группам, но о них подробнее я расскажу в следующий раз, может быть). Вот со всеми входящими в группу хостами мы и производим действия.
Кстати вместо all
можно указать local
, и тогда все действия будут происходить на машине, на которой запустилась плейбука. Это удобно для разделения задач, например на локальной машине можно собрать артефакт или сбилдить образ, залив его на докер-хаб, а на хосте уже спуллить образ и запустить.
Далее мы видим список tasks
. У каждой таски есть одинаковые параметры, это имя name
, где любой текст, и имя модуля.
К слову о модулях, из коробки в ансибл есть ооооооочень дохуя модулей на все случаи жизни, да и сторонние можно ставить, их ещё больше. Описывать весь список я не смогу, но подробности есть в документации. Сейчас рассмотрим два модуля, это apt
и copy
.apt
имеет дополнительный параметр name:, который принимает строку или список строк с названиями того, что надо установить из apt. И ниже мы видим странное become: True
, которое направлено на всю задачу. Как мы помним из inventory, мы заходим под пользователем pi
, а он не имеет прав на установку пакетов. Чтоб он это умел, надо повысить права дописав перед командой sudo. (само собой юзер pi
должен быть включён в sudoers
). Именно для задач, где надо повысить права, прописывается become: True
(можно так же become: yes
)
copy, как можно понять из названия, копирует файл (или директорию) с хоста на целевую машину. Из параметров src: путь до файла на хосте и dest: куда положить на целевой машине. В src мы использовали переменную ансибла, где лежит путь до директории, где лежит текущая плейбука. Этих переменных у ансибла куча и о них поговорим потом. И да, знающие уже увидели тут Jinja2. Чтож - это он и есть) Всё (почти) что можете писать в jinja2, можете и тут.
Я рассмотрел только малую часть возможностей модулей apt и copy, там куча параметров и куча возможностей.
Запускаем
ansible-playbook test_playbook.yaml -i inventory.yaml
и наблюдаем за исполнением. Если запустить ещё раз, то ансибл просто пройдётся по задачам, убедится что всё уже сделано ранее и ничего менять не надо, поставить везде ok вместо changed и не будет нихрена делать =)
Если интересно посмотреть что он делает подробнее, можно к команде запуска дописать -vvv
На этом наша вводная лекция закончена.
Специально для python_sripts, Вадик.