Keepalived軟件起初是專為LVS負載均衡軟件設計的,用來管理並監控LVS集群系統中各個服務節點的狀態,后來又加入了可以實現高可用的VRRP功能。因此,Keepalived除了能夠管理LVS軟件外,還可以作為其他服務(例如:Nginx、Haproxy、MySQL等)的高可用解決方案軟件。
keepalived: vrrp協議:Virtual Router Redundancy Protocol 術語: 虛擬路由器:Virtual Router 虛擬路由器標識:VRID(0-255),唯一標識虛擬路由器 物理路由器: master:主設備 backup:備用設備 priority:優先級 VIP:Virtual IP VMAC:Virutal MAC (00-00-5e-00-01-VRID) 通告:心跳,優先級等;周期性 工作方式:搶占式,非搶占式 安全工作: 認證: 無認證 簡單字符認證:預共享密鑰 MD5 工作模式: 主/備:單虛擬路徑器 主/主:主/備(虛擬路徑器1),備/主(虛擬路徑器2)
二、Keepalived服務的重要功能
1、管理LVS負載均衡軟件
早期的LVS軟件,需要通過命令行或腳本實現管理,並且沒有針對LVS節點的健康檢查功能。為了解決LVS的這些使用不便的問題,Keepalived就誕生了,可以說,Keepalived軟件起初是專為解決LVS的問題而誕生的。因此,Keepalived和LVS的感情很深,它們的關系如同夫妻一樣,可以緊密地結合,愉快地工作。Keepalived可以通過讀取自身的配置文件,實現通過更底層的接口直接管理LVS的配置以及控制服務的啟動、停止等功能,這使得LVS的應用更加簡單方便了。
2、實現對LVS集群節點健康檢查功能(healthcheck)
Keepalived可以通過在自身的keepalived.conf文件里配置LVS的節點IP和相關參數實現對LVS的直接管理;除此之外,當LVS集群中的某一個甚至是幾個節點服務器同時發生故障無法提供服務時,Keepalived服務會自動將失效的節點服務器從LVS的正常轉發隊列中清除出去,並將請求調度到別的正常節點服務器上,從而保證最終用戶的訪問不受影響;當故障的節點服務器被修復以后,Keepalived服務又會自動地把它們加入到正常轉發隊列中,對客戶提供服務。
3、作為系統網絡服務的高可用功能(failover)
Keepalived可以實現任意兩台主機之間,例如Master和Backup主機之間的故障轉移和自動切換,這個主機可以是普通的不能停機的業務服務器,也可以是LVS負載均衡、Nginx反向代理這樣的服務器。
Keepalived高可用功能實現的簡單原理為,兩台主機同時安裝好Keepalived軟件並啟動服務,開始正常工作時,由角色為Master的主機獲得所有資源並對用戶提供服務,角色為Backup的主機作為Master主機的熱備;當角色為Master的主機失效或出現故障時,角色為Backup的主機將自動接管Master主機的所有工作,包括接管VIP資源及相應資源服務;而當角色為Master的主機故障修復后,又會自動接管回它原來處理的工作,角色為Backup的主機則同時釋放Master主機失效時它接管的工作,此時,兩台主機將恢復到最初啟動時各自的原始角色及工作狀態。
三、Keepalived高可用故障切換轉移原理
Keepalived高可用服務對之間的故障切換轉移,是通過VRRP(Virtual Router Redundancy Protocol,虛擬路由器冗余協議)來實現的。
在Keepalived服務正常工作時,主Master節點會不斷地向備節點發送(多播的方式)心跳消息,用以告訴備Backup節點自己還活着,當主Master節點發生故障時,就無法發送心跳消息,備節點也就因此無法繼續檢測到來自主Master節點的心跳了,於是調用自身的接管程序,接管主Master節點的IP資源及服務。而當主Master節點恢復時,備Backup節點又會釋放主節點故障時自身接管的IP資源及服務,恢復到原來的備用角色。
四、keepalived的工作原理
1、Keepalived高可用對之間是通過VRRP通信的
1)VRRP,全稱Virtual Router Redundancy Protocol,中文名為虛擬路由冗余協議,VRRP的出現是為了解決靜態路由的單點故障。
2)VRRP是通過一種競選協議機制來將路由任務交給某台VRRP路由器的。
3)VRRP用IP多播的方式(默認多播地址(224.0.0.18))實現高可用對之間通信。
4)工作時主節點發包,備節點接包,當備節點接收不到主節點發的數據包的時候,就啟動接管程序接管主節點的資源。備節點可以有多個,通過優先級競選,但一般Keepalived系統運維工作中都是一對。
5)VRRP使用了加密協議加密數據,但Keepalived官方目前還是推薦用明文的方式配置認證類型和密碼。
2、Keepalived服務的工作原理
2)在Keepalived服務對之間,只有作為主的服務器會一直發送VRRP廣播包,告訴備它還活着,此時備不會搶占主,當主不可用時,即備監聽不到主發送的廣播包時,就會啟動相關服務接管資源,保證業務的連續性。接管速度最快可以小於1秒。
keepalived: vrrp協議的軟件實現,原生設計目的為了高可用ipvs服務 功能: 1、vrrp協議完成地址流動 2、為vip地址所在的節點生成ipvs規則(在配置文件中預先定義) 3、為ipvs集群的各RS做健康狀態檢測 4、基於腳本調用接口通過執行腳本完成腳本中定義的功能,進而影響集群事務,以此支持nginx、haproxy等服務
五、keepalived配置文件說明
(1) 各節點時間必須同步:ntp, chrony (2) 確保iptables及selinux不會成為阻礙 (3) 各節點之間可通過主機名互相通信(對KA並非必須):建議使用/etc/hosts文件實現 (4) 各節點之間的root用戶可以基於密鑰認證的ssh服務完成互相通信(對KA並非必須)
keepalived.x86_64 0:1.3.5-16.el7
主配置文件:/etc/keepalived/keepalived.conf 主程序文件:/usr/sbin/keepalived Unit File:/usr/lib/systemd/system/keepalived.service Unit File的環境配置文件:/etc/sysconfig/keepalived
TOP HIERACHY GLOBAL CONFIGURATION Global definitions Static routes/addresses VRRPD CONFIGURATION VRRP synchronization group(s):vrrp同步組 VRRP instance(s):即一個vrrp虛擬路由器 LVS CONFIGURATION Virtual server group(s) Virtual server(s):ipvs集群的vs和rs
配置虛擬路由器: vrrp_instance <STRING> { .... } #專用參數: #state MASTER|BACKUP:當前節點在此虛擬路由器上的初始狀態;只能有一個是MASTER,余下的都應該為BACKUP #interface IFACE_NAME:綁定為當前虛擬路由器使用的物理接口 #virtual_router_id VRID:當前虛擬路由器惟一標識,范圍是0-255 #priority 100:當前物理節點在此虛擬路由器中的優先級;范圍1-254 #advert_int 1:vrrp通告的時間間隔,默認1s authentication { #認證機制 auth_type AH|PASS auth_pass <PASSWORD> 僅前8位有效 } virtual_ipaddress { #虛擬IP <IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL> 192.168.200.17/24 dev eth1 192.168.200.18/24 dev eth2 label eth2:1 } track_interface { #配置監控網絡接口,一旦出現故障,則轉為FAULT狀態 實現地址轉移 eth0 eth1 … } #nopreempt:定義工作模式為非搶占模式 #preempt_delay 300:搶占式模式,節點上線后觸發新選舉操作的延遲時長,默認模式 #定義通知腳本: #notify_master <STRING>|<QUOTED-STRING>: #當前節點成為主節點時觸發的腳本 #notify_backup <STRING>|<QUOTED-STRING>: #當前節點轉為備節點時觸發的腳本 #notify_fault <STRING>|<QUOTED-STRING>: #當前節點轉為“失敗”狀態時觸發的腳本 #notify <STRING>|<QUOTED-STRING>: #通用格式的通知觸發機制,一個腳本可完成以上三種狀態的轉換時的通知
5、單主配置示例
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node1 #主機名,在另一結點為node2 vrrp_mcast_group4 224.0.100.100 } vrrp_instance VI_1 { state MASTER #在另一個結點上為BACKUP interface eth0 virtual_router_id 6 #多個節點必須相同 priority 100 #在另一個結點上為90 advert_int 1 #通告間隔1s authentication { auth_type PASS #預共享密鑰認證 auth_pass 571f97b2 } virtual_ipaddress { 172.18.100.66/16 dev eth0 label eth0:0 } track_interface { eth0 } }
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node2 #主機名,在另一結點為node1 vrrp_mcast_group4 224.0.100.100 } vrrp_instance VI_1 { state BACKUP#在另一個結點上為MASTER interface eth0 virtual_router_id 6 #多個節點必須相同 priority 90 #在另一個結點上為100 advert_int 1 #通告間隔1s authentication { auth_type PASS #預共享密鑰認證 auth_pass 571f97b2 } virtual_ipaddress { 172.18.100.66/16 dev eth0 label eth0:0 } track_interface { eth0 } }
在vrrp_instance VI_1 語句塊最后面加下面行
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
master與backup配置一樣
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node2 #主機名,在另一結點為node1 vrrp_mcast_group4 224.0.100.100 } vrrp_instance VI_1 { state BACKUP#在另一個結點上為MASTER interface eth0 virtual_router_id 6 #多個節點必須相同 priority 90 #在另一個結點上為100 advert_int 1 #通告間隔1s authentication { auth_type PASS #預共享密鑰認證 auth_pass 571f97b2 } virtual_ipaddress { 172.18.100.66/16 dev eth0 label eth0:0 } track_interface { eth0 } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" }
通知腳本
#!/bin/bash # contact='root@localhost' notify() { mailsubject="$(hostname) to be $1, vip floating" mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1" echo "$mailbody" | mail -s "$mailsubject" $contact } case $1 in master) notify master ;; backup) notify backup ;; fault) notify fault ;; *) echo "Usage: $(basename $0) {master|backup|fault}" exit 1 ;; esac
配置發送郵件的郵箱設置: vim ~/.mailrc 或 /etc/mail.rc set from=29308620@qq.com set smtp=smtp.qq.com set smtp-auth-user=29308620@qq.com set smtp-auth-password=lzhdjmtznbftbiai set smtp-auth=login set ssl-verify=ignore 測試:echo test mail | mail –s test 29308620@qq.com
node1
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node1 vrrp_mcast_group4 224.0.100.100 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 6 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 571f97b2 } virtual_ipaddress { 172.16.0.10/16 dev eth0 } } vrrp_instance VI_2 { state BACKUP interface eth0 virtual_router_id 8 priority 98 advert_int 1 authentication { auth_type PASS auth_pass 578f07b2 } virtual_ipaddress { 172.16.0.11/16 dev eth0 } }
node2
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node2 vrrp_mcast_group4 224.0.100.100 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 6 priority 98 advert_int 1 authentication { auth_type PASS auth_pass 571f97b2 } virtual_ipaddress { 172.16.0.10/16 dev eth0 } } vrrp_instance VI_2 { state MASTER interface eth0 virtual_router_id 8 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 578f07b2 } virtual_ipaddress { 172.16.0.11/16 dev eth0 } }
配置參數: virtual_server IP port | virtual_server fwmark int { ... real_server { ... } ... } delay_loop <INT>:檢查后端服務器的時間間隔 lb_algo rr|wrr|lc|wlc|lblc|sh|dh:定義調度方法 lb_kind NAT|DR|TUN:集群的類型 persistence_timeout <INT>:持久連接時長 protocol TCP:服務協議,僅支持TCP sorry_server <IPADDR> <PORT>:所有RS故障時,備用服務器地址 real_server <IPADDR> <PORT> { weight <INT> RS權重 notify_up <STRING>|<QUOTED-STRING> RS上線通知腳本 notify_down <STRING>|<QUOTED-STRING> RS下線通知腳本 HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHEC K { ... }:定義當前主機的健康狀態檢測方法 } HTTP_GET|SSL_GET:應用層檢測 HTTP_GET|SSL_GET { url { path <URL_PATH>:定義要監控的URL status_code <INT>:判斷上述檢測機制為健康狀態的響應碼 digest <STRING>:判斷為健康狀態的響應的內容的校驗碼 } connect_timeout <INTEGER>:連接請求的超時時長 nb_get_retry <INT>:重試次數 delay_before_retry <INT>:重試之前的延遲時長 connect_ip <IP ADDRESS>:向當前RS哪個IP地址發起健康狀態檢測請求 connect_port <PORT>:向當前RS的哪個PORT發起健康狀態檢測請求 bindto <IP ADDRESS>:發出健康狀態檢測請求時使用的源地址 bind_port <PORT>:發出健康狀態檢測請求時使用的源端口 } 傳輸層檢測 TCP_CHECK TCP_CHECK { connect_ip <IP ADDRESS>:向當前RS的哪個IP地址發起健康狀態檢測請求 connect_port <PORT>:向當前RS的哪個PORT發起健康狀態檢測請求 bindto <IP ADDRESS>:發出健康狀態檢測請求時使用的源地址 bind_port <PORT>:發出健康狀態檢測請求時使用的源端口 connect_timeout <INTEGER>:連接請求的超時時長 }
6.1單主模型IPVS示例
MASTER節點配置
高可用的ipvs集群示例master節點: ! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node1 vrrp_mcast_group4 224.0.100.10 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 6 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 571f97b2 } virtual_ipaddress { 172.16.0.10/16 dev eth0 } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" } virtual_server 172.16.0.10 80 { delay_loop 3 lb_algo rr lb_kind DR protocol TCP sorry_server 127.0.0.1 80 real_server 172.16.0.11 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } real_server 172.16.0.12 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } }
BACKUP節點
高可用的ipvs集群示例BACKUP節點: ! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node2 vrrp_mcast_group4 224.0.100.10 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 6 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 571f97b2 } virtual_ipaddress { 172.16.0.10/16 dev eth0 } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" } virtual_server 172.16.0.10 80 { delay_loop 3 lb_algo rr lb_kind DR protocol TCP sorry_server 127.0.0.1 80 real_server 172.16.0.11 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } real_server 172.16.0.12 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } }
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from kaadmin@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node1 vrrp_mcast_group4 224.0.100.100 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 6 priority 100 advert_int 1 authentication { auth_type PASS auth_pass f1bf7fde } virtual_ipaddress { 172.16.0.80/16 dev eth0 label eth0:0 } track_interface { eth0 } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" } vrrp_instance VI_2 { state BACKUP interface eth0 virtual_router_id 8 priority 98 advert_int 1 authentication { auth_type PASS auth_pass f2bf7ade } virtual_ipaddress { 172.16.0.90/16 dev eth0 label eth0:1 } track_interface { eth0 } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" } virtual_server fwmark 3 { delay_loop 2 lb_algo rr lb_kind DR nat_mask 255.255.0.0 protocol TCP sorry_server 127.0.0.1 80 real_server 172.16.0.11 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 2 nb_get_retry 3 delay_before_retry 3 } } real_server 172.16.0.12 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 2 nb_get_retry 3 delay_before_retry 3 } } }
1、keepalived調用外部的輔助腳本進行資源監控,並根據監控的結果狀態能實現優先動態調整 2、vrrp_script:自定義資源監控腳本,vrrp實例根據腳本返回值,公共定義,可被多個實例調用,定義在vrrp實例之外 3、track_script:調用vrrp_script定義的腳本去監控資源,定義在實例之內,調用事先定義的vrrp_script 4、分兩步:(1) 先定義一個腳本;(2) 調用此腳本 vrrp_script <SCRIPT_NAME> { script "" interval INT weight -INT } track_script { SCRIPT_NAME_1 SCRIPT_NAME_2 }
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id node1 vrrp_mcast_group4 224.0.100.100 } vrrp_script chk_down { script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0" interval 1 weight -20 } vrrp_script chk_nginx { script “/usr/bin/killall -0 nginx " interval 1 weight -20 fall 2 #2次檢測失敗為失敗 rise 1 #1次檢測成功為成功 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 14 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 571f97b2 } virtual_ipaddress { 172.18.0.93/16 dev eth0 } track_script { chk_down #調用前面的vrrp_script chk_down腳本 chk_nginx #調用前面的vrrp_script chk_nginx腳本 } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" }
notify.sh腳本
#!/bin/bash # contact='root@localhost' notify() { mailsubject="$(hostname) to be $1, vip floating" mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1" echo "$mailbody" | mail -s "$mailsubject" $contact } case $1 in master) notify master ;; backup) notify backup ;; fault) notify fault ;; *) echo "Usage: $(basename $0) {master|backup|fault}" exit 1 ;; esac
chk_nginx腳本
#!/bin/bash killall -0 nginx > /dev/null if [ $? -ne 0 ];then systemctl stop keepalived fi
vrrp_sync_group VG_1 { group { VI_1 # name of vrrp_instance (below) VI_2 # One for each moveable IP } } vrrp_instance VI_1 { eth0 vip } vrrp_instance VI_2 { eth1 dip }