目錄
- 概述
- 規(guī)劃與準(zhǔn)備工作
- 安裝、部署Nginx和Keepalived
- 高可用方案--主主配置
- 高可用方案--主從配置
- Keepalived配置選項(xiàng)說明
1. 概述
1.1 Keepalived介紹
Keepalived是一個(gè)基于VRRP協(xié)議來實(shí)現(xiàn)的服務(wù)高可用方案,可以利用其來避免IP單點(diǎn)故障,類似的工具還有heartbeat、corosync、pacemaker。但是它一般不會單獨(dú)出現(xiàn),而是與其它負(fù)載均衡技術(shù)(如LVS、HAProxy、Nginx)一起工作來達(dá)到集群的高可用。
VRRP(Virtual Router Redundancy Protocol),即虛擬路由冗余協(xié)議。可以認(rèn)為它是實(shí)現(xiàn)路由器高可用的容錯(cuò)協(xié)議,即將多臺提供相同功能的路由器組成一個(gè)路由器組(Router Group),這個(gè)組里面有一個(gè)master和多個(gè)backup,但在外界看來就像一臺一樣,構(gòu)成虛擬路由器,擁有一個(gè)虛擬IP(vip,也就是路由器所在局域網(wǎng)內(nèi)其他機(jī)器的默認(rèn)路由),占有這個(gè)IP的master實(shí)際負(fù)責(zé)ARP相應(yīng)和轉(zhuǎn)發(fā)IP數(shù)據(jù)包,組中的其它路由器作為備份的角色處于待命狀態(tài)。master會發(fā)組播消息,當(dāng)backup在超時(shí)時(shí)間內(nèi)收不到vrrp包時(shí)就認(rèn)為master宕掉了,這時(shí)就需要根據(jù)VRRP的優(yōu)先級來選舉一個(gè)backup當(dāng)master,保證路由器的高可用。
在VRRP協(xié)議實(shí)現(xiàn)里,虛擬路由器使用 00-00-5E-00-01-XX 作為虛擬MAC地址,XX就是唯一的 VRID (Virtual Router IDentifier),這個(gè)地址同一時(shí)間只有一個(gè)物理路由器占用。在虛擬路由器里面的物理路由器組里面通過多播IP地址 224.0.0.18 來定時(shí)發(fā)送通告消息。每個(gè)Router都有一個(gè) 1-255 之間的優(yōu)先級別,級別最高的(highest priority)將成為主控(master)路由器。通過降低master的優(yōu)先權(quán)可以讓處于backup狀態(tài)的路由器搶占(pro-empt)主路由器的狀態(tài),兩個(gè)backup優(yōu)先級相同的IP地址較大者為master,接管虛擬IP。
一般Keepalived用于實(shí)現(xiàn)前端高可用,常用的前端高可用的組合有,就是我們常見的LVS+Keepalived、Nginx+Keepalived、HAproxy+Keepalived。
1.2 Nginx + Keepalived
keepalived可以認(rèn)為是VRRP協(xié)議在Linux上的實(shí)現(xiàn),主要有三個(gè)模塊,分別是core、check和vrrp。core模塊為keepalived的核心,負(fù)責(zé)主進(jìn)程的啟動、維護(hù)以及全局配置文件的加載和解析。check負(fù)責(zé)健康檢查,包括常見的各種檢查方式。vrrp模塊是來實(shí)現(xiàn)VRRP協(xié)議的。本文基于如下的拓?fù)鋱D:
2. 規(guī)劃與準(zhǔn)備工作
-
關(guān)閉SELinux
為了保證Nginx和Keepalived之間的正常數(shù)據(jù)通信, 需要關(guān)閉Linux的SELinux。
[root@localhost ~]# vi /etc/sysconfig/selinux # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - SELinux is fully disabled. SELINUX=disabled # SELINUXTYPE= type of policy in use. Possible values are: # targeted - Only targeted network daemons are protected. # strict - Full SELinux protection. SELINUXTYPE=targeted
-
配置iptables
配置iptables, 允許相應(yīng)的端口通信。
[root@Docker-OA-98 ~]# vi /etc/sysconfig/iptables *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 89 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 9080 -j ACCEPT # 允許VRRP(虛擬路由冗余協(xié)議)通信 -A INPUT -p vrrp -j ACCEPT # 允許Keepalived虛擬路由組播地址通信 -A INPUT -d 224.0.0.18 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT
環(huán)境規(guī)劃
序號 | 服務(wù)器名稱 | 主機(jī)名 | IP地址 | 操作系統(tǒng) | 備注 |
---|---|---|---|---|---|
1 | VIP1(Keepalived) | 無 | 192.168.1.100 | - | 虛擬節(jié)點(diǎn) |
2 | VIP2(Keepalived) | 無 | 192.168.1.101 | - | 主主模式 |
3 | Nginx 01 | Nginx-A-98 | 192.168.1.98 | CentOS LInux 7.3 | |
4 | Nginx 02 | Nginx-B-99 | 192.168.1.99 | CentOS LInux 7.3 | |
5 | Tomcat 01 | Tomcat-Web-91 | 192.168.202.91 | CentOS LInux 7.3 | |
6 | Tomcat 02 | Tomcat-Web-92 | 192.168.202.92 | CentOS LInux 7.3 | |
7 | Tomcat 03 | Tomcat-Web-93 | 192.168.202.93 | CentOS LInux 7.3 | ? |
3. 安裝、部署Nginx與Keepalived
3.1 安裝Nginx與Keepalived
分別在服務(wù)器Nginx 01和Nginx 02安裝Nginx和Keepalived。
# 安裝Nginx
[root@Docker-OA-98 ~]# yum -y install nginx
# 安裝Keepalived
[root@Docker-OA-98 ~]# yum -y install keepalived
3.2 配置Nginx負(fù)載均衡
分別在服務(wù)器Nginx 01和Nginx02上配置Nginx的應(yīng)用負(fù)載均衡。
[root@Docker-OA-98 ~]# vi /etc/nginx/nginx.conf
upstream application01 {
ip_hash;
server 192.168.202.91:8080;
server 192.168.202.92:8080;
server 192.168.202.93:8080;
}
server {
listen 80;
listen [::]:80;
server_name service.test01.com;
#root /usr/share/nginx/html;
location / {
proxy_pass http://application01/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
access_log /var/log/nginx/access.ecology.log main;
client_max_body_size 100m;
client_body_buffer_size 1024k;
proxy_connect_timeout 5000;
proxy_read_timeout 5000;
proxy_send_timeout 6000;
proxy_buffer_size 1024k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 1024k;
proxy_temp_file_write_size 1024k;
}
}
4. 高可用方案 -- 主主模式
- Nginx 01服務(wù)器Keepalived腳本配置
[root@Nginx-A-98 src]# vim /etc/keepalived/keepalived.conf
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" # 檢測nginx狀態(tài)的腳本路徑
interval 2 # 檢測時(shí)間間隔2s
weight -20 # 如果腳本的條件成立,權(quán)重-20
}
vrrp_instance VI_1 { # VRRP實(shí)例名;多實(shí)例的情況下,名稱必須不一致
state MASTER # 服務(wù)狀態(tài);MASTER(工作狀態(tài))BACKUP(備用狀態(tài))
interface eth0 # VIP綁定網(wǎng)卡
virtual_router_id 51 # 虛擬路由ID,主、備節(jié)點(diǎn)必須一致;多實(shí)例的情況下,ID必須不一致
mcast_src_ip 192.168.1.98 # 本機(jī)IP
nopreempt # 優(yōu)先級高的設(shè)置,解決異常回復(fù)后再次搶占的問題
priority 100 # 優(yōu)先級;取值范圍:0~254;MASTER > BACKUP
advert_int 1 # 組播信息發(fā)送間隔,主、備節(jié)點(diǎn)必須一致,默認(rèn)1s
authentication { # 驗(yàn)證信息;主、備節(jié)點(diǎn)必須一致
auth_type PASS # VRRP驗(yàn)證類型,PASS、AH兩種
auth_pass 1111 # VRRP驗(yàn)證密碼,在同一個(gè)vrrp_instance下,主、從必須使用相同的密碼才能正常通信
}
track_script { # 將track_script塊加入instance配置塊
chk_nginx # 執(zhí)行Nginx監(jiān)控的服務(wù)
}
virtual_ipaddress { # 虛擬IP池,主、備節(jié)點(diǎn)必須一致,可以定義多個(gè)VIP
192.168.1.100 # 虛擬IP
}
}
vrrp_instance VI_2 {
state BACKUP
interface eth0
virtual_router_id 52
mcast_src_ip 192.168.1.98
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.1.101
}
}
- Nginx 02服務(wù)器Keepalived配置
[root@Nginx-B-99 src]# vim /etc/keepalived/keepalived.conf
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2
weight -20
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
mcast_src_ip 192.168.1.99
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.1.100
}
}
vrrp_instance VI_2 {
state MASTER
interface eth0
virtual_router_id 52
mcast_src_ip 192.168.1.99
nopreempt
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.1.101
}
}
- Nginx狀態(tài)監(jiān)測腳本
分別在服務(wù)器Nginx 01和Nginx 02上添加Nginx狀態(tài)監(jiān)測腳本。
[root@Nginx-A-98 keepalived]# vim /etc/keepalived/nginx_check.sh
#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
killall keepalived
fi
fi
我們也可以根據(jù)自己的業(yè)務(wù)需求,總結(jié)出在什么情形下關(guān)閉keepalived,如 curl 主頁連續(xù)2個(gè)5s沒有響應(yīng)則切換:
#!/bin/bash
count = 0
for (( k=0; k<2; k++ ))
do
check_code=$( curl --connect-timeout 3 -sL -w "%{http_code}\\n" http://localhost/login.html -o /dev/null )
if [ "$check_code" != "200" ]; then
count = count +1
continue
else
count = 0
break
fi
done
if [ "$count" != "0" ]; then
# /etc/init.d/keepalived stop
exit 1
else
exit 0
fi
5. 高可用方案 -- 主從模式
- Nginx 01服務(wù)器Keepalived腳本配置
[root@Nginx-A-98 src]# vim /etc/keepalived/keepalived.conf
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" # 檢測nginx狀態(tài)的腳本路徑
interval 2 # 檢測時(shí)間間隔2s
weight -20 # 如果腳本的條件成立,權(quán)重-20
}
vrrp_instance VI_1 { # VRRP實(shí)例名;多實(shí)例的情況下,名稱必須不一致
state MASTER # 服務(wù)狀態(tài);MASTER(工作狀態(tài))BACKUP(備用狀態(tài))
interface eth0 # VIP綁定網(wǎng)卡
virtual_router_id 51 # 虛擬路由ID,主、備節(jié)點(diǎn)必須一致;多實(shí)例的情況下,ID必須不一致
mcast_src_ip 192.168.1.98 # 本機(jī)IP
nopreempt # 優(yōu)先級高的設(shè)置,解決異常回復(fù)后再次搶占的問題
priority 100 # 優(yōu)先級;取值范圍:0~254;MASTER > BACKUP
advert_int 1 # 組播信息發(fā)送間隔,主、備節(jié)點(diǎn)必須一致,默認(rèn)1s
authentication { # 驗(yàn)證信息;主、備節(jié)點(diǎn)必須一致
auth_type PASS # VRRP驗(yàn)證類型,PASS、AH兩種
auth_pass 1111 # VRRP驗(yàn)證密碼,在同一個(gè)vrrp_instance下,主、從必須使用相同的密碼才能正常通信
}
track_script { # 將track_script塊加入instance配置塊
chk_nginx # 執(zhí)行Nginx監(jiān)控的服務(wù)
}
virtual_ipaddress { # 虛擬IP池,主、備節(jié)點(diǎn)必須一致,可以定義多個(gè)VIP
192.168.1.100 # 虛擬IP
}
}
- Nginx 02服務(wù)器Keepalived配置
[root@Nginx-B-99 src]# vim /etc/keepalived/keepalived.conf
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2
weight -20
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
mcast_src_ip 192.168.1.99
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.1.100
}
}
- Nginx狀態(tài)監(jiān)測腳本
分別在服務(wù)器Nginx 01和Nginx 02上添加Nginx狀態(tài)監(jiān)測腳本。
[root@Nginx-A-98 keepalived]# vim /etc/keepalived/nginx_check.sh
#!/bin/bash
A=`ps -C nginx –no-header |wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
killall keepalived
fi
fi
6. Keepalived配置選項(xiàng)說明
6.1 global_defs
- notification_email : keepalived在發(fā)生諸如切換操作時(shí)需要發(fā)送email通知地址,后面的 smtp_server 相比也都知道是郵件服務(wù)器地址。也可以通過其它方式報(bào)警,畢竟郵件不是實(shí)時(shí)通知的。
- router_id : 機(jī)器標(biāo)識,通常可設(shè)為hostname。故障發(fā)生時(shí),郵件通知會用到
6.2 vrrp_instance
- state : 指定instance(Initial)的初始狀態(tài),就是說在配置好后,這臺服務(wù)器的初始狀態(tài)就是這里指定的,但這里指定的不算,還是得要通過競選通過優(yōu)先級來確定。如果這里設(shè)置為MASTER,但如若他的優(yōu)先級不及另外一臺,那么這臺在發(fā)送通告時(shí),會發(fā)送自己的優(yōu)先級,另外一臺發(fā)現(xiàn)優(yōu)先級不如自己的高,那么他會就回?fù)屨紴镸ASTER
- interface : 實(shí)例綁定的網(wǎng)卡,因?yàn)樵谂渲锰摂MIP的時(shí)候必須是在已有的網(wǎng)卡上添加的
- mcast_src_ip : 發(fā)送多播數(shù)據(jù)包時(shí)的源IP地址,這里注意了,這里實(shí)際上就是在那個(gè)地址上發(fā)送VRRP通告,這個(gè)非常重要,一定要選擇穩(wěn)定的網(wǎng)卡端口來發(fā)送,這里相當(dāng)于heartbeat的心跳端口,如果沒有設(shè)置那么就用默認(rèn)的綁定的網(wǎng)卡的IP,也就是interface指定的IP地址
- virtual_router_id : 這里設(shè)置VRID,這里非常重要,相同的VRID為一個(gè)組,他將決定多播的MAC地址
- priority : 設(shè)置本節(jié)點(diǎn)的優(yōu)先級,優(yōu)先級高的為master
- advert_int : 檢查間隔,默認(rèn)為1秒。這就是VRRP的定時(shí)器,MASTER每隔這樣一個(gè)時(shí)間間隔,就會發(fā)送一個(gè)advertisement報(bào)文以通知組內(nèi)其他路由器自己工作正常
- authentication : 定義認(rèn)證方式和密碼,主從必須一樣
- virtual_ipaddress : 這里設(shè)置的就是VIP,也就是虛擬IP地址,他隨著state的變化而增加刪除,當(dāng)state為master的時(shí)候就添加,當(dāng)state為backup的時(shí)候刪除,這里主要是有優(yōu)先級來決定的,和state設(shè)置的值沒有多大關(guān)系,這里可以設(shè)置多個(gè)IP地址
- track_script : 引用VRRP腳本,即在 vrrp_script 部分指定的名字。定期運(yùn)行它們來改變優(yōu)先級,并最終引發(fā)主備切換。
6.3 vrrp_script
告訴 keepalived 在什么情況下切換,所以尤為重要。可以存在多個(gè) vrrp_script。
- script : 自己寫的檢測腳本。也可以是一行命令如killall -0 nginx
- interval 2 : 每2s檢測一次
- weight -5 : 檢測失敗(腳本返回非0)則優(yōu)先級 -5
- fall 2 : 檢測連續(xù) 2 次失敗才算確定是真失敗。會用weight減少優(yōu)先級(1-255之間)
- rise 1 : 檢測 1 次成功就算成功。但不修改優(yōu)先級
這里要提示一下script一般有2種寫法:
- 通過腳本執(zhí)行的返回結(jié)果,改變優(yōu)先級,keepalived繼續(xù)發(fā)送通告消息,backup比較優(yōu)先級再決定
- 腳本里面檢測到異常,直接關(guān)閉keepalived進(jìn)程,backup機(jī)器接收不到advertisement會搶占IP
上文 vrrp_script 配置部分,killall -0 nginx
屬于第1種情況,/etc/keepalived/check_nginx.sh
屬于第2種情況(腳本中關(guān)閉keepalived)。個(gè)人更傾向于通過shell腳本判斷,但有異常時(shí)exit 1,正常退出exit 0,然后keepalived根據(jù)動態(tài)調(diào)整的 vrrp_instance 優(yōu)先級選舉決定是否搶占VIP:
- 如果腳本執(zhí)行結(jié)果為0,并且weight配置的值大于0,則優(yōu)先級相應(yīng)的增加
- 如果腳本執(zhí)行結(jié)果非0,并且weight配置的值小于0,則優(yōu)先級相應(yīng)的減少
其他情況,原本配置的優(yōu)先級不變,即配置文件中priority對應(yīng)的值。
提示:
- 優(yōu)先級不會不斷的提高或者降低
- 可以編寫多個(gè)檢測腳本并為每個(gè)檢測腳本設(shè)置不同的weight(在配置中列出就行)
- 不管提高優(yōu)先級還是降低優(yōu)先級,最終優(yōu)先級的范圍是在[1,254],不會出現(xiàn)優(yōu)先級小于等于0或者優(yōu)先級大于等于255的情況
- 在MASTER節(jié)點(diǎn)的 vrrp_instance 中 配置 nopreempt ,當(dāng)它異常恢復(fù)后,即使它 prio 更高也不會搶占,這樣可以避免正常情況下做無謂的切換
以上可以做到利用腳本檢測業(yè)務(wù)進(jìn)程的狀態(tài),并動態(tài)調(diào)整優(yōu)先級從而實(shí)現(xiàn)主備切換。