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

 

Для кого?

Цель этого материала — показать основные приемы работы с Ansible для решения простой и понятной задачи. Рассказать о промышленном использовании Ansible для развертывания инфраструктуры в рамках этой заметки, разумеется, невозможно. Но уверен, после прочтения ты придумаешь, как подстроить этот замечательный инструмент под свой workflow. Или как минимум обратишь на него внимание, если раньше обходил стороной.

 

Зачем нужна оркестрация локальной машины?

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

  • автоматическую установку программ;
  • размещение файлов конфигураций;
  • выполнение единовременных команд (вроде установки плагинов);
  • клонирование рабочих репозиториев;
  • настройку среды разработки

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

Зачем это может потребоваться? Несмотря на то что большинство людей годами не переустанавливают систему, причин дисциплинированно держать свои конфиги в порядке может быть масса. Для себя я выделил следующие.

 

Воспроизводимость

Мне важно иметь возможность быстро поднять привычную рабочую среду на новой машине. Ситуации бывают разные:

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

В подобных случаях часто приходится раскатывать ОС с нуля, ставить весь необходимый софт и, что самое неприятное, мучительно вспоминать все пляски с бубном, которые устраивал при предыдущей настройке ОС. Поясню: в моем случае это установка Arch Linux (сама по себе довольно муторная), допиливание оконного менеджера i3, донастройка железа (вплоть до чувствительности BT-мыши), стандартная ерунда вроде локалей, шрифтов, systemd-юнитов и shell-скриптов. И все это без учета установки и настройки непосредственно рабочего софта.

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

 

Предсказуемость

Очень полезно знать, что в системе установлено и как настроено. Когда конфиг перед глазами, быстрее понимаешь, почему ОС так работает (или не работает).

Если не представляешь четко, что, как и когда ты сконфигурировал в системе (а в Linux невозможно запомнить все даже с опорой на ArchWiki), ты вскоре обнаружишь, что также не понимаешь, почему эта программа сейчас работает так, хотя раньше работала иначе. Возможно, ты ставил какой-то плагин или что-то исправлял в конфиге, но забыл?

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

 

Декларативность и поддерживаемость

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

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

Кстати, если ты тоже без ума от декларативного подхода к описанию ОС, обрати внимание на дистрибутив NixOS.

 

Другие решения?

Разумеется, для быстрого развертывания можно приспособить и другие инструменты, например системы образов вроде эппловской Time Machine или Norton Ghost. Можно подойти и более радикально: запускать софт в контейнерах Docker или даже виртуалках в AppVM. Проблема в том, что сложно их поддерживать, управлять ими и обновлять софт на регулярной основе. Другими словами, они созданы для решения несколько других задач и не так бесшовно встраиваются в повседневную жизнь, если это не твоя работа 24/7.

 

Как нам поможет Ansible

Ansible — это система оркестрации. Она написана на Python, присутствует в популярных дистрибутивах и не требует клиента на целевых машинах. Инструмент активно развивается, под него существует много плагинов. Он достаточно новый, но уже популярен наряду с Puppet и Chef.

Для работы с Ansible достаточно передать скрипт (сценарий, конфиг) с перечислением действий, который он должен выполнить на целевой машине. Давай посмотрим, как писать эти конфиги.

Конфиг Ansible называется playbook. Он описывается на языке YAML. Ключевой объект конфига — задача. Это массив (список) вложенных блоков-задач, каждая из которых описывает одно действие. Задачи могут быть атомарны, а могут, в свою очередь, содержать блок подзадач. И так далее, выстраивая дерево подзадач. Примеры задач:

  • обновить систему;
  • установить пакет (или пакеты);
  • скопировать конфиг;
  • выполнить команду.

Задач может быть сколько угодно, и Ansible пройдется по всем и выполнит каждую по очереди. Посмотри на пример простого конфига — он описан в одном файле (часть блоков свернута для наглядности). Конечно, большие боевые конфиги удобно разделять на несколько файлов и тегировать, но для наших задач хватит и одной простыни. 🙂

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

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

 

Пробуем Ansible

 

Что нужно для работы Ansible?

Linux, Python и в некоторых случаях SSH. Сразу оговорим термины:

  • master — машина, с которой мы осуществляем управление, другими словами — на которой мы запускаем Ansible со скриптом. Она выполняет команды на удаленной (целевой) машине;
  • target — машина, над которой мы выполняем задачи, другими словами — целевая машина, на которой по скрипту нужно развернуть рабочее окружение.

Строго говоря, в отличие от других систем оркестрации, устанавливать Ansible на целевом хосте не обязательно. Если у тебя есть еще один компьютер (я проделывал это, например, с Raspberry Pi 3), Ansible нужно иметь именно на нем.

Но мы провернем трюк: используем одну машину и как target-хост, и как master-хост. Поэтому просто установим Ansible через pip Install ansible.

Только что установленный Arch Linux с Python и Ansible через pip. Больше ничего не нужно
Только что установленный Arch Linux с Python и Ansible через pip. Больше ничего не нужно
 

Перечисляем хосты и запускаем playbook

С этого момента договоримся, что мы не разделяем master- и target-машины, все действия выполняем на одной машине. Для удаленных хостов процедура будет почти такая же.

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

[control]
localhost ansible_connection=local

Этими строками мы:

  • создали группу control;
  • определили в ней один хост c адресом localhost (можно указать любой доступный IP);
  • дополнительно для хоста localhost указали тип соединения local.

Здесь необходимо пояснение. Обычно при работе с удаленными хостами Ansible соединяется с ними по SSH и выполняет определенные в скрипте операции. Однако, поскольку мы выполняем действия над «самим собой», было бы излишне поднимать sshd-демон, чтобы законнектиться к самому себе. Для таких случаев Ansible позволяет указать дополнительный параметр ansible_connection, который определит тип соединения. В нашем случае это local.

Попробуем пропинговать хосты на отклик (в нашем случае единственный хост):

$ ansible all -m ping
localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Ответ по localhost — работает.

 

Собираем свой playbook

Мы уже знаем, что по большей части playbook — это набор задач разной степени вложенности. Теперь научимся писать эти задачи.

Главное, что нужно усвоить, — для выполнения каждой задачи требуется использовать модуль. Модуль — это actor, который может совершать действия определенного типа. К примеру:

  • устанавливать и обновлять пакеты;
  • создавать и удалять файлы;
  • клонировать репозитории;
  • пинговать хосты;
  • отправлять сообщения в Slack.

Для каждой задачи передаем модуль и набор параметров его запуска, например список пакетов для установки. Модулей очень много, с их полным списком ты можешь ознакомиться здесь. А пока пройдемся по тем, которые нам понадобятся.

 

1. Обновление системы и установка пакетов

Модули pacman, apt, brew и другие пакетные менеджеры для языков и систем.

Для обновления системы и установки базовых пакетов программ напишем пару тасков с использованием модуля pacman. Вот пример подобной задачи:

- name: full system upgrade
  become: yes
  pacman:
    update_cache: yes
    upgrade: yes
- name: install cli apps
  become: yes
  pacman:
    name:
      - xterm
      - tmux
      - neovim
      - ranger
      - mutt
      - rsync
    state: present

Здесь мы определили две задачи: в первой обновляем систему, во второй передаем модулю pacman список пакетов, которые нужно установить, и инструкцией become сообщаем, что надо поднять привилегии до суперпользователя.

Кстати, мы можем также передать имя юзера, которым нужно стать при выполнении этой команды, как мы сделали бы это при использовании su. Например, таким образом можно поменять шелл для себя при установке zsh в задаче с модулем command:

- name: install zsh
  become: yes
  block:
    - pacman:
        name:
          - ...
          - zsh
    - command: chsh -s /usr/bin/zsh
      become_user: user

Обрати внимание на блочный конфиг задачи install zsh: это удобный (но необязательный) способ записи для группировки нескольких действий, не требующих выноса в отдельные (под)задачи.

Для установки из AUR можно использовать и yaourt (правда, сейчас его уже подвинул новый yay). Поскольку устанавливать из AUR под рутом нельзя, а мы определили повышение привилегий в корневой задаче, создадим отдельного юзера aur_builder и будем переходить под него в задачах установки из AUR:

- name: create aur_builder user
  become: yes
  block:
    - user:
        name: aur_builder
        group: wheel
    - lineinfile:
        path: /etc/sudoers.d/11-install-aur_builder
        line: 'aur_builder ALL=(ALL) NOPASSWD: /usr/bin/pacman'
        create: yes
        validate: 'visudo -cf %s'

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

- aur: name=yaourt skip_installed=true
  become: yes
  become_user: aur_builder

Продолжение доступно только подписчикам

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

Подпишись на «Хакер» по выгодной цене!

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

1 комментарий

  1. Anon

    13.09.2018 at 17:32

    Немешало бы больше уделить внемания ansible-playbook, т.е. не только в контексте запуска с тэгами

Оставить мнение

Check Also

Нагнуть Nagios. Разбираем хитрую цепочку уязвимостей в популярной системе мониторинга

Nagios — это одно из популярнейших решений для мониторинга, которое используется во многих…