# Ansible
![](/IaC/Ansible/ansible_main.jpg)

**Ansible** (Ансибл) - система управления конфигурациями. Написана и работает на Python. Позволяет настраивать удаленные машины на базе nix и windows (сомнительно но окей) используя скрипты с конфигурациями. Если уж совсем без айтишной душноты, то описав конфигурацию один раз, можно раскатить, к примеру, некий сервис на 10, 20 или тысячу тачек всего одним скриптом (плейбуком). Функционал настолько гибкий, что позволяет в зависимости от подключения к тачке, брать данные из конкретной машины (модуль setup) и подставлять данные в конфигурационные файлы. Так же в зависимости от версии Linux можно устанавливать отдельный набор программ для установки и учитывать специфику различных дистрибутивов. Самый простой пример - в RHEL/CentOS пакет apache2 там представлен как пакет httpd, а в Debian - просто apache2. Этот момент можно учесть и скрипт автоматически выберет нужную вилку для действий. Вобщем очень мощный инструмент, его функционал сложно описать в одном абзаце.

Основополагающим фактором отличия от аналогов типа Chef - нет потребности в агенте который будет обрабатывать операции с системой. Нужен только SSH.

## Основные понятия

Простые примеры для понимания:

### Inventory
Список хостов и параметров подключения к ним. Так же инвентарь можно обьединять в группы хостов, что может быть удобно, в случае если часть хостов относится к одному сервису, а часть - к другому. Если инвентарь отсутствует, то Ansible обращается к /etc/ansible/hosts. Если нет и его - /etc/hosts. Может быть представлен в виде ini-файла (простой вариант) и yaml (более гибкий). Это простой пример, поскольку не включает в себя дополнительные и возможно необходимые параметры вроде порта SSH, указания ключа/пароля и т.п.
Пример inventory.ini:
```ini
[web]
192.168.1.50
192.168.1.51
web-server.ru

[db]
192.168.1.51
db-server.local
```
Он же но в формате yaml
```yaml
web:
  hosts:
    192.168.1.50:
    192.168.1.51:
    web-server.ru:
db:
  hosts:
    192.168.1.51:
    db-server.local:
```

### Playbook
Задачи которые выполняются на удаленных машинах. Запускается, как правило, с указанием группы хостов или хоста на котором будут производиться операции. 
Пример playbook.yaml
```yaml
- hosts: web

- name: Create File
  file:
    path: "/var/www/web-server.ru/index.php"
    state: touch
    owner: www-data
    group: www-data
    mode: 0644
```
Задача создаст фаил по пути указанном в path и назначит права/владельца на созданный php-фаил. Этот плейбук будет применен к группе хостов web

### Roles
Организация задач по автоматизации. Имеет свою структуру в папке плейбука и позволяет отдельно выделять задачи для упрощения администрирования парка машин
Пример структуры
```
roles/
    common/               #  Папка с ролью
        tasks/            #
            main.yml      #  Фаил с задачей роли
        handlers/         #
            main.yml      #  Фаил с задачей handler (описано ниже)
        templates/        #  Папка с шаблонами
            nginx.conf.j2 #  Шаблон конфига nginx с синтаксисом jinja2 (описано ниже)
        files/            #
            bar.txt       #  Файлы для копирования на удаленную машину
            foo.sh        #  К примеру конфиги, скрипты или бинарные файлы
        vars/             #
            main.yml      #  Фаил с обьявлением переменных для этой роли
        defaults/         #
            main.yml      #  Переменные с более низким приоритетом для этой роли
        meta/             #
            main.yml      #  Зависимости для этой роли
        library/          #  Библиотеки для этой роли
        module_utils/     #  Модули для этой роли (module_utils)
                          # По аналогии корневая папка с ролями ниже
    somerole/             # С такой же структурой как и выше 
    role2/                # ""
    role3/                # ""
```

### Handlers
Задачи которые выполняются только если их вызвать директивой notify. К примеру есть некое условие (Перезапуск веб сервера), при котором произойдет некое действие (перезапуск сервиса nginx и mysql).
```yaml
tasks:
  - name: Restart WebServices
    command: echo "this task will restart the web services"
    notify: "restart web services"

handlers:
  - name: Restart mariadb
    service:
      name: mariadb
      state: restarted
    listen: "restart web services"

  - name: Restart nginx
    service:
      name: nginx
      state: restarted
    listen: "restart web services"
 ```
 
### Templates
Шаблоны которые заполняются из переменных. Например модуль который запрашивает множество переменных с каждой машины (Ansible Facts) может быть использован в шаблоне файла с расширением j2. К примеру в файле index.html можно после отработки скрипта автоматически изменить содержимое. Например подставим значение имени хоста:
```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>My Website</title>
    <link rel="stylesheet" href="./style.css">
    <link rel="icon" href="./favicon.ico" type="image/x-icon">
  </head>
  <body>
    <main>
        <h1>My name is {{ ansible_facts['hostname'] }}</h1>  
    </main>
  </body>
</html>
```
### Переменные
Переменные они и в Африке переменные. Можно задать самому, можно дергать Ansible Facts. Можно использовать сторонние модули. В случае использования роли, например, можно задавать переменные в vars/main.yaml в таком виде:
```yaml
---
root_dir: /var/www/html
web_dir: "{{ root_dir }}/web"
web_adminpanel_dir: "{{ root_dir }}/admin"
```
Затем в playbook передаем тот фаил с переменной:
```yaml
vars_files:
- "/path/to/var/file"
```

Так же можно напрямую в playbook обозначить директивой vars:
```yaml
vars: http-set-port: 80
```

Так же можно переменную передавать ad-hoc методом, например
```bash
ansible-playbook playbook.yaml -e "http-set-port=80"
```
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9