環境說明
系統: centos 7.4
軟件: keepalived: 1.3.5 nginx: 1.10.2 tcpdump工具
主機:192.168.9.222 192.168.9.223
vip地址: 192.168.9.151
keepalived說明
Keepalived軟件主要是通過VRRP協議實現高可用功能的。VRRP是Virtual Router RedundancyProtocol(虛擬路由器冗餘協議)的縮寫,VRRP出現的目的就是爲了解決靜態路由單點故障問題的,它能夠保證當個別節點宕機時,整個網絡可以不間斷地運行。
1、keepalived服務的三個重要功能
管理LVS負載均衡軟件
實現LVS集羣節點的健康檢查中
作爲系統網絡服務的高可用性(failover)
1.2、Keepalived高可用故障轉移原理
keepalived高可用服務對主機之間的故障切換轉移是通過vrrp (虛擬路由冗餘協議)來實現的, 當keepalived主正常工作時,主節點會不停的備節點發送(多播)心跳信息證明還存活,當主web發送故障就無法發送心跳信息,這裏keeplaived會將資源vip切換到備節點,但當主節點又活過來之後,備節點會釋放自己的資源給主節點,恢復原來的角色。
1.3、keepalived工作原理
keepalived是通過vrrp協議進行通信的,我們首先需要先了解一下vrrp協議的信息
1)vrrp 虛擬路由冗餘協議,vrrp最早是爲了解決路由單機故障而出現;
2)vrrp是通過一種竟選協議機制來將路由任務交給某臺vrrp rs的;
3)vrrp是通過多播的方式實現高可用對之間通信;
4)備節點可以有多個通過優先級競選,但一般keepalived系統運維工作都是一對;避免競爭產生的問題;
5)vrrp使用了加密協議加密數據,但keepalived官方目前還是推薦用明文的方式配置認證類型和密碼
2、安裝及配置
2.1、keepalived安裝
# 安裝keepalived 這裏兩臺機器都需要安裝
# 實驗基於 keepalived+nginx
Host# yum -y install keepalived libnl3-devel ipset-devel nginx
# 查看安裝的相關包
Host# rpm -ql keepalived
/etc/keepalived
/etc/keepalived/keepalived.conf
/etc/sysconfig/keepalived
/usr/bin/genhash
/usr/lib/systemd/system/keepalived.service
/usr/libexec/keepalived
/usr/sbin/keepalived
默認配置說明
Host # cat keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
# 從這往上是配置郵件信息的
router_id LVS_DEVEL # 用於標識本節點的名稱
vrrp_skip_check_adv_addr 默認是不跳過檢查。檢查收到的VRRP通告中的所有地址可能會比較耗時,設置此命令的意思是,如果通告與接收的上一個通告來自相同的master路由器,則不執行檢查(跳過檢查)。
vrrp_strict #嚴格執行VRRP協議規範,此模式不支持節點單播
vrrp_garp_interval 0 # 接口發送ARP之間的延遲
vrrp_gna_interval 0 #
}
vrrp_instance VI_1 {
state MASTER # 狀態有兩個 MASTER 主 | BACKUP 從
interface eth0 # 對外的網卡接口,ifconfig 或者ip addr show可查看
virtual_router_id 51 # 虛擬路由id,每個節點設置必須一樣,相同的ID爲一組
priority 100 # 優先級
advert_int 1 # 主往從發送多播消息的間隔時長
authentication { # 認證信息
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 虛擬ip 可以多個,但建議一個就OK了
192.168.200.16
192.168.200.17
192.168.200.18
}
}
virtual_server 192.168.200.100 443 { # 虛擬服務器地址 IP 對外提供服務的端口
delay_loop 6 # 健康檢查時長 單位秒
lb_algo rr # 負載均衡算法 一般是 rr但 wlc
lb_kind NAT # 負載均衡轉發規則,一般用dr,nat調度器會有瓶頸問題
persistence_timeout 50 # http服務會話時長 單位秒
protocol TCP # 協議 tcp
real_server 192.168.201.100 443 { # 真實的對外提供服務的地址跟IP
weight 1 # 權重 權重越高轉發優先級越高
SSL_GET { # HTTP_GET | SSL_GET | TCP_CHECK
url {
path /index.html
digest e93e7f6cfbc7c343707f21e2f681dd31
}
connect_timeout 3 # 服務連接端口
nb_get_retry 3 # 服務連接失敗重試次數
delay_before_retry 3 # 重試連接間隔 單位 秒
}
}
}
相關拓展:關於HTTP_GET | SSL_GET | TCP_CHECK 用法
2.2、配置
真實使用配置
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id keepalived
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 222
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.9.151
}
}
virtual_server 192.168.9.151 80 {
delay_loop 60
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.9.222 8080 { 兩臺真實主機
weight 1
HTTP_GET {
url {
path /
digest 0b03c354bbc6af44b42712a6f6497dc8
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.9.223 8080 {
weight 1
HTTP_GET {
url {
path /
digest 78d47efe7fe7916ee20e034bfe24c5b7
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
keepalived]# genhash -s 192.168.9.222 -p 8080 -u /index.html
MD5SUM = 0b03c354bbc6af44b42712a6f6497dc8
將這個獲取到的值填到 digest xxxxxxxxxxxxxx中
Host# scp keepalived.conf [email protected]:/etc/keepalived/
備節點保需要更改一下接口地址、優先級、狀態爲BACKUP備節點 其它跟主節點保持一致
vrrp_instance VI_1 {
state BACKUP
interface ens160
virtual_router_id 222
priority 90
兩邊都啓動nginx跟keepalived systemctl start keepalive systemctl start nginx
啓動Keepalived 查看接口地址
keepalived]# ip addr show | grep en
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
inet 192.168.9.222/24 brd 192.168.9.255 scope global ens160
inet 192.168.9.151/32 scope global ens160
2.3、檢查
此時這裏可以看到主通過Http-get獲取這個地址是否有效,
Host# tcpdump -i ens160 dst 192.168.9.223 and port 8080
此時我們在查看 nginx的日誌,發現這裏每秒也有一條記錄在查詢。
這裏delay_loop 6 太短了 我們修改一下改成60秒一次
此時通過tcpdump可以抓取到主一直在往這個組播地址 每次一秒發送一個包
Host# tcpdump -i ens160 dst 224.0.0.18
3、腦裂問題
當兩臺主機互相無法感知對方的存在,那麼就會認爲主已經掛掉, 此時通過自身的調用機制會將vip等資源都弄過來,這樣當兩個主機都同時認爲自己是主,那麼有可能會在某一時刻同時寫給數據庫會造成死鎖的現象,也有可能會產生其它的資源爭用,更主要的是兩個一樣的ip在同一個局域網內它們兩都可能上不了網無法提供服務。
3.1、腦裂產生的原因
1)心跳線壞了
2)IP設置問題
3)心跳線之間的設備故障 (正常來說,兩個keepalived是用網線直連的方式)
4)仲裁的機器出問題了
5)iptables的設置問題,端口沒有放出來
6)心跳網卡設置的不對,軟件bug等
7)同一個keepalived的 virtual_route_id兩端設置參數不一樣也會有腦裂問題的發生
3.2、腦裂解決辦法
1)同時使用串行電纜和網線連接,同時使用兩個心跳線路(這種方式最廉價,也是最有效的)
2)使用stonith,feyce設備檢測當有設備腦裂時強制重啓機器,或者斷電(需要採購設備成本)
3)做好腦裂的解決,發現問題第一時間介入仲裁,但如果使用人工干預的方式的話 會造成一定的損失,如果可容忍那就可以採用這種方式(可以寫腳本,但人工干預會很慢,比如凌晨4點半。)
3.3、腦裂解決方案
3.3.1、使用zabbix監控
此處略過..待更新
3.3.2、腦裂腳本
先附上腳本
Host# vim check_nginx.sh
#!/bin/bash
#
count=`ps -C nginx --no-heading | wc -l`
time=`date "+%Y-%m-%d %H-%M"`
if [ ${count} == 0 ];then
echo "${time} - keepalived fail " > /tmp/keepalive_status.txt
/usr/bin/systemctl stop keepalived
else
echo "${time} - keepalive ok" > /tmp/keepalive_status.txt
fi
# 這裏是主節點 在vrrp_instance前面增加 有這個vrrp_script 那一定就會有 執行 track_script
vrrp_script chk_http_port {
script "/etc/keepalived/check_nginx.sh"
interval 1
weight -15
fall 3
}
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 222
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.9.151
}
track_script {
chk_http_port
}
}
#這裏是從節點 配置信息一致
vrrp_script chk_http_port {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -15
}
vrrp_instance VI_1 {
state BACKUP
interface ens160
virtual_router_id 222
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.9.151
}
track_script {
chk_http_port
}
重啓服務,檢查日誌 tail -f /var/log/messages
測試關閉 systemctl stop nginx
從節點,查看IP地址就自動切換過來了。
附一個V2版本腳本
keepalived]# cat check_nginx.sh
#!/bin/bash
#
# 檢查nginx是否正常,如果不正常,先重啓兩次,最後還是不行就直接幹掉keepalived
counts(){
count=`ps -C nginx --no-heading | wc -l`
for i in {1..2};do
if [ ${count} == 0 ];then
systemctl restart nginx
sleep 2
fi
done
}
counts
if [ counts == 0 ];then
/usr/bin/systemctl stop keepalived
fi
3.3.3、郵件提醒
notify_master 當切換成主時發送郵件
notify_backup 切換成備時也發送郵件
notify_fault 失敗時
notify腳本
#!/bin/bash
#
# description: An example of notify script
#
vip=172.16.100.1
contact='root@localhost'
notify() {
mailsubject="`hostname` to be $1: $vip floating"
mailbody="`date '+%F %H:%M:%S'`: vrrp transition, `hostname` changed to be $1"
echo $mailbody | mail -s "$mailsubject" $contact
}
case "$1" in
master)
notify master
/etc/rc.d/init.d/nginx start
exit 0
;;
backup)
notify backup
/etc/rc.d/init.d/nginx stop
exit 0
;;
fault)
notify fault
/etc/rc.d/init.d/nginx stop
exit 0
;;
*)
echo 'Usage: `basename $0` {master|backup|fault}'
exit 1
;;
esac
將這個加到 track_script 下邊如
track_script {
chk_http_port
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
FAQ
缺少這個組件: https://bugzilla.redhat.com/show_bug.cgi?id=1477572
libipset.so.3: cannot open shared object file: No such file or directory
解決: yum -y install libnl3-devel ipset-devel