2.5 Ansible: Автоматизация конфигурации

2.5 Ansible: Автоматизация конфигурации #

📚 Градация сложности изучения Ansible:

  • 🟢 Новичок (0-3 месяца): Ad-hoc команды, простые playbook’и, inventory
  • 🟡 Базовый (3-6 месяцев): Roles, variables, templates, handlers
  • 🟠 Средний (6-12 месяцев): Vault, Galaxy, custom modules, testing
  • 🔴 Продвинутый (1+ год): AWX/Tower, collections, CI/CD интеграция

🟢 Что такое Ansible (простыми словами) #

Ansible — это как “умный помощник” для настройки серверов. Представьте, что вам нужно настроить 100 серверов одинаково: установить пакеты, создать пользователей, настроить конфигурации. Ansible делает это автоматически по заранее написанному “рецепту”.

Ключевые особенности:

  • Agentless — не требует установки агентов на управляемые хосты
  • Idempotent — можно запускать много раз, результат будет одинаковый
  • YAML синтаксис — простой и читаемый формат
  • SSH соединение — использует стандартные протоколы

🛠️ Установка Ansible #

Ubuntu/Debian (обновлено для 2025) #

Команды для установки Ansible на Ubuntu/Debian:

Метод 1: Через официальный PPA (рекомендуется):

  • Обновление списка пакетов
  • Установка дополнительных компонентов
  • Добавление официального репозитория Ansible
  • Установка пакета Ansible

Метод 2: Через pip (для последней версии):

  • Установка pip для Python 3
  • Установка Ansible через pip для текущего пользователя

Метод 3: Через snap:

  • Установка Ansible как snap-пакет с классическими правами

Проверка установки:

  • Проверка версии Ansible и ansible-playbook

macOS #

Команды для установки Ansible на macOS:

Через Homebrew:

  • Установка Ansible с помощью менеджера пакетов Homebrew

Через pip:

  • Установка Ansible через pip для Python 3

Windows (WSL2) #

Команды для установки Ansible на Windows:

В WSL2 Ubuntu (рекомендуется):

  • Запуск WSL2
  • Обновление пакетов и установка Ansible в Ubuntu подсистеме

Через pip в PowerShell:

  • Прямая установка Ansible через pip в Windows PowerShell

🟢 Ваш первый Ansible команда (Hello World) #

Начнем с самого простого примера:

Первые команды Ansible для начинающих:

Проверка подключения к localhost:

  • Команда использует модуль ping для проверки связи
  • Результат: JSON с полем “ping”: “pong” и статусом SUCCESS

Выполнение команды на удаленном хосте:

  • Использование модуля command для выполнения echo команды
  • Вывод сообщения “Hello Ansible!” на целевом хосте

Получение информации о системе:

  • Модуль setup собирает факты о системе
  • Фильтрация результата для отображения информации об ОС

Что только что произошло?

  1. Ansible подключился к localhost через SSH
  2. Выполнил модуль ping для проверки связи
  3. Вернул результат в JSON формате

📋 Основные концепции Ansible #

🟢 Ключевые компоненты (простыми словами) #

Inventory — “список серверов” которыми управляет Ansible
Playbook — “рецепт” действий для выполнения на серверах
Module — “инструмент” для выполнения конкретной задачи
Task — “шаг” в рецепте
Role — “готовый набор” рецептов для типичных задач

Базовая архитектура #

Базовая архитектура Ansible:

Control Node (управляющая машина):

  • ansible.cfg - конфигурационный файл
  • inventory.ini - список управляемых серверов
  • playbook.yml - сценарии автоматизации
  • roles/ - переиспользуемые компоненты
    • webserver/ - роль веб-сервера
      • tasks/ - задачи для выполнения
      • templates/ - шаблоны конфигураций
      • vars/ - переменные
      • handlers/ - обработчики событий

Соединение: SSH подключения к управляемым узлам

Managed Nodes (управляемые серверы):

  • web1.example.com - первый веб-сервер
  • web2.example.com - второй веб-сервер
  • db1.example.com - сервер базы данных

📝 Inventory: Управление хостами #

Простой inventory файл #

Пример простого inventory файла в INI формате:

Одиночные хосты:

  • web1.example.com
  • db1.example.com

Группы хостов:

  • Группа webservers: web1, web2, web3.example.com
  • Группа databases: db1, db2.example.com

Группы групп:

  • production: объединяет webservers и databases

Переменные для групп:

  • webservers: http_port=80, max_connections=200
  • databases: mysql_port=3306

Продвинутый inventory (YAML формат) #

Продвинутый inventory в YAML формате:

Структура:

  • all: корневая группа всех хостов
    • children: дочерние группы

Группа webservers:

  • web1.example.com: IP 192.168.1.10, пользователь deploy, приватный ключ
  • web2.example.com: IP 192.168.1.11, пользователь deploy
  • Переменные: http_port=80, nginx_version=1.24

Группа databases:

  • db1.example.com: IP 192.168.1.20, пароль из Vault
  • Переменные: mysql_port=3306

Группа production:

  • Объединяет webservers и databases
  • Переменные: environment=prod, backup_enabled=true

Динамический inventory (для облачных провайдеров) #

Настройка динамического inventory для AWS EC2:

Подготовка:

  • Установка библиотеки boto3 для работы с AWS
  • Настройка переменных окружения AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY

Использование:

  • Просмотр списка всех EC2 инстансов через динамический inventory
  • Проверка доступности всех хостов через ping

🎭 Playbooks: Автоматизация задач #

🟢 Простой playbook для новичков #

Пример простого playbook для новичков:

Основные параметры:

  • Название: “Мой первый playbook”
  • Целевые хосты: localhost
  • Права: выполнение с sudo

Список задач:

  1. Обновление кэша пакетов - только для Debian-основанных систем
  2. Установка базовых пакетов:
    • curl - утилита для HTTP-запросов
    • wget - утилита для скачивания файлов
    • git - система контроля версий
    • htop - улучшенный монитор процессов
  3. Создание пользователя deploy:
    • Оболочка: /bin/bash
    • Создание домашней директории
    • Добавление в группу sudo
  4. Вывод сообщения - подтверждение успешного выполнения

Команды для запуска playbook:

Обычный запуск:

  • Выполнение всех задач из файла first-playbook.yml

Запуск с дополнительными опциями:

  • -i inventory.ini: указание конкретного inventory файла
  • –check: режим “сухого прогона” (проверка без выполнения)
  • –diff: показ различий в файлах
  • -v: подробный вывод (режим verbose)

🟡 Продвинутый playbook с переменными #

Продвинутый playbook для настройки веб-сервера Nginx:

Основные параметры:

  • Название: “Настройка веб-сервера Nginx”
  • Целевые хосты: группа webservers
  • Права: выполнение с sudo

Переменные:

  • nginx_version: “1.24” - версия Nginx
  • app_name: “myapp” - имя приложения
  • app_port: 3000 - порт приложения
  • ssl_enabled: true - включение SSL
  • Импорт зашифрованных переменных из vars/secrets.yml

Предварительные задачи:

  • Обновление системы: обновление кэша и дистрибутива (тег system_update)

Основные задачи:

  1. Установка Nginx с уведомлением restart nginx
  2. Настройка конфигурации из шаблона nginx.conf.j2 (тег config)
  3. Активация сайта через симлинк
  4. Открытие портов 80 и 443 в firewall (только при ssl_enabled)
  5. Проверка синтаксиса Nginx конфигурации

Обработчики событий:

  • restart nginx: полная перезагрузка сервиса
  • reload nginx: перезагрузка конфигурации без остановки

Заключительные задачи:

  • HTTP-проверка работоспособности Nginx (выполняется на localhost)

Template файл для Nginx #

Пример шаблона Nginx конфигурации (templates/nginx.conf.j2):

HTTP серверный блок:

  • Прослушивание порта 80
  • Имя сервера: IP-адрес хоста (ansible_default_ipv4.address)

Условное перенаправление на HTTPS (если ssl_enabled):

  • Автоматическое перенаправление HTTP на HTTPS (301 redirect)

HTTPS серверный блок (если SSL включен):

  • Прослушивание порта 443 с SSL и HTTP/2
  • SSL сертификат: /etc/ssl/certs/{{ app_name }}.crt
  • SSL ключ: /etc/ssl/private/{{ app_name }}.key

Настройка reverse proxy:

  • Проксирование на локальный порт app_port (127.0.0.1:3000)
  • Передача заголовков: Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto

Настройки производительности:

  • proxy_connect_timeout, proxy_send_timeout, proxy_read_timeout: 60 секунд

Логирование:

  • access_log: /var/log/nginx/{{ app_name }}_access.log
  • error_log: /var/log/nginx/{{ app_name }}_error.log

Безопасность:

  • X-Frame-Options DENY - защита от clickjacking
  • X-Content-Type-Options nosniff - предотвращение MIME sniffing
  • X-XSS-Protection “1; mode=block” - защита от XSS атак

🎭 Roles: Переиспользуемые компоненты #

Создание роли #

Создание структуры роли Ansible:

Команда создания:

  • Использование ansible-galaxy init для создания шаблона роли webserver

Структура созданной роли:

  • webserver/ - корневая директория роли
    • defaults/main.yml - переменные по умолчанию
    • files/ - статические файлы для копирования
    • handlers/main.yml - обработчики событий
    • meta/main.yml - метаданные и зависимости роли
    • tasks/main.yml - основные задачи для выполнения
    • templates/ - шаблоны Jinja2 для конфигураций
    • tests/ - тесты для проверки роли
    • vars/main.yml - переменные роли

🟠 Продвинутая роль webserver #

Продвинутая структура роли webserver (roles/webserver/tasks/main.yml):

Модульная структура задач:

  1. Установка зависимостей - включение install.yml (тег install)
  2. Настройка Nginx - включение configure.yml (тег config)
  3. Настройка SSL сертификатов - включение ssl.yml (тег ssl)
    • Условие: выполняется только при ssl_enabled = true
  4. Настройка мониторинга - включение monitoring.yml (тег monitoring)
    • Условие: выполняется по умолчанию (можно отключить)

Файл установки зависимостей (roles/webserver/tasks/install.yml):

Последовательность установки:

  1. Добавление репозитория:

    • Добавление PPA репозитория “ppa:nginx/stable”
    • Условие: только для Ubuntu
  2. Установка Nginx:

    • Установка пакета nginx через менеджер пакетов
    • Регистрация результата в переменной nginx_installed
  3. Установка дополнительных модулей:

    • nginx-module-geoip - модуль геолокации
    • nginx-module-image-filter - модуль обработки изображений
    • Условие: только при nginx_modules_enabled = true
  4. Создание системного пользователя:

    • Имя: app_user (по умолчанию ‘www-data’)
    • Системный аккаунт с оболочкой /bin/false
    • Без создания домашней директории
# roles/webserver/defaults/main.yml
---
# Основные настройки
nginx_version: "1.24"
app_name: "myapp"
app_port: 3000
app_user: "www-data"

# SSL настройки
ssl_enabled: false
ssl_cert_path: "/etc/ssl/certs"
ssl_key_path: "/etc/ssl/private"

# Производительность
nginx_worker_processes: "auto"
nginx_worker_connections: 1024
nginx_keepalive_timeout: 65

# Безопасность
nginx_server_tokens: "off"
nginx_hide_version: true

# Мониторинг
monitoring_enabled: true
log_level: "warn"

# Переменные окружения
environments:
  development:
    log_level: "debug"
    ssl_enabled: false
  production:
    log_level: "error"
    ssl_enabled: true
    monitoring_enabled: true
# roles/webserver/handlers/main.yml
---
- name: restart nginx
  service:
    name: nginx
    state: restarted
  listen: "restart web services"

- name: reload nginx
  service:
    name: nginx
    state: reloaded
  listen: "reload web services"

- name: validate nginx config
  command: nginx -t
  register: nginx_syntax
  failed_when: nginx_syntax.rc != 0
  listen: "validate config"

Использование роли в playbook #

# site.yml
---
- name: Настройка веб-серверов
  hosts: webservers
  become: yes
  vars:
    environment_name: production
    
  roles:
    - role: webserver
      vars:
        app_name: "mywebapp"
        app_port: 8080
        ssl_enabled: true
        nginx_worker_processes: 4
      tags: web
      
    - role: monitoring
      vars:
        services_to_monitor:
          - nginx
          - mywebapp
      tags: monitoring

🔐 Ansible Vault: Безопасное хранение секретов #

Создание и использование Vault #

Команды для работы с Ansible Vault:

Создание зашифрованного файла:

  • Создание нового зашифрованного файла vars/secrets.yml

Редактирование:

  • Открытие зашифрованного файла для редактирования

Шифрование существующих файлов:

  • Шифрование уже созданного файла vars/database.yml

Расшифрование:

  • Полное расшифрование файла в обычный текст

Просмотр:

  • Просмотр содержимого без сохранения в расшифрованном виде

Пример зашифрованных переменных #

# vars/secrets.yml (зашифровано)
---
# Database credentials
db_root_password: "SuperSecretPassword123!"
db_app_password: "AppUserPassword456!"

# API keys
aws_access_key: "AKIAIOSFODNN7EXAMPLE"
aws_secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

# SSL certificates
ssl_private_key: |
  -----BEGIN PRIVATE KEY-----
  MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGHp...
  -----END PRIVATE KEY-----

Использование Vault в playbook #

# playbook-with-vault.yml
---
- name: Настройка базы данных
  hosts: databases
  become: yes
  vars_files:
    - vars/secrets.yml  # зашифрованный файл
    
  tasks:
    - name: Установить MySQL
      apt:
        name: mysql-server
        state: present
        
    - name: Настроить root пароль MySQL
      mysql_user:
        name: root
        password: "{{ db_root_password }}"
        login_unix_socket: /var/run/mysqld/mysqld.sock
        
    - name: Создать базу данных приложения
      mysql_db:
        name: "{{ app_name }}"
        state: present
        login_user: root
        login_password: "{{ db_root_password }}"

Запуск playbook с зашифрованными данными:

Метод 1: Интерактивный запрос пароля:

  • Использование опции –ask-vault-pass для ввода пароля во время выполнения

Метод 2: Использование файла с паролем:

  • Создание файла ~/.ansible_vault_pass с паролем
  • Использование опции –vault-password-file для автоматического чтения пароля

🧪 Тестирование Ansible #

Molecule для тестирования ролей #

Команды для тестирования Ansible ролей с Molecule:

Подготовка:

  • Установка Molecule с поддержкой Docker

Инициализация:

  • Переход в директорию роли webserver
  • Создание сценария тестирования с Docker драйвером

Полное тестирование:

  • Автоматическое выполнение всех этапов тестирования

Поэтапное тестирование:

  • create: создание тестового контейнера
  • converge: применение роли к тестовому окружению
  • verify: выполнение проверок и тестов
  • destroy: очистка тестового окружения

Molecule конфигурация #

# roles/webserver/molecule/default/molecule.yml
---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: ubuntu20
    image: ubuntu:20.04
    pre_build_image: true
    command: /sbin/init
    privileged: true
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
  - name: centos8
    image: centos:8
    pre_build_image: true
    command: /sbin/init
    privileged: true
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
provisioner:
  name: ansible
  inventory:
    host_vars:
      ubuntu20:
        app_name: test-app-ubuntu
      centos8:
        app_name: test-app-centos
verifier:
  name: ansible

Тесты с pytest и Testinfra #

Тестовый файл для проверки конфигурации Nginx с помощью Testinfra:

Этот тестовый модуль выполняет следующие проверки:

  1. Проверка установки - убеждается, что пакет Nginx установлен в системе
  2. Проверка статуса службы - проверяет, что Nginx запущен и включен для автозапуска
  3. Валидация конфигурации - запускает тест конфигурации Nginx (nginx -t)
  4. Проверка портов - убеждается, что Nginx слушает на порту 80
  5. HTTP тестирование - выполняет HTTP запрос для проверки отклика сервера

Тесты автоматически запускаются после применения роли и помогают убедиться в корректности развертывания.

🏭 Лучшие практики Ansible #

1. Структура проекта #

Рекомендуемая структура Ansible проекта:

Корневая директория ansible-project/:

  • ansible.cfg - основная конфигурация Ansible

inventory/ - списки серверов:

  • production/ - продакшен окружение
    • hosts.yml - список хостов
    • group_vars/ - переменные для групп
  • staging/ - тестовое окружение

roles/ - переиспользуемые роли:

  • common/ - общие настройки
  • webserver/ - конфигурация веб-серверов
  • database/ - настройка баз данных

playbooks/ - сценарии выполнения:

  • site.yml - основной playbook
  • webservers.yml - настройка веб-серверов
  • deploy.yml - развертывание приложений

vars/ - переменные:

  • secrets.yml - зашифрованные данные
  • common.yml - общие переменные

Дополнительно:

  • files/ - статические файлы
  • templates/ - шаблоны конфигураций
  • requirements.yml - список внешних ролей

2. ansible.cfg - оптимальная конфигурация #

Оптимальная конфигурация ansible.cfg:

Секция [defaults] - основные настройки:

  • inventory: путь к inventory файлу продакшена
  • remote_user: пользователь для подключения (deploy)
  • private_key_file: путь к SSH ключу
  • host_key_checking: отключение проверки ключей хостов
  • retry_files_enabled: отключение файлов повторных попыток
  • stdout_callback: использование YAML формата вывода
  • vault_password_file: файл с паролем для Vault

Настройки производительности:

  • forks: 50 параллельных процессов
  • poll_interval: интервал опроса 2 секунды
  • timeout: таймаут подключения 30 секунд
  • gather_timeout: таймаут сбора фактов 30 секунд

Логирование:

  • log_path: путь к лог-файлу
  • display_skipped_hosts: скрытие пропущенных хостов
  • display_ok_hosts: скрытие успешных хостов

Безопасность:

  • command_warnings: включение предупреждений о командах
  • deprecation_warnings: предупреждения об устаревших функциях

Секция [ssh_connection] - SSH настройки:

  • ssh_args: оптимизация SSH соединений
  • pipelining: включение SSH pipelining для ускорения
  • control_path: путь для SSH ControlMaster

3. Идемпотентность - ключевой принцип #

Примеры идемпотентности в Ansible:

Неправильный подход (не идемпотентно):

Добавление строки в файл:

  • Проблема: shell с » приписывает каждый раз

Создание пользователя:

  • Проблема: command useradd ошибка при повторном запуске

Правильный подход (идемпотентно):

Добавление строки в файл:

  • Решение: модуль lineinfile проверяет наличие строки
  • Параметры: path, line, state: present

Создание пользователя:

  • Решение: модуль user проверяет существование
  • Параметры: name, state: present

4. Использование переменных #

# group_vars/all.yml - общие переменные
---
# Настройки приложения
app_version: "1.2.3"
app_user: "appuser"
app_port: 8080

# Пути
app_install_dir: "/opt/{{ app_name }}"
log_dir: "/var/log/{{ app_name }}"
config_dir: "/etc/{{ app_name }}"

# Окружения
environments:
  development:
    debug: true
    log_level: debug
    replicas: 1
  production:
    debug: false
    log_level: error
    replicas: 3

# Использование в playbook
- name: Создать каталог приложения
  file:
    path: "{{ app_install_dir }}"
    state: directory
    owner: "{{ app_user }}"
    mode: '0755'
    
- name: Настроить логирование
  template:
    src: logconfig.j2
    dest: "{{ config_dir }}/logging.conf"
  vars:
    log_level: "{{ environments[env].log_level }}"

5. Обработка ошибок и отладка #

# Обработка ошибок
- name: Проверить доступность сервиса
  uri:
    url: "http://{{ ansible_host }}:{{ app_port }}/health"
    method: GET
    status_code: 200
  register: health_check
  retries: 5
  delay: 10
  until: health_check.status == 200
  failed_when: false
  
- name: Показать результат проверки
  debug:
    msg: "Сервис {{ 'доступен' if health_check.status == 200 else 'недоступен' }}"
    
- name: Остановить выполнение при ошибке
  fail:
    msg: "Сервис недоступен после 5 попыток"
  when: health_check.status != 200

# Условное выполнение
- name: Установить пакеты для Ubuntu
  apt:
    name: "{{ ubuntu_packages }}"
  when: 
    - ansible_distribution == "Ubuntu"
    - ansible_distribution_version is version('20.04', '>=')
    
- name: Установить пакеты для CentOS
  yum:
    name: "{{ centos_packages }}"
  when: ansible_os_family == "RedHat"

6. Оптимизация производительности #

# Параллельное выполнение
- name: Обновить все пакеты
  package:
    name: "*"
    state: latest
  async: 300  # максимум 5 минут
  poll: 10    # проверять каждые 10 секунд
  
# Группировка задач
- name: Установить пакеты одной командой
  package:
    name:
      - nginx
      - redis
      - postgresql
      - supervisor
    state: present
    
# Кеширование фактов
- name: Собрать факты только один раз
  setup:
    gather_subset: network
  delegate_to: "{{ item }}"
  delegate_facts: true
  run_once: true
  loop: "{{ groups['all'] }}"

🚀 Практические примеры #

🟠 Полный deployment веб-приложения #

# deploy-webapp.yml
---
- name: Развертывание веб-приложения
  hosts: webservers
  become: yes
  serial: "30%"  # обновлять по 30% серверов
  max_fail_percentage: 10
  
  vars:
    app_name: "mywebapp"
    app_version: "{{ version | default('latest') }}"
    health_check_url: "http://localhost:{{ app_port }}/health"
    
  pre_tasks:
    - name: Вывести серверы из балансировщика
      uri:
        url: "{{ load_balancer_api }}/disable/{{ inventory_hostname }}"
        method: POST
      delegate_to: localhost
      
  tasks:
    - name: Остановить приложение
      systemd:
        name: "{{ app_name }}"
        state: stopped
      ignore_errors: yes
      
    - name: Создать backup старой версии
      archive:
        path: "{{ app_install_dir }}"
        dest: "/backup/{{ app_name }}-{{ ansible_date_time.epoch }}.tar.gz"
      when: backup_enabled | default(true)
      
    - name: Скачать новую версию
      get_url:
        url: "{{ artifact_repo }}/{{ app_name }}/{{ app_version }}/{{ app_name }}.tar.gz"
        dest: "/tmp/{{ app_name }}-{{ app_version }}.tar.gz"
        timeout: 300
        
    - name: Распаковать приложение
      unarchive:
        src: "/tmp/{{ app_name }}-{{ app_version }}.tar.gz"
        dest: "{{ app_install_dir }}"
        remote_src: yes
        owner: "{{ app_user }}"
        group: "{{ app_user }}"
        
    - name: Обновить конфигурацию
      template:
        src: "{{ app_name }}.conf.j2"
        dest: "{{ config_dir }}/{{ app_name }}.conf"
        backup: yes
      notify: restart application
      
    - name: Запустить приложение
      systemd:
        name: "{{ app_name }}"
        state: started
        enabled: yes
        daemon_reload: yes
        
    - name: Проверить здоровье приложения
      uri:
        url: "{{ health_check_url }}"
        status_code: 200
      register: app_health
      retries: 30
      delay: 5
      until: app_health.status == 200
      
  post_tasks:
    - name: Вернуть сервер в балансировщик
      uri:
        url: "{{ load_balancer_api }}/enable/{{ inventory_hostname }}"
        method: POST
      delegate_to: localhost
      
    - name: Очистить временные файлы
      file:
        path: "/tmp/{{ app_name }}-{{ app_version }}.tar.gz"
        state: absent
        
  handlers:
    - name: restart application
      systemd:
        name: "{{ app_name }}"
        state: restarted

🔴 Продвинутая настройка мониторинга #

# monitoring-setup.yml
---
- name: Настройка системы мониторинга
  hosts: monitoring
  become: yes
  
  vars:
    prometheus_version: "2.45"
    grafana_version: "10.0"
    alertmanager_version: "0.25"
    
  roles:
    - role: prometheus
      vars:
        prometheus_config:
          global:
            scrape_interval: 15s
            evaluation_interval: 15s
          rule_files:
            - "alert_rules.yml"
          scrape_configs:
            - job_name: 'prometheus'
              static_configs:
                - targets: ['localhost:9090']
            - job_name: 'node-exporter'
              static_configs:
                - targets: "{{ groups['all'] | map('extract', hostvars, 'ansible_host') | map('regex_replace', '^(.*)$', '\\1:9100') | list }}"
            - job_name: 'nginx'
              static_configs:
                - targets: "{{ groups['webservers'] | map('extract', hostvars, 'ansible_host') | map('regex_replace', '^(.*)$', '\\1:9113') | list }}"
                
    - role: grafana
      vars:
        grafana_datasources:
          - name: Prometheus
            type: prometheus
            url: http://localhost:9090
            access: proxy
            isDefault: true
            
    - role: alertmanager
      vars:
        alertmanager_config:
          global:
            smtp_smarthost: 'localhost:587'
            smtp_from: 'alerts@example.com'
          route:
            group_by: ['alertname']
            group_wait: 10s
            group_interval: 10s
            repeat_interval: 1h
            receiver: 'web.hook'
          receivers:
            - name: 'web.hook'
              slack_configs:
                - api_url: "{{ slack_webhook_url }}"
                  channel: '#alerts'
                  username: 'AlertManager'
                  title: 'Alert: {{ range .Alerts }}{{ .Annotations.summary }}{{ end }}'
                  text: '{{ range .Alerts }}{{ .Annotations.description }}{{ end }}'

🔧 Интеграция с CI/CD #

GitLab CI интеграция #

# .gitlab-ci.yml
variables:
  ANSIBLE_HOST_KEY_CHECKING: "False"
  ANSIBLE_FORCE_COLOR: "True"

stages:
  - validate
  - test
  - deploy-staging
  - deploy-production

validate-ansible:
  stage: validate
  image: alpine:latest
  before_script:
    - apk add --no-cache python3 py3-pip
    - pip3 install ansible ansible-lint
  script:
    - ansible-lint playbooks/
    - ansible-playbook --syntax-check playbooks/site.yml
  only:
    - merge_requests
    - main

test-with-molecule:
  stage: test
  image: quay.io/ansible/molecule:latest
  services:
    - docker:dind
  variables:
    DOCKER_HOST: tcp://docker:2376
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - cd roles/webserver
    - molecule test
  only:
    - merge_requests
    - main

deploy-staging:
  stage: deploy-staging
  image: alpine:latest
  before_script:
    - apk add --no-cache python3 py3-pip openssh-client
    - pip3 install ansible
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
  script:
    - ansible-playbook -i inventory/staging playbooks/deploy.yml
      --extra-vars "version=$CI_COMMIT_SHA"
      --vault-password-file <(echo "$VAULT_PASSWORD")
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - main

deploy-production:
  stage: deploy-production
  image: alpine:latest
  before_script:
    - apk add --no-cache python3 py3-pip openssh-client
    - pip3 install ansible
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
  script:
    - ansible-playbook -i inventory/production playbooks/deploy.yml
      --extra-vars "version=$CI_COMMIT_TAG"
      --vault-password-file <(echo "$VAULT_PASSWORD")
  environment:
    name: production
    url: https://example.com
  when: manual
  only:
    - tags

📊 Мониторинг и логирование Ansible #

Callback плагины для детального логирования #

Callback плагин для детального логирования выполнения Ansible:

Этот плагин расширяет стандартный вывод Ansible и обеспечивает:

  1. Инициализация - сохраняет время начала выполнения playbook
  2. Отслеживание запуска - выводит информацию о запускаемом playbook
  3. Детализация результатов - показывает статус каждой задачи с цветовой индикацией:
    • Зеленый цвет для изменений (CHANGED)
    • Синий цвет для успешных задач без изменений (OK)
  4. Обработка ошибок - выводит подробную информацию об ошибках красным цветом
  5. Финальная статистика - показывает общее время выполнения и детальную статистику по каждому хосту в JSON формате

Плагин помогает лучше отслеживать процесс выполнения и быстрее выявлять проблемы.

Prometheus метрики для Ansible #

# Установка ansible-prometheus-callback
- name: Установить callback для Prometheus
  pip:
    name: ansible-prometheus-callback
    
# ansible.cfg
[defaults]
callback_whitelist = prometheus_callback

[callback_prometheus_callback]
prometheus_server = http://prometheus:9090
job_name = ansible-playbook

🔗 Полезные ресурсы #

Официальная документация #

Обучающие материалы #

Инструменты и расширения #

  • ansible-lint - линтер для playbooks
  • Molecule - фреймворк для тестирования ролей
  • AWX - web UI для Ansible (open source версия Tower)

🎯 Заключение и следующие шаги #

Ansible — мощный инструмент автоматизации, который:

  • Упрощает управление инфраструктурой
  • Обеспечивает консистентность конфигураций
  • Ускоряет развертывание приложений
  • Снижает количество ошибок за счет автоматизации

📈 План изучения Ansible #

🟢 Новичок (1-3 месяца):

  1. Изучите основы: inventory, playbooks, modules
  2. Напишите простые playbook’и для личных проектов
  3. Освойте ad-hoc команды для быстрых задач

🟡 Базовый уровень (3-6 месяцев):

  1. Создайте первые роли и используйте переменные
  2. Изучите templates и handlers
  3. Настройте Ansible Vault для секретов

🟠 Средний уровень (6-12 месяцев):

  1. Интегрируйте Ansible в CI/CD
  2. Используйте динамический inventory
  3. Начните тестировать роли с Molecule

🔴 Продвинутый уровень (1+ год):

  1. Разработайте собственные модули
  2. Настройте AWX/Tower для команды
  3. Оптимизируйте производительность больших развертываний

🛠️ Практические задания #

  1. Создайте playbook для настройки вашего рабочего окружения
  2. Напишите роль для развертывания любимого приложения
  3. Настройте мониторинг Ansible выполнений
  4. Интегрируйте с Git для версионирования конфигураций

Следующий раздел: 2.6 Облачные платформы


💡 Помните: Ansible лучше всего изучать на практике. Начните с простых задач и постепенно усложняйте автоматизацию!