Ansible для начинающих: настройка VPS кодом вместо рук

Администрирование
Ansible для начинающих: настройка VPS кодом вместо рук

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

Как работает Ansible: без агентов, по SSH

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

  • управляющая машина — ваш ноутбук с Linux, macOS или WSL на Windows, где установлен Ansible;
  • SSH-доступ к серверам — лучше по ключу (как его настроить — в статье про SSH-ключи вместо пароля);
  • Python на сервере — в Ubuntu, Debian, AlmaLinux и Rocky Linux он есть из коробки.

Установка на управляющую машину (Ubuntu/Debian/WSL):

sudo apt update
sudo apt install -y pipx
pipx install --include-deps ansible
pipx ensurepath

Проверка: ansible --version должна показать версию 2.16 или новее.

Inventory: список ваших серверов

Inventory — файл, в котором перечислены серверы и их группы. Ansible применяет задачи не к «айпишникам из головы», а к именам и группам из этого файла. Простейший inventory.ini:

[web]
site1 ansible_host=203.0.113.10 ansible_user=root
site2 ansible_host=203.0.113.11 ansible_user=root

[bots]
mybot ansible_host=203.0.113.12 ansible_user=root ansible_port=2222

[all:vars]
ansible_python_interpreter=/usr/bin/python3

Здесь две группы: web из двух серверов и bots из одного (у него нестандартный SSH-порт — частая ситуация после смены SSH-порта). Группы позволяют применять разные плейбуки к разным ролям машин: веб-серверы получают Nginx, боты — Python-окружение.

Проверим, что Ansible достучался до всех:

ansible -i inventory.ini all -m ping

Каждый сервер должен ответить "ping": "pong". Модуль ping здесь — не ICMP, а проверка «SSH работает и Python найден».

Playbook: желаемое состояние сервера в YAML

Playbook — YAML-файл со списком задач (tasks). Каждая задача вызывает модуль: apt ставит пакеты, user управляет пользователями, copy и template раскладывают файлы, service управляет службами. Ключевой сдвиг в мышлении: вы описываете не команды, а состояние. Не «выполни apt install nginx», а «пакет nginx должен быть установлен».

Мини-пример:

- name: Веб-серверы
  hosts: web
  become: true
  tasks:
    - name: Nginx установлен
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true

    - name: Nginx запущен и в автозагрузке
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true

Запуск: ansible-playbook -i inventory.ini play.yml. Параметр become: true означает выполнение через sudo.

Идемпотентность: почему повторный запуск ничего не ломает

Идемпотентность — свойство, ради которого Ansible вообще существует. Плейбук можно запускать сколько угодно раз: модули сначала проверяют текущее состояние и меняют только то, что отличается от описанного. Nginx уже установлен? Задача вернёт ok, а не changed, и ничего не сделает. Строка в конфиге уже есть? Модуль lineinfile не добавит дубль.

Это принципиально отличает плейбук от bash-скрипта: скрипт при повторном запуске может создать второго пользователя, дописать конфиг дважды или упасть на середине. Практическое правило: после первого запуска плейбука запустите его второй раз. Если в итоговом отчёте changed=0 — плейбук идемпотентен и его безопасно гонять хоть по расписанию. Если какая-то задача каждый раз показывает changed — вы, скорее всего, использовали модуль command/shell там, где есть специализированный модуль.

Практика: настройка нового VPS одним плейбуком

Соберём всё вместе. Сценарий: вы заказали VPS (у Cheap-Host он выдаётся за 45–60 секунд с IP и root-доступом по SSH), и вместо часа ручной работы прогоняете плейбук базовой настройки — тот самый чек-лист из статьи про первые шаги после покупки VPS, но кодом. Файл setup.yml:

- name: Базовая настройка нового VPS
  hosts: all
  become: true
  vars:
    admin_user: admin
    admin_key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"

  tasks:
    - name: Обновить кэш apt и пакеты
      ansible.builtin.apt:
        update_cache: true
        upgrade: safe

    - name: Установить базовые пакеты
      ansible.builtin.apt:
        name:
          - ufw
          - fail2ban
          - htop
          - unattended-upgrades
          - nginx
        state: present

    - name: Создать пользователя с sudo
      ansible.builtin.user:
        name: "{{ admin_user }}"
        groups: sudo
        shell: /bin/bash
        create_home: true

    - name: Разрешить sudo без пароля
      ansible.builtin.copy:
        dest: /etc/sudoers.d/{{ admin_user }}
        content: "{{ admin_user }} ALL=(ALL) NOPASSWD:ALL\n"
        mode: "0440"
        validate: /usr/sbin/visudo -cf %s

    - name: Добавить SSH-ключ пользователю
      ansible.posix.authorized_key:
        user: "{{ admin_user }}"
        key: "{{ admin_key }}"

    - name: Запретить вход root по SSH
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^#?PermitRootLogin'
        line: 'PermitRootLogin no'
      notify: Restart sshd

    - name: Запретить вход по паролю
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^#?PasswordAuthentication'
        line: 'PasswordAuthentication no'
      notify: Restart sshd

    - name: UFW — разрешить SSH
      community.general.ufw:
        rule: allow
        name: OpenSSH

    - name: UFW — разрешить HTTP и HTTPS
      community.general.ufw:
        rule: allow
        port: "{{ item }}"
        proto: tcp
      loop:
        - "80"
        - "443"

    - name: UFW — включить файрвол
      community.general.ufw:
        state: enabled
        policy: deny

    - name: Nginx запущен и в автозагрузке
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: Restart sshd
      ansible.builtin.service:
        name: ssh
        state: restarted

Обратите внимание на детали:

  • vars — переменные: имя пользователя и публичный ключ подставляются в задачи, плейбук легко переиспользовать;
  • handlers — обработчики: SSH перезапустится один раз в конце, и только если конфиг реально менялся;
  • validate у sudoers — Ansible проверит синтаксис файла до записи, чтобы не отрезать себе sudo;
  • loop — одна задача открывает несколько портов.

Запуск на свежий сервер:

ansible-playbook -i inventory.ini setup.yml

Через пару минут получите отчёт вида ok=12 changed=11 failed=0. Второй запуск даст changed=0 — сервер уже в целевом состоянии. Тот же плейбук настроит и один сервер, и двадцать: добавьте строки в inventory — и всё.

Полезные приёмы для повседневной работы

  • --check — «сухой прогон»: показывает, что изменилось бы, ничего не трогая;
  • --diff — показывает построчные изменения файлов;
  • --limit site1 — применить плейбук только к одному серверу из группы;
  • ansible-vault — шифрование паролей и токенов прямо в репозитории;
  • роли (roles) — способ упаковать задачи в переиспользуемые блоки: роль «nginx», роль «postgresql», роль «hardening». На Ansible Galaxy тысячи готовых ролей;
  • git — храните inventory и плейбуки в репозитории: история изменений инфраструктуры бесплатно.

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

Частые ошибки новичков

  • shell вместо модулей — команда shell: apt install nginx не идемпотентна и не покажет, изменилось ли что-то. Почти всегда есть специализированный модуль;
  • Правка серверов руками поверх Ansible — следующий запуск плейбука перезапишет ручные изменения. Правило: всё, что настроено плейбуком, меняется только плейбуком;
  • Секреты в открытом виде — пароли в YAML попадут в git. Используйте ansible-vault;
  • Отключение SSH-доступа самому себе — меняете порт или запрещаете пароли? Сначала убедитесь, что задача с вашим ключом выполнилась, и держите открытой запасную SSH-сессию.

FAQ

Нужно ли устанавливать Ansible на сам сервер?

Нет. Ansible безагентный: ставится только на вашу машину и работает по SSH. На сервере нужен лишь Python, который в Ubuntu и Debian есть из коробки.

Что такое идемпотентность простыми словами?

Сколько бы раз вы ни запускали плейбук, результат один: модули приводят сервер к описанному состоянию и не трогают то, что уже настроено. Повторный запуск с changed=0 — признак правильного плейбука.

Есть ли смысл в Ansible, если сервер всего один?

Да: плейбук — это всегда актуальная документация настройки плюс возможность пересоздать сервер за минуты после сбоя или при переезде. С выдачей VPS за 45–60 секунд у Cheap-Host полное окружение с нуля — вопрос пяти минут.

Чем Ansible лучше bash-скрипта настройки?

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

Какой VPS взять для практики с Ansible?

Для экспериментов — любой сервер с Ubuntu/Debian. Под реальные проекты у Cheap-Host подойдёт Pro за 750 ₽/мес: 12 vCPU, 16 ГБ RAM, NVMe — с запасом для приложений, которые вы будете разворачивать плейбуками.

Вывод

Ansible превращает настройку серверов из ремесла в код: inventory описывает, где применять, playbook — что должно быть, а идемпотентность гарантирует, что повторный запуск ничего не сломает. Начните с плейбука базовой настройки из этой статьи, положите его в git — и каждый следующий сервер будет готов за минуты, а не за вечер. Если нужны серверы для практики или продакшена — у Cheap-Host VPS Pro от 750 ₽/мес: KVM с полным root, NVMe, безлимитный трафик и деплой за минуту, а апгрейд CPU/RAM проходит без потери данных. Тарифы — на cheap-host.onl.

Читайте также