Keepalived 是一種高性能的服務器高可用或熱備解決方案, Keepalived 可以用來防止服務器單點故障的發(fā)生,通過配合 Nginx 可以實現(xiàn) web 前端服務的高可用。
Keepalived 以 VRRP 協(xié)議為實現(xiàn)基礎。 VRRP(Virtual RouterRedundancy Protocol)協(xié)議是用于實現(xiàn)路由器冗余的協(xié)議, 它將兩臺或多臺路由器設備虛擬成一個設備,對外提供虛擬路由器 IP(一個或多個),而在路由器組內部,如果實際擁有這個對外 IP 的路由器如果工作正常就是 MASTER,或者是通過算法選舉產生, MASTER 實現(xiàn)針對虛擬路由器 IP 的各種網(wǎng)絡功能,其他設備不擁有該虛擬 IP,狀態(tài)是 BACKUP,除了接收 MASTER 的VRRP 狀態(tài)通告信息外,不執(zhí)行對外的網(wǎng)絡功能。
當主機失效時, BACKUP 將接管原先 MASTER 的網(wǎng)絡功能。VRRP 協(xié)議使用多播數(shù)據(jù)來傳輸 VRRP 數(shù)據(jù), VRRP 數(shù)據(jù)使用特殊的虛擬源 MAC 地址發(fā)送數(shù)據(jù)而不是自身網(wǎng)卡的 MAC 地址, VRRP 運行時只有 MASTER 路由器定時發(fā)送 VRRP 通告信息,表示 MASTER 工作正常以及虛擬路由器 IP(組), BACKUP 只接收 VRRP 數(shù)據(jù),不發(fā)送數(shù)據(jù),如果一定時間內沒有接收到 MASTER 的通告信息,各 BACKUP 將宣告自己成為 MASTER,發(fā)送通告信息,重新進行 MASTER 選舉狀態(tài)。
安裝nginx
$ cd /usr/local/src/
$ wget http://nginx.org/download/nginx-1.13.0.tar.gz
$ tar -zxvf nginx-1.13.0.tar.gz
$ cd nginx-1.13.0
$ ./configure --prefix=/usr/local/nginx
$ make && make install
安裝完成后,檢查并連接nginx
# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.13.0
# ln /usr/local/nginx/sbin/nginx /usr/local/bin/
連接完成后就可以直接使用命令nginx。
配置nginx.conf,模擬簡單的負載均衡,這里采用baidu和360兩個地址做測試。
修改/usr/local/nginx/conf/nginx.conf文件,參照下面的內容。
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
upstream api {
server 61.135.169.121:80 max_fails=1; #baidu.com
server 42.236.9.70:80 max_fails=1; #so.com
}
server {
listen 80;
location / {
proxy_next_upstream error timeout http_500 http_502 http_504;
proxy_read_timeout 10s;
proxy_pass http://api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
修改完了,重啟nginx,nginx -s reload
然后在瀏覽器上輸入對應機器的IP,此時應該看到地址切換效果。
防火墻開放端口
若不能訪問此機器,則可能是防火墻沒有開放80端口,可以打開端口或關閉防火墻
下面我們打開80端口
firewall-cmd --list-all #檢查 80 端口
firewall-cmd --zone=public --add-port=80/tcp #開放80端口
firewall-cmd --reload
安裝keepalived
$ yum -y install keepalived
這樣安裝版本較低,下載最新版http://www.keepalived.org/download.html
設置 keepalived 服務開機啟動
$ chkconfig keepalived on
配置/etc/keepalived/keepalived.conf,加上以下內容:
global_defs {
#這里發(fā)郵件只對內網(wǎng)
notification_email {
xxx@qq.com #郵件報警
}
notification_email_from xxx@163.com #指定發(fā)件人
smtp_server smtp.163.com #指定smtp服務器地址
smtp_connect_timeout 30 #指定smtp連接超時時間
router_id LVS_DEVEL #負載均衡標識,在局域網(wǎng)內應該是唯一的。
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
#每2秒檢測一次nginx的運行狀態(tài)
interval 2
#失敗一次,將自己的優(yōu)先級調整為-20
weight -20
}
# virtual_ipaddress vip
# vrrp-虛擬路由冗余協(xié)議
# vrrp_instance 用來定義對外提供服務的VIP區(qū)域及其相關屬性
vrrp_instance VI_1 {
state BACKUP #指定該keepalived節(jié)點的初始狀態(tài)
interface enp0s3 #@@vrrp實例綁定的接口,用于發(fā)送VRRP包
virtual_router_id 51 #取值在0-255之間,用來區(qū)分多個instance的VRRP組播, 同一網(wǎng)段中該值不能重復,并且同一個vrrp實例使用唯一的標識
priority 150 #@@指定優(yōu)先級,優(yōu)先級高的將成為MASTER
nopreempt #設置為不搶占。默認是搶占的
authentication {
auth_type PASS
auth_pass 11111
}
###采用單播通信,避免同一個局域網(wǎng)中多個keepalived組之間的相互影響
unicast_src_ip 172.19.165.254 ##@@本機ip
unicast_peer { #@@采用單播的方式發(fā)送VRRP通告,指定單播鄰居的IP地址
172.19.165.222
}
virtual_ipaddress { #@@指定VIP地址
172.19.165.251
}
#nginx存活狀態(tài)檢測腳本
track_script {
chk_nginx
}
#提示如:I'm the MASTER! Whup whup
notify "/container/service/keepalived/assets/notify.sh"
#節(jié)點變?yōu)閙aster時執(zhí)行
notify_master "/etc/keepalived/send_mail.sh"
}
vrrp_instance VI_2 {
state BACKUP
interface enp0s3
virtual_router_id 52
priority 99
nopreempt
authentication {
auth_type PASS
auth_pass 1111
}
###采用單播通信,避免同一個局域網(wǎng)中多個keepalived組之間的相互影響
unicast_src_ip 172.19.165.254 ##本機ip
unicast_peer { #采用單播的方式發(fā)送VRRP通告,指定單播鄰居的IP地址
172.19.165.222
}
virtual_ipaddress {
172.19.165.252
}
#nginx存活狀態(tài)檢測腳本
track_script {
chk_nginx
}
notify "/container/service/keepalived/assets/notify.sh"
#節(jié)點變?yōu)閙aster時執(zhí)行
notify_master "/etc/keepalived/send_mail.sh"
}
注意,標@@的地方是要修改的。
同時,我們還需要2個腳本,一個用來監(jiān)視nginx,另一個用來發(fā)送報警郵件。
nginx_check.sh
#!/bin/bash
A=`ps -C nginx -no-header |wc -l`
if [ $A -eq 1 ];then
pkill keepalived
fi
send_mail.sh
#!/usr/bin/perl -w
use Net::SMTP_auth;
use strict;
#smtp服務器
my $mailhost = 'smtp.163.com';
#發(fā)送郵件的郵箱
my $mailfrom = 'xxx@163.com';
#接收郵件的郵箱
my @mailto = ('xxx@qq.com');
#郵件主題
my $subject = 'keepalived up on backup';
#郵件正文
my $text = "正文\n nginx-1服務器宕機??!nginx-2變?yōu)閙aster?。?!";
#發(fā)送郵件的用戶名
my $user = 'xxx@163.com';
#發(fā)送郵件的郵箱--163授權碼
my $passwd = 'xxx';
&SendMail();
##############################
# Send notice mail
##############################
sub SendMail() {
my $smtp = Net::SMTP_auth->new( $mailhost, Timeout => 120, Debug => 1 )
or die "Error.\n";
$smtp->auth( 'LOGIN', $user, $passwd );
foreach my $mailto (@mailto) {
$smtp->mail($mailfrom);
$smtp->to($mailto);
$smtp->data();
$smtp->datasend("To: $mailto\n");
$smtp->datasend("From:$mailfrom\n");
$smtp->datasend("Subject: $subject\n");
$smtp->datasend("\n");
$smtp->datasend("$text\n\n");
$smtp->dataend();
}
$smtp->quit;
}
給這2個腳本添加執(zhí)行權限
# chmod +x send_mail.sh nginx_check.sh
注意,調用的send_mail.sh腳本為使用Perl編寫的,需要安裝環(huán)境:
$ yum -y install perl-CPAN
$ cpan Net::SMTP_auth
寫完腳本,可以直接測試發(fā)郵件,執(zhí)行./send_mail.sh。
重啟keepalived服務,則可發(fā)現(xiàn)接收到相關郵件提醒,因為state發(fā)生改變。
$ service keepalived restart
同樣的方式,再部署另一臺,依次修改的地方為:
- interface
- priority(減1)
- unicast_src_ip
- unicast_peer
修改完成后,重啟服務。
驗證keepalived高可用
在瀏覽器上輸入虛擬IP,如輸入http://172.19.165.251會自動切換到MASTER的機器上,可以查看虛擬IP綁定在哪臺機器上,輸入 命令ip addr

可以看到MASTER真實IP下面綁定了2個虛擬IP
再看下SLAVE有沒有綁定虛擬IP

從圖上看到SLAVE上并沒有綁定虛擬IP
當關掉MASTER,可以收到相關郵件
[root@localhost ~]# nginx -s stop
然后,也看到虛擬IP綁定也發(fā)生了改變。


當MASTER再次啟動,由于是非搶占模式,所以它仍然是BACKUP狀態(tài)。
keepalived也要啟動
systemctl start keepalived
#service keepalived start
注意,上面的nginx_check.sh會關閉keepalived,當nginx停止時keepalived也會停止,所以啟動nginx也要一起啟動keepalived.
keepalived不能自動切換原因
- 查看keepalived是否啟動
ps -ef|grep keepalived - 防火墻放行keepalived
centos7是firewall,之前的是iptables
# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 \
--in-interface enp0s8 --destination 172.19.165.222 --protocol vrrp -j ACCEPT
success
# firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 \
--out-interface enp0s8 --destination 172.19.165.222 --protocol vrrp -j ACCEPT
success
# firewall-cmd --reload
success