KB 2444: HIGH AVAILABILITY WITH OLFEO SERVERS

Published November 28, 2023Amended on February 29, 2024

How to set up high availability on Olfeo servers.

Objective

Set up high availability with the VRRP protocol to use a virtual IP for Olfeo service continuity on one of the cluster members.

Steps

1. On the master machine, in the Settings > High availability > Olfeo domain page, click on Add a slave :

The Slave Machine screen appears. Add the IP address of the future slave machine:

On the slave machine, enter the ID supplied by the master machine and the master IP to be able to join the Olfeo domain, then confirm:

A page of patience will then indicate that the connection to the domain is in progress:

Log in using an administrator account on the master machine: only menus specific to local machine configuration appear. The graphical interface now indicates that the server is in slave mode:

Refresh the Olfeo domain page on the master machine: slavestatus changes to Online

2. The second step is to create a cluster so that each member has a virtual IP. Click on the Add a cluster link:

Enter a number between 1 and 254 in the First VRRP ID field. The first VRRP ID is an identifier to be used for node management.

For each machine previously added to the Olfeo cluster, enter a virtual IP address in the Virtual IP column.

 

Load distribution by proxy.pac

Load balancing between nodes can be achieved by implementing a .pac proxy, as in one of the three examples below:

  • Example 1: high availability (fail over).

    function FindProxyForURL(url, host) {

    // Ne passe pas par le proxy si le host n’est pas un FQDN.
    if (isPlainHostName(host))
    return « DIRECT »;

    // Exceptions : Ne pas passer par le proxy si l’URL match les regex suivantes :
    if (shExpMatch(url, »*domain.com* ») || shExpMatch(url, »*vpn.domain.com* »))
    return « DIRECT »;

    // Ne pas passer par le proxy si les noms d’hôtes de destination sont sur le réseau local.

    var resolved_ip = dnsResolve(host);

    if (isInNet(resolved_ip, " 10.0.0.0 ", " 255.0.0.0 ") || perform replication
    isInNet(resolved_ip, " 172.16.0.0 ", " 255.240.0.0 ") ||
    isInNet(resolved_ip, " 192.168.0.0 ", " 255.255.0.0 ") ||
    isInNet(resolved_ip, " 127.0.0.0 ", " 255.255.255.0 "))
    return "DIRECT";

    // Ne pas passer par le proxy entreprise si l’utilisateur n’est pas connecté au LAN entreprise.
    if (!isInNet(myIpAddress(), « 10.10.1.0 », « 255.255.255.0 »))
    return « DIRECT »;

    // Tout le reste passe par le proxy entreprise.
    //exemple 1 : Un seul proxy :
    return « PROXY proxy.mondomaine.tld:3129 »;

    //exemple 2 : 2 proxy en Fail Over
    // return « PROXY proxy1.mondomaine.tld:3129; PROXY proxy2.mondomaine.tld:3129; DIRECT »;
    }

  • Example 2: use of a protocol-specific proxy.

    function FindProxyForURL(url, host) {

    // Si l’hôte de destination (FQDN ou IP) est interne : ne pas passer par le proxy.

    var resolved_ip = dnsResolve(host);

    if (isInNet(resolved_ip, " 10.0.0.0 ", " 255.0.0.0 ") ||
    isInNet(resolved_ip, " 172.16.0.0 ", " 255.240.0.0 ") ||
    isInNet(resolved_ip, " 192.168.0.0 ", " 255.255.0.0 ") ||
    isInNet(resolved_ip, " 127.0.0.0 ", " 255.255.255.0 "))
    return "DIRECT";

    // Utiliser un proxy différent en fonction du protocole.
    if (shExpMatch(url, « http:* »))  return « PROXY proxy1.mondomain.tld:3129 »;
    if (shExpMatch(url, « https:* »)) return « PROXY proxy2.mondomain.tld:3129 »;
    if (shExpMatch(url, « ftp:* »)) return « PROXY proxy3.mondomain.tld:3129 »;

    }

  • Example 3: load balancing.
    function FindProxyForURL(url, host)
    {// Does not go through the proxy if the host is not an FQDN.
    if (isPlainHostName(host))
    return "DIRECT";

    // Exceptions : ne pas passer par le proxy si l’URL match les regex suivantes.
    if (shExpMatch(url, »*domain.com* ») || shExpMatch(url, »*vpn.domain.com* »))
    return « DIRECT »;

    // Ne pas passer par le proxy si les noms d’hôtes de destination sont internes.

    var resolved_ip = dnsResolve(host);

    if (isInNet(resolved_ip, " 10.0.0.0 ", " 255.0.0.0 ") ||
    isInNet(resolved_ip, " 172.16.0.0 ", " 255.240.0.0 ") ||
    isInNet(resolved_ip, " 192.168.0.0 ", " 255.255.0.0 ") ||
    isInNet(resolved_ip, " 127.0.0.0 ", " 255.255.255.0 "))
    return "DIRECT";

    // Ne pas passer par le proxy entreprise si l’utilisateur n’est pas connecté au LAN entreprise.
    if (!isInNet(myIpAddress(), « 10.10.1.0 », « 255.255.255.0 »))
    return « DIRECT »;

    // On retourne une chaîne de proxy en fonction du hash de l’URL modulo le nombre de proxy. Ceci permet d’obtenir à la fois une répartition de charge et une tolérance aux pannes.
    ret = URLhash(url);

    if ( (ret % 2) == 0 ) {
    return « PROXY proxy1.mondomaine.tld:3129 ; PROXY proxy2.mondomaine.tld:3129  » ;
    } else  {
    return « PROXY proxy2.mondomaine.tld:3129 ; PROXY proxy1.mondomaine.tld:3129  » ;
    }

    }

    function URLhash(name)
    {
    var  cnt=0;
    var str=name.toLowerCase(name);

    if ( str.length ==0) {
    return cnt;
    }

    for(var i=0;i < str.length ; i++) {
    var ch= atoi(str.substring(i,i + 1));
    cnt = cnt + ch;
    }

    return cnt ;
    }

    function atoi(charstring)
    {

    if ( charstring == " a " ) return 0x61; if ( charstring == " b " ) return 0x62;
    if ( charstring == " c " ) return 0x63; if ( charstring == " d " ) return 0x64;
    if ( charstring == " e " ) return 0x65; if ( charstring == " f " ) return 0x66;
    if ( charstring == " g " ) return 0x67; if ( charstring == " h " ) return 0x68;
    if ( charstring == " i " ) return 0x69; if ( charstring == " j " ) return 0x6a;
    if ( charstring == " k " ) return 0x6b; if ( charstring == " l " ) return 0x6c;
    if ( charstring == " m " ) return 0x6d; if ( charstring == " n " ) return 0x6e;
    if ( charstring == " o " ) return 0x6f; if ( charstring == " p " ) return 0x70;
    if ( charstring == " q " ) return 0x71; if ( charstring == " r " ) return 0x72;
    if ( charstring == " s " ) return 0x73; if ( charstring == " t " ) return 0x74;
    if ( charstring == " u " ) return 0x75; if ( charstring == " v " ) return 0x76;
    if ( charstring == " w " ) return 0x77; if ( charstring == " x " ) return 0x78;
    if ( charstring == " y " ) return 0x79; if ( charstring == " z " ) return 0x7a;
    if ( charstring == " 0 " ) return 0x30; if ( charstring == " 1 " ) return 0x31;
    if ( charstring == " 2 " ) return 0x32; if ( charstring == " 3 " ) return 0x33;
    if ( charstring == " 4 " ) return 0x34; if ( charstring == " 5 " ) return 0x35;
    if ( charstring == " 6 " ) return 0x36; if ( charstring == " 7 " ) return 0x37;
    if ( charstring == " 8 " ) return 0x38; if ( charstring == " 9 " ) return 0x39;
    if ( charstring == " . " ) return 0x2e;
    return 0x20;
    }

Validation

  • Prefer the "ip a" command to "ifconfig" for an exact reading of virtual IP parameters.
  • Check the IP configuration of each cluster member. Each cluster member must have 2 IPs (one physical and one virtual).
  • On the master server, stop the keepalived service (/etc/init.d/keepalived stop); the slave server must retrieve the master's virtual IP.
  • Restart the keepalive service on the master server (/etc.init.d/keepalived start). The master server must recover its virtual IP and the slave must not keep it.
WARNING!
When updating Olfeo, always start with the master machine.