Ansible — система управления конфигурациями, написанная на языке программирования Python. Используется для автоматизации настройки и развертывания программного обеспечения. Обычно используется для управления Linux-узлами, но есть большая коллекция плагинов для подключения к другим устройствам и ОС. Наряду с Chef, Puppet и SaltStack считается одной из наиболее популярных систем управления конфигурациями для Linux. Главное отличие Ansible от аналогов — не нужна установка агента/клиента на целевые системы. С помощью Ansible можно развернуть, удалить или сконфигурировать любое ПО на удаленных серверах.
В этой статье будет рассмотрен процесс создания роли для установки и настройки Asterisk.
Настройка параметров Ansible для подключения к серверам
Для начала создадим конфигурационный файл ansible.cfg. Ниже представлен список каталогов где он может находиться, от наиболее приоритетного к наименее:
-
Каталог определенный переменной окружения $ANSIBLE_CONFIG
-
Текущий каталог
-
Домашний каталог пользователя
-
Глобальный/общий файл в каталоге /etc/ansible
Проверить место расположения файла можно командой:
$ ansible --version
Я расположил его в каталоге ansible в домашней директории пользователя.
Содержимое файла:
[defaults] inventory = /home/kstrakhov/ansible/hosts host_key_checking = false
-
С помощью параметра inventory мы указываем файл со списком хостов и групп, на которых могут быть выполнены наши задачи.
-
Параметр host_key_checking позволяет отключить проверку ключа сервера при подключении по ssh.
Теперь создадим файл inventory, в котором будут перечислены целевые серверы:
[asterisk_group] asterisk1 ansible_host=192.168.30.12 asterisk2 ansible_host=192.168.30.13
В квадратных скобках мы указываем название группы, в дельнейшем, при запуске плэйбука, мы сможем ссылаться на это название. Эти названия могут содержать в себе только буквы, цифры и нижнее подчеркивание. По умолчанию все серверы входят в группу all, те которые не принадлежат ни одной группе, входят в группу ungrouped. Группы можно объединять в группы:
[asterisk_all_group:children] asterisk_group1 asterisk_group2
В списке хостов мы прописываем алиас и переменную ansible_host, в которой указывается ip-адрес хоста, можно указать FQDN, можно прописать FQDN без алиаса. Также с помощью переменных можно задать другие параметры подключения, например:
-
Порт ssh — ansible_port
-
Имя пользователя — ansible_user
-
Путь к ssh ключу — ansible_ssh_private_key_file
-
Пароль пользователя
Для дальнейшего удобства при использовании файла hosts некоторые параметры можно вынести в отдельный файл. Для этого создаем каталог group_vars в директории с файлом hosts и внутри создаем файл с названием группы. Добавляем в этот файл переменные, с использованием двоеточия вместо равно:
ansible_user : root ansible_ssh_private_key_file : /home/kstrakhov/.ssh/id_rsa
Теперь Ansible будет использовать эти переменные для подключения к серверам, которые находятся в группе asterisk_group.
Посмотреть какие переменные применяются к хостам можно командой:
$ ansible-inventory --graph --vars
Создание роли
Теперь, когда подключение настроено, приступим к созданию роли:
$ ansible-galaxy init asterisk-role
В текущей директории появился каталог asterisk-role.
По умолчанию Ansible будет искать в каталогах роли файл main.yml и в зависимости от назначения файла, которое определяется его местонахождением, выполнять определенные действия.
-
defaults/main.yml- переменные по умолчанию для роли. Могут быть переопределены в файле inventory (hosts) или с помощью параметра –e (—extra-vars key=value) при запуске playbook.
-
files- файлы, которые могут быть скопированы при развертывании asterisk.
-
handlers/main.yml- файл обработчиков, используются в роли для выполнения действий при определенных условиях или определенных событиях.
-
meta/main.yml- метаданные роли.
-
tasks/main.yml- основной список задач, которые выполняет роль.
-
templates/ — шаблоны, которые развертывает роль, имеют расширение j2 (jinja2) и используются, например для генерации конфигурационных файлов. Их преимущество в том, что они могут содержать в себе переменные и/или факты (facts).
-
tests/ – этот каталог содержит в себе тестовый inventory файл и тестовый плэйбук (test.yml), используется для тестов.
-
vars/main.yml – здесь хранятся переменные, которые не переопределяются файлом inventory, но могут быть переопределены с помощью параметра -e (—extra-vars) при запуске плэйбука.
Для начала добавим переменные в файл vars/main.yml
--- SIP_MODULE: load RTP_PORT_START: 22000 RTP_PORT_END: 23000 SOURCE_DIR: /usr/local/src/ ASTERISK_PACKAGE: "https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-18-current.tar.gz" ASTERISK_USER: asterisk ASTERISK_GROUP: asterisk
Далее создадим первый плэйбук update_system.yml в каталоге tasks (который будет обновлять систему):
- name: Install epel repo yum: name: epel-release state: present - name: Update system yum: name: "*" state: latest register: allupdate - name: Reboot machine after update and wait reconnect reboot: reboot_timeout: 300 when: allupdate.changed
В первых двух задачах мы добавляем репозиторий epel и обновляем систему. С помощью параметра state можно указать модулю yum, что делать с пакетами:
-
present и installed — гарантирует, что нужный пакет установлен.
-
latest — обновит указанный пакет, если он не последней доступной версии.
-
absent и removed — удалит указанный пакет.
С помощью параметра register мы помещаем результат выполнения команды в переменную allupdate. В третьей задаче, с помощью оператора when, мы проверяем значение секции changed в переменной allupdate, и если были изменения, перезагружаем сервер.
В следующем плэйбуке будут задачи, которые установят Asterisk из исходников и настроят систему для его запуска:
- name: Check if Asterisk is installed shell: asterisk -V | grep -wo Asterisk ignore_errors: true changed_when: false register: check_asterisk - name: Create Asterisk User Group group: name: "{{ ASTERISK_GROUP }}" state: present - name: Create Asterisk User user: name: "{{ ASTERISK_USER }}" shell: /sbin/nologin group: "{{ ASTERISK_GROUP }}" create_home: no - name: Install Asterisk Process block: - name: Set SELinux to Permissive mode command: "{{ item }}" with_items: - setenforce permissive - sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config - name: Download and Extract Asterisk unarchive: src: "{{ ASTERISK_PACKAGE }}" dest: "{{ SOURCE_DIR }}" remote_src: yes list_files: yes register: asterisk_archive_contents - debug: msg: "Asterisk directory path is {{ SOURCE_DIR }}{{ asterisk_archive_contents.files[0] }}" - name: Install Asterisk Packages command: "{{ item }}" with_items: - contrib/scripts/install_prereq install - ./configure --libdir=/usr/lib64 --without-pjproject-bundled --with-jansson-bundled - make menuselect.makeopts - menuselect/menuselect --disable-category MENUSELECT_CORE_SOUNDS --enable CORE-SOUNDS-RU-WAV --enable CORE-SOUNDS-RU-ALAW - make - make install - make samples - make config args: chdir: "{{ SOURCE_DIR }}{{ asterisk_archive_contents.files[0] }}" - name: Set All Asterisk directory owner to asterisk user file: path: "{{ item }}" owner: "{{ ASTERISK_USER }}" group: "{{ ASTERISK_GROUP }}" state: directory recurse: yes mode: 0750 with_items: - /var/lib/asterisk - /var/spool/asterisk - /var/run/asterisk - /var/log/asterisk when: - check_asterisk.rc != 0 - check_asterisk.stdout != 'Asterisk' notify: - start asterisk service
В первой задаче с помощью модуля shell, мы проверяем установлен ли Asterisk на сервере и указываем ему не выводить сообщения об изменениях (changed_when: false) и игнорировать сообщения об ошибках (ignore_errors: true), чтобы плэйбук выполнялся дальше. С помощью параметра register сохраняем результат в переменную check_asterisk.
Далее в задачах Create Asterisk User Group и Create Asterisk User мы создаем группу и пользователя, от которого будет запускаться Asterisk, и запрещаем ему вход в систему.
Далее приступаем к установке Asterisk. Задача “Install Asterisk Process” содержит в себе блок, который будет запускаться, если выполняются условия определенные оператором when (должен располагаться строго под блоком):
-
check_asterisk.rc != 0 — return code в переменной check_asterisk не равен нулю, если он равен нулю, значит команда была выполнена без ошибок.
-
check_asterisk.stdout != ‘Asterisk’ — stdout не содержит в себе «Asterisk», если содержит, значит он уже установлен на сервере.
Первой задачей в блоке мы переводим SELinux в режим permissive.
Далее мы скачиваем и распаковываем исходники Asterisk с помощью модуля unarchive. Параметр src в связке с remote_src, если src содержит ://, указывает удаленному серверу скачать файл с URL-адреса, а потом распаковать его и вернуть список распакованных файлов (list_files: yes). Результат выполнения этой команды помещается в переменную asterisk_archive_contents.
В следующей задаче, мы запускаем модуль debug, который выведет на экран полный путь до исходников Asterisk-а . С помощью [0] мы указываем модулю использовать первый элемент в списке (массиве) поля files ([1] – второй, [2] — третий и т.д.).
В задаче “Install Asterisk Packages” с помощью модуля command мы запускаем процесс установки Asterisk поочередно выполняя команды из директории с исходниками (chdir – указывает модулю перейти в каталог перед выполнением команд). Если вы захотите запускать команды с пайпами, символами экранирования переноса строки или другими спец символами, то лучше использовать модуль shell.
В следующей задаче с помощью модуля file и цикла with_items мы устанавливаем права и меняем владельца рабочих каталогов Asterisk.
Последним действием в этом плэйбуке будет запуск обработчика событий “start asterisk service” (который мы поместим в файл handlers/main.yml), если в предыдущем блоке задач были внесены изменения.
Переходим к созданию конфигурационных файлов Asterisk. Для этого создадим третий плэйбук configure_asterisk:
- name: Create asterisk.conf ini_file: path: "/etc/asterisk/asterisk.conf" owner: "{{ ASTERISK_USER }}" group: "{{ ASTERISK_GROUP }}" mode: 0640 section: "{{ item.section }}" option: "{{ item.option }}" value: "{{ item.value }}" with_items: - { section: "files", option: "astctlpermissions", value: "0775" } - { section: "files", option: "astctlowner", value: "{{ ASTERISK_USER }}" } - { section: "files", option: "astctlgroup", value: "{{ ASTERISK_GROUP }}" } - { section: "files", option: "astctl", value: "asterisk.ctl" } - { section: "options", option: "runuser", value: "{{ ASTERISK_USER }}" } - { section: "options", option: "rungroup", value: "{{ ASTERISK_GROUP }}" } - { section: "options", option: "defaultlanguage", value: "ru" } notify: restart asterisk service - name: Create modules.conf and rtp.conf from templates template: src: "config/{{ item }}.conf" dest: "/etc/asterisk/{{ item }}.conf" owner: "{{ ASTERISK_USER }}" group: "{{ ASTERISK_GROUP }}" mode: 0640 loop: - modules - rtp notify: restart asterisk service - name: Copy extensions.conf sip.conf iax.conf copy: src: "{{ item }}" dest: /etc/asterisk/ owner: "{{ ASTERISK_USER }}" group: "{{ ASTERISK_GROUP }}" mode: 0640 with_fileglob: "{{ inventory_hostname }}/*" notify: - restart asterisk service
В первой задаче мы создаем конфигурационный файл asterisk.conf. Модуль ini_file является частью коллекции community.general. Чтобы проверить, установленна она или нет, запустите:
$ ansible-galaxy collection list
Для установки используйте:
$ ansible-galaxy collection install community.general
Модуль ini_file позволяет добавлять, удалять или изменять отдельные парамеры и разделы в конфигурационных файлах формата INI. Здесь с помощью переменных мы указываем модулю: путь к файлу (path), владельца (owner), группу владельца (group), права на файл (mode), раздел (section), параметр (option), его значение (value) и перечисляем последние три в цикле with_items. В конце перезапускаем Asterisk, если были внесены изменения (restart asterisk service).
В следующей задаче мы создаем конфигурационные файлы modules.conf и rtp.conf, используя шаблоны Jinja2, которые расположены в каталоге templates/config. Здесь все аналогично предыдущей задаче, за исключением используемого цикла — loop, который появился в ansible 2.5 и является более предпочтительным для использования в плэйбуках. В шаблонах можно использовать переменные и факты (facts — собираются при запуске плэйбуков), например мы можем создать шаблон для файла конфигурации, затем развернуть этот файл на нескольких серверах и предоставить нужные нам данные в каждой среде (IP-адрес, имя хоста и т.д.). Шаблон templates/config/rtp.conf содержит в себе две переменные RTP_PORT_START и RTP_PORT_END.
Шаблон templates/config/modules.conf содержит одну переменную SIP_MODULE, с помощью которой мы указываем Asterisk загружать или нет драйвер канала chan_sip.so, в зависимости от того, был ли собран Asterisk с поддержкой pjsip или без нее.
В последней задаче нашей роли мы указываем Ansible скопировать все файлы из директорий files/asterisk1 и files/asterisk2 на сервера asterisk1 и asterisk2 соответственно.
Теперь добавим обработчики событий в файл handlers/main.yml
--- # handlers file for asterisk-role - name: start asterisk service systemd: name: asterisk state: started enabled: yes - name: restart asterisk service systemd: name: asterisk state: restarted enabled: yes
Здесь с помощью модуля systemd запускается или перезапускается Asterisk и заодно добавляется в автозагрузку.
Последнее, что осталось сделать, это добавить созданные плэйбуки в файл tasks/main.yml
--- # tasks file for asterisk-role - name: Update system import_tasks: update_system.yml - name: Install Asterisk import_tasks: install_asterisk.yml - name: Configure Asterisk import_tasks: configure_asterisk.yml
В итоге у нас получилась следующая файловая структур (лишние каталоги и файлы можно удалить):
Запуск роли
Теперь создаем плэйбук, который будет запускать нашу роль и запускаем его:
--- - name: Deploy Asterisk hosts: asterisk_group become: true roles: - asterisk-role
Параметр become:true позволяет выполнять задачи с привилегиями пользователя root, в параметре hosts мы указываем на каких серверах запустится установка Asterisk.
На рисунках ниже представлен процесс установки Asterisk.
Проверим содержимое конфигурационных файлов Asterisk:
На этом развертывание Asterisk с помощью Ansible завершено.
ссылка на оригинал статьи https://habr.com/ru/articles/854792/
Добавить комментарий