Ansible — это инструмент с открытым исходным кодом, используемый для автоматизации задач по управлению, настройке и обслуживанию серверов или сетевых устройств.
Офицbальный сайт и документация: https://docs.ansible.com/
Ansible подключается к выбранным узлам (хостам) из вашего списка и выполняет поочередно задачи для приведения их в нужное состояние.
Преимущества:
Кроме того, у Ansible большое комьюнити, которое разрабатывает и поддерживает различные модули.
Основные области применения:
Необходимо понимать, что Ansible — всего лишь инструмент. Следует грамотно подходить к выбору инструмента в зависимости поставленных от задач. Скажем, теоретически Ansible можно использовать для управления конфигурациями k8s, однако для этих целей есть инструменты лучше: Helm, helmwave, kustomize. Другой пример — с помощью Ansible можно создавать виртуальные машины, контейнеры в облаках или гипервизорах, но тот же Terraform лучше подойдет для таких задач.
Ansible можно установить как отдельный пакет или через библиотеки Python
Установка Ansible под разные операционные системы описана в документации.
В этой статье в качестве универсального способа предлагаю использовать версию в контейнере. Это даст возможность выполнить запуск на любых операционных системах или в CI/CD c полностью идентичными готовыми настройками и не тратить время на установку дополнительных компонентов и конфигурацию.
Для этой инструкции создан специальный репозиторий с базовыми настройками и примерами: Ansible Sandbox. Можно использовать как песочницу для закрепления практик и экспериментов в Ansible.
vds
Подготовка:
Docker + docker-compose или аналоги, например, Podman — система управления контейнерами. Инструкции для установки: Docker или Podman.
git (необязательно) — система контроля версий, используется только в первой команде в этой инструкции. Альтернативный вариант — скачать и распаковать репозиторий вручную.
удаленный узел — хост, где планируется проводить эксперименты.
Для демонстрации я создал отдельный VPS в Timeweb Cloud:
Последовательно выполняем следующие действия.
Клонируем репозиторий
git clone https://github.com/timeweb-cloud-tutorials/ansible-sandbox.git
cd ansible-sandbox
Выполняем сборку и запуск:
docker compose up -d
Подключаемся к оболочке контейнера (заходим внутрь контейнера и работаем оттуда):
docker compose exec ansible bash
Проверяем версию:
ansible --version
На момент написания статьи установлена версия:
ansible [core 2.18.3]
config file = /srv/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.13/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.13.2 (main, Feb 25 2025, 02:24:34) [GCC 12.2.0] (/usr/local/bin/python3.13)
jinja version = 3.1.5
libyaml = True
В выводе информации видим путь до конфигурационного файла:
config file = /srv/ansible/ansible.cfg
В нем можно настроить некоторые параметры
[defaults]
inventory = ./hosts.yaml
host_key_checking = False
log_path = /var/log/ansible.log
vault_password_file = ./vault.key
force_color = 1
callback_result_format = yaml
[ssh_connection]
timeout = 10
retries = 2
server_alive_interval = 60
pipelining = True
ssh_args = "-o StrictHostKeyChecking=no"
scp_if_ssh = True
allow_world_readable_tmpfiles = True
Раздел [defaults]
inventory = ./hosts.yaml
— указывает путь до файла с хостами. Здесь храним информацию о всех управляемых хостах и их организацию в логические группы.
host_key_checking = False
— по умолчанию в Ansible включена проверка ключей хостов. Проверка ключей хостов защищает от подмены сервера. Не рекомендуется в прод-окружении, но удобно для разработки
log_path = /var/log/ansible.log
— путь до файла логов.
vault_password_file = ./vault.key
— путь до файла с мастер-паролем, используется для шифрования ansible vault.
force_color = 1
— вывод цветных логов для наглядности.
callback_result_format = yaml
— форматирует вывод результатов в YAML.
Некоторые параметры есть возможность задать в переменных окружения, например:
ANSIBLE_HOST_KEY_CHECKING=False
А такие параметры, как inventory
или vault_password_file
, можно задавать в команде запуска:
ansible-playbook ansible/debug.yaml -i ansible/hosts.yaml
Но базовые настройки удобнее и нагляднее хранить в файле ansible/ansible.cfg
.
Локально у нас уже есть готовый файл ansible/hosts.yaml
, нужно отредактировать его и записать свои устройства:
all:
vars:
ansible_user: ansible
hosts:
31.130.148.5: # your host IP or domain
ansible_user: root
# ansible_password: 'SuperPass'
ansible_ssh_private_key_file: ./ansible/ssh/id_rsa
В качестве точек подключения используется IP-адрес или доменное имя. В моем случае нет доменного имени, поэтому указываю внешний IP-адрес, полученный при создании виртуальной машины Timeweb Cloud. Обратите внимание, что пароль пользователя должен быть в кавычках.
Для подключения обычно используется пароль или сертификат (публичный ключ должен быть заранее установлен на удаленных узлах).
Для экспериментов проще использовать пароль; при использовании приватного ключа необходимо проверить разрешения на файл id_rsa
— только владелец имеет права на чтение, никто не может копировать или изменять ключ.
chmod -R 400 ./ansible/ssh/id_rsa
В файле ansible/hosts.yaml
для демонстрации установлена переменная vars.ansible_user
, а внутри hosts.ansible_user
такая же переменная, но значение переопределено на root
. Если не переопределять и задавать уровнем выше в vars, то можно не дублировать повторяющиеся переменные для разных хостов.
На данном этапе у нас запущен контейнер с Ansible и настроен файл hosts.yaml
в inventory
, где указаны хосты и данные для подключения.
Проверить, что все хосты доступны, можно с помощью встроенного модуля ping
:
ansible all -m ping
В ответ получаем pong
, что означает, что хост доступен и готов к работе.
Для начала рассмотрим обычные задачи (tasks), которые не будут делать изменения в системе, но помогут понять, как выглядит структура команд:
Локально есть готовый файл: ansible/debug.yaml
, это пример простого playbook.
Запустим его:
ansible-playbook ansible/debug.yaml
В выводе увидим различную системную информацию и по порядку изучим команды из файла ansible/debug.yaml
:
- hosts: all
vars:
my_variable: aaaawww
tasks:
- name: Show ansible variable
debug:
msg: "variable: {{ my_variable }}"
- name: Show environment variable
debug:
var: lookup('env', 'ANSIBLE_CONFIG')
- name: Show OS release info
debug:
msg: "{{ ansible_distribution }} {{ ansible_distribution_version}} {{ansible_distribution_release}}"
hosts
— на каких узлах (хостах) выполнять команды. Так как выше в файле ansible/hosts.yaml
мы указывали только один хост, все задачи будут выполняться на нем.vars
— можем задать переменные на уровне данного playbook.tasks
— последовательность задач для выполнения.Вывод переменной, которую задали в vars
:
- name: Show ansible variable
debug:
msg: "variable: {{ my_variable }}"
Вывод переменной из переменных окружения:
- name: Show environment variable
debug:
var: lookup('env', 'ANSIBLE_CONFIG')
Вывод информации об операционной системе и о CPU и RAM:
- name: Show OS release info
debug:
msg: "{{ ansible_distribution }} {{ ansible_distribution_version}} {{ansible_distribution_release}}"
- name: Show total CPU + RAM
debug:
msg: |
CPU cores: {{ ansible_processor_cores * ansible_processor_count }}
Total memory: {{ ansible_memtotal_mb }} MB"
Откуда Ansible берет эти данные?
По умолчанию, если не задано gather_facts: false
, Ansible первым делом при подключении к хосту автоматически собирает информацию о системе
Посмотреть всю информацию, которую получает Ansible, можно с помощью task:
tasks:
- name: Show all facts
debug:
var: ansible_facts
Сами task описываем с помощью модулей и его параметров:
name
— название task (любое)debug
— название модуля (из списка доступных, в зависимости от целей и задач)debug.var
— параметр модуля debug
В документации могут быть такие примеры:
tasks:
- name: Show all facts
ansible.builtin.debug:
var: ansible_facts
ansible.builtin.debug
— это тот же самый модуль debug
(можно сокращать, убирая приставку ansible.builtin
).
debug
и другие стандартные модули входят в ядро Ansible, посмотреть все встроенные модули можно в документации.
- name: Install packages
apt:
pkg:
- htop
- curl
По коду даже без документации можно понять что сделает данный task (установит пакеты htop
и curl
аналогично команде apt install -y htop curl
).
Цель: Проверить, что переменная my_age
содержит число в диапазоне от 18 до 100.
- name: Check var
hosts: all
vars:
my_age: 42
tasks:
- name: Checking the type of a variable
fail:
msg: "The variable must be an integer"
when: my_age is not integer
- name: The value of the my_age variable must be between 18 and 100
assert:
that:
- my_age <= 100
- my_age >= 18
fail_msg: "Incorrect my_age value - must be from 0 to 100"
success_msg: "The value of my_age is correct"
В начале задали переменную my_age = 42
.
В первой task проверяем с помощью when
, действительно ли переменная — целое число, если нет — завершаем и сообщаем об ошибке.
С помощью второй task проверяем, что входит в нужный диапазон.
При запуске playbook успешно отработает. Но попробуем переопределить переменную my_age
в команде запуска:
ansible-playbook ansible/playbooks/assert.yaml --extra-vars "{ my_age: 769 }"
Получаем ошибку и прерывание playbook:
TASK [The value of the my_age variable must be between 18 and 100] **************
fatal: [31.130.148.5]: FAILED! =>
assertion: my_age <= 100
changed: false
evaluated_to: false
msg: Incorrect my_age value - must be from 0 to 100
Циклы в Ansible называются loop (петля).
- hosts: all
tasks:
- name: Register loop output as a variable
shell: "echo {{ item }}"
loop:
- "test"
- "test2"
- "test3"
register: echo
В этой task команда echo
будет выполнена для каждого элемента из списка loop.
Дополнительные функции:
map
: это базовый цикл for; позволяет перебирать элементы в списке.select
/ reject
: это цикл for
с условием; позволяет создать подмножество списка, которое соответствует (или нет) заданным условиям.selectattr
/ rejectattr
: очень похоже на описанное выше, но использует определенный атрибут элементов списка для условного оператора.В данном примере выберем из списка только фрукты красного цвета, используя selectattr
.
- hosts: all
vars:
fruits_list:
- name: apple
color: red
- name: banana
color: yellow
- name: cherry
color: red
tasks:
- name: Selectattr show red fruits
debug:
msg: "{{ item.name }} is red."
loop: "{{ fruits_list | selectattr('color', '==', 'red') | list }}"
Другие примеры, включая map
, будут в файле ansible/playbooks/selectattr.yaml
.
Playbook ansible/playbooks/copy.yaml
- name: Copy files to remote locations
hosts: all
tasks:
- name: Copy file with owner and permissions
copy:
src: ../files
dest: /tmp
owner: root
group: root
mode: '0644'
Данный task копирует директорию из ansible/files
на удаленный хост в /tmp/files
.
В параметрах src
, если путь является каталогом, он копируется рекурсивно. В случае, если путь заканчивается на /
, в путь назначения (dest
) копируется только внутреннее содержимое этого каталога. Это поведение аналогично работе инструмента rsync
.
Когда нужно наоборот скопировать данные из удаленного хоста к себе, используется модуль fetch. Документация по модулю.
Шаблоны позволяют создавать динамические файлы, автоматически подставляя в них значения переменных. Используется шаблонизатор Jinja2.
Пример файла шаблона ansible/files/simple_template.j2
(файлы шаблонов не обязательно должны быть в расширении *.j2
, это просто рекомендуемый формат для обозначения jinja-шаблонов):
# This is a simple example of using a template.
name: {{ name }}
task: {{ task }}
При запуске плейбука передаем переменные name и task:
- name: Template a file out to a target host
hosts: all
tasks:
- name: Simple template a file
template:
src: ../files/simple_template.j2
dest: /tmp/test.conf
vars:
name: "Ansible"
task: "Template"
Получаем на удаленном хосте файл:
Дополнительные примеры использования templates можно найти в файле ansible/playbooks/templates.yaml
.
Готовый онлайн-сервис для создания и проверки шаблонов: tech-playground.com
Основной способ запуска и использования Ansible — это командная строка, но также есть проекты, которые добавляют графический интерфейс для управления разными задачами. Основные из них:
Ansible AWX (бесплатная Apache License 2.0)
Red Hat Ansible Tower (коммерческая)
Semaphore (бесплатная MIT License)
Веб-интерфейс Semaphore UI
Инструменты автоматизации инфраструктуры можно разделить на две основные категории:
Их основная задача — настройка и управление программным обеспечением на уже существующих серверах . Эти системы автоматизируют процесс установки ПО, обновления пакетов и настройки системных параметров.
Они отвечают за создание самой инфраструктуры: от виртуальных машин до сетевых настроек и баз данных. Это более широкий подход к автоматизации, который начинается с самого фундамента IT-системы.
Инструменты можно комбинировать, наиболее часто встречается связка Terraform + Ansible.
Основные особенности инструментов, на основе отзывов на форумах и Телеграм-каналов:
Ansible
Chef
SaltStack
Puppet
В любом случае изучение автоматизации инфраструктуры рекомендую начинать с Ansible.
Надежные VDS/VPS для ваших проектов
В статье я постарался максимально наглядно показать встроенные модули и базовые примеры использования Ansible, однако самым эффективным способом изучения таких инструментов является практика. Навыки владения Ansible часто требуются в вакансиях системных администраторов, инженеров DevOps, SRE.
Следующие шаги для изучения:
Проект Ansible-Sandbox постараюсь поддерживать в актуальном состоянии и добавлять новые и более сложные примеры. Желающих помочь просьба присоединиться и предложить в PR свои примеры, роли, плейбуки или другие полезные материалы.