#keepalived
keepalived原理:
基於VIP (虛擬IP) vrrp協議,即建立一個虛擬IP地址(如172.24.0.1/16),讓所有設備都能連接這個虛擬的IP,通過配置主從,master首先使用虛擬IP,slave standby狀態,master機器主動定時(如1s)廣播狀態給slave,
如果slave一定時間內沒有接收到master的廣播,認定master down機,從而slave主動且切換到該虛擬IP;
問:keepalived一定要接入LVS嗎?
答:keepalived初始就是爲了解決LVS負載均衡而出現的,後期加入了vrrp協議提高了高可用並實現了IP漂移,keepalived三大核心模塊之一就有LVS,但是使用keepalived IP漂移是在virtual_server上實現的,雖然理論上不接virtual_server或者只接一臺real_server機器,但實際後端服務都是集羣容災形式,所以keepalived不一定非要接入LVS,但是通常我們都接入了LVS;
問:LVS是啥?
答:LVS是集羣的負載均衡解決方案,在keepalived高可用集羣中,配置文件virtual_server指令塊的內容就是LVS配置項
前提:
由於VIP(虛擬IP)只能在子網實現,所以機器只能是在同一個子網中(例如是同一個交換機分出來的設備,而不是獨立網絡的設備)
服務對接:
上游服務,需接入到裝有keepalived的子網中,可直接訪問虛擬IP,一般來說上游是接核心交換機,虛擬IP轉換成公網IP,測試環境可以接成nginx反向代理實現該功能
下游服務,接入keepalived的real_server服務中
快速搭建:
環境:樹莓派4B,額外說明,在公司測試環境和生產環境已驗證過,和樹莓派方式差不多;
角色:root
方式:apt
安裝:
apt install keepalived -y
調試牢記:apt安裝的軟件配置文件基本都放在/etc/目錄下,日誌文件基本放在/var/log/目錄下,centos7.5和樹莓派都測試過,方法一致,KP配置文件/etc/keepalived/keepalived.conf,KP日誌文件/var/log/message
配置文件主要塊功能說明:
global_defs{}:全局塊,主要放置的是預警郵件地址或router id等唯一機器標識或一些其他全局信息,此模塊爲配置文件必要模塊
vrrp_script <塊名>{}:腳本塊,主要作用是配置監測腳本位置及其執行時間和執行後動作模塊,非必須模塊,可以在配置文件中不寫該塊, 如果後端直接接服務,如數據庫,建議寫入,指定監測服務是否存活的腳本,如果後端接K8S等有額外功能的中間件,可以不寫該塊
vrrp_instance <塊名>{}:vrrp實列塊,主要作用是建立一個keepalived集羣使用的虛擬IP及其配置keepalived集羣個master/backup之間的關係和權重等,非必須模塊,如果只是單臺機器搭建keepalived可以不需要該模塊,若是有多臺機器做keepalived的高可用主備集羣,需要該模塊建立集羣通信廣播、虛擬IP和配置主從關係,注意該虛擬IP就是給外網訪問的可漂移的IP,這裏的IP可以是單個也可以是多個;
virtual_server <IP + PORT>{}:後端服務塊,和全局塊一樣是必須模塊,是這裏配置的IP如果有vrrp_instance配置,那麼必須要和vrrp_instance配置中的虛擬IP一致,如果vrrp_instance配置的虛擬IP是多個,那麼這裏的IP要是其中的一個,如果keepalived集羣模式,那麼集羣各機器的服務塊必須要一致,才能保障keepalived機器切換後連接的服務配置完全一致,該塊中的real_server{}子塊是連接真實的後端服務地址,也是必須塊,如果沒有,keepalived服務不會正常運行
查看配置文件:
建議參考官方文檔:
https://www.keepalived.org/doc/configuration_synopsis.html#vrrp-instance-definitions-synopsis
cd /etc/keepalived/
cat keepalived.conf
! Configuration File for keepalived
global_defs { #全局參數
notification_email {
[email protected] #告警郵件收件人地址
}
notification_email_from [email protected] #郵件發件人地址
smtp_server 192.168.200.1 #發送郵件服務器地址,可以是本機也可以不是本機
smtp_connect_timeout 30 #郵件服務器連接超時
router_id 192.168.1.7 #發送告警郵件的IP主機,最好是主機IP,如果down了該機器,會發送down掉的機器id,可快速判定掛掉的機器位置
vrrp_skip_check_adv_addr
#vrrp_strict #配置這個參數不能直接訪問本機服務,注意
vrrp_garp_interval 0
vrrp_gna_interval 0
}
#監測服務是否正常腳本,非必須
vrrp_script check_nginx {
script "/etc/keepalived/scripts/check_nginx.sh"
#間隔
interval 3
#失敗後重試次數
fall 3
}
#keepalived實列配置,主要是建立一個keepalived集羣通信的虛擬IP及其相關屬性,
#注意,相同服務的keepalived集羣的virtual_router_id需要一致,而不同服務則不能一致,
#所以這裏也可以設置多個vrrp_instance,比如,對接K8S設置一個vrrp_instance,對接MySQL設置一個vrrp_instance,對接nginx設置一個vrrp_instance,即一個keepalived用作多個服務的高可用
vrrp_instance VI_1 {
#MASTER或者BACKUP,如果MASTER初始的權重沒有BACKUP高,會被主動切換到BACKUP;
state MASTER
#採用的接口網卡,注意後續所有的虛擬IP都需要在網卡支持的網段範圍內,
#比如centos默認是ens33,樹莓派是eth0,用ifconfig查看網卡網段,如果網卡只有192.168的內網網段那麼虛擬IP也必須要用這個網段
interface eth0
#設置爲不搶佔,說明:這個配置只能在BACKUP主機上面設置
#nopreempt|preempt
#搶佔時間,說明:這個配置只能在BACKUP主機上面設置
#preempt delay 300
#設置VRID標記,不同服務集羣內不能重複
virtual_router_id 51
#權重,越高越容易被選爲主
priority 100
#心跳監測時間,默認1s
advert_int 1
#VIP組是否需要認證才能加入
authentication {
#驗證方式,默認PASS
auth_type PASS
#驗證密碼,默認1111
auth_pass 1111
}
#這裏就是內網中有VIP心跳的虛擬IP,用於檢測keepalived集羣機器的存活,如果master機器掛了這個IP廣播就會不通,backup機器就會主動提升到master,
#虛擬IP可以是一個也可以是多個,多個虛擬IP作用是可以讓多個服務使用,如果只是一個服務,如只接K8S,一個IP就夠了
#比如K8S使用一個虛擬IP,nginx使用一個虛擬ip,各機器都需要加入相同數據才能加入虛擬IP組
virtual_ipaddress {
#虛擬ip,後面可以指定掛載在那個網卡上,方式:192.168.10.80/32 dev eth0,或者掛載在那個網卡別名上:192.168.200.16/32 dev label eth1:1
192.168.10.16
}
#可選執行腳本,非必須,寫法和vrrp_script一樣
#track_script {
#}
}
#LVS負載均衡和服務可漂移的虛擬IP配置
#這個IP是就是可漂移的虛擬IP,每個keepalived的機器上virtual_server配置都需要一樣才能保障IP正常的漂移
#virtual_server的IP必須要和virtual_ipaddress中的IP地址一致或是virtual_ipaddress地址中的一個
virtual_server 192.168.10.30 80 {
#6秒循環監測
delay_loop 6
# 算法,默認rr
lb_algo rr
# 模式,默認NAT,可以是DR|TUN,注意keepalived和後端服務機器在同一網段下,虛擬IP單獨設置一個網段IP,NAT模式會訪問不了後端服務,
#這裏的模式選擇很重要,選錯會產生很多無法訪問的異常
lb_kind NAT
#連接超時時間
persistence_timeout 50
#連接協議
protocol TCP
# 如果後端應用服務器都不可用,就會定向到那個服務器上
#sorry_server 192.168.200.200 1358
#這個IP是keepalived轉發服務的後端服務機器IP,比如後端飢餓nginx機器IP,k8s集羣IP等
real_server 192.168.1.7 80 {
#權重
weight 1
#針對應用服務器做健康檢查的方法,可以是MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET等多種形式,例如:
## 用於檢查SMTP服務器的:SMTP_CHEKC {},如果應用服務器不是WEB服務器,就用TCP_CHECK檢查:TCP_CHECK {}
#如果對方是HTTPS服務器就用SSL_GET方法去檢查 SSL_GET {},使用HTTP_GET方法去檢查: HTTP_GET{}
#這裏默認的是SSL方法和HTTP_GET用法差不多,但建議還是用TCP_CHECK,最常用和最簡單的方式
SSL_GET {
# 檢測URL
url {
# 具體檢測哪一個URL
path /
# 檢測內容的哈希值
digest ff20ad2481f97b1754ef3e12ecd3a9cc
# 除了檢測哈希值還可以檢測狀態碼,比如HTTP的200 表示正常,兩種方法二選一即可,默認配置是檢測哈希值
#status_code 200
}
url {
path /mrtg/
digest 9b3a0c85a887a256d6939da88aabd8cd
}
#向哪一個端口檢查,如果不指定默認使用上面定義的端口
#connect_port <PORT>
# 向哪一個IP檢測,如果不指定默認使用上面定義的IP地址
#bindto <IP>
connect_timeout 3 # 連接超時時間
nb_get_retry 3 # 嘗試次數
delay_before_retry 3 # 每次嘗試之間間隔幾秒
}
#建議使用TCP_CHECK,當然如果是掛載web服務器,最好還是用http模式檢查
TCP_CHECK{
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
#第二臺後端服務機器配置
real_server 192.168.1.4 80 {
weight 2
TCP_CHECK{
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
#第三臺後端服務機器配置
real_server 192.168.1.8 80 {
weight 2
TCP_CHECK{
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
#如果在keepalived中還想給其他服務配置,比如數據庫/中間件等,則在這裏就可以再添加vrrp_instance和virtual_server,
#同一個配置文件中不同服務之間virtual_router_id不能相同,而相同服務不同機器之間virtual_router_id各keepalived集羣機器配置文件除了主從和權重其他的都需要一致
#vrrp_instance{}
#virtual_server{}
異常排查於解決:
排查:
方式:看日誌,默認位置打在系統日誌裏面,/var/log/message
問題點:
如果當前運行的是主節點並且出現:VRRP_Instance(VI_1) removing protocol VIPs
代表該服務異常,異常來源在這個日誌前後會展示,該信息表示因爲某種異常導致VIP被移除掉成爲不可用狀態
可能異常:
1、Unable to load ipset library - libipset.so
沒有ipset庫,雖然git上說keepalived默認不使用ipset,但既然報錯了,安裝下也許會解決
以下命令是在公司測試環境centos7下執行的,debian或樹莓派相關命令可能有所區別
yum install ipset libnl3-devel ipset-devel
2、虛擬IP能PING通,不能telnet後端服務
這種現象可能有多種情況:
1、arp 緩存,清除即可,arp -n|awk '/^[1-9]/{system("arp -d "$1)}'
2、防火牆,關閉
3、lb_kind選擇的通信模式於虛擬IP網段和真實服務IP網段衝突,比如,telnet的機器是內網同真實IP同一網段,然後虛擬IP設置另一個網段,此時通信模式選擇NAT時,是無法訪問後端的
解決:可以把虛擬IP地址和真實IP放在同一網段下或者調整通信模式,具體知識點參考LVS原理
4、主機能訪問從機不能訪問,查看virtual_router_id是否一致,相同組的機器virtual_router_id需要一致
5、從加入主後整體不可訪問,查看從機和主機配置是否有衝突,比如master、權重等
3、虛擬IP不通
1、關閉vrrp_strict
2、虛擬IP需要設置爲網卡支持的IP
心得:
1、lb_kind可以設置爲NAT、DR、TUN。這個選項直接關係到你做的 virtual_server和real_server能否進行正確映射
2、日誌沒有error級別的,所以要多仔細讀
3、配置文件衝突要避免
主要還是對網絡通信知識需要加深瞭解
有一個現象不知道有沒有人關注過:
假設:我有兩臺機器A 192.168.32.53 ;B 192.168.32.55,構建虛擬IP地址爲:192.168.32.100 端口80
若在A B上同時安裝keepalived和nginx,如果nginx默認是80端口
那麼啓動curl http://192.168.32.100 的時候,53機器永遠只會得到55機器nginx的反饋,55機器永遠只會得到53機器nginx的反饋,
若55機器下掉了ngixn,那麼53機器會curl不通報錯網絡異常;
這是由於nginx 的網絡服務端口和虛擬IP 80端口衝突導致的,即使配置權重也不會得到任何改變,所以後端服務端口建議不要和虛擬IP同一個端口,或者用單獨機器跑keepalived
最後貼一下我的測試環境配置文件:
主:
#! 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 11
vrrp_skip_check_adv_addr
# vrrp_strict
# vrrp_garp_interval 0
# vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 11
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.32.100
}
}
virtual_server 192.168.32.100 80{
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
# sorry_server 192.168.200.200 1358
real_server 192.168.32.53 80 {
weight 2
TCP_CHECK {
connect_timeout 3
delay_before_retry 3
}
}
real_server 192.168.32.55 80 {
weight 2
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
從:
#! 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 53
vrrp_skip_check_adv_addr
# vrrp_strict
# vrrp_garp_interval 0
# vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 11
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.32.100
}
}
virtual_server 192.168.32.100 80{
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
# sorry_server 192.168.200.200 1358
real_server 192.168.32.53 80 {
weight 2
TCP_CHECK {
connect_timeout 3
delay_before_retry 3
}
}
real_server 192.168.32.55 80 {
weight 2
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}