понедельник, 9 июня 2014 г.

"Полувысокая" доступность сервиса

Столкнулся со следующей задачей: есть два сервера с развернутым на них СУБД Oracle, один из серверов основной рабочий, второй, соответственно, резервный, операционная система - oel 6. При смене ролей серверов (не буду рассказывать о методе резервирования и процедуре смены, поскольку к теме заметки это не относится), основной становится резервным и наоборот. Все хорошо, но как нетрудно догадаться, на клиентах придется менять IP адрес подключения, что может доставить определенные трудности и затраты времени. Реализовывать варианты HA для IP адреса поздновато, т.к. все работает и времени простоя на внедрение и отладку нет, и просто не имеет смысла т.к. смена ролей серверов производится вручную. В таком случае, напрашивается сразу решение - вынести ip подключения как alias на сетевой интерфейс и переносить его при смене ролей. Это просто, логично, но есть следующая трудность - при переносе IP адреса меняется физический интерфейс и, как следствие, MAC адрес. Таким образом, для того чтобы пакеты пошли на новый интерфейс, необходимо у каждого клиента обновить ARP запись для этого IP адреса. Это можно сделать с помощью пакета ARP оповещения, т.е. сервер, на который "переехал" IP адрес должен отправить широковещательный пакет c новым IP и с mac адресом своего интерфейса. Это можно реализовать с помощью утилиты send_arp. Man страничка для нее несколько запутанно написана, поэтому немного о том, как ее использовать.

send_arp [-i dev] src_ip_addr src_hw_addr targ_ip_addr tar_hw_addr

Итого, допустим, что переносимый IP - 192.168.10.10, интерфейс eth2 и MAC этого интерфейса - 94:de:82:a8:4f:0c, тогда:

send_arp -i eth2 192.168.10.10 94:de:82:a8:4f:0c 192.168.10.10 ffffffffffff

Непонятно почему такие targ_ip_addr и tar_hw_addr? IP адрес назначения, в пакете анонсирования должен быть идентичен IP источника, см RFC 3927. MAC адрес назначения должен быть широковещательным.
Где взять саму утилиту? Она входит в состав пакета piranha, естественно, нет смысла ставить сам пакет и зависимости. Ставим:

# yum install yum-plugin-downloadonly
# yum --downloadonly install piranha
# rpm2cpio /var/cache/yum/x86_64/6Server/public_ol6_latest/packages/piranha-0.8.6-4.0.1.el6.x86_64.rpm | cpio -iumd ./usr/sbin/send_arp
# mv usr/sbin/send_arp /usr/sbin/

Можно уже пользоваться, а можно написать небольшой скрипт, для удобства использования. Входные данные для скрипта - имя alias'а, а так же IP адрес и сетевая маска. Разместим эти данные в файле:


# cat /etc/ipalias.conf
alias_name=eth2:1
alias_ip=192.168.10.10
alias_netmask=255.255.255.0
Собственно сам скрипт:

# cat /usr/local/bin/ipalias.sh
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
. /etc/ipalias.conf
interface_name=`echo $alias_name | awk -F: '{ print $1 }'`
new_mac=`ifconfig $interface_name | grep HWaddr | awk -FHWaddr '{ print $2 }'`
case "$1" in
  up)
        #Up alias
        ping -c 1 $alias_ip > /dev/null 2>&1
        OUT=$?
        if [ "$OUT" == "0" ]
          then
            echo "ERROR! IP $alias_ip is exist"
            exit 1
          else
            ifconfig $alias_name $alias_ip netmask $alias_netmask
            send_arp -i $interface_name $alias_ip $new_mac $alias_ip ffffffffffff
        fi
        ;;
  down)
        #Down alias
        ifconfig -a | grep $alias_name > /dev/null 2>&1
        OUT=$?
        if [ "$OUT" != "0" ]
          then
            echo "ERROR! Interface $alias_name is not exist"
            exit 1
          else
            ifconfig $alias_name down
        fi
        ;;
  *)
        echo
        echo "Usage:"
        echo "$0 up"
        echo "  or"
        echo "$0 down"
        echo
        echo "/etc/ipalias.conf - Configuration file"
        echo
        ;;
esac