实验目的:
利用keepalived实现高可用反向代理的nginx。以及双主模型的ipvs
实验环境:
node1:在nginx做代理时做反向代理节点,在keepalived实现LVS时做Director。VIP1:172.16.18.22 VIP2:172.16.18.23
node2:在nginx做代理时做反向代理节点,在keepalived实现LVS时做Director。VIP1:172.16.18.22 VIP2:172.16.18.23
node3:在nginx做代理时做web服务器。在keepalived实现时做real server
实验模型:
实验内容:
keepalived实现高可用nginx的反向代理
1,为实验提供应用程序:
安装nginx,keepalived.本实验我使用的是自己编译安装的nginx最新版本。大家也可以自己编译安装,也可以选择程序包安装。keepalived选择程序包安装!编译安装nginx此处不做说明。大家可以自己去寻找教程。
yum install keepalived
这两个程序需要在两个节点提供安装。
2,首先我们先配置nginx让他提供web服务。
编辑nginx的配置文件/usr/local/nginx/conf/nginx.conf 提供最基本的服务,先让他可以显示出页面来。
user root; worker_processes 1; #error_log logs/error.log; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; gzip on; server { listen 80; server_name node1.aolens.com; location / { root /data/webapps/www; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /data/webapps/html; } location ~ \.php$ { root /data/webapps/www/; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; }
下边来为nginx提供一个页面文件。启动nginx
访问页面node1
下边停止nginx,并且不让它开机启动
service nginx stop
chkconfig nginx off
[root@node1 ~]# chkconfig --list |grep nginx
nginx 0:off 1:off 2:off 3:off 4:off 5:off 6:off
将配置文件发送到node2上。提供一个访问页面。启动nginx。
停止nginx,并且不让它开机启动
service nginx stop
[root@node2 ~]# service nginx stop
Stopping nginx: [ OK ]
[root@node2 ~]# chkconfig nginx off
[root@node2 ~]# chkconfig --list |grep nginx
nginx 0:off 1:off 2:off 3:off 4:off 5:off 6:off
好,这里我们的nginx服务就可以正常启动了。
3,下来我们来利用keepalived实现高可用。
前边我们安装好了keepalived编译配置文件/etc/keepalived/keepalived.conf
global_defs { notification_email { [email protected] #邮箱 } notification_email_from [email protected] #邮箱地址 smtp_server 127.0.0.1 #邮箱发往地址 smtp_connect_timeout 30 } vrrp_script chk_nginx{ #定义检测nginx script "killall -0 nginx" #killall -0 nginx 检测nginx是否在线 interval 1 #多长 时间检测一次 weight -5 #如果不在线,权重-5 fall 2 #不在线检测次数 raise 1 #上线检测次数 } vrrp_instance VI_1 { #定义一个资源 state MASTER #定义为主节点 interface eth0 #定义网卡 virtual_router_id 18 #虚拟路由ID priority 100 #优先级 advert_int 1 #广播间隔 authentication { auth_type PASS #认证方式 auth_pass 1111 #认证密码 } track_script{ #调用检测 chk_nginx } notify_master "/etc/init.d/nginx start" #通知脚本,执行指定选项 notify_backup "/etc/init.d/nginx stop" notify_fault "/etc/init.d/nginx stop" virtual_ipaddress { #虚拟路由地址 172.16.18.22 } }
发送到node2 修改
state BACKUP
priority 99
我们先启动node2上的keepalived,会发现nginx跟随一起启动了,而且日志中显示此为主节点。因为node1节点此时没有上线。
[root@node2 ~]# service keepalived restart
Starting keepalived: [ OK ]
[root@node2 ~]# service nginx status
nginx (pid 11425 11424) is running...
tail /var/log/message
Sep 15 12:48:32 node2 Keepalived_vrrp[11313]: VRRP_Instance(VI_1) Transition to MASTER STATE
Sep 15 12:48:33 node2 Keepalived_vrrp[11313]: VRRP_Instance(VI_1) Entering MASTER STATE
Sep 15 12:48:33 node2 Keepalived_vrrp[11313]: VRRP_Instance(VI_1) setting protocol VIPs.
Sep 15 12:48:33 node2 Keepalived_healthcheckers[11312]: Netlink reflector reports IP 172.16.18.22 added
Sep 15 12:48:33 node2 Keepalived_vrrp[11313]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.16.18.22
Sep 15 12:48:38 node2 Keepalived_vrrp[11313]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.16.18.22
此时启动node1 ,会发现node1上的nginx也启动了。访问会发现是node2
[root@node1 ~]# service keepalived start
Starting keepalived: [ OK ]
[root@node1 ~]# service nginx status
nginx (pid 16512 16511) is running...
tail /var/log/message
Sep 15 16:00:49 node1 Keepalived_vrrp[16853]: VRRP_Instance(VI_1) Transition to MASTER STATE
Sep 15 16:00:49 node1 Keepalived_vrrp[16853]: VRRP_Instance(VI_1) Received lower prio advert, forcing new election
Sep 15 16:00:50 node1 Keepalived_vrrp[16853]: VRRP_Instance(VI_1) Entering MASTER STATE
Sep 15 16:00:50 node1 Keepalived_vrrp[16853]: VRRP_Instance(VI_1) setting protocol VIPs.
Sep 15 16:00:50 node1 Keepalived_healthcheckers[16852]: Netlink reflector reports IP 172.16.18.22 added
Sep 15 16:00:50 node1 Keepalived_vrrp[16853]: VRRP_Instance(VI_1) Sending gratuitous ARPs on eth0 for 172.16.18.22
发现主节点到了node1上,此时node2变为了备节点,而且发现node2的nginx已stop
Sep 15 13:47:56 node2 Keepalived_vrrp[11313]: VRRP_Instance(VI_1) Transition to MASTER STATE
Sep 15 13:47:56 node2 Keepalived_vrrp[11313]: VRRP_Instance(VI_1) Received higher prio advert
Sep 15 13:47:56 node2 Keepalived_vrrp[11313]: VRRP_Instance(VI_1) Entering BACKUP STATE
[root@node2 ~]# service nginx status
nginx is stopped
访问会发现是node1
此时就实现了nginx的高可用,但是这种模式有着明显的缺陷,他只能在keepalived出现问题是可以完美切换,但是有没有想过如果是nginx程序出现故障了,那还能不能高可用呢?
假如:node1上的nginx出现问题,权限-5,此时node1上的权限低于node2,主节点会切到node2上,如果node1上的nginx起来,权限是不会+5的,也就是说此时node1上的权限是95,node2上的权限是99.主节点不会切回来,如果node2上的nginx挂了权限-5才会切到node1上来。这样如果主备节点的性能差距较大的话是很不理想的状况。
解决办法在全局段添加
vrrp_script chk_mantaince_down { script "[[ -e /etc/keepalived/down ]] && exit 1 || exit 0" interval 1 weight -2 } 修改track_script,添加chk_mantaince_down track_script { chk_haproxy chk_mantaince_down }
这样当你在node1 上的nginx恢复,就可以在node2 节点/etc/keeplived下touch个down,权重就会再+5.也就是100,就会转回来了。
当然也可以利用脚本来监控,下边提供一个脚本仅供参考。
下面是一个notify.sh脚本的简单示例:
#!/bin/bash # Author: MageEdu < [email protected] > # description: An example of notify script vip=172.16.100.1 contact=' root@localhost ' notify() { mailsubject="`hostname` to be $1: $vip floating" mailbody="`date '+%F %H:%M:%S'`: vrrp transition, `hostname` changed to be $1" echo $mailbody | mail -s "$mailsubject" $contact } case "$1" in master) notify master /etc/rc.d/init.d/haproxy start exit 0 ;; backup) notify backup /etc/rc.d/init.d/haproxy stop exit 0 ;; fault) notify fault /etc/rc.d/init.d/haproxy stop exit 0 ;; *) echo 'Usage: `basename $0` {master|backup|fault}' exit 1 ;; esac
4,下来便需要使用nginx做反向代理。所以我们需要提供两个real server提供web 服务。
由于资源原因我们下边实现只提供一台real server。
好,前提说完下边我们来为新的real server提供nginx,让nginx提供web服务。
real server上的nginx我们选择yum安装。
安装好后访问以下
好的,访问没有问题。
下边我们来配置nginx的反向代理。在node1,node2上。
下来配置nginx让其具有反向代理的作用。
在nginx的配置文件中server段中添加如下段。
[root@node1 ~]# vim /usr/local/nginx/conf/nginx.conf
location = / {
proxy_pass http://172.16.18.3; #执行代理主机
proxy_redirect off; #关闭重写location并刷新从upstream server收到的报文的首部
proxy_set_header X-Forwarded-For Proxy_add_x_forwarded_for;
}
nginx加载
[root@node1 ~]# service nginx reload
访问node1节点
为node2添加同样的段落。
[root@node2 ~]# vim /usr/local/nginx/conf/nginx.conf
location = / { proxy_pass http://172.16.18.3; proxy_redirect off; proxy_set_header X-Forwarded-For Proxy_add_x_forwarded_for; #将本地地址发给后端 }
5,配置keepalived,生成ipvs
node1作为Director转发所有real server的请求,且node1,node2具有高可用性保障Director正常工作。
配置keepalived的配置文件,生成ipvs规则
vrrp_instance VI_1 { #在这个段落中提供virtual_ipaddress ,生成VIP virtual_ipaddress { 172.16.18.22 } } virtual_server 172.16.18.22 80 { delay_loop 6 lb_algo rr lb_kind DR persistence_timeout 50 protocol TCP real_server 172.16.18.3 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 2 #超时时间 nb_get_retry 2 #重试2次 delay_before_retry 2 #延迟1秒 } } }
下边启动keepalived。发现抓发规则已经生成。
[root@node1 ~]# service keepalived start
Starting keepalived: [ OK ]
[root@node1 ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.18.22:80 rr persistent 50
-> 172.16.18.3:80 Route 1 0 0
node2 上keepalived同样配置,但要注意,如果你复制配置文件过去的话要记得修改优先级和notify为备节点。
配置node3做real server。先修改内核参数
[root@node3 html]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@node3 html]# echo 1 > /proc/sys/net/ipv4/conf/ens33/arp_ignore
[root@node3 html]# echo 2 > /proc/sys/net/ipv4/conf/ens33/arp_ignore
[root@node3 html]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_ignore
配置lo:0接口和路由。
[root@node3 html]# ifconfig lo:0 172.16.18.22 netmask 255.255.255.255 broadcast 172.16.18.22 up
[root@node3 html]# route add -host 172.16.18.22 dev lo:0
好的,real server配置OK 。
下边我们物理机访问VIP看看效果
可以看到我们访问Director上的VIP转发访问到了real server上去了。此时keepalived的IPVS功能转发成功
6,那么下来我们来配置双主模式的IPVS,所以我们需要两个VIP
VIP1还是用:172.16.18.22,VIP2还是用:172.16.18.23
双主模型
配置node1的配置文件 /etc/keepalived/keepalived.conf
vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 18 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.16.18.22 } track_script{ chk_nginx } notify_master "/etc/init.d/nginx start" notify_backup "/etc/init.d/nginx stop" notify_fault "/etc/init.d/nginx stop" } vrrp_instance VI_2 { state BACKUP interface eth0 virtual_router_id 19 priority 99 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.16.18.23 } track_script{ chk_nginx } notify_master "/etc/init.d/nginx start" notify_backup "/etc/init.d/nginx stop" notify_fault "/etc/init.d/nginx stop" } virtual_server 172.16.18.22 80 { delay_loop 6 lb_algo rr lb_kind DR netmask 255.255.0.0 protocol TCP real_server 172.16.18.3 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 1 delay_before_retry 1 } } } virtual_server 172.16.18.23 80 { delay_loop 6 lb_algo rr lb_kind DR netmask 255.255.0.0 protocol TCP real_server 172.16.18.3 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 1 delay_before_retry 1 } } }
复制配置文件到node2,修改主节点为 VI_2,备节点是 VI_1。还有优先级。
node1,node2 都重启keepalived
ipvsadm -L -n 查看一下生成的ipvs规则。
[root@node1 ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.18.23:80 rr
-> 172.16.18.3:80 Route 1 0 0
TCP 172.16.18.22:80 rr
-> 172.16.18.3:80 Route 1 0 0
OK ,IPVS规则也没有问题,查看node2上的,方法一样。
7,测试keepalived与nginx配合运行以及双主模型的ipvs.
因为本实验只提供了一个realserver,所以就不做轮询的测试。
测试ipvs规则是否转义,转移后访问vip1,vip2是否正常
测试nginx程序挂点会不会转移,
到此双主模型的LVS,高可用构建完毕,没有单点故障,任何一点故障不影响业务。
实验到此结束。