Развертывание Asterisk с помощью Ansible

от автора

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 (должен располагаться строго под блоком):

  1. check_asterisk.rc != 0 — return code в переменной check_asterisk не равен нулю, если он равен нулю, значит команда была выполнена без ошибок.

  2. 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:

sip.conf, iax.conf

sip.conf, iax.conf
asterisk.conf

asterisk.conf
modules.cortp.conf

modules.cortp.conf

На этом развертывание Asterisk с помощью Ansible завершено.


ссылка на оригинал статьи https://habr.com/ru/articles/854792/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *