Skip to main content

Command Palette

Search for a command to run...

Freepbx 17 (Debian) отказоустойчивый кластер, бесплатно

Updated
•4 min read•View as Markdown

Для реалезации отказоустойчевого кластера на Freepbx 17 будем использовать CARP протокол. Устанавливаем два сервера Freepbx на которых будет настроен отказоустойчивый кластер.

Freepbx01(Master) - 192.168.121.214

Freepbx02(Slave) - 192.168.121.215

HA(общий адрес) - 192.168.121.14

  1. Редактируем файлы конфигурации:

Freepbx01(Master) - 192.168.121.214

cat /etc/network/interfaces

auto lo
iface lo inet loopback

auto ens192
iface ens192 inet static
    address 192.168.121.214
    netmask 255.255.255.0
    gateway 192.168.121.1

    ucarp-vid 3
    ucarp-vip 192.168.121.14
    ucarp-password 12qwae21sS
    ucarp-advbase 1
    ucarp-advskew 0
    ucarp-master yes
iface ens192:ucarp inet static
        address 192.168.121.14
        netmask 255.255.255.0

Carp интерфейс появился 192.168.121.14. Также добавляю скрипт который будет мониторить состояние сервиса asterisk, и если по какой то причине он не работает, то интерфейс CARP будет отключен, соответственно все устройства переподключатся на резервный сервер, так как он станем Мастером.

sudo mkdir -p /var/log/ucarp-watchdog
sudo touch /var/log/ucarp-watchdog/watchdog.log
sudo chmod 664 /var/log/ucarp-watchdog/watchdog.log

sudo mcedit /usr/local/bin/ucarp-watchdog.sh

#!/bin/bash

LOG="/var/log/ucarp-watchdog/watchdog.log"
NIC="ens192"
TARGET_IP="192.168.121.14/24"    # IP з префіксом, який має бути на інтерфейсі
ASTERISK_BINARY="/usr/sbin/asterisk"

mkdir -p /var/log/ucarp-watchdog

echo "$(date '+%F %T') UCARP Watchdog started" >> "$LOG"

ASTERISK_WAS_DOWN=0       # 0 = раніше був UP (або стартовий стан), 1 = виявлено DOWN
NETWORK_RESTARTED=0      # 0 = ще не рестартували після останнього підняття Asterisk, 1 = рестарт вже зроблено

while true; do
    # Лог часу перевірки
    TS="$(date '+%F %T')"
    echo "$TS CHECK: start" >> "$LOG"

    # Перевіряємо чи процес Asterisk існує (повний шлях)
    if pgrep -f "$ASTERISK_BINARY" > /dev/null ; then
        echo "$TS CHECK: Asterisk process FOUND" >> "$LOG"

        # Якщо раніше був DOWN (тобто тепер відновився) — помітимо відновлення
        if [ $ASTERISK_WAS_DOWN -eq 1 ]; then
            echo "$TS INFO: Asterisk recovered" >> "$LOG"
            # скидаємо прапорець NETWORK_RESTARTED, щоб дозволити рестарт мережі при потребі
            NETWORK_RESTARTED=0
            ASTERISK_WAS_DOWN=0
        fi

        # Перевіряємо наявність CARP-IP на інтерфейсі
        if ip a show dev "$NIC" | grep -qF "$TARGET_IP"; then
            echo "$TS INFO: $TARGET_IP is present on $NIC" >> "$LOG"
            # якщо IP є — нічого не робимо
            NETWORK_RESTARTED=1
        else
            echo "$TS WARN: $TARGET_IP NOT found on $NIC" >> "$LOG"
            # Якщо Asterisk працює і ми ще не рестартували мережу під час цієї сесії → рестарт
            if [ $NETWORK_RESTARTED -eq 0 ]; then
                echo "$TS ACTION: restarting networking.service because Asterisk is running but $TARGET_IP is missing" >> "$LOG"
                systemctl restart networking.service >> "$LOG" 2>&1
                if [ $? -eq 0 ]; then
                    echo "$TS OK: networking.service restarted" >> "$LOG"
                else
                    echo "$TS ERROR: networking.service restart failed" >> "$LOG"
                fi
                NETWORK_RESTARTED=1
            else
                echo "$TS INFO: networking already restarted once while Asterisk is up; skipping" >> "$LOG"
            fi
        fi

    else
        # Asterisk не працює
        echo "$TS CHECK: Asterisk process NOT FOUND" >> "$LOG"

        # Якщо тільки-но впав — вбити ucarp і поставити прапорець DOWN
        if [ $ASTERISK_WAS_DOWN -eq 0 ]; then
            echo "$TS ACTION: Asterisk DOWN detected → killing UCARP" >> "$LOG"
            pkill ucarp >> "$LOG" 2>&1 || true
            ASTERISK_WAS_DOWN=1
        else
            echo "$TS INFO: Asterisk still down" >> "$LOG"
        fi

        # Скидаємо прапорець NETWORK_RESTARTED, щоб при наступному піднятті Asterisk була нова спроба рестарту мережі
        NETWORK_RESTARTED=0
    fi

    echo "$TS CHECK: end" >> "$LOG"
    sleep 60
done

sudo chmod +x /usr/local/bin/ucarp-watchdog.sh

sudo nano /etc/systemd/system/ucarp-watchdog.service

[Unit]
Description=UCARP Asterisk Watchdog
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/ucarp-watchdog.sh
Restart=always
RestartSec=5
User=root
StandardOutput=append:/var/log/ucarp-watchdog/watchdog.log
StandardError=append:/var/log/ucarp-watchdog/watchdog.log

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable ucarp-watchdog
sudo systemctl start ucarp-watchdog

Проверка

systemctl status ucarp-watchdog

tail -f /var/log/ucarp-watchdog/watchdog.log

  1. Freepbx02(Secondory) - 192.168.121.215
auto lo
iface lo inet loopback

auto ens192
iface ens192 inet static
    address 192.168.121.215
    netmask 255.255.255.0
    gateway 192.168.121.1

    ucarp-vid 3
    ucarp-vip 192.168.121.14
    ucarp-password 12qwae21sS
    ucarp-advbase 1
    ucarp-advskew 100
    ucarp-master no

iface ens192:ucarp inet static
        address 192.168.121.14
        netmask 255.255.255.0

Install zabbix

apt install zabbix-agent2

mcedit /etc/sudoers

zabbix ><------>ALL=(ALL) NOPASSWD: /usr/sbin/asterisk

usermod -aG asterisk zabbix systemctl restart zabbix-agent2

Время

ln -sf /usr/share/zoneinfo/Europe/Kiev /etc/localtime

Настройка file2ban уведомлений через Graylog

mcedit /etc/rsyslog.d/30-fail2ban.conf

module(load="imfile")

input(
  type="imfile"
  File="/var/log/fail2ban.log"
  Tag="fail2ban:"
  Severity="info"
  Facility="local0"
)

local0.* action(
  type="omfwd"
  target="192.168.96.20"
  port="514"
  protocol="udp"
)

sudo systemctl restart rsyslog

Вариант 2 отправка всех системных логов. mcedit /etc/rsyslog.conf

*.* @Ip_your_server:12223

Отправка логов Asterisk mcedit /etc/rsyslog.conf добавляю

#Asterisk full log                        
module(load="imfile")                     
input(type="imfile"                       
      File="/var/log/asterisk/full"       
      Tag="asterisk"                      
      Severity="info"                     
      Facility="local6")                  

#File2ban log
input(type="imfile"
      File="/var/log/fail2ban.log"
      Tag="fail2ban"
      Severity="info"
      Facility="local6")

Перезапуск

systemctl restart rsyslog
systemctl status rsyslog