Автоматизация управления с помощью Ansible

888d5a6759eb4c30e982913e792be787.png

Автоматизация управления с помощью Ansible

В предыдущей статье мы достаточно подробно рассмотрели вопросы связанные с автоматизацией управлением и настройкой ПО в средних и крупных сетях. Рассмотрели Vagrant и основные методы работы с виртуальной инфраструктурой. В этой статье мы подробно поговорим об использовании такого интересного инструмента, как Ansible.

Данное решение позволяет автоматизировать развертывание и настройку ресурсов в сети, подготовку контейнеров и виртуальных машин, и многое другое. Само приложение Ansible работает в так называемом проталкивающем режиме. Вся работа с инфраструктурой осуществляется с сервера управления. И с этой машины ведется применение настроек к управляемым узлам.

В этой статье не будет длинных вступлений, рассказывающих о том, зачем вообще нужен Ansible, чем он отличается от других подобных решений и так далее. Вместо этого я предлагаю сразу перейти к практике и развернуть необходимую тестовую среду.

Сначала нам необходимо будет развернуть сервер управления Ansible. В качестве ОС я буду использовать Ubuntu 22.04. Предварительно сделав апгрейд и апдейт, выполним следующую команду:  

5c25cf3fd43131ab481b3eec52e7616c.png

Установка не должна вызвать каких-либо сложностей. После ее завершения мы получим узел управления со всем необходимым ПО для администрирования целевых узлов. Как настоящие DevOps мы будем работать через консоль и для начала нам необходимо внести правки в файл инвентаризации /etc/ansible/hosts. Это файл содержит информацию о тех хостах, которыми будем управлять, параметры конфигурации и переменные.

В качестве примера пропишем в этот файл два сервера .150 и .137. Также пропишем путь к интерпретатору Python.

[servers]

server1 ansible_host=192.168.222.150

server2 ansible_host=192.168.222.137

[all: vars]

ansible_python_interpreter=/usr/bin/python3

С этим значением параметра удаленный сервер использует исполняемый файл Python 3 /usr/bin/python3, который может отсутствовать в некоторых версиях Ubuntu.

Об аутентификации

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

d5394b8156a0b27eb75262196016f025.png6ebfaed8a5a11472ec08222aadbcd7f0.png

Однако, пароли — это не лучший механизм защиты и SSH-ключи надежнее. Для того, чтобы настроить аутентификацию по ключам. Для этого выполним следующие действия:

На сервере управления Ansible отобразим открытый ключ в терминале:

b0eb4c912bc5257bdc5a2da9f8a7cbfa.png

Если такого файла нет, его можно создать:

a1383c43fa7aa9ddb25a90f0cd9fbf57.png

Далее необходимо зайти на клиентскую машину, перейти в сессию root и открыть файл  nano ~/.ssh/authorized_keys и поместить в него открытый ключ сервера управления:

240e529d90bac7dd1fa9d51d183b4131.png

В качестве проверки результатов настройки узнаем, какие версии ядра на управляемых машинах.

448628dc219de176f522f79bc85ccd6c.png

Используем плейбуки

Мы научились выполнять команды на управляемых серверах и получать ответы от их операционных систем. Однако для настоящей автоматизации этого явно недостаточно. И здесь на помощь приходят плейбуки — базовые компоненты, которые записывают и исполняют конфигурацию Ansible, что позволяет по-настоящему автоматизировать выполнение задач на управляемых машинах.  

Немного о терминологии. В последнее время есть тенденция к отказу от англоязычных терминов, поэтому в некоторых источниках, особенно связанных с ИБ можно встретить замену иностранного слова «плейбук» российским аналогом — карта реагирования. Однако в данной статье мы будем использовать термин плейбук.

Итак, что из себя представляет плейбук: по сути это набор сценариев, которые выполняются в заданном порядке. Сценарий — это список задач для определенной группы хостов.

Инструментом для создания плейбуков является язык YAML. При написании сценариев большое значение имеет отступы, которые необходимо делать только с помощью пробелов, TAB использовать нельзя. У одинаковых элементов отступы тоже должны быть одинаковые. Вот пример Hello world в Ansible:

---

— hosts: all

  tasks:

 — name: Print message

      debug:

        msg: Hello Ansible World

В этом сценарии мы указываем в качестве целей все узлы из нашего hosts файла. Наименование задачи Print message, и вывод сообщения Hello Ansible World.

Сохраним этот плейбук в файл и запустим на выполнение.

673f197a7e77c52052795bdbfa340629.png

Задача успешно выполнена. В случае, если нам необходимо выполнить плейбук только на одном управляемом узле, необходимо указать параметр –limit и имя данного узла, указанное в файле hosts.

a77151ecd032e88ee608c5af28022eeb.png

Далее рассмотрим работу с переменными в Ansible. В следующем примере мы будем работать сразу с двумя видами переменных: встроенной переменной Ansible и определенной в нашем плейбуке.

Перед началом блока определяемых в плейбуке переменных мы указываем vars:, далее указываем сами переменные и их значения. В нашем примере мы определяем переменную txt со значением IP_address. В блоке tasks, в разделе msg переменные указываются в двойных фигурных скобках с отступом с каждой стороны. Сначала мы указываем нашу переменную txt, а затем встроенную переменную ansible_default_ipv4.address. Определять данную переменную не надо, так как она уже определена в самом Ansible.

— hosts: all

  vars:

    txt: IP_address

  tasks:

 — name: print facts

      debug:

        msg:»{{ txt }}: {{ ansible_default_ipv4.address }}»

c7f7d7618f5c2a3cea7d9f313d4eadff.png

Сохраним созданный файл и выполним плейбук для всех узлов.

0ba9c8ca17cab0d9e63971c378fa93cb.png

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

Для этого мы сначала определим переменные user и file_name

  vars:

 — user: otus

 — file_name: test1

Затем выполним команду ls  

      command: ls /home/{{ user }}/{{ file_name }}

Далее мы используем ключевое слово register, которое создает новую переменную file_exists и присваивает ей выходные данные, полученные из команды.

Одна важная вещь, на которую следует обратить внимание, заключается в том, что по умолчанию Ansible прерывает работу плейбука, если команда, которую вы используете для оценки условия, завершается неудачей. По этой причине мы используем директиву ignore_errors, имеющую значение yes, и это заставит Ansible перейти к следующей задаче и продолжить работу.

      register: file_exists

      ignore_errors: yes

В Ansible вы можете определить условия, которые будут оцениваться перед выполнением задачи. Когда условие не выполняется, задача пропускается. Это делается с помощью ключевого слова when, которое принимает выражения, которые обычно основаны на переменной или факте.

Далее в случае, если fail_exists имеет значение failed, мы создаем новый файл.

 — name: create file for user

      file:

        path: /home/{{ user }}/{{ file_name }}

        state: touch

      when: file_exists is failed

Если файл уже существует, мы просто выводим соответствующее сообщение:

 — name: show message if file exists

      debug:

        msg: The user file already exists.

      when: file_exists is succeeded

Далее приведен полный текст всего плейбука:

---

— hosts: all

  vars:

 — user: otus

 — file_name: test1

  tasks:

 — name: Check if file already exists

      command: ls /home/{{ user }}/{{ file_name }}

      register: file_exists

      ignore_errors: yes

 — name: create file for user

      file:

        path: /home/{{ user }}/{{ file_name }}

        state: touch

      when: file_exists is failed

 — name: show message if file exists

      debug:

        msg: The user file already exists.

      when: file_exists is succeeded

Запустим наш плейбук на выполнение:

8c941c2d042b39f0f949568c300fb6aa.png

Как видно, при первом запуске мы получили ругательства на тему отсутствия файла с таким именем. Однако, все эти сообщения были успешно проигнорированы и выполнение сценария было продолжено.

При повторном запуске плейбука:

a795878f95ed1315462f4a8b25fe8cff.png

Получаем сообщения, что файлы уже существуют.

Циклы в Ansible

Еще одной важной задачей автоматизации является необходимость повторения  выполнения одной и той же задачи, с использованием разных значений. Например, вам может потребоваться изменить разрешения для нескольких файлов или создать нескольких пользователей. Чтобы избежать многократного повторения задачи в вашем файле playbook, для этого лучше всего использовать циклы.

В следующем примере мы объявляем в переменной file_name значение ansible, затем создаем файлы с именами, содержащими значение file_name и через дефис значение одной из переменных внутри loop.

---

— hosts: all

  vars:

 — user: otus

 — file_name: ansible

  tasks:

 — name: creates users files

      file:

        path: /home/{{ user }}/{{ file_name }}-{{ item }}

        state: touch

      loop:

 — test10

 — test20

 — test30

Запустим получившийся плейбук:

e5f80ca2e2d21876f5356f6c049c89b5.png

В результате работы сценария получаем три файла с именами, соответствующими заданному шаблону:

afe4fb203e727472e7cef54b519e1b5a.png

Заключение

В этой статье мы рассмотрели основные моменты связанные с установкой Ansible и выполнением базовых задач. Но это только малая часть того, что умеет данная система, например за кадром осталось управление узлами под Windows, поднятие привилегий, установка обновлений и многое другое. Так что мы еще обязательно вернемся к рассмотрению вопросов использования Ansible.

Также хочу порекомендовать всем бесплатный урок курса DevOps практики и инструменты от OTUS, где мои коллеги расскажут про 3 основных принципа безопасности инфраструктуры. В уроке будет демо, где эксперты OTUS разберут одну проблему на инфраструктуре — очень интересный протокол Диффи-Хеллмана на примере больших чисел с отсылкой на эллиптические кривые и криптографию.Преподаватель на пальцах покажет как работает алгоритм и как исправить проблему связанную с ним в nginx.

© Habrahabr.ru