Ansible — это инструмент с открытым исходным кодом, используемый для автоматизации задач по управлению, настройке и обслуживанию серверов или сетевых устройств.
Официальный сайт и документация: https://docs.ansible.com/
Основные принципы работы Ansible
Ansible подключается к выбранным узлам (хостам) из вашего списка и выполняет поочередно задачи для приведения их в нужное состояние.
- playbook — файл с описанием задач и их последовательности
 - task — задача, отдельное действие для проверки или выполнения
 - inventory — группировка и список управляемых узлов (хостов)
 
Преимущества:
- Самый простой и мощный инструмент для автоматизаций
 - Не требует установки дополнительного ПО на управляемых узлах (для работы необходим только Python, который обычно доступен «из коробки»)
 - Использует стандартный протокол SSH для подключения
 - Выполняются только необходимые изменения
 - Операции можно безопасно выполнять повторно (система не будет делать лишних изменений)
 - Гарантируется консистентное состояние системы
 - Позволяет удобно и понятно описывать инфраструктуру
 
Кроме того, у Ansible большое комьюнити, которое разрабатывает и поддерживает различные модули.
Где используется Ansible?
Основные области применения:
- Подготовка и настройка систем
 - Массовое развертывание ПО, управление пакетами и сервисами
 - Автоматизация CI/CD-процессов
 - Конфигурация сетевых устройств (управление сетью)
 - Аудит систем, применение политик безопасности и автоматическое приведение в соответствие
 
Необходимо понимать, что Ansible — всего лишь инструмент. Следует грамотно подходить к выбору инструмента в зависимости поставленных от задач. Скажем, теоретически Ansible можно использовать для управления конфигурациями k8s, однако для этих целей есть инструменты лучше: Helm, helmwave, kustomize. Другой пример — с помощью Ansible можно создавать виртуальные машины, контейнеры в облаках или гипервизорах, но тот же Terraform лучше подойдет для таких задач.
Как установить и настроить Ansible?
Ansible можно установить как отдельный пакет или через библиотеки Python.
Установка Ansible под разные операционные системы описана в документации.
В этой статье в качестве универсального способа предлагаю использовать версию в контейнере. Это даст возможность выполнить запуск на любых операционных системах или в CI/CD c полностью идентичными готовыми настройками и не тратить время на установку дополнительных компонентов и конфигурацию.
Для этой инструкции создан специальный репозиторий с базовыми настройками и примерами: Ansible Sandbox. Можно использовать как песочницу для закрепления практик и экспериментов в Ansible.
vds
Установка
Подготовка:
- 
Docker + docker-compose или аналоги, например, Podman — система управления контейнерами. Инструкции для установки: Docker или Podman.
 - 
git (необязательно) — система контроля версий, используется только в первой команде в этой инструкции. Альтернативный вариант — скачать и распаковать репозиторий вручную.
 - 
удаленный узел — хост, где планируется проводить эксперименты.
 
Для демонстрации я создал отдельный VPS в Timeweb Cloud:
- ОС: Ubuntu 24.04
 - Регион: Москва
 - CPU: 1 x 3.3 ГГц
 - RAM: 1 ГБ
 - NVMe: 15 ГБ
 
Последовательно выполняем следующие действия.
Клонируем репозиторий
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: ключевые файлы и параметры
На момент написания статьи установлена версия:
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 Inventory – как управлять хостами
Локально у нас уже есть готовый файл 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, посмотреть все встроенные модули можно в документации.
Пример модуля apt (менеджер пакетов Debian/Ubuntu)
    - name: Install packages
      apt:
        pkg:
          - htop
          - curl
По коду даже без документации можно понять что сделает данный task (установит пакеты htop и curl аналогично команде apt install -y htop curl).
Проверка переменных с использованием when assert
Цель: Проверить, что переменная 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: очень похоже на описанное выше, но использует определенный атрибут элементов списка для условного оператора.
Ansible selectattr – фильтрация данных в плейбуках
В данном примере выберем из списка только фрукты красного цвета, используя 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.
Пример модуля copy
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. Документация по модулю.
Пример модуля template
Шаблоны позволяют создавать динамические файлы, автоматически подставляя в них значения переменных. Используется шаблонизатор 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 Web UI
Основной способ запуска и использования Ansible — это командная строка, но также есть проекты, которые добавляют графический интерфейс для управления разными задачами. Основные из них:
- 
Ansible AWX (бесплатная Apache License 2.0)
 - 
Red Hat Ansible Tower (коммерческая)
 - 
Semaphore (бесплатная MIT License)
 
Ansible и другие системы автоматизации
Инструменты автоматизации инфраструктуры можно разделить на две основные категории:
- Инструменты управления конфигурацией:
 
- 
- Ansible
 - Chef
 - SaltStack
 - Puppet
 
 
Их основная задача — настройка и управление программным обеспечением на уже существующих серверах . Эти системы автоматизируют процесс установки ПО, обновления пакетов и настройки системных параметров.
- Инструменты обеспечения:
 
- 
- Terraform
 - Pulumi
 
 
Они отвечают за создание самой инфраструктуры: от виртуальных машин до сетевых настроек и баз данных. Это более широкий подход к автоматизации, который начинается с самого фундамента IT-системы.
Инструменты можно комбинировать, наиболее часто встречается связка Terraform + Ansible.
Основные особенности инструментов, на основе отзывов на форумах и Телеграм-каналов:
Ansible
- Самый простой для начала работы.
 - Не требует установки дополнительного ПО на управляемые узлы, кроме Python.
 - Использует стандартный SSH-протокол для подключения.
 
Chef
- Использует метафоры приготовления пищи (recipes, cookbooks).
 - Хорошо подходит для сложных инфраструктур.
 - Сильная поддержка тестирования конфигураций.
 - Требует больше времени на изучение.
 
SaltStack
- Высокая производительность благодаря оптимизированной архитектуре.
 - Подходит для больших масштабных решений.
 - Использует Python для написания модулей.
 - Хорошо работает в распределенных системах.
 
Puppet
- Мощный инструмент для крупных предприятий.
 - Хорошо документирован.
 - Сложнее в освоении, но очень мощный.
 - Отлично подходит для стандартизации конфигураций.
 
В любом случае изучение автоматизации инфраструктуры рекомендую начинать с Ansible.
Надежные VDS/VPS для ваших проектов
Итоги
В статье я постарался максимально наглядно показать встроенные модули и базовые примеры использования Ansible, однако самым эффективным способом изучения таких инструментов является практика. Навыки владения Ansible часто требуются в вакансиях системных администраторов, инженеров DevOps, SRE.
Следующие шаги для изучения:
- Роли
 - Шифрование ansible-vault
 - Community Collections
 
Проект Ansible-Sandbox постараюсь поддерживать в актуальном состоянии и добавлять новые и более сложные примеры. Желающих помочь просьба присоединиться и предложить в PR свои примеры, роли, плейбуки или другие полезные материалы.