Version 13 (modified by 8 years ago) ( diff ) | ,
---|
Вариант настройки отказоустойчивого сервера FreeSwitch
Исходные данные
Имеется ubuntu-16.04 c настроенным и работающим сервером FreeSwitch, установленным из нашего репозитория, и используемым для организации диспетчерской связи. Требуется сделать резервирование из двух идентичных серверов FreeSwitch.
Переносим базы данных FreeSwitch в MySQL
Устанавливаем драйвер MyODBC и настраиваем доступ к базе данных
Устанавливаем необходимые пакеты
$ sudo apt-get install libodbc1 odbcinst unixodbc
Установим драйвер myodbc
- Скачиваем архив mysql-connector-odbc-5.3.7-linux-ubuntu16.04-x86-64bit.tar.gz отсюда;
- Распаковываем архив:
$ tar zxvf mysql-connector-odbc-5.3.7-linux-ubuntu16.04-x86-64bit.tar.gz
- Переходим в распакованный каталог:
$ cd mysql-connector-odbc-5.3.7-linux-ubuntu16.04-x86-64bit
- Скопируем драйвер в каталог odbc:
$ sudo cp lib/* /usr/lib/x86_64-linux-gnu/odbc/
- Конфигурируем установленный драйвер с помощью инсталлятора:
$ sudo bin/myodbc-installer -d -a -n MySQL -t "DRIVER=/usr/lib/x86_64-linux-gnu/odbc/libmyodbc5w.so;"
- Конфигурирвем источник:
$ sudo bin/myodbc-installer -s -a -n freeswitch -t "DRIVER=MySQL;SERVER=127.0.0.1;DATABASE=dispatcher;OPTION=67108864"
где "dispatcher" - имя нашей базы данных на сервере MySQL.
В результате в каталоге /etc должны быть созданы файлы odbc.ini и odbcinst.ini с приблизительно таким содержанием:
odbc.ini:
[freeswitch] Driver=MySQL SERVER=127.0.0.1 DATABASE=dispatcher PORT=3306 MULTI_STATEMENTS=1
odbcinst.ini:
[MySQL] Driver=/usr/lib/x86_64-linux-gnu/odbc/libmyodbc5w.so UsageCount=1 FileUsage=1
Проверим работу с базой данных MySQL серез ODBC
$ isql freeswitch <username> <password> +---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> show tables; +-----------------------------------------------------------------+ | Tables_in_dispatcher | +-----------------------------------------------------------------+ | cdr | | options | | recordings | +-----------------------------------------------------------------+ SQLRowCount returns 10 10 rows fetched SQL> quit
где <username> и <password> - имя и пароль, установленные для доступа FreeSwitch к базе данных при конфигурации FreeSwitch.
Теперь необходимо установить базе данных charset по умолчанию utf8, чтобы новые таблицы, которые создаст FreeSwitch, использовали именно его:
mysql> alter database <db-name> character set utf8; Query OK, 1 row affected (0,00 sec)
где <db-name> - имя базы данных.
Конфигурируем FreeSwitch для хранения его данных в MySQL
Конфигурируем SIP профили FreeSwitch для хранения данных в MySQL
В файлах конфигурации SIP профилей в разделе <settings/> добавляем такой параметр:
<param name="odbc-dsn" value="odbc://freeswitch:<username>:<password>"/>
где <username> и <password> - имя и пароль, установленные для доступа FreeSwitch к базе данных при конфигурации FreeSwitch. Например:
<param name="odbc-dsn" value="odbc://freeswitch:freeswitch:lagjh46dh3"/>
Здесь же включаем track-calls:
<!-- Enable Track Calls --> <param name="track-calls" value="true"/>
Теперь в консоли FreeSwitch перезапускаем профили командой:
> sofia profile <profile-name> restart
где <profile-name> - имя SIP профиля, например:
> sofia profile internal restart
Контролируем, что профили перезупустились с помощью команды в консоли FreeSwitch:
> sofia status
В нашей базе данных должны создаться новые таблицы. Проверим это:
$ mysql -u <username> -p <dbname> -e 'show tables' Enter password: +-------------------------------------+ | Tables_in_dispatcher | +-------------------------------------+ | cdr | | options | | recordings | | sip_authentication | | sip_dialogs | | sip_presence | | sip_registrations | | sip_shared_appearance_dialogs | | sip_shared_appearance_subscriptions | | sip_subscriptions | +-------------------------------------+
Конфигурируем хранение core-db в MySQL
Одна из таблиц (а именно, channels) при попытке ее создания с использованием кодировки utf8 превосходила лимит на максимальный размер строки в таблице mysql. Поэтому создаем эту таблицу вручную, немного изменив тип некоторых особо "жирных" столбцов:
CREATE TABLE channels ( uuid VARCHAR(256), direction VARCHAR(32), created VARCHAR(128), created_epoch INTEGER, name VARCHAR(1024), state VARCHAR(64), cid_name VARCHAR(1024), cid_num VARCHAR(256), ip_addr VARCHAR(256), dest VARCHAR(1024), application VARCHAR(128), application_data TEXT(4096), dialplan VARCHAR(128), context VARCHAR(128), read_codec VARCHAR(128), read_rate VARCHAR(32), read_bit_rate VARCHAR(32), write_codec VARCHAR(128), write_rate VARCHAR(32), write_bit_rate VARCHAR(32), secure VARCHAR(64), hostname VARCHAR(256), presence_id TEXT(4096), presence_data TEXT(4096), accountcode VARCHAR(256), callstate VARCHAR(64), callee_name VARCHAR(1024), callee_num VARCHAR(256), callee_direction VARCHAR(5), call_uuid VARCHAR(256), sent_callee_name VARCHAR(1024), sent_callee_num VARCHAR(256), initial_cid_name VARCHAR(1024), initial_cid_num VARCHAR(256), initial_ip_addr VARCHAR(256), initial_dest VARCHAR(1024), initial_dialplan VARCHAR(128), initial_context VARCHAR(128) );
В конфиг-файле switch.conf.xml добавляем параметр:
<param name="core-db-dsn" value="odbc://freeswitch:<username>:<password>"/>
где <username> и <password> - имя и пароль, установленные для доступа FreeSwitch к базе данных при конфигурации FreeSwitch.
Здесь же устанавливаем имя коммутатора:
<param name="switchname" value="freeswitch"/>
Теперь выполняем рестарт FreeSwitch:
$ sudo service freeswitch restart
Убедимся, что в базе данных появились новые таблицы:
$ mysql -u root -p dispatcher -e 'show tables' Enter password: +-------------------------------------+ | Tables_in_dispatcher | +-------------------------------------+ | aliases | | basic_calls | | calls | | cdr | | channels | | complete | | detailed_calls | | interfaces | | nat | | options | | recordings | | recovery | | registrations | | sip_authentication | | sip_dialogs | | sip_presence | | sip_registrations | | sip_shared_appearance_dialogs | | sip_shared_appearance_subscriptions | | sip_subscriptions | | tasks | +-------------------------------------+
Конфигурируем второй сервер
Устанавливаем и конфигурируем второй сервер полностью аналогично первому. Проверим, что установлены все необходимые модули. Конфигурацию нового сервера (/etc/freeswitch) можно целиком скопировать с первого.
Настраиваем репликацию между двумя серверами mysql
Останавливаем FreeSwitch на обоих серверах:
$ sudo service freeswitch stop
В конфиг-файлы mysqld добавляем следующее:
server-id = 1 log_bin = /var/log/mysql/mysql-bin.log expire_logs_days = 10 max_binlog_size = 100M binlog_do_db = dispatcher
где server-id
- идентификатор сервера, он должен быть разный у разных серверов.
Перезапускаем mysqld на обоих серверах:
$ sudo service mysql restart
Подключаемся к mysql серверу и создаем пользователя для репликации:
mysql> CREATE USER 'replicator'@'%' IDENTIFIED BY 'password';
заменив "password" каким-нибудь паролем.
Даем пользователю право на репликацию:
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%';
На сервере 1 блокируем базу данных на запись:
mysql> FLUSH TABLES WITH READ LOCK;
Выводим состояние мастера:
mysql> SHOW MASTER STATUS;
Будет выведена примерно такая таблица:
+------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000002 | 62249651 | dispatcher | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
Не выходя из консоли mysql (при выходе снимется блокировка), из другого терминала дампим базу данных:
$ mysqldump -u root -p dispatcher >dispatcher.dump
Когда дамп будет готов, снова выведем SHOW MASTER STATUS;
и убедимся, что значение Position
не изменилось. Теперь можно снять блокировку:
mysql> UNLOCK TABLES;
или просто выйти из консоли mysql.
Копируем сделанный дамп базы на второй сервер. Записываем дамп в базу данных:
$ mysql -u root -p dispatcher <dispatcher.dump
Теперь входим в консоль mysql сервера 2 и запускаем репликацию:
mysql> STOP SLAVE; mysql> CHANGE MASTER TO MASTER_HOST = '<server 1 address>' , MASTER_USER = 'replicator', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000002', MASTER_LOG_POS = 62249651; mysql> START SLAVE;
заменив "password" на тот пароль, который установили пользователю replicator ранее.
Проверим, что репликация активирована:
mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.64 Master_User: replicator Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 118750 Relay_Log_File: r3-relay-bin.000002 Relay_Log_Pos: 82017 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 118750 Relay_Log_Space: 82221 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: 7603167a-1081-11e6-9637-902b3433882b Master_Info_File: /var/lib/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)
Аналогично, только без выполнения/восстановления дампа настраиваем репликацию сервера 2 на сервер 1.
Настраиваем общий адрес
Общий адрес - это IP адрес, используя который один из двух серверов (активный) будет предоставлять сервис. Пусть для определенности это будет адрес 192.168.0.63
.
Для начала установим пакет arping:
$ sudo apt-get install arping
В файле /etc/network/interfaces обоих серверов добавляем настройку для общего адреса:
iface eth0:0 inet static address 192.168.0.63 netmask 255.255.255.0
где вместо "eth0" следует вписать имя используемого сетевого интерфейса.
Отредактируем файл /etc/default/arping, вписав в него IPUP=1
и DOWN=1
.
На первом сервере выполняем команду
$ sudo ifup eth0:0
Выполнение этой команды на втором сервере должно дать ошибку, так как адрес уже присутствует в сети:
$ sudo ifup eth0:0 * Using arping to check duplicity of 192.168.0.63... ...fail! run-parts: /etc/network/if-up.d/arping exited with return code 1 Failed to bring up eth0:0.
Теперь необходимо изменить настройки odbc таким образом, чтобы оба сервера FreeSwitch подключались к базе данных используя общий адрес и, таким образом, подключались к одному и тому же серверу mysql. Для этого в ранее созданном файле /etc/odbc.ini указываем адрес сервера 192.168.0.63
.
Устанавливаем параметр sysctl net.ipv4.ip_nonlocal_bind в значение 1 чтобы дать возможность неактивному серверу FreeSwitch слушать адрес, отсутствующий на его интерфейсах:
$ sudo sysctl net.ipv4.ip_nonlocal_bind=1
Для автоматической установки этого значения в файл /etc/sysctl.conf добавляем строку
net.ipv4.ip_nonlocal_bind=1
В конфигурации профилей FreeSwitch устанавливаем параметры sip-ip
, rtp-ip
, presence-hosts
, ext-sip-ip
и ext-rtp-ip
в значение 192.168.0.63
.
Теперь можно запустить сервера FreeSwitch:
$ sudo service freeswitch start
Синхронизация файлов конфигурации и записей переговоров
Синхронизацию файлов конфигурации и записей переговоров сделаем с помощью rsync. Чтобы схема была симметричной, каждый из серверов будет копировать свои обновившиеся файлы на другой сервер. Копирование будет производиться по SSH.
Для начала проверим, что в /etc/passwd пользователю freeswitch установлен реальный shell (а не /bin/false или что-то аналогичное). При необходимости установим шелл командой:
$ sudo usermod -s /bin/sh freeswitch
Генерируем пользователю freeswitch rsa ключ для ssh:
$ sudo su -l freeswitch $ ssh-keygen -t rsa -b 4096
В результате в домашнем каталоге пользователя freeswitch будет создан файл .ssh/id_rsa.pub
. Добавляем содержимое этого файла в файл .ssh/authorized_keys
в домашнем каталоге пользователя freeswitch на другом сервере. Проверим, что пользователь freeswitch с одного сервера может войти по ssh на другой сервер без ввода пароля:
$ sudo su -l freeswitch $ ssh <address> Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-62-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage Last login: Wed Feb 22 11:27:59 2017 from 192.168.0.61 $
Теперь, когда каждый из серверов может соединиться по SSH со своим собратом, настроим синхронизацию файлов конфигурации и записей переговоров. Для этого добавим в /etc/crontab каждого сервера такие записи:
*/5 * * * * freeswitch rsync -au -e ssh /etc/freeswitch/ <address>:/etc/freeswitch/ */5 * * * * freeswitch rsync -au -e ssh /var/lib/freeswitch/recordings/ <address>:/var/lib/freeswitch/recordings/
В вышеприведенном примере файлы синхронизируются каждые 5 минут.
Для более равномерного распределения нагрузки на сеть можно настроить серверам разное время синхронизации, например:
0-59/5 * * * * freeswitch rsync -au -e ssh /etc/freeswitch/ ....... 1-59/5 * * * * freeswitch rsync -au -e ssh /var/lib/freeswitch/recordings/ ........
на первом сервере и
2-59/5 * * * * freeswitch rsync -au -e ssh /etc/freeswitch/ ....... 3-59/5 * * * * freeswitch rsync -au -e ssh /var/lib/freeswitch/recordings/ ........
на втором сервере.
Проверим работу синхронизации: на первом сервере создадим новый файл в /var/lib/freeswitch/recordings/ и изменим какой-нибудь файл в /etc/freeswitch/. Подождем 5 минут и убедимся, что на втором сервере появился новый файл в /var/lib/freeswitch/recordings/ и отразилось изменение файла в /etc/freeswitch/. Аналогично проверим копирование в обратном направлении.
Переключение на резерв
Далее будет описано два варианта настройки переключения на резервный сервер:
- автоматическое переключение;
- ручное переключение.
Автоматическое переключение
Для автоматического переключения будем использовать протокол VRRP и демон keepalived. Устанавливаем пакет keepalived:
$ sudo apt-get install keepalived
Конфигурируем keepalived. Сначала создадим скрипт /etc/keepalived/ka-master.pl, который будет передавать FreeSwitch команду sofia recover при переходе сервера в состояние MASTER:
#!/usr/bin/perl my $password = "secret"; open(STDOUT, "|/usr/bin/logger -t ka-master"); print "Instance went to master, issuing sofia recover.\n"; system("/usr/bin/fs_cli", "-p$password", "-x", "sofia recover");
где "secret" меняем на наш пароль доступа к event-socket FreeSwitch. Так как файл содержит пароль, не забываем установить ему права доступа, разрешающие чтение только для пользователя root:
$ sudo chown root:root /etc/keepalived/ka-master.pl $ sudo chmod 700 /etc/keepalived/ka-master.pl
Создаем базовый файл конфигурации /etc/keepalived/keepalived.conf:
global_defs { router_id FREESW } vrrp_instance VI_FREESW { state BACKUP interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass labuda25 } notify_master "/etc/keepalived/ka-master.pl" virtual_ipaddress { 192.168.0.63/24 dev eth0 label eth0:0 } }
где "eth0" - имя сетевого интерфейса, "eth0:0" - алиас с общим адресом - меняем их в соответствии с именем интерфейса каждого сервера.
Запускаем keepalived на одном из серверов:
$ sudo service keepalived start
Контролируем в /var/log/syslog, что демон успешно запустился и, так как на втором сервере keepalived еще не запуцщен, сразу после запуска keepalived должен перейти в состояние MASTER. Контролируем, что у сервера появился адрес 192.168.0.63.
Теперь запускаем keepalived на втором сервере. Контролируем, что демон запустился, на находится в состоянии BACKUP, так как в сети уже есть MASTER.
Контролируем переход сервера из состояния BACKUP в состояние MASTER. Для этого на несколько секунд отключаем активный в данный момент MASTER от сети (или просто останавливаем на нем демон keepalived). Контролируцем, что сервер, находившийся в состоянии BACKUP, перешел в состояние MASTER.
На данном этапе у нас настроен переход сервера из резерва в активное состояние по единственному критерию - недоступности мастера, определяемой по протоколу VRRP. Теперь добавим сюда контроль работоспособности FreeSwitch. Для этого создаем скрипт /etc/keepalived/ka-status.sh:
#!/bin/sh password="secret"; profiles="internal internal6"; # Если общий адрес еще не поднят, возвращаем успех. arping -q -c3 -W0.1 192.168.0.63 || exit 0 # Если общий адрес поднят, проверяем работоспособность FreeSwitch RESULT=`/usr/bin/fs_cli -p$password -x "sofia xmlstatus"` for P in $profiles; do echo $RESULT | grep -q "<name>$P</name>" || exit 1 done exit 0;
где "secert" заменяем на пароль доступа к event-socket FreeSwitch-сервера, а переменной profiles
присваиваем имена SIP-профилей, наличие которых необходимо контролировать. Теперь, если все перечисленные в profiles
профили запущены, скрипт вернет 0, иначе - 1.
Если требуется контролировать только один профиль, скрипт можно сделать более лаконичным:
#!/bin/sh password="secret"; profile="internal"; # Если общий адрес еще не поднят, возвращаем успех. arping -q -c3 -W0.1 192.168.0.63 || exit 0 # Если общий адрес поднят, проверяем работоспособность FreeSwitch /usr/bin/fs_cli -p$password -x "sofia xmlstatus" | grep -q "<name>${profile}</name>" || exit 1 exit 0;
arping в начале скрипта нужен для разрешения проблемы яйца и курицы: keepalived не перейдет в состояние MASTER и не поднимет на сетевом интерфейсе общий адрес, пока наш скрипт не вернет 0, в то же время профиль FreeSwitch не сможет стартовать, пока в сети не поднят общий адрес, так как именно этот адрес используется для подключения к базе данных. Благодаря строчке с arping при включении первого из двух серверов, когда общего адреса еще нет, скрипт вернет 0, keepalived успешно перейдет в состояние MASTER и активирует общий адрес.
Проверим функционирование скрипта, запустив его вручную. Если все хорошо, укажем keepalived проверять работоспособность FreeSwitch каждые 10 секунд. Для этого в /etc/keepalived/keepalived.conf добавляем секцию с описанием скрипта:
vrrp_script chk_fs { script "/etc/keepalived/ka-status.sh" interval 10 }
и в секцию vrrp_instance VI_FREESW
добавляем указание использовать этот скрипт:
track_script { chk_fs }
Перезапустим keepalived:
$ sudo service keepalived restart
Контролируем, что сервер в состоянии BACKUP. Теперь подключаемся к консоли FreeSwitch и останавливаем профиль internal:
> sofia profile internal stop
Ждем 10 секунд и контролируем, что keepalived перешел в состояние FAULT.
Ручное переключение
Attachments (1)
- pic1.jpg (19.5 KB ) - added by 8 years ago.
Download all attachments as: .zip