Перейти к основному содержимому
Вернуться в категорию

Автоматизация серверов с Ansible: Infrastructure as Code

Установка Ansible, файл инвентаря, написание playbook, структура ролей, переменные, зашифрованный vault, ad-hoc команды и автоматизация конфигурации серверов. Пошаговое руководство.

Время чтения: 20 мин DevOps и автоматизация
ansibleавтоматизацияinfrastructure as codedevopsplaybookyamllinux
Автор
REXE Teknoloji Network & Security Team
Редактор
REXE Teknoloji Technical Editorial
Первая публикация
Последнее обновление

Автоматизация серверов с Ansible: Infrastructure as Code

Ansible — инструмент с открытым исходным кодом, позволяющий управлять конфигурацией серверов, развёртыванием приложений и автоматизацией задач как кодом. Благодаря безагентной архитектуре он подключается к целевым серверам только по SSH.

Что такое Ansible?

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

  • Безагентный: Не требует установки дополнительного ПО на целевых серверах
  • Идемпотентный: Многократный запуск одного playbook даёт одинаковый результат
  • На основе YAML: Легко читать и писать
  • Большая библиотека модулей: 3000+ готовых модулей

Ansible подключается с управляющего узла к целевым серверам по SSH. Для Windows-серверов используется WinRM.

Установка Ansible

Ubuntu/Debian

hljs bash
# Добавить PPA-репозиторий
sudo apt update
sudo apt install software-properties-common -y
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible -y

# Проверить версию
ansible --version

RHEL/CentOS/AlmaLinux

hljs bash
# Добавить EPEL-репозиторий
sudo dnf install epel-release -y
sudo dnf install ansible -y

# Альтернатива: установить через pip
pip3 install ansible

Установка через pip (Рекомендуется)

hljs bash
# Создать виртуальное окружение Python
python3 -m venv ansible-env
source ansible-env/bin/activate

# Установить Ansible и дополнительные инструменты
pip install ansible ansible-lint

# Проверить версию
ansible --version

Файл инвентаря

Инвентарь определяет серверы, которыми будет управлять Ansible:

Формат INI

hljs ini
# /etc/ansible/hosts или пользовательский файл инвентаря

# Одиночный сервер
web1.example.com

# Определение группы
[webservers]
web1.example.com
web2.example.com ansible_port=2222
192.168.1.10 ansible_user=ubuntu

[databases]
db1.example.com
db2.example.com

# Переменные группы
[webservers:vars]
ansible_user=deploy
ansible_python_interpreter=/usr/bin/python3

# Родительская группа
[production:children]
webservers
databases

Формат YAML

hljs yaml
# inventory.yml
all:
  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_port: 22
        web2.example.com:
          ansible_port: 2222
      vars:
        ansible_user: deploy
        http_port: 80

    databases:
      hosts:
        db1.example.com:
        db2.example.com:
      vars:
        ansible_user: dbadmin
        db_port: 5432

Ad-hoc команды

Выполняйте команды без написания playbook для быстрых задач:

hljs bash
# Тест ping
ansible all -m ping
ansible webservers -m ping -i inventory.yml

# Выполнить команду
ansible all -m command -a "uptime"
ansible webservers -m shell -a "df -h"

# Скопировать файл
ansible webservers -m copy -a "src=/local/file dest=/remote/path"

# Установить пакет
ansible webservers -m apt -a "name=nginx state=present" --become

# Управление сервисом
ansible webservers -m service -a "name=nginx state=started enabled=yes" --become

# Создать/удалить файл
ansible all -m file -a "path=/tmp/test state=touch"
ansible all -m file -a "path=/tmp/test state=absent"

# Собрать факты
ansible web1.example.com -m setup
ansible all -m setup -a "filter=ansible_os_family"

Написание Playbook

Базовая структура Playbook

hljs yaml
# site.yml
---
- name: Настройка веб-серверов
  hosts: webservers
  become: yes  # использовать sudo
  vars:
    http_port: 80
    max_clients: 200

  tasks:
    - name: Установить Nginx
      apt:
        name: nginx
        state: present
        update_cache: yes

    - name: Скопировать конфигурацию Nginx
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
      notify: Перезапустить Nginx

    - name: Запустить сервис Nginx
      service:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: Перезапустить Nginx
      service:
        name: nginx
        state: restarted

Tasks, Handlers и Roles

hljs yaml
# Условные задачи
- name: Установить пакет на Ubuntu
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - curl
    - git
  when: ansible_os_family == "Debian"

- name: Установить пакет на RHEL
  dnf:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - curl
    - git
  when: ansible_os_family == "RedHat"

# Создание пользователей в цикле
- name: Создать пользователей
  user:
    name: "{{ item.name }}"
    groups: "{{ item.groups }}"
    state: present
  loop:
    - { name: 'alice', groups: 'sudo' }
    - { name: 'bob', groups: 'www-data' }

# Регистрация и условие
- name: Проверить версию Nginx
  command: nginx -v
  register: nginx_version
  ignore_errors: yes

- name: Установить Nginx если не установлен
  apt:
    name: nginx
    state: present
  when: nginx_version.rc != 0

Переменные и факты

hljs yaml
# group_vars/webservers.yml
http_port: 80
https_port: 443
app_user: www-data
app_dir: /var/www/html

# host_vars/web1.example.com.yml
ansible_host: 192.168.1.10
server_name: web1.example.com
hljs yaml
# Использование переменных в playbook
- name: Создать директорию приложения
  file:
    path: "{{ app_dir }}"
    state: directory
    owner: "{{ app_user }}"
    mode: '0755'

# Использование фактов
- name: Показать информацию о системе
  debug:
    msg: |
      ОС: {{ ansible_distribution }} {{ ansible_distribution_version }}
      CPU: {{ ansible_processor_vcpus }} ядер
      RAM: {{ ansible_memtotal_mb }} МБ
      IP: {{ ansible_default_ipv4.address }}

Ansible Vault

Для шифрования конфиденциальных данных:

hljs bash
# Создать зашифрованный файл
ansible-vault create secrets.yml

# Зашифровать существующий файл
ansible-vault encrypt vars/passwords.yml

# Редактировать зашифрованный файл
ansible-vault edit secrets.yml

# Просмотреть зашифрованный файл
ansible-vault view secrets.yml

# Удалить шифрование
ansible-vault decrypt vars/passwords.yml

# Изменить пароль
ansible-vault rekey secrets.yml

# Запустить playbook с vault
ansible-playbook site.yml --ask-vault-pass
ansible-playbook site.yml --vault-password-file ~/.vault_pass

Структура ролей

hljs bash
# Создать роль
ansible-galaxy init roles/nginx

# Структура директорий роли
roles/nginx/
├── defaults/
│   └── main.yml      # Переменные по умолчанию
├── files/
│   └── nginx.conf    # Статические файлы
├── handlers/
│   └── main.yml      # Обработчики
├── meta/
│   └── main.yml      # Метаданные роли
├── tasks/
│   └── main.yml      # Основные задачи
├── templates/
│   └── vhost.conf.j2 # Шаблоны Jinja2
└── vars/
    └── main.yml      # Переменные

Примеры Playbook

Playbook установки Nginx

hljs yaml
---
- name: Установка веб-сервера Nginx
  hosts: webservers
  become: yes
  vars:
    domain: example.com
    web_root: /var/www/{{ domain }}

  tasks:
    - name: Установить Nginx
      apt:
        name: nginx
        state: present
        update_cache: yes

    - name: Создать веб-директорию
      file:
        path: "{{ web_root }}"
        state: directory
        owner: www-data
        group: www-data
        mode: '0755'

    - name: Создать пример index.html
      copy:
        content: "<h1>Привет от {{ inventory_hostname }}</h1>"
        dest: "{{ web_root }}/index.html"
        owner: www-data

    - name: Настроить виртуальный хост
      template:
        src: vhost.conf.j2
        dest: /etc/nginx/sites-available/{{ domain }}
      notify: Перезагрузить Nginx

    - name: Включить виртуальный хост
      file:
        src: /etc/nginx/sites-available/{{ domain }}
        dest: /etc/nginx/sites-enabled/{{ domain }}
        state: link
      notify: Перезагрузить Nginx

    - name: Отключить сайт по умолчанию
      file:
        path: /etc/nginx/sites-enabled/default
        state: absent
      notify: Перезагрузить Nginx

    - name: Разрешить Nginx в UFW
      ufw:
        rule: allow
        name: 'Nginx Full'

  handlers:
    - name: Перезагрузить Nginx
      service:
        name: nginx
        state: reloaded

Запуск Playbook

hljs bash
# Базовый запуск
ansible-playbook site.yml

# С конкретным инвентарём
ansible-playbook -i inventory.yml site.yml

# Конкретный хост или группа
ansible-playbook site.yml --limit webservers
ansible-playbook site.yml --limit web1.example.com

# Dry-run (проверка без изменений)
ansible-playbook site.yml --check

# Подробный режим
ansible-playbook site.yml -v
ansible-playbook site.yml -vvv

# Запустить конкретные теги
ansible-playbook site.yml --tags "nginx,ssl"
ansible-playbook site.yml --skip-tags "debug"

# Дополнительные переменные
ansible-playbook site.yml -e "env=production version=1.5"

Заключение

Ansible — один из наиболее доступных способов управления автоматизацией серверов как кодом. Благодаря безагентной архитектуре, большой библиотеке модулей и структуре на основе YAML вы можете легко управлять как небольшой, так и крупной инфраструктурой. Храните конфиденциальные данные в безопасности с Vault, создавая повторно используемые конфигурации с ролями.

Часто задаваемые вопросы

В чём разница между Ansible и Puppet/Chef?

Ansible работает без агентов (требуется только SSH), тогда как Puppet и Chef требуют установки агента на целевых серверах. Ansible основан на YAML и проще в изучении. Puppet и Chef предлагают более мощное управление состоянием, но сложнее в настройке и изучении. Ansible обычно предпочтителен для небольшой и средней инфраструктуры.

Что такое идемпотентность и почему она важна?

Идемпотентность означает, что многократное выполнение одной операции всегда даёт одинаковый результат. Модули Ansible спроектированы идемпотентными: если nginx уже установлен, он не будет переустановлен; если файл уже правильный, он не будет изменён. Это позволяет безопасно повторно запускать playbook.

Что произойдёт, если пароль Ansible Vault будет забыт?

Если пароль vault забыт, зашифрованные файлы не могут быть восстановлены. Поэтому критически важно хранить пароль vault в надёжном менеджере паролей (1Password, Bitwarden и т.д.). В производственных средах рекомендуется записать пароль vault в файл (--vault-password-file) и хранить его в безопасном месте.

Что такое Ansible Galaxy?

Ansible Galaxy — официальная платформа, где публикуются роли и коллекции, созданные сообществом (galaxy.ansible.com). Готовые роли можно загрузить командами вроде 'ansible-galaxy install geerlingguy.nginx'. Это позволяет использовать проверенные роли вместо написания с нуля.

Как улучшить производительность Ansible в крупной инфраструктуре?

Увеличьте значение 'forks' в ansible.cfg (по умолчанию 5, рекомендуется 20-50). Уменьшите количество SSH-соединений с 'pipelining = True'. Включите параллельное выполнение независимых хостов с 'strategy: free'. Контролируйте размер пакета с 'serial' в больших инвентарях.

Могу ли я управлять Windows-серверами с помощью Ansible?

Да, Ansible может управлять Windows-серверами через протокол WinRM (Windows Remote Management). Требуются настройки 'ansible_connection: winrm' и 'ansible_winrm_transport: ntlm'. Модули Windows начинаются с префикса 'win_': win_package, win_service, win_file и т.д.

Связанные статьи

Руководство по Docker Compose: Управление многоконтейнерными приложениями

Определение и управление многоконтейнерными приложениями с Docker Compose: зависимости сервисов, переменные окружения, проверки работоспособности, масштабирование и развёртывание в production. Полное руководство.

16 мин
docker-composedockerконтейнер
Сетевой трафикВходящий GbpsИсходящий Gbps