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

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

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

Время чтения: 20 мин DevOps и автоматизация
ansibleавтоматизацияinfrastructure as codedevopsplaybookyamllinux

Содержание

Автоматизация серверов с 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, создавая повторно используемые конфигурации с ролями.