mysurik.ru

Ansible: автоматизация сервера с первого плейбука

Ansible: автоматизация сервера с первого плейбука

Раньше я настраивал каждый новый сервер руками. Установка пакетов, правка конфигов, создание пользователей — всё через SSH. Когда серверов стало два, я задумался. Когда дошло до трёх — понял, что так больше нельзя.

Ansible пришёл как решение, о котором я жалею, что не узнал раньше.

Что такое Ansible и почему он лучше shell-скриптов

Ansible — это инструмент управления конфигурацией. Ты описываешь желаемое состояние сервера в YAML-файлах (плейбуках), а Ansible сам приводит сервер к этому состоянию.

Почему не bash-скрипты? Потому что скрипты — это процедурный код: делай шаг 1, шаг 2, шаг 3. Если шаг 2 упал — скрипт остановится. Ansible же идемпотентен: он проверяет текущее состояние и меняет только то, что нужно. Поставил пакет? В следующий раз он не будет переустанавливаться. Хочешь обновить конфиг Nginx? Ansible применит только изменения и перезагрузит сервер.

Ставлю Ansible на свою машину

На Windows через WSL2:
sudo apt update && sudo apt install ansible -y

На сервере ничего ставить не надо — Ansible работает по SSH. Это его главное преимущество. Никаких агентов, никаких демонов.

Создаю первый плейбук

Структура директории:
ansible/
inventory.yml
playbooks/
init.yml
docker.yml
wordpress.yml

Инвентарь (inventory.yml) — список серверов:

all:
hosts:
webserver:
ansible_host: 192.168.1.100
ansible_user: deploy
ansible_become: yes

Первый плейбук — базовая инициализация сервера:

— name: Init server
hosts: webserver
tasks:
— name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600

— name: Install essential packages
apt:
name:
— htop
— ncdu
— git
— ufw
— fail2ban
state: present

— name: Setup UFW
ufw:
rule: allow
port: ‘{{ item }}’
proto: tcp
loop:
— 22
— 80
— 443

— name: Enable UFW
ufw:
state: enabled
policy: deny

Запускаю:
ansible-playbook -i inventory.yml playbooks/init.yml

Ansible подключается по SSH, выполняет задачи. Если где-то упало — видно сразу, какая задача и почему. Красиво и предсказуемо.

Плейбук для Docker

Следом написал плейбук для установки Docker на сервер:

— name: Install Docker
hosts: webserver
tasks:
— name: Install dependencies
apt:
name:
— ca-certificates
— curl
— gnupg
state: present

— name: Add Docker GPG key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present

— name: Add Docker repository
apt_repository:
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable
state: present

— name: Install Docker
apt:
name:
— docker-ce
— docker-ce-cli
— containerd.io
— docker-compose-plugin
state: present

— name: Add user to docker group
user:
name: deploy
groups: docker
append: yes

Этот плейбук можно прогнать на любом новом сервере — и через 2 минуты на нём будет Docker. Руками я бы потратил 10-15 минут и мог ошибиться.

Переменные и шаблоны

Самая крутая фича Ansible — шаблоны Jinja2. Я сделал шаблон конфига Nginx с переменными:

server {
listen 80;
server_name {{ domain_name }};
root /var/www/{{ domain_name }}/;
index index.php index.html;
}

И в плейбуке:
— name: Deploy Nginx config
template:
src: templates/site.conf.j2
dest: /etc/nginx/sites-available/{{ domain_name }}.conf
vars:
domain_name: example.com
notify: reload nginx

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

Теперь любой новый сервер у меня поднимается за 10 минут. Запустил playbook — и готово. Руками я больше не настраиваю ничего.

Продолжу с того, на чём остановился в первой части. После первого плейбука я обрадовался и побежал автоматизировать всё подряд. И вот тут началось самое интересное — когда один плейбук распух до пары сотен строк, я понял, что нужна структура. Так я пришёл к ролям.

Роли — это как шкафчики с инструментами. Вместо одного гигантского файла ты раскладываешь логику по папкам: vars, tasks, handlers, templates. У меня теперь роль nginx, роль docker, роль fail2ban, роль wordpress. Каждая роль самодостаточна и переиспользуется между проектами. Подключение роли к плейбуку выглядит лаконично:

— name: Setup webserver
hosts: webserver
roles:
— common
— nginx
— docker
— wordpress

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

Теперь про секреты. Изначально я тупо вписывал пароли прямо в плейбуки и инвентарь. Удобно? Да. Безопасно? Категорически нет. Если репозиторий утечёт — все пароли уйдут вместе с ним. Решение — Ansible Vault. Шифруешь файл с секретами паролем-ключом, а в плейбуке просто ссылаешься на переменные из него:

ansible-vault create group_vars/all/vault.yml
ansible-vault edit group_vars/all/vault.yml

Внутри лежат переменные типа db_password, api_token. А при запуске плейбука указываешь файл с ключом:

ansible-playbook -i inventory.yml playbooks/site.yml —vault-password-file ~/.vault_pass

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

Обработчики — ещё одна фишка, которую я не оценил сразу. Это задачи, которые запускаются только если что-то изменилось. Классика: обновил конфиг nginx → нужно перезапустить nginx. Без обработчиков я бы перезапускал службу при каждом прогоне плейбука, даже если ничего не менялось. С обработчиком всё аккуратно:

— name: Reload nginx
systemd:
name: nginx
state: reloaded
listen: reload nginx

Задача-обработчик вызывается notify из других задач. Сработает только при изменении конфига. Сервисы не дёргаются впустую — это заметно, когда прогоняешь плейбук на десяти серверах.

Теги и лимиты. Когда плейбук большой, не хочется каждый раз гонять всё целиком. Я разметил задачи тегами:

— name: Install docker
apt:
name: docker-ce
state: present
tags: docker

И теперь могу запустить только нужную часть:

ansible-playbook -i inventory.yml playbooks/site.yml —tags docker

А —limit позволяет применить плейбук только к конкретному хосту из инвентаря. У меня три сервера в inventory, но если нужно обновить только один — я не трогаю остальные. Эта пара опций сэкономила мне уйму времени на тестировании.

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

ansible-playbook -i inventory.yml playbooks/site.yml —check —diff

Это показывает, что Ansible собирается менять, не применяя ничего. Красный/зелёный дифф наглядно показывает, какая строка конфига поменяется. Я делаю это на 100% плейбуков — глупо ломать работающий сервер из-за опечатки в YAML, которую можно увидеть заранее.

Про грабли, на которые я наступил. Первая — YAML чувствителен к отступам. Один лишний пробел — и плейбук падает с загадочной ошибкой. Теперь всегда проверяю ansible-lint. Вторая — я долго не понимал разницу между списком и словарём в YAML, из-за чего плейбук вёл себя непредсказуемо. Разобрался, когда прочитал документацию. Третья — модули apt и systemd требуют become. Если забыть — Ansible ругается на права. Четвёртая — не стоит хранить инвентарь и плейбуки в разных репозиториях, потом теряешь актуальность. Я держу всё в одном git-репо и версионирую.

Где я это применил. Мой главный плейбук сейчас поднимает полностью новый сервер: обновляет систему, ставит Docker, nginx, fail2ban, создаёт пользователя deploy, настраивает SSH по ключу и сразу разворачивает WordPress. Это один файл, который я запускаю на свежем VPS — и через десять минут получаю готовый блог с HTTPS. Раньше на это уходил вечер и куча ручных действий, где можно было ошибиться.

Что я посоветую в итоге. Начни с простого плейбука, который приводит сервер к нужному состоянию. Не пытайся объять всё сразу — сначала инициализация (обновления, пользователи, фаервол), потом по одной роли. Обязательно подключай vault для секретов и check mode перед применением. И версионируй конфигурацию в git — через месяц ты будешь благодарен себе, когда сможешь воспроизвести сервер из файлов, а не по памяти.

Ansible не отменяет понимание Linux — отменяет рутину. Ты всё ещё должен знать, какие пакеты ставить и как их настраивать. Но вместо того чтобы повторять одни и те же команды на каждом сервере, ты описываешь это один раз. И каждый следующий сервер поднимается сам. Вот ради этого, честно говоря, я и перешёл на Ansible — и не жалею ни одной потраченной минуты.

Отдельно расскажу про работу с несколькими серверами, потому что именно это подтолкнуло меня к Ansible. У меня три машины: домашний сервер Proxmox, VPS-дублёр и тестовая виртуалка. Раньше я настраивал каждую по очереди и постоянно ловил расхождения: на одной стоят пакеты, на другой — нет. С Ansible я описываю желаемое состояние один раз, а инвентарь просто перечисляет хосты. Один плейбук — все серверы в одинаковом состоянии. Это невероятно упрощает поддержку: если я меняю конфиг nginx, я меняю его в одном файле, а не в трёх местах вручную.

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

И напоследок маленький, но важный совет: сделай первый плейбук на какой-нибудь неважной машине. Я учился на рабочей, и пару раз почти уронил прод. Проверка на тестовой виртуалке сэкономила мне кучу нервов. Когда плейбук работает на ней — смело применяй на боевых серверах с —check. Такой подход у меня стал правилом, и я ни разу не пожалел.

Кстати, про мой самый первый плейбук. Я написал его ночью, когда в третий раз вручную настраивал один и тот же сервер. Помню, сидел, копировал команды из истории bash и думал: «Стоп, а если я просто запишу все команды в файл и перестану это делать руками?». Так и родился мой первый init.yml. Он был корявый, без ролей и переменных, но он работал. Через неделю я уже добавлял роли, vault и теги. Главное было — начать. Если ты ещё настраиваешь серверы руками — просто запиши свои команды в плейбук. Дальше всё само затянет.

Ваш комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *