Когда у вас один сервер, его можно настроить вручную. Когда их десять — это уже утомительно. Когда сто — без автоматизации не обойтись. Infrastructure as Code (IaC) — это подход, при котором инфраструктура описывается в виде кода, который можно версионировать, тестировать и многократно применять. Ansible — один из самых популярных инструментов для реализации IaC, который не требует установки агентов на целевые серверы и использует простой язык YAML.
В этой статье мы подробно разберём:
- Что такое Infrastructure as Code и зачем он нужен.
- Что такое Ansible, его архитектура и преимущества.
- Установку и настройку Ansible.
- Инвентарь (Inventory) — описание серверов.
- Плейбуки (Playbooks) — сценарии автоматизации.
- Модули, переменные, шаблоны, условия и циклы.
- Роли (Roles) — структурирование плейбуков.
- Ansible Vault — хранение секретов.
- Практические примеры: настройка веб-сервера, деплой приложения.
- Интеграцию с CI/CD.
- Лучшие практики и частые ошибки.
1. Что такое Infrastructure as Code (IaC)
Infrastructure as Code — это практика управления инфраструктурой (серверы, сети, базы данных, балансировщики) через машиночитаемые файлы конфигурации, а не через ручные операции или интерактивные панели.
Преимущества IaC:
- Воспроизводимость — одна и та же конфигурация применяется к разным серверам.
- Версионирование — конфигурация хранится в Git, можно откатывать изменения.
- Документация — код сам документирует, что и как настроено.
- Скорость — развёртывание нового сервера занимает минуты, а не часы.
- Снижение ошибок — исключается человеческий фактор.
- Масштабирование — легко добавить новые серверы.
Инструменты IaC:
- Ansible — безагентный, простой, на YAML.
- Terraform — для управления облачными ресурсами (AWS, Yandex Cloud, DigitalOcean).
- Puppet — требует агентов, сложнее.
- Chef — тоже требует агентов, используется реже.
- SaltStack — мощный, но сложный.
Мы сосредоточимся на Ansible, так как он наиболее дружелюбен для начинающих и не требует установки агентов на серверы.
2. Что такое Ansible
Ansible — это open-source инструмент для автоматизации настройки, управления конфигурациями и развёртывания приложений. Он был создан в 2012 году и сейчас поддерживается Red Hat.
2.1 Архитектура Ansible
Ansible работает по модели push: управляющая машина (control node) подключается к целевым серверам (managed nodes) по SSH и выполняет задачи.
Компоненты:
- Control node — машина, с которой запускается Ansible (обычно ваш компьютер или CI-сервер).
- Managed nodes — целевые серверы, которыми управляют.
- Inventory — файл со списком серверов и их группировкой.
- Playbook — YAML-файл с описанием задач.
- Module — единица работы (установка пакета, копирование файла, запуск сервиса).
- Role — структурированный набор плейбуков, шаблонов и переменных.
- Ansible Vault — шифрование секретов.
Ключевая особенность: Ansible не требует установки агента на целевые серверы. Всё, что нужно — SSH и Python (обычно уже установлен).
2.2 Преимущества Ansible
- Безагентность — не нужно ставить и обновлять агенты.
- Простота — YAML-синтаксис, легко читается.
- Идемпотентность — повторный запуск не меняет состояние, если всё уже настроено.
- Мощность — более 3000 модулей для разных задач.
- Интеграция — работает с облаками, Docker, Kubernetes, CI/CD.
3. Установка Ansible
3.1 Установка на Ubuntu/Debian
sudo apt update
sudo apt install ansible
ansible --version3.2 Установка на CentOS/RHEL/Rocky Linux
sudo dnf install epel-release
sudo dnf install ansible
ansible --version3.3 Установка на macOS
brew install ansible3.4 Установка через pip (универсальный способ)
sudo apt install python3-pip
pip3 install ansible3.5 Настройка SSH-доступа
Ansible подключается к серверам по SSH. Убедитесь, что у вас есть SSH-ключи и доступ к целевым серверам.
Генерация ключа (если ещё нет):
ssh-keygen -t ed25519Копирование ключа на сервер:
ssh-copy-id user@serverПроверка подключения:
ssh user@serverВАЖНО! Если при запуске Ansible появляется ошибка «Permission denied (publickey)», проверь, добавлен ли ключ в ssh-agent:
ssh-add ~/.ssh/id_ed255194. Инвентарь (Inventory)
Inventory — это файл, в котором перечислены серверы, сгруппированные по назначению.
4.1 Простой инвентарь
Создайте файл inventory.ini:
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
[all:vars]
ansible_user=admin
ansible_ssh_private_key_file=~/.ssh/id_ed25519
Проверка доступности:
ansible all -i inventory.ini -m pingЕсли всё настроено правильно, вы увидите:
text
web1.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
4.2 Группы и подгруппы
ini
[webservers]
web1.example.com
web2.example.com
[webservers:children]
web_prod
web_stage
[web_prod]
prod-web1.example.com
prod-web2.example.com
[web_stage]
stage-web1.example.com
4.3 Динамический инвентарь
Ansible может получать список серверов из облака (AWS, Yandex Cloud) через плагины. Например, для AWS:
ansible-inventory -i aws_ec2.yml --graphГде aws_ec2.yml — файл конфигурации плагина.
Пример для AWS:
plugin: aws_ec2
regions:
- us-east-1
filters:
tag:Environment: production
keyed_groups:
- key: tags.Role
prefix: role5. Плейбуки (Playbooks)
Playbook — это YAML-файл, который описывает, какие задачи выполнить на каких серверах.
5.1 Структура плейбука
---
- name: Установка и настройка Nginx
hosts: webservers
become: yes
tasks:
- name: Обновление кеша apt
apt:
update_cache: yes
- name: Установка Nginx
apt:
name: nginx
state: present
- name: Запуск и включение Nginx
systemd:
name: nginx
state: started
enabled: yesРазбор:
name— описание плейбука.hosts— группа серверов из инвентаря.become: yes— выполнять задачи от root (аналог sudo).tasks— список задач.- Каждая задача использует модуль (apt, systemd) и параметры.
5.2 Запуск плейбука
ansible-playbook -i inventory.ini playbook.ymlПроверка без изменений (dry run):
ansible-playbook -i inventory.ini playbook.yml --checkПросмотр различий:
ansible-playbook -i inventory.ini playbook.yml --diff5.3 Идемпотентность
Ansible гарантирует, что повторный запуск плейбука не изменит систему, если она уже в нужном состоянии. Это называется идемпотентностью.
Например, если Nginx уже установлен, модуль apt не будет ничего делать и вернёт changed: false.
6. Модули, переменные, шаблоны, условия и циклы
6.1 Модули
Ansible имеет тысячи модулей. Вот самые популярные:
| Модуль | Назначение |
|---|---|
apt / yum / dnf | Управление пакетами |
copy | Копирование файлов |
template | Копирование с подстановкой переменных |
file | Управление файлами и директориями |
systemd / service | Управление сервисами |
user / group | Управление пользователями и группами |
git | Клонирование репозиториев |
command / shell | Выполнение команд |
docker_container | Управление Docker-контейнерами |
mysql_db / mysql_user | Управление MySQL |
Пример с модулем copy:
- name: Копирование конфигурации Nginx
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
notify: reload nginx6.2 Переменные
Переменные позволяют параметризовать плейбуки.
- name: Установка пакетов
hosts: webservers
vars:
packages:
- nginx
- php8.1-fpm
- mysql-client
tasks:
- name: Установка пакетов
apt:
name: "{{ packages }}"
state: presentПеременные можно задавать в:
varsв плейбуке.- Отдельных файлах (
vars/main.ymlв роли). - Инвентаре (групповые и хостовые переменные).
- Командной строке (
-e "var=value").
6.3 Шаблоны (Templates)
Шаблоны — это файлы с подстановкой переменных. Используется Jinja2.
Пример шаблона templates/nginx.conf.j2:
server {
listen 80;
server_name {{ server_name }};
root {{ document_root }};
location / {
try_files $uri $uri/ =404;
}
}Использование в плейбуке:
- name: Генерация конфигурации Nginx
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/{{ server_name }}.conf
notify: reload nginx6.4 Условия (when)
- name: Установка пакета только на Ubuntu
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"Другие примеры:
- name: Запуск только если файл существует
command: /opt/script.sh
when: ansible_facts['distribution'] == "Ubuntu"6.5 Циклы (loop)
- name: Создание пользователей
user:
name: "{{ item }}"
state: present
loop:
- user1
- user2
- user3С переменными:
- name: Установка пакетов
apt:
name: "{{ item }}"
state: present
loop: "{{ packages }}"6.6 Обработчики (Handlers)
Обработчики выполняются только при изменении задачи.
tasks:
- name: Копирование конфигурации
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: reload nginx
handlers:
- name: reload nginx
systemd:
name: nginx
state: reloaded7. Роли (Roles)
Роли — это способ структурировать плейбуки для повторного использования.
7.1 Структура роли
roles/
└── nginx/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── templates/
│ └── nginx.conf.j2
├── files/
│ └── index.html
├── vars/
│ └── main.yml
├── defaults/
│ └── main.yml
└── meta/
└── main.yml
7.2 Создание роли
ansible-galaxy init roles/nginx7.3 Пример роли для Nginx
roles/nginx/tasks/main.yml:
---
- name: Установка Nginx
apt:
name: nginx
state: present
- name: Копирование конфигурации
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify: reload nginx
- name: Запуск Nginx
systemd:
name: nginx
state: started
enabled: yesroles/nginx/handlers/main.yml:
---
- name: reload nginx
systemd:
name: nginx
state: reloadedroles/nginx/defaults/main.yml:
server_name: example.com
document_root: /var/www/html7.4 Использование роли в плейбуке
- name: Настройка веб-сервера
hosts: webservers
become: yes
roles:
- nginxИли с передачей переменных:
- name: Настройка веб-сервера
hosts: webservers
become: yes
roles:
- role: nginx
vars:
server_name: mysite.com
document_root: /var/www/mysite7.5 Ansible Galaxy
Ansible Galaxy — это репозиторий готовых ролей. Можно скачать и использовать.
# Поиск роли
ansible-galaxy search nginx
# Установка роли
ansible-galaxy install geerlingguy.nginxУстановка из файла requirements.yml:
roles:
- geerlingguy.nginx
- geerlingguy.mysqlansible-galaxy install -r requirements.yml8. Ansible Vault — хранение секретов
Vault позволяет шифровать пароли, ключи и другие секреты.
8.1 Создание зашифрованного файла
ansible-vault create secrets.ymlВас попросят ввести пароль. Затем откроется редактор, где можно ввести секреты:
db_password: super_secret_password
api_key: my_api_key_123458.2 Просмотр и редактирование
ansible-vault view secrets.yml
ansible-vault edit secrets.yml8.3 Шифрование существующего файла
ansible-vault encrypt vars.yml8.4 Использование в плейбуке
- name: Использование секретов
hosts: dbservers
vars_files:
- secrets.yml
tasks:
- name: Создание базы данных
mysql_db:
name: mydb
login_user: root
login_password: "{{ db_password }}"8.5 Запуск с паролем
ansible-playbook playbook.yml --ask-vault-passИли через файл с паролем:
echo "my_vault_password" > .vault_pass
ansible-playbook playbook.yml --vault-password-file .vault_pass9. Практические примеры
9.1 Настройка LEMP-стека (Nginx, MySQL, PHP-FPM)
---
- name: Настройка LEMP-стека
hosts: webservers
become: yes
vars:
db_name: myapp
db_user: myuser
db_password: "{{ vault_db_password }}"
tasks:
- name: Обновление кеша apt
apt:
update_cache: yes
- name: Установка Nginx
apt:
name: nginx
state: present
- name: Установка MySQL
apt:
name: mysql-server
state: present
- name: Установка PHP и расширений
apt:
name:
- php8.1-fpm
- php8.1-mysql
- php8.1-curl
- php8.1-gd
state: present
- name: Создание базы данных
mysql_db:
name: "{{ db_name }}"
state: present
login_user: root
login_password: "{{ vault_db_root_password }}"
- name: Создание пользователя MySQL
mysql_user:
name: "{{ db_user }}"
password: "{{ db_password }}"
priv: "{{ db_name }}.*:ALL"
state: present
login_user: root
login_password: "{{ vault_db_root_password }}"
- name: Запуск сервисов
systemd:
name: "{{ item }}"
state: started
enabled: yes
loop:
- nginx
- mysql
- php8.1-fpm9.2 Деплой приложения из Git
---
- name: Деплой приложения
hosts: webservers
become: yes
vars:
app_dir: /var/www/myapp
repo_url: https://github.com/user/myapp.git
tasks:
- name: Клонирование репозитория
git:
repo: "{{ repo_url }}"
dest: "{{ app_dir }}"
version: main
force: yes
- name: Установка зависимостей Composer
command: composer install --no-dev --optimize-autoloader
args:
chdir: "{{ app_dir }}"
become_user: www-data
- name: Установка прав
file:
path: "{{ app_dir }}/storage"
owner: www-data
group: www-data
mode: '0775'
recurse: yes
- name: Настройка Nginx
template:
src: templates/app.conf.j2
dest: /etc/nginx/sites-available/myapp
notify: reload nginx
- name: Активация сайта
file:
src: /etc/nginx/sites-available/myapp
dest: /etc/nginx/sites-enabled/myapp
state: link
notify: reload nginx
handlers:
- name: reload nginx
systemd:
name: nginx
state: reloadedВАЖНО! Модуль composer не является стандартным, поэтому используем command. Для идемпотентности можно добавить register и проверять наличие vendor/autoload.php
9.3 Настройка Docker и запуск контейнеров
---
- name: Установка Docker
hosts: all
become: yes
tasks:
- name: Установка зависимостей
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
state: present
- name: Скачивание GPG-ключа Docker
ansible.builtin.get_url:
url: https://download.docker.com/linux/ubuntu/gpg
dest: /usr/share/keyrings/docker-archive-keyring.gpg
mode: '0644'
- name: Добавление репозитория Docker
lineinfile:
path: /etc/apt/sources.list.d/docker.list
line: "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
- name: Установка Docker
apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
state: present
- name: Запуск Docker
systemd:
name: docker
state: started
enabled: yes
- name: Установка Docker Compose
get_url:
url: https://github.com/docker/compose/releases/latest/download/docker-compose-Linux-x86_64
dest: /usr/local/bin/docker-compose
mode: '0755'10. Интеграция с CI/CD
Ansible отлично вписывается в пайплайны CI/CD.
10.1 Пример GitHub Actions
name: Deploy with Ansible
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Установка Ansible
run: sudo apt install ansible
- name: Настройка SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name: Запуск плейбука
run: |
echo "${{ secrets.VAULT_PASSWORD }}" > .vault_pass
chmod 600 .vault_pass
ansible-playbook -i inventory.ini playbook.yml --vault-password-file .vault_pass10.2 Пример GitLab CI
deploy:
stage: deploy
image: alpine/ansible
script:
- apk add openssh-client
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ansible-playbook -i inventory.ini playbook.yml
only:
- main11. Лучшие практики
- Храните всё в Git. Инвентарь, плейбуки, роли, переменные.
- Используйте роли. Не пишите всё в одном плейбуке.
- Шифруйте секреты. Ansible Vault.
- Пишите идемпотентные задачи. Повторный запуск не должен ломать систему.
- Проверяйте синтаксис.
ansible-playbook --syntax-check. - Используйте
--checkи--diff. Перед применением смотрите, что изменится.--checkне работает с некоторыми модулями (например,command,shellбез явной проверки состояния). - Логируйте. Ansible пишет логи в
/var/log/ansible.log(если настроено). - Не используйте
shellиcommand, если есть модуль. Модули идемпотентны. - Организуйте структуру.
group_vars/,host_vars/для переменных. - Тестируйте. Используйте Molecule для тестирования ролей.
Для реальных проектов лучше выносить переменные в group_vars/ и host_vars/:
group_vars/webservers.yml
---
php_version: "8.1"
wp_document_root: "/var/www/html"
ВАЖНО! В YAML нельзя использовать табы — только пробелы. Это одна из самых частых ошибок.
12. Частые ошибки
| Ошибка | Последствия | Решение |
|---|---|---|
Отсутствует become: yes | Задачи не выполняются (нет прав) | Добавьте become: yes на уровне плейбука или задачи. |
| Неправильный отступ в YAML | Синтаксическая ошибка | YAML чувствителен к отступам. Используйте пробелы (не табы). |
Использование shell вместо модуля | Неидемпотентность | Используйте модули, где возможно. |
| Секреты в открытом виде | Утечка | Используйте Ansible Vault. |
| Нет обработчика для перезапуска сервиса | Изменения не применяются | Добавьте notify и handlers. |
| Игнорирование ошибок | Плейбук падает | Используйте ignore_errors: yes, если ошибка допустима. |
| Неправильный инвентарь | Ansible не видит серверы | Проверьте синтаксис и доступность. |
| Отсутствует SSH-ключ | Ошибка подключения | Настройте ключи и ssh-agent. |
Освоив Ansible, вы сможете управлять десятками и сотнями серверов так же легко, как одним. Инфраструктура станет предсказуемой, а время на развёртывание сократится с часов до минут.
