Keepalived 是一種高性能的服務器高可用或熱備解決方案岁钓, Keepalived 可以用來防止服務器單點故障的發(fā)生,通過配合 Nginx 可以實現 web 前端服務的高可用偎巢。
Keepalived 以 VRRP 協議為實現基礎蔼夜。 VRRP(Virtual RouterRedundancy Protocol)協議是用于實現路由器冗余的協議, 它將兩臺或多臺路由器設備虛擬成一個設備压昼,對外提供虛擬路由器 IP(一個或多個)求冷,而在路由器組內部,如果實際擁有這個對外 IP 的路由器如果工作正常就是 MASTER窍霞,或者是通過算法選舉產生匠题, MASTER 實現針對虛擬路由器 IP 的各種網絡功能,其他設備不擁有該虛擬 IP但金,狀態(tài)是 BACKUP韭山,除了接收 MASTER 的VRRP 狀態(tài)通告信息外,不執(zhí)行對外的網絡功能。
當主機失效時钱磅, BACKUP 將接管原先 MASTER 的網絡功能巩踏。VRRP 協議使用多播數據來傳輸 VRRP 數據, VRRP 數據使用特殊的虛擬源 MAC 地址發(fā)送數據而不是自身網卡的 MAC 地址续搀, VRRP 運行時只有 MASTER 路由器定時發(fā)送 VRRP 通告信息,表示 MASTER 工作正常以及虛擬路由器 IP(組)菠净, BACKUP 只接收 VRRP 數據禁舷,不發(fā)送數據,如果一定時間內沒有接收到 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ā)郵件只對內網
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 #負載均衡標識楚午,在局域網內應該是唯一的昭齐。
}
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-虛擬路由冗余協議
# 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組播, 同一網段中該值不能重復把沼,并且同一個vrrp實例使用唯一的標識
priority 150 #@@指定優(yōu)先級啊易,優(yōu)先級高的將成為MASTER
nopreempt #設置為不搶占。默認是搶占的
authentication {
auth_type PASS
auth_pass 11111
}
###采用單播通信饮睬,避免同一個局域網中多個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
}
###采用單播通信,避免同一個局域網中多個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!R巳浮切平!";
#發(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ā)現接收到相關郵件提醒,因為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