Keepalived+Nginx高可用叢集搭建筆記

akiya發表於2019-09-30

前言

Keepalived是以VRRP(Virtual Router Redundancy Protocol,虛擬路由冗餘協議)協議為實現基礎的,這個協議可以認為是實現了路由器高可用的協議,將多臺提供相同功能的路由器組成一個路由器組。

原理:在整個Keepalived叢集中會有一個MASTER和多個BACKUPmaster節點上有一個對外提供服務的Virtual IP(VIP),並且MASTER會發組播的心跳資訊,當BACKUP收不到VRRP包時就認為MASTER宕掉了,這時就需要根據VRRP優先順序來選舉一個BACKUP作為MASTER,當MASTER恢復時,BACKUP又會釋放在MASTER故障時自身接管的IP資源和服務,恢復到原來的備用角色,這樣就可以保證路由器的高可用。

環境說明

  • 作業系統:CentOS 7 (Minimal Install)
# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
複製程式碼
  • 演示環境
VIP IP 主機名
10.10.0.10 10.10.0.11 master
10.10.0.10 10.10.0.12 backup

部署

更換伺服器源倉庫

# mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# yum makecache
# yum -y update
複製程式碼

安裝Keepalived

yum安裝

Keepalived可以使用yum直接安裝,在master伺服器和backup伺服器執行:

# yum -y install keepalived
複製程式碼

原始碼編譯安裝

參考文件:Keepalived官方文件

安裝依賴庫

# yum -y install openssl-devel libnl3-devel ipset-devel iptables-devel file-devel net-snmp-devel glib2-devel json-c-devel pcre2-devel libnftnl-devel libmnl-devel
複製程式碼

下載Keepalived

# wget https://github.com/acassen/keepalived/archive/v2.0.18.tar.gz
複製程式碼

解壓Keepalived

# tar -zxvf v2.0.18.tar.gz
# cd keepalived-2.0.18
複製程式碼

開始安裝

# ./build_setup
./build_setup:行3: aclocal: 未找到命令
./build_setup:行4: autoheader: 未找到命令
./build_setup:行5: automake: 未找到命令
./build_setup:行6: autoreconf: 未找到命令
複製程式碼

如果出現如上報錯,安裝autotools系列工具

# yum -y install aclocal autoheader automake autoreconf
複製程式碼

繼續

# ./configure
# make && make install
複製程式碼

最後複製相關配置檔案到系統預設路徑

# mkdir /etc/keepalived
# cp ./keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
# cp ./keepalived/etc/init.d/keepalived /etc/init.d/
# cp ./keepalived/etc/sysconfig/keepalived /etc/sysconfig/
複製程式碼

修改/usr/lib/systemd/system/keepalived.servicePIDFile的值為/var/run/keepalived.pid

配置Keepalived

Keepalived提供了兩種模式

  • 搶佔式:MASTER與BACKUP節點上state配置不同,當MASTER節點宕掉後由BACKUP節點接手MASTER節點的VIP與服務,在MASTER節點恢復後重新由MASTER節點來接手VIP與服務,BACKUP節點繼續回到備用狀態。
  • 非搶佔式:MASTER與BACKUP節點上state配置都為BACKUP,且在vrrp_instance塊下兩個節點都增加nopreempt,表示不爭搶VIP。兩個節點啟動後預設都為BACKUP狀態,雙方在傳送組播資訊後,會根據優先順序來選舉一個MASTER出來,由於兩者都配置了nopreempt,所以MASTER從故障中恢復後不會搶佔VIP,這樣會避免VIP切換可能造成的服務延遲

MASTER節點

首先,我們先確認下網路卡及IP

# ip addr show | grep inet
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    inet 10.10.0.11/8 brd 10.255.255.255 scope global noprefixroute ens192
    inet6 fd08:815:48b2::e91/128 scope global noprefixroute
    inet6 fd08:815:48b2:0:d419:f3f5:85de:b72/64 scope global noprefixroute
    inet6 fe80::49a2:321d:8cf6:651a/64 scope link noprefixroute
複製程式碼

可以看到本次使用的是ens192這塊網路卡,IP為:10.10.0.11,然後我們編輯keepalived配置檔案

# vim /etc/keepalived/keepalived.conf
複製程式碼

配置如下:

! Configuration File for keepalived

global_defs {
   # email 收件人
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   # email 發件人
   notification_email_from Alexandre.Cassen@firewall.loc
   # email SMTP伺服器地址
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   # 標識本節點的ID,通常為hostname
   router_id akiya01
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}
# vrrp例項,相同例項的備節點名字要相同
vrrp_instance VI_1 {
    # 指定keepalived的角色,“MASTER”表示此主機是主伺服器,“BACKUP”表示此主機是備用伺服器
    state MASTER
    # 指定網路卡介面,這裡改為我們當前使用的網路卡“ens192”
    interface ens192
    # 虛擬路由標識,這個標識是一個數字,同一個vrrp例項使用唯一的標識
    # 即同一vrrp_instance下,MASTER和BACKUP必須是一致的
    virtual_router_id 51
     # 定義優先順序;數字越大,優先順序越高(0-255)
    # 在同一個vrrp_instance下,“MASTER”的優先順序必須大於“BACKUP”的優先順序
    priority 100
    # 設定MASTER與BACKUP負載均衡器之間同步檢查的時間間隔,單位是秒
    advert_int 1
    # 設定驗證型別和密碼
    authentication {
        # 設定驗證型別,主要有PASS和AH兩種
        auth_type PASS
        # 設定驗證密碼,在同一個vrrp_instance下,MASTER與BACKUP必須使用相同的密碼才能正常通訊
        auth_pass akiya
    }
    # 有故障時是否啟用郵件通知
    #smtp_alert
    # 禁止搶佔服務
    # 預設情況,當MASTER服務掛掉之後,BACKUP自動升級為MASTER並接替它的任務
    # 當MASTER服務恢復後,升級為MASTER的BACKUP服務又自動降為BACKUP,把工作權交給原MASTER
    # 當配置了nopreempt,MASTER從掛掉到恢復,不再將服務搶佔過來。
    #nopreempt
    # 虛擬IP,兩個節點設定必須一樣。可以設定多個,一行寫一個
    virtual_ipaddress {
        # 虛擬IP為10.10.0.10/8;繫結介面為ens192;別名ha:net,主備相同
        10.10.0.10/8 dev ens192 label ha:net
    }
}
複製程式碼

BACKUP節點

BACKUP配置基本與Master一致,僅有部分地方變動

  • state角色為BACKUP
  • interface為網路卡的ID,需要根據機器實際情況確認填寫
  • virtual_route_id要和MASTER一致,預設為51
  • priority要比MASTER

修改BACKUP節點Keepalived配置,部署配置如下:

! Configuration File for keepalived
...
rrp_instance VI_1 {
    # 指定Keepalived的角色,BACKUP表示此主機是備用節點
    state BACKUP
    # 確認網路卡的ID
    interface ens192
    # 即同一vrrp_instance下,“MASTER”和“BACKUP”必須是一致的
    virtual_router_id 51
    # 優先順序,比MASTER小
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 虛擬IP,兩個節點設定必須一樣。可以設定多個,一行寫一個
    virtual_ipaddress {
        # 虛擬IP為10.10.0.10/8;繫結介面為ens192;別名ha:net,主備相同
        10.10.0.10/8 dev ens192 label ha:net
    }
}
複製程式碼

啟動服務

配置完MASTERBACKUP節點後,我們就可以啟動並測試服務了

新增防火牆規則

因為vrrp使用224.0.0.18這個組播地址

# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface ens192 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
# firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface ens192 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
# firewall-cmd --reload
複製程式碼

檢視規則

# firewall-cmd --direct --get-rules ipv4 filter INPUT
0 --in-interface ens192 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
# firewall-cmd --direct --get-rules ipv4 filter OUTPUT
0 --out-interface ens192 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
複製程式碼

啟動Keepalived

啟動Keepalived並新增到開機自啟

# systemctl start keepalived
# systemctl enable keepalived
複製程式碼

然後我們再次檢視MASTER節點IP可以發現新增了一個

# ip addr show | grep inet
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    inet 10.10.0.11/8 brd 10.255.255.255 scope global noprefixroute ens192
    inet 10.10.0.10/32 scope global ha:net
    inet6 fd08:815:48b2::e91/128 scope global noprefixroute
    inet6 fd08:815:48b2:0:d419:f3f5:85de:b72/64 scope global noprefixroute
    inet6 fe80::49a2:321d:8cf6:651a/64 scope link noprefixroute
複製程式碼

同樣在BACKUP節點上檢視IP結果為

# ip addr show | grep inet
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    inet 10.10.0.12/8 brd 10.255.255.255 scope global noprefixroute ens192
    inet6 fd08:815:48b2::1ca/128 scope global noprefixroute
    inet6 fd08:815:48b2:0:b840:33aa:f6de:253b/64 scope global noprefixroute
    inet6 fe80::a96d:fe89:d95:3dfd/64 scope link noprefixroute
複製程式碼

測試Keepalived

安裝tcpdump工具

# yum -y install tcpdump
複製程式碼

MASTER節點上執行如下命令

# tcpdump -i ens192 vrrp -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens192, link-type EN10MB (Ethernet), capture size 262144 bytes
10:10:24.193943 IP 10.10.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
10:10:25.194972 IP 10.10.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
10:10:26.196009 IP 10.10.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
10:10:27.197038 IP 10.10.0.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
...
複製程式碼

如果關閉MASTER上的Keepalived則無包可抓,並且VIP會對應的漂移到BACKUP上去。

配置日誌

Keepalived預設日誌輸出到系統日誌/var/log/messages中,因為系統日誌很多,在查詢時相對麻煩。

我們可以將Keepalived日誌單獨拿出來,這裡需要修改日誌輸出路徑。

  1. 修改Keepalived配置
# vim /etc/sysconfig/keepalived
複製程式碼

更改如下:

# Options for keepalived. See `keepalived --help' output and keepalived(8) and
# keepalived.conf(5) man pages for a list of all options. Here are the most
# common ones :
#
# --vrrp               -P    Only run with VRRP subsystem.
# --check              -C    Only run with Health-checker subsystem.
# --dont-release-vrrp  -V    Dont remove VRRP VIPs & VROUTEs on daemon stop.
# --dont-release-ipvs  -I    Dont remove IPVS topology on daemon stop.
# --dump-conf          -d    Dump the configuration data.
# --log-detail         -D    Detailed log messages.
# --log-facility       -S    0-7 Set local syslog facility (default=LOG_DAEMON)
#

KEEPALIVED_OPTIONS="-D"
複製程式碼

修改KEEPALIVED_OPTIONS="-D"KEEPALIVED_OPTIONS="-D -d -S 0"-S指定syslog的facility

  1. 修改/etc/rsyslog.conf,在末尾新增
...
local0.*            /var/log/keepalived.log
複製程式碼
  1. 重啟日誌記錄服務
# systemctl restart rsyslog
複製程式碼
  1. 重啟Keepalived
# systemctl restart keepalived
複製程式碼
  1. 檢視日誌
# ls -lh /var/log/keepalived.log
-rw-------. 1 root root 14K 9月  30 13:22 /var/log/keepalived.log
# head -n 10 /var/log/keepalived.log
Sep 30 13:22:52 master Keepalived[30707]: Starting Keepalived v1.3.5 (03/19,2017), git commit v1.3.5-6-g6fa32f2
Sep 30 13:22:52 master Keepalived[30707]: Opening file '/etc/keepalived/keepalived.conf'.
Sep 30 13:22:52 master Keepalived[30708]: Starting Healthcheck child process, pid=30709
Sep 30 13:22:52 master Keepalived[30708]: Starting VRRP child process, pid=30710
Sep 30 13:22:52 master Keepalived_healthcheckers[30709]: Initializing ipvs
Sep 30 13:22:52 master Keepalived_healthcheckers[30709]: Opening file '/etc/keepalived/keepalived.conf'.
Sep 30 13:22:52 master Keepalived_healthcheckers[30709]: ------< Global definitions >------
Sep 30 13:22:52 master Keepalived_healthcheckers[30709]: Router ID = ha01
Sep 30 13:22:52 master Keepalived_healthcheckers[30709]: Smtp server = 192.168.200.1
Sep 30 13:22:52 master Keepalived_healthcheckers[30709]: Smtp server port = 25
複製程式碼

Keepalived+Nginx

在實際情況中,業務停止而Keepalived服務還在工作的情況會導致VIP無法找到對應的服務,這時就需要寫守護程式指令碼,下面以Nginx為例。

Nginx安裝

  • 增加對應的Nginx源
# rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
複製程式碼
  • yum安裝Nginx
# yum -y install nginx
複製程式碼
  • NGINX啟動、停止、重啟、開機自啟
# systemctl start nginx   # 啟動Nginx服務
# systemctl stop nginx    # 停止Nginx服務
# systemctl restart nginx # 重啟Nginx服務
# systemctl enable nginx  # 開機自啟Nginx服務
# nginx -t                # 檢查配置檔案正確性
# nginx -s reload         # 平滑過載配置
複製程式碼
  • 檢查啟動是否成功啟動
# curl -i localhost
複製程式碼

建立Nginx服務檢測指令碼

分別在主備伺服器的/etc/keepalived目錄下建立nginx_check.sh指令碼,指令碼如下:

#!/bin/bash
# author:akiya
A=$(ps -C nginx --no-header | wc -l)
if [ $A -eq 0 ]; then
    systemctl start nginx
    sleep 2
    if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
        systemctl stop keepalived
    fi
fi
複製程式碼

為指令碼新增可執行許可權

# chmod +x /etc/keepalived/nginx_check.sh
複製程式碼

此指令碼用於Keepalived定時檢測Nginx的服務狀態,如果Nginx停止,會嘗試重新啟動Nginx,如果啟動失敗,會將Keepalived服務停止,使IP漂移到備用節點上。

修改Keepalived配置

/etc/keepalived/keepalived.conf中增加檢測指令碼配置

global_defs {
   ...
   }
...
# keepalived會定時執行指令碼並對指令碼執行的結果進行分析,動態調整vrrp_instance的優先順序
# 如果指令碼執行結果為0,並且weight配置的值大於0,則優先順序相應的增加。
# 如果指令碼執行結果非0,並且weight配置的值小於 0,則優先順序相應的減少。
# 其他情況,維持原本配置的優先順序,即配置檔案中priority對應的值。
vrrp_script chk_nginx {
       script "/etc/keepalived/nginx_check.sh"
       interval 2  #每2秒檢測一次nginx的執行狀態
       weight -20  #失敗一次,將自己的優先順序-20
}
vrrp_instance VI_1 {
    ...
    virtual_ipaddress {
        10.10.0.10/8 dev ens192 label ha:net
    }
    track_script {
        # Nginx存活狀態監測指令碼
        chk_nginx
    }
}
複製程式碼

問題處理

Unable to access script

在使用yum安裝的版本為1.3.5,在配置檔案中編寫vrrp_script塊後,啟動服務遇到一個問題Unable to access script,經查資料發現Git Issues中有提到這個問題,新版本目前已解決。

部分報錯相關日誌如下:

Sep 30 14:25:42 master Keepalived_vrrp[30930]:     chk_nginx no match, ignoring...
Sep 30 14:26:04 master Keepalived_vrrp[30944]:     nginx_check no match, ignoring...
Sep 30 14:44:18 master Keepalived_vrrp[30980]: Unable to access script `/etc/keepalived/nginx_check.sh`
Sep 30 14:44:18 master Keepalived_vrrp[30980]: Disabling track script chk_nginx since not found
複製程式碼

如果使用yum安裝可以在安裝前檢視下對應的包資訊

# yum info keepalived
複製程式碼

default user...

使用編譯安裝後(安裝版本2.0.18),新增Nginx檢測指令碼並啟動Keepalived服務後,日誌顯示 default user 'keepalived_script' for script execution does not exist - please create.

解決方法:在配置檔案中新增執行檢測指令碼的使用者或組即可

! Configuration File for keepalived

global_defs {
...
   script_user root
   enable_script_security
}
...
複製程式碼

相關文章