postgresql 高可用 etcd + patroni 之八 haproxy + keepalived

os: ubuntu 16.04
postgresql: 9.6.9
etcd: 3.2.18
patroni: 1.4.4
haproxy: 1.6.3
keepalived: 1.2.24html

ip規劃
192.168.56.101 node1 master
192.168.56.102 node2 slave
192.168.56.103 node3 slave
192.168.56.104 node4 slave
192.168.56.105 node5 slavenode

192.168.56.201 haproxy1
192.168.56.202 haproxy2web

192.168.56.210 keepalived vip
192.168.56.211 keepalived vip
192.168.56.212 keepalived vipsql

keepalived 是 ha 的一把利器,應用範圍極廣,這裏主要用來對 haproxy 作高可用。關於 keepalived 的更多知識,能夠自行baidu。ubuntu

安裝、配置好haproxy

haproxy一、haproxy2節點都須要作
詳細過程略,參考上一篇blogbash

安裝 keepalived

# apt install keepalived
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  ipvsadm libnl-route-3-200 libsensors4 libsnmp-base libsnmp30
Suggested packages:
  heartbeat ldirectord lm-sensors snmp-mibs-downloader
The following NEW packages will be installed:
  ipvsadm keepalived libnl-route-3-200 libsensors4 libsnmp-base libsnmp30
0 upgraded, 6 newly installed, 0 to remove and 171 not upgraded.
Need to get 1,427 kB of archives.
After this operation, 5,570 kB of additional disk space will be used.
Do you want to continue? [Y/n]

去除了 /usr/share/snmp、/usr/share/doc、/usr/share/man微信

# dpkg -L keepalived
/.
/usr
/usr/lib
/usr/lib/systemd
/usr/lib/systemd/system
/usr/lib/systemd/system/keepalived.service
/usr/bin
/usr/bin/genhash
/usr/share
/usr/sbin
/usr/sbin/keepalived
/lib
/lib/systemd
/lib/systemd/system
/lib/systemd/system/keepalived.service
/etc
/etc/keepalived
/etc/default
/etc/default/keepalived
/etc/init.d
/etc/init.d/keepalived

查看 keepalived.serviceide

# more /lib/systemd/system/keepalived.service 
[Unit]
Description=Keepalive Daemon (LVS and VRRP)
After=network-online.target
Wants=network-online.target
# Only start if there is a configuration file
ConditionFileNotEmpty=/etc/keepalived/keepalived.conf

[Service]
Type=forking
KillMode=process
PIDFile=/var/run/keepalived.pid
# Read configuration variable file if it is present
EnvironmentFile=-/etc/default/keepalived
ExecStart=/usr/sbin/keepalived $DAEMON_ARGS
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

查看 /etc/init.d/keepalivedsvg

# more /etc/init.d/keepalived

#! /bin/sh
#
# keepalived   LVS cluster monitor daemon.
#
#              Written by Andres Salomon <dilinger@voxel.net>
#
### BEGIN INIT INFO
# Provides:          keepalived
# Required-Start:    $syslog $network $remote_fs
# Required-Stop:     $syslog $network $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts keepalived
# Description:       Starts keepalived lvs loadbalancer
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/keepalived
NAME=keepalived
DESC=keepalived
CONFIG=/etc/keepalived/keepalived.conf
TMPFILES="/tmp/.vrrp /tmp/.healthcheckers"

#includes lsb functions 
. /lib/lsb/init-functions

test -f $CONFIG || exit 0 
test -f $DAEMON || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

case "$1" in
  start)
	log_daemon_msg "Starting $DESC" "$NAME"
	for file in $TMPFILES
	do 
       		test -e $file && test ! -L $file && rm $file
	done
	if start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
               --exec $DAEMON -- $DAEMON_ARGS; then
		log_end_msg 0
	else
		log_end_msg 1
	fi
       ;;
  stop)
	log_daemon_msg "Stopping $DESC" "$NAME"
	if start-stop-daemon --oknodo --stop --quiet --pidfile /var/run/$NAME.pid \
        	--exec $DAEMON; then
		log_end_msg 0
	else
		log_end_msg 1
	fi
       ;;
  reload|force-reload)
	log_action_begin_msg "Reloading $DESC configuration..."
      	if start-stop-daemon --stop --quiet --signal 1 --pidfile \
               /var/run/$NAME.pid --exec $DAEMON; then
	       log_end_msg 0
	else
		log_action_end_msg 1
	fi
       ;;
  restart)
  	log_action_begin_msg "Restarting $DESC" "$NAME"

       	start-stop-daemon --stop --quiet --pidfile \
		/var/run/$NAME.pid --exec $DAEMON || true 
       sleep 1
       if start-stop-daemon --start --quiet --pidfile \
               /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_ARGS; then
	       log_end_msg 0
	else
		log_end_msg 1
	fi
       ;;
  *)
       echo "Usage: /etc/init.d/$NAME {start|stop|restart|reload|force-reload}" >&2
       exit 1
       ;;
esac

exit 0

配置 keepalived

注意:能夠修改 state爲 MASTER、BACKUPpost

# vi /etc/keepalived/keepalived.conf


! Configuration File for keepalived    #! 表示註釋
global_defs {
        router_id LVS_HAProxy1                  # 路由標示,相同局域網內惟一
}

vrrp_script chk_health {
        script "/etc/keepalived/scripts/health_check.sh"   # 監控腳本
        interval 5   # 每隔5s探測一次
        fall 5       # 連續檢測5次失敗後,則進行切換IP
        rise 5       # 5次檢測成功後將OK

}


vrrp_instance VI_HAProxy {                      # 定義VRRP熱備實例
        state MASTER                            # 熱備狀態,MASTER(主);SLAVE(從);BACKUP(備份);只能有一個MASTER
        interface eno1                          # 承載VIP地址的物理接口
        virtual_router_id 51                    # 虛擬路由器的ID號,組內保存一致
        priority 100                            # 優先級,數值越大優先級越高。
        advert_int 2                            # 主備之間的通告間隔秒數(心跳頻率)
        nopreempt                               # 不搶佔,只在優先級高的機器上設置便可,優先級低的機器不設置
        authentication {                        # 認證信息,每一個熱備組保持一致
                auth_type PASS                  # 認證類型,主備切換時的驗證
                auth_pass 1qaz                  # 密碼字串
        }
        track_script {
                chk_health
        }
        virtual_ipaddress {                     # 指定漂移地址(VIP),能夠有多個
                192.168.56.210/24 dev eno1 label eno1:1
                192.168.56.211/24 dev eno1 label eno1:2
                192.168.56.212/24 dev eno1 label eno1:3
        } 
        notify_master /etc/keepalived/scripts/lvs_notify_master.sh     # 切換成爲主時的通知
        notify_backup /etc/keepalived/scripts/lvs_notify_backup.sh     # 切換成爲備時的通知
        notify_fault  /etc/keepalived/scripts/lvs_notify_fault.sh      # 調用失敗時的通知
}

/etc/keepalived/scripts/health_check.sh

#!/bin/bash
# 檢查本身是否能夠成爲主 0:能夠 大於0:不能夠

IP_GATEWAY="192.168.56.1"
IP_LIST=$IP_GATEWAY" 192.168.56.201 192.168.56.202"

logfile="/var/log/keepalived_lvs_status.log"
log() {
	now=`date`
	content=$1
	echo  ${now}":"${content}  >>$logfile
}

ping_status() {
    IP=$1
    for ((i=1;i<=3;i++)); do
        if ping -c 1 -W 1 $IP >/dev/null; then
            #log "$IP Ping is successful."
            return 0
        else
            log "$IP Ping is failure " 
        fi
    done
    #三次都沒有ping通,按失敗處理。
    if [ "$IP" = "$IP_GATEWAY" ] ;then
        return 99
    else
        return 1
    fi
}

log '---------- health check start ...---------'

FAIL_COUNT=0
for IP in $IP_LIST; do
    log "ping $IP ..."
    ping_status $IP
    ret=$?
    FAIL_COUNT=$(($FAIL_COUNT+$ret))
done

log "fail ping num:$FAIL_COUNT"


if [ $FAIL_COUNT -gt 2 ]; then
    log "fail ping more than 2,exit 1"
    exit 1	
fi

status=$(systemctl status haproxy|grep Active|grep running|wc -l)
if [ "${status}" = "0" ]; then
    log 'haproxy is not running, restart it'
    service haproxy restart

    status2=$(systemctl status haproxy|grep Active|grep running|wc -l)
    if [ "${status2}" = "0"  ]; then
        log 'haproxy is not running, exit 1'
        exit 1
    fi
else
    log 'haproxy is running'
fi

log 'check ok,exit 0'
exit 0

/etc/keepalived/scripts/lvs_notify_master.sh

#!/bin/bash
# 調用公司內部的短信接口通知或者微信通知,郵件通知時效性較差

logfile="/var/log/keepalived_lvs_master.log"
log() {
        now=`date`
        content=$1
        echo  ${now}":"${content}  >>$logfile
}

log 'keepalived to master'

/etc/keepalived/scripts/lvs_notify_backup.sh

#!/bin/bash
# 調用公司內部的短信接口通知或者微信通知,郵件通知時效性較差

logfile="/var/log/keepalived_lvs_backup.log"
log() {
        now=`date`
        content=$1
        echo  ${now}":"${content}  >>$logfile
}

log 'keepalived to backup'

/etc/keepalived/scripts/lvs_notify_fault.sh

#!/bin/bash
# 調用公司內部的短信接口通知或者微信通知,郵件通知時效性較差

logfile="/var/log/keepalived_lvs_fault.log"
log() {
        now=`date`
        content=$1
        echo  ${now}":"${content}  >>$logfile
}

log 'keepalived to fault'

驗證 keepalived

# systemctl start keepalived
# systemctl enable keepalived
# ps -ef|grep -i keep
root     16568     1  0 10:34 ?        00:00:00 /usr/sbin/keepalived
root     16569 16568  0 10:34 ?        00:00:00 /usr/sbin/keepalived
root     16570 16568  0 10:34 ?        00:00:00 /usr/sbin/keepalived

# ip a show eno1
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:7d:f5:f0 brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.101/24 brd 192.168.56.255 scope global eno1
       valid_lft forever preferred_lft forever
    inet 192.168.56.210/24 scope global secondary eno1:1
       valid_lft forever preferred_lft forever
    inet 192.168.56.211/24 scope global secondary eno1:2
       valid_lft forever preferred_lft forever
    inet 192.168.56.212/24 scope global secondary eno1:3
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe7d:f5f0/64 scope link 
       valid_lft forever preferred_lft forever

chk_health功能驗證

# systemctl stop haproxy

# tail -f /var/log/keepalived_lvs_status.log
Mon Oct 15 10:40:53 CST 2018:---------- health check start ...---------
Mon Oct 15 10:40:53 CST 2018:ping 192.168.56.1 ...
Mon Oct 15 10:40:53 CST 2018:ping 192.168.56.101 ...
Mon Oct 15 10:40:53 CST 2018:ping 192.168.56.102 ...
Mon Oct 15 10:40:53 CST 2018:fail ping num:0
Mon Oct 15 10:40:53 CST 2018:haproxy is not running, restart it
Mon Oct 15 10:40:53 CST 2018:check ok,exit 0

notify_master功能驗證
haproxy1 節點上關閉 keepalived

# systemctl stop keepalived

haproxy2 節點上查看日誌

# cat /var/log/keepalived_lvs_master.log 
Mon Oct 15 10:45:53 CST 2018:keepalived to master

notify_backup功能驗證
haproxy1 節點再啓動 keepalived,因爲是不搶佔模式,因此haproxy1起來後就是backup模式。

# systemctl start keepalived
# cat /var/log/keepalived_lvs_backup.log 
Mon Oct 15 11:15:46 CST 2018:keepalived to backup

此時,應用只須要鏈接 keepalived 的 vip 便可。

參考:
http://www.javashuo.com/article/p-esqjlspd-ds.html
http://www.keepalived.org/

相關文章
相關標籤/搜索