Wednesday, August 9, 2017

Freeswitch HA mode based on Keepalived.

Idea to have 2 instances of Freeswitch in Master-Slave mode, if one node dies, second will automatically takeover calls with 2-3 seconds lag. Yep, media would be restored.

Main scheme is looks like this



We need 3 IP's. 2 for nodes and 1 for floating.

Solution based on this, but with a bit of additional config.
Used Debian 8x64 as a host OS.
Assume, that we have FreeSWITCH'es already installed.

Install keepalived on both nodes.

apt-get install keepalived

Create files on both nodes

/etc/keepalived/keepalived.conf

global_defs {
    router_id FREESW
}

vrrp_script chk_fs {
    script "/etc/keepalived/scripts/ka-status.pl"
    interval 1
}

vrrp_instance VI_FREESW {
    # replace with SLAVE on a slave node
    state MASTER
    # change to SLAVE on slave node
    interface <YOUR_INTERFACE_HERE>
    #interface eth0
    virtual_router_id <YOUR_ROUTER_ID>
    # virtual_router_id 15
    # higher is preferred for master
    # disable to have failover be sticky
    priority 1
    advert_int 1
    unicast_src_ip <CURRENT_NODE_IP>
    #unicast_src_ip 192.168.10.10
    unicast_peer {
        <SLAVE_NODE_IP>
        #192.168.10.11
    }
    authentication {
        auth_type PASS
        auth_pass YourPassHere
    }
    notify "/etc/keepalived/scripts/ka-notify.pl"
    virtual_ipaddress {
        <FLOATING_IP/CIDR> dev <YOUR_INTERFACE_HERE>
       # 192.168.0.15/24 dev eth0 - Example
    }
    track_script {
        chk_fs
    }
}

/etc/keepalived/scripts/ka-notify.pl
#!/usr/bin/perl

# INSTANCE|VI_FREESW|BACKUP|50
my ($what,$id,$state,$prio) = @ARGV;
open(STDOUT, "|/usr/bin/logger -t ka-notify");

print "what($what) id($id) state($state) prio($prio)\n";

if ( $state eq "MASTER" )
{
    print "Instance went to master, issuing sofia recover.\n";
    system("/usr/bin/fs_cli", "-x", "sofia recover");
}


/etc/keepalived/scripts/ka-status.pl
#!/usr/bin/perl

use Sys::Syslog;
openlog "ka-status", "ndelay,pid", "local0";

my @required = ("internal", "external");

my %saw = ();
open(my $in, "-|") || exec("/usr/bin/fs_cli", "-x", "sofia xmlstatus");
while ( defined(my $line = <$in>) )
{
    if ( $line =~ m|<name>(.*)</name>|o )
    {
        $saw{$1} = 1;
    }
}
close($in);

foreach my $profile ( @required )
{
    if ( ! $saw{$profile} )
    {
        syslog(LOG_INFO, "sip profile $profile not found, marking failure");
        exit(1);
    }
}
exit(0);


chmod +x /etc/keepalived/scripts/*.pl
echo "net.ipv4.ip_nonlocal_bind = 1" >>  /etc/sysctl.conf 

Make sure, that FreeSWITCH'es uses same runtime database and uses same hostname in switch.conf Also profiles you control, need to listen on FLOATING_IP address.
Better reboot here.

service keepalived start

To check state, best is to use ip addr show. On which node FLOATING_IP address is, this is master :)

You can play with priority parameter in keepalived.conf file to make one node Master at all cases.
Point, there is a issue, when you restore calls on one node, you can't get same calls back with sofia recover.

2 comments:

  1. Hi, thank you so much for writing this post. I followed exactly same method but floating IP doesn't get assigned to any freeswitch server and we keep getting below errors on both freeswitch servers.

    Mar 31 09:46:55 fs-ha-2 Keepalived_vrrp[5333]: Opening script file /etc/freeswitch/ka-notify.pl
    Mar 31 09:46:55 fs-ha-2 Keepalived_vrrp[5333]: Opening script file /etc/freeswitch/ka-notify.pl
    Mar 31 09:46:55 fs-ha-2 ka-notify: what(INSTANCE) id(VI_FREESW) state(FAULT) prio(1)
    Mar 31 09:46:55 fs-ha-2 ka-notify: what(INSTANCE) id(VI_FREESW) state(FAULT) prio(1)
    Mar 31 09:47:01 fs-ha-2 ka-status[5353]: sip profile internal not found, marking failure
    Mar 31 09:47:01 fs-ha-2 ka-status[5352]: sip profile internal not found, marking failure

    Any suggestions please? Thanks


    ReplyDelete
  2. # service keepalived start
    ->it ran successfully but after checking the "service keepalived status" it
    is showing error "sip profile internal not found".

    # service freeswitch status
    -> freeswitch working fine but when inside FS cli when i type "sofia status profile internal"
    -> it showed me "Invalid Profile!!" message.

    #ip -br a
    running this command showed me that there is no Virtual IP assigned to the interface of MASTER.

    I don't know the solution to this but i think it has something to do with configurations of Freeswitch maybe inside "/usr/local/freeswitch/conf/autoload_configs/sip_profiles" . But i have assigned both internal & external.xml with virtual IP but still the same error. I have used "Freeswitch with Fred HA" video on Youtube to update the configurations similar to him. But still the same error is coming up.

    Any suggestions might be helpful for me.

    ReplyDelete