利用Keepalive+Nginx搭建与阿里云SLB一样高效的高可用WEB应用架构
文章目录
1 高可用介绍
1.1 高可用场景需求
keepalived在很多高可用的集群都会用到,一般前端放置的会是nginx、ipvs、haproxy
比如我们在使用rabbitmq的时候做了这么一个集群,一般做了集群的话,那肯定就需要这么一个高可用的负载均衡器来实现流量的分发,如果使用的是haproxy,比如一台rebbitmq的节点突然宕机或者网卡失效,那么虽然RabbitMQ集群没有任何故障,但是对于外界的客户端来说所有的连接都会被断开,结果将是灾难性的。确保负载均衡服务的可靠性同样显得十分的重要。这里就引入Keepalived工具,它能够通过自身健康检查、资源接管功能做高可用(双机热备),实现故障转移。
1.2 Keepalived介绍
Keepalived 是一种高性能的服务器高可用或热备解决方案,Keepalived可以用来防止服务器单点故障的发生,通过配合Nginx可以实现web前端服务的高可用。
Keepalived以VRRP协议为实现基础,用VRRP协议来实现高可用性(HA)。VRRP(Virtual Router Redundancy Protocol)协议是用于实现路由器冗余的协议,VRRP协议将两台或多台路由器设备虚拟成一个设备,对外提供虚拟路由器IP(一个或多个),而在路由器组内部,如果实际拥有这个对外IP的路由器如果工作正常的话就是MASTER,或者是通过算法选举产生,MASTER实现针对虚拟路由器IP的各种网络功能,如ARP请求,ICMP,以及数据的转发等;其他设备不拥有该虚拟IP,状态是BACKUP,除了接收MASTER的VRRP状态通告信息外,不执行对外的网络功能。当主机失效时,BACKUP将接管原先MASTER的网络功能。
VRRP协议使用多播数据来传输VRRP数据,VRRP数据使用特殊的虚拟源MAC地址发送数据而不是自身网卡的MAC地址,VRRP运行时只有MASTER路由器定时发送VRRP通告信息,表示MASTER工作正常以及虚拟路由器IP(组),BACKUP只接收VRRP数据,不发送数据,如果一定时间内没有接收到MASTER的通告信息,各BACKUP将宣告自己成为MASTER,发送通告信息,重新进行MASTER选举状态。
Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7
交换机制软件,具备我们平时说的第3层、第4层和第7层交换机的功能。主要提供loadbalancing(负载均衡)和high-availability(高可用)功能,负载均衡实现需要依赖Linux的虚拟服务内核模块(ipvs),而高可用是通过VRRP协议实现多台机器之间的故障转移服务。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
上图是Keepalived的功能体系结构,大致分两层:用户空间(user space)和内核空间(kernel space)。
内核空间:主要包括IPVS(IP虚拟服务器,用于实现网络服务的负载均衡)和NETLINK(提供高级路由及其他相关的网络功能)两个部份。
用户空间:
- WatchDog:负载监控checkers和VRRP进程的状况
- VRRP Stack:负载负载均衡器之间的失败切换FailOver,如果只用一个负载均稀器,则VRRP不是必须的。
- Checkers:负责真实服务器的健康检查healthchecking,是keepalived最主要的功能。换言之,可以没有VRRP Stack,但健康检查healthchecking是一定要有的。
- IPVS wrapper:用户发送设定的规则到内核ipvs代码
- Netlink Reflector:用来设定vrrp的vip地址等。
2 高可用集群规划
2.1 集群环境介绍
- 操作系统环境:centos7.8mini2003
- Nginx 版本: nginx-1.18.0.tar.gz
- 高可用版本:keepalived-1.4.5.tar.gz
- root 系统管理员用户登录安装部署
2.2 集群规划与配置
节点名称 | 节点 IP Addr | 主机名 | Nginx端口 | 默认主从 | 配置 |
---|---|---|---|---|---|
VIP | 192.168.66.150 | ||||
MASTER | 192.168.66.8 | fdfs-proxy1 | 80 | MASTER | 2核2G20GB |
BACKUP | 192.168.66.9 | fdfs-proxy2 | 80 | BACKUP | 2核2G20GB |
FAULT | 192.168.66.10 | fdfs-proxy3 | 80 | FAULT | 2核2G20GB |
3 Nginx 安装与配置
3.1 安装 nginx
3.1.1 安装编译Nginx依赖包
# yum install gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel
3.1.2 下载 nginx
下载地址:https://nginx.org/en/download.html
# cd /opt
# wget https://nginx.org/download/nginx-1.18.0.tar.gz
3.1.3 编译安装
# tar -zxvf nginx-1.18.0.tar.gz
# mv /opt/nginx-1.18.0 /usr/local/src/
# cd /usr/local/src/nginx-1.18.0
# ./configure --prefix=/usr/local/nginx
# make && make install
3.2 彻底卸载Nginx
# service nginx stop
# chkconfig nginx off
# rm -rf /usr/sbin/nginx
# rm -rf /etc/nginx
# rm -rf /etc/init.d/nginx
# rm -rf /usr/local/nginx
# rm -rf /usr/local/src/nginx-1.18.0
# yum remove nginx
3.3 配置Nginx
修改第3行,去掉注释:user root
修改38行,端口改为:80
# vim /usr/local/nginx/conf/nginx.conf
user root;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include 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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
修改Nginx欢迎首页内容(用于后面测试,用于区分两个节点的Nginx):
# vim /usr/local/nginx/html/index.html
192.168.66.8中的标题加 8
<h1>Welcome to nginx! 8</h1>
192.168.66.9中的标题加 9
<h1>Welcome to nginx! 9</h1>
3.4 配置防火墙端口
# firewall-cmd --zone=public --add-port=80/tcp --permanent
# firewall-cmd --reload ## 重启防火墙
其他参考
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=9000 --permanent
systemctl reload firewalld
3.5 测试Nginx安装
测试Nginx是否安装成功
# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
3.6 设置开机启动
1、在系统服务目录里创建nginx.service文件
vi /usr/lib/systemd/system/nginx.service
2、写入内容如下:
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Description:描述服务
After:描述服务类别
[Service]服务运行参数的设置
Type=forking是后台运行的形式
ExecStart为服务的具体运行命令
ExecReload为重启命令
ExecStop为停止命令
PrivateTmp=True表示给服务分配独立的临时空间
注意:[Service]的启动、重启、停止命令全部要求使用绝对路径
[Install]运行级别下服务安装的相关设置,可设置为多用户,即系统运行级别为3
设置开机自启动
# systemctl enable nginx.service
查看nginx状态
# systemctl status nginx.service
很奇怪,明明启动成功了,为什么显示Active: inactive (dead)?
杀死nginx重启nginx
# pkill -9 nginx
# ps aux | grep nginx
# systemctl restart nginx #重启
# systemctl start nginx 启动
# systemctl stop nginx 停止
再次查看状态,变成了active,搞定。
另一种设置启动方式,,修改系统文件:
# vi /etc/rc.local
/usr/local/nginx/sbin/nginx
3.7 验证两个Nginx
访问两个Nginx
4 Keepalived 安装
4.1 下载 Keepalived
下载地址:http://www.keepalived.org/download.html
# cd /opt
# wget https://www.keepalived.org/software/keepalived-1.4.5.tar.gz
# tar -zxvf keepalived-1.4.5.tar.gz
# mv /opt/keepalived-1.4.5 /usr/local/src/
4.2 编译安装
# cd /usr/local/src/keepalived-1.4.5
# ./configure --prefix=/usr/local/keepalived
# make && make install
4.3 编译问题解决
如果编译没有问题即可跳过此章节,出问题主要是在2.X版本
4.3.2 安装警告信息1
checking for a BSD-compatible install… /usr/bin/install -c
checking whether build environment is sane… configure: error: newly created file is older than distributed files!
Check your system clock
”此报错是由于系统时间与硬件时间不一致导致的。
linux系统的时间分为系统时间 和 硬件时间。
硬件时间 就是指RTC中的时间,hwclock命令就是对这个时间操作。
系统时间 是系统开机时读取硬件时间作为系统的时间,此后系统时钟独立运作,在系统关机时再将系统时间写回RTC。
date命令只操作系统时间,hwclock操作硬件时钟,在date 修改时间后,最好用hwclock 同步一下,以免系统非正常关机造成时间不同步。
# date
2020年 11月 13日 星期五 20:17:11 CST
# hwclock
2020年11月13日 星期五 20时18分15秒 -0.350529 秒
同步时间,写入CMOS:
# ntpdate ntp1.aliyun.com
13 Nov 20:19:08 ntpdate[17801]: adjust time server 120.25.115.20 offset -0.000921 sec
# date
2020年 11月 13日 星期五 20:19:33 CST
# hwclock
2020年11月13日 星期五 20时19分40秒 -0.943450 秒
4.3.2 安装警告信息2
!!! OpenSSL is not properly installed on your system. !!!
!!! Can not include OpenSSL headers files. !!!
解决方法:
# yum install -y openssl openssl-devel
4.3.3 安装警告信息3
WARNING - this build will not support IPVS with IPv6. Please install` `libnl
/libnl-3dev libraries to support IPv6 with IPVS.
解决方法:执行yum命令yum -y install libnl libnl-devel解决上述警告问题
# yum -y install libnl libnl-devel
4.3.4 系统出现错误信息
“configure: error: libnfnetlink headers missing”,具体日志如下:
checking for nl_socket_modify_cb in -lnl... yes
checking for linux/rtnetlink.h... yes
checking libnfnetlink/libnfnetlink.h usability... no
checking libnfnetlink/libnfnetlink.h presence... no
checking for libnfnetlink/libnfnetlink.h... no
configure: error: libnfnetlink headers missing
解决方法:
# yum install -y libnfnetlink-devel
4.3.5 安装警告信息4
utils.c:1140:1: 警告:function might be candidate for attribute ‘pure’ [-Wsuggest-attribute=pure]
memcmp_constant_time(const void *s1, const void *s2, size_t n)
安装完成以后,重新执行configure命令
# ./configure --prefix=/usr/local/keepalived
# make && make install
4.4 安装网络工具
为验证高可用,查看VIP漂移需要安装一些网络工具
因一直习惯使用 ifconfig 命令查看 CentOS 中的网络连接,包括 IP 地址、MAC 地址、网络连接状态等。升级到 CentOS 7 之后 ifconfig 就找不到了,因为这个指令已经被废弃,改用 ip 指令。包括RHEL 7、Oracle Linux 7、Scientific Linux 7 的 minimal 版本中。
在 CentOS 7 minimal 系统中,可以用 “ip addr”、“ip link”查看网络连接及其状态,使用“ip –s link”还可以查看统计信息。
4.4.1 查看网卡信息(ifconfig)
如果还是想使用 ifconfig 的话就需要自己安装了。
首先要知道 ifconfig 指令是哪个软件包提供的
# yum provides ifconfig
### 或者
# yum whatprovides ifconfig
可以查询到对应的软件包为 net-tools,
# yum -y install net-tools
安装好了就可以用 ifconfig –a 查看网络状态了。
CentOS7里面的网卡名称默认不再是eth0,而是ens33或ens160
4.4.2 服务管理
systemd对Linux来说,就是init程序,可以作为sysvinit和upstat的替代,centos服务管理主要命令是systemctl,centos7的服务不再放在/etc/init.d/下;而放在/usr/lib/systemd/system下,centos7系统中systemctl管理工具整合了chkconfig和service于一体。
4.4.3 重启网卡
# service network restart
### 或者
# systemctl restart network
4.4.4 查看网络
# ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.66.8 netmask 255.255.255.0 broadcast 192.168.66.255
inet6 fe80::6de1:c1f2:c387:c2de prefixlen 64 scopeid 0x20<link>
inet6 fe80::6b25:20ec:48aa:cfd4 prefixlen 64 scopeid 0x20<link>
inet6 fe80::f284:bd63:2a7d:d8dd prefixlen 64 scopeid 0x20<link>
ether 00:50:56:b0:4b:5b txqueuelen 1000 (Ethernet)
RX packets 309759 bytes 40511299 (38.6 MiB)
RX errors 0 dropped 49 overruns 0 frame 0
TX packets 15785 bytes 1179022 (1.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 64 bytes 5536 (5.4 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 64 bytes 5536 (5.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
4.5 安装killall命令
为验证高可用,因centos安装的是minimal 版本,默认没有该命令,需要安装一下
# yum install -y psmisc
编写脚本使用killall命令杀死进程
4.6 安装抓包工具
为验证高可用,因centos安装的是minimal 版本,默认没有该命令,需要安装一下
# yum install -y tcpdump
采用tcpdump抓包定位问题
5 keepalived 配置
设置keepalived安装成Linux系统服务
因为没有使用keepalived的默认路径安装(默认是/usr/local),安装完成之后,需要做一些工作。
5.1 复制配置文件
5.1.1 复制默认配置文件到默认路径
### 安装完成,复制配置文件模板到/etc/keepalived
mkdir /etc/keepalived
cp /usr/local/src/keepalived-1.4.5/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
cp /usr/local/src/keepalived-1.4.5/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
### 复制服务启动脚本
cp /usr/local/src/keepalived-1.4.5/keepalived/etc/init.d/keepalived /etc/init.d/
5.1.2 建立软连接
### 创建软连接:
ln -s /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived
### 如果存在修改软连接
ln -snf /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived
5.1.2.1 创建软链接
- ln -s 【目标目录】 【软链接地址】
【目标目录】指软连接指向的目标目录下,【软链接地址】指“快捷键”文件名称,该文件是被指令创建的。如下示例,public文件本来在data文件下是不存在的,执行指令后才存在的。 - 软链接创建需要同级目录下没有同名的文件。就像你在windows系统桌面创建快捷键时,不能有同名的文件。
当同级目录下,有同名的文件存在时,会报错误。
5.1.2.2 删除软链接
- rm -rf 【软链接地址】
- 上述指令中,软链接地址最后不能含有“/”,当含有“/”时,删除的是软链接目标目录下的资源,而不是软链接本身。
5.1.2.3 修改软链接
- ln -snf 【新目标目录】 【软链接地址】
- 这里修改是指修改软链接的目标目录 。
5.2 赋予配置文件执行权限
# chmod +x /etc/init.d/keepalived
5.3 修改启动服务文件
centos7的话还需要改/lib/systemd/system/keepalived.service
# vim /lib/systemd/system/keepalived.service
### 将下面两行
EnvironmentFile=-/usr/local/keepalived/etc/sysconfig/keepalived
ExecStart=/usr/local/keepalived/sbin/keepalived $KEEPALIVED_OPTIONS
### 修改为
EnvironmentFile=/etc/sysconfig/keepalived
ExecStart=/sbin/keepalived $KEEPALIVED_OPTIONS
然后重新加载service
# systemctl daemon-reload
5.4 配置keepalived日志
5.4.1 修改服务日志
keepalived服务日志默认是写入系统日志,改变keepalived服务的日志路径。
把KEEPALIVED_OPTIONS="-D" 修改为:KEEPALIVED_OPTIONS="-D -d -S 0"
常用的选项 keepalived -D -f /etc/keepalived/keepalived.conf
- -D 将日志输出到message日志,默认日志也在message
- -f 是指定配置文件
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 -d -S 0" ## -S 是syslog的facility,0表示放在local 0
在/etc/rsyslog.conf 末尾添加
# vim /etc/rsyslog.conf
local0.* /var/log/keepalived.log
配置完成,两台都需要修改。
5.4.2 重启系统日志服务
重启syslog
# systemctl restart rsyslog
重启keepalived后就可以看到日志在/var/log/keepalived.log下了。
两台都需要重启
5.4.3 启动keepalived服务
# systemctl enable keepalived.service
# systemctl start keepalived
# systemctl status keepalived
# systemctl restart keepalived
两台 keepalived 都启动
5.4.4 查看keepalived日志
# tail -f /var/log/keepalived.log
6 高可用配置
6.1 配置文件说明
默认配置文件中各配置的含义
# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs { //全局配置
notification_email { //定义报警邮件地址
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc //定义发送邮件的地址
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL //定义路由标识信息,相同局域网唯一
vrrp_skip_check_adv_addr //检查vrrp报文中的所有地址比较耗时,设置此标志的意思是如果接收的到报文和上一个报文来至同一个路由器,则不执行检查。默认是跳过检查
vrrp_strict // #严格遵守vrrp协议,下面这些功能将会禁止:1. 0 VIP 2. unicast(单播) peers 3. vrrp 版本2的ipv6功能
vrrp_garp_interval 0 //小数类型,单位秒,在一个网卡上每组gratuitous arp消息之间的延迟时间,默认为0,一个发送的消息=n组 arp报文
vrrp_gna_interval 0 //小数类型,单位秒, 在一个网卡上每组na消息之间的延迟时间,默认为0
}
vrrp_instance VI_1 { //定义实例
state MASTER //初始状态,MASTER|BACKUP ,一旦有其他机器加入,将会举行选举,具有最高优先级的机器将会成为MASTER,所以这个条目的并不重要
interface eth0 //指定该实例用户vrrp的网卡,用于发送vrrp
virtual_router_id 51 //指定VRRP实例ID,范围是0-255.同一个组要一致
priority 100 // 指定优先级,优先级高的将成为MASTER。
advert_int 1 // 指定发送VRRP通告的间隔。单位是秒。
authentication { //指定认证方式。PASS简单密码认证(推荐),AH:IPSEC认证(不推荐)。密码" 最多8位
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { //设备之间使用的虚拟ip地址
192.168.200.16
192.168.200.17
192.168.200.18
}
6.2 配置 master 节点
在主节点 192.168.66.8 上配置
# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id fdfs-proxy1
}
vrrp_script chk_nginx {
#检查nginx的脚本,需要我们自己定义,下面讲到
script "/etc/keepalived/nginx_check.sh"
#检查时间间隔,这个时间不要超过脚本的执行时间,否则会报“Track script chk_nginx is being timed out, expect idle - skipping run”
interval 2
#脚本执行失败则优先级减20
weight -20
#表示两次失败才算失败
fall 2
}
# weight:
#1. 如果脚本执行成功(退出状态码为0),weight大于0,则priority增加。
#2. 如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少。
#3. 其他情况下,priority不变。
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 8
mcast_src_ip 192.168.66.8
priority 100
#设置为不抢占。默认是抢占的,当高优先级的机器恢复后,会抢占低优先级的机器成为MASTER,而不抢占,则允许低优先级的机器继续成为MASTER,即使高优先级的机器已经上线。如果要使用这个功能,则初始化状态必须为BACKUP。
# nopreempt
#指定发送VRRP通告的间隔。单位是秒。
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
#对应上面的检查脚本,使之生效
track_script {
chk_nginx
}
#vip的地址
virtual_ipaddress {
192.168.66.150
}
}
注意:
(1)例如:chk_nginx{ ,这里的 “{” 要与前面的名称要有空格
(2)vip(virtual_ipaddress) 的地址网关要与实际服务器的网关一致,例如服务器IP地址为 192.168.66.8 ,写的vip的地址也应该是 192.168.66.xxx
6.3 配置 backup 节点
从节点 192.168.66.9 上配置
! Configuration File for keepalived
global_defs {
router_id fdfs-proxy2
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2
}
vrrp_instance VI_1 {
#修改初始状态为备机
state BACKUP
interface ens160
virtual_router_id 8
mcast_src_ip 192.168.66.9
#修改优先级为小于正常状态下master的优先级,大于降低了权重之后的优先级
priority 90
# nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.66.150
}
}
6.4 Nginx状态检测脚本
两台主机都设置nginx检查脚本
说明:
keepalived主备切换方式:①根据vrrp的优先级,优先级高的为主,优先级低的为备 ②vrrp探测主节点的keepalived挂掉时备节点主动升级为master角色
两种方式的检查脚本不同
①根据vrrp的优先级,定义脚本检查nginx状态,如果状态异常则放回脚本执行失败 返回码为1。这个时候服务优先级根据配置调整
6.4.1 编写检测脚本
创建并编写Nginx状态检测脚本 /etc/keepalived/nginx_check.sh (已在keepalived.conf中配置)
脚本要求:如果nginx停止运行,尝试启动,如果无法启动则杀死本机的keepalived进程,keepalied将虚拟ip绑定到BACKUP机器上。
MASTER注册脚本内容如下:
# vi /etc/keepalived/nginx_check.sh
#!/bin/sh
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ]
then
### 这种方式启动nginx,使用 systemctl status nginx 查看状态非 active
#/usr/local/nginx/sbin/nginx
systemctl start nginx
sleep 1
A2=`ps -C nginx --no-header |wc -l`
if [ $A2 -eq 0 ]
then
exit 1
fi
fi
通过scp命令拷贝脚本到192.168.66.9机器
# scp /etc/keepalived/nginx_check.sh root@192.168.66.9:/etc/keepalived/
②vrrp探测主节点的keepalived挂掉时备节点主动升级为master角色,脚本中当检查到nginx状态异常后将执行杀死keepalived服务
修改BACKUP从脚本如下
# vi /etc/keepalived/nginx_check.sh
#!/bin/sh
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ]
then
### 这种方式启动nginx,使用 systemctl status nginx 查看状态非 active
#/usr/local/nginx/sbin/nginx
systemctl start nginx
sleep 1
A2=`ps -C nginx --no-header |wc -l`
if [ $A2 -eq 0 ]
then
systemctl stop keepalived
fi
fi
保存后,给脚本赋执行权限:
# chmod +x /etc/keepalived/nginx_check.sh
6.4.2 监测脚本解析
nginx 服务启动后,我们需要对其服务状态进行监控,今天学习过程中了解到一段非常有用的小脚本,不仅可以监控Nginx,也可以用来监控其他服务
ps -C nginx –no-header
这里涉及ps 的用法,我们一般用ps查看相关进程,一般都是用
ps -ef | grep XX 或 ps -aux| grep XX 的模式
如下:
# ps -ef | grep nginx
root 2248 1 0 19:13 ? 00:00:00 nginx: master process ./nginx
nobody 3265 2248 0 20:16 ? 00:00:00 nginx: worker process
root 4791 4742 0 22:05 pts/1 00:00:00 grep --color=auto nginx
但是这样通常都会覆盖一个grep的进程
我们可以用ps -C 或ps -c 的方式, -C 后面接命令的名字 ,如下:
# ps -C nginx
PID TTY TIME CMD
4983 ? 00:00:00 nginx
4984 ? 00:00:00 nginx
–no-header 就是去挑title,如下:
# ps -C nginx --no-header
4983 ? 00:00:00 nginx
4984 ? 00:00:00 nginx
wc -l 这个很熟悉了,行数计算
所以用这种方式可判断,如果
ps -C nginx --no-header|wc -l
如果值为0,即代表服务未启动
如果值为非0,即代表服务已启动
还有一个知识点,killall keepalived 这个是以服务名称杀死进程,日常中也用的挺多的
6.4.3 举一反三
上面那段完整的脚本意思即为:
判断nginx 服务是否启动
如果未启动,执行启动命令
再次判断,如果启动失败,关掉keepalived,进入从节点
关于Nginx的主从我们后面会实操后记录
最重要的一点是,这段脚本不仅可以用来监控Nginx,其他服务也是可以的,模式是一样的,大家可以自行试试
7.3 防止脑裂
7.3.1 关闭SELinux
1、查看 SELinux
MASTER主
# getenforce
Permissive ### 允许的
# /usr/sbin/sestatus -v
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
BACKUP从
# getenforce
Enforcing ### 强制执行
# /usr/sbin/sestatus -v
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
2、临时关闭
##设置SELinux 成为permissive模式
##setenforce 1 设置SELinux 成为enforcing模式
# setenforce 0
setenforce 0 #设置为宽容模式
但这样只在本次生效,重启服务器后将失效。
3、永久关闭
如果要永久关闭,还需要修改配置文件:
# vim /etc/selinux/config
### 将
SELINUX=enforcing
### 改为
SELINUX=disabled
设置后需要重启才能生效
7.3.2 iptables防火墙配置
centos 防火墙有两种管理方式firewall, iptables两者不能同时开启
防火墙开启的情况下,我们需要加入一条配置:
iptables
编辑vim /etc/sysconfig/iptables
-A INPUT -p vrrp -j ACCEPT
注意:
添加规则一定不要在
-A INPUT -j REJECT --reject-with icmp-host-prohibited
之后,一定要加在其前面。
配置完之后reload
service iptables reload
7.3.3 Firewalld 防火墙配置
问题就是出现在了防火墙这里,防火墙阻止了vrrp组包发送
如果是Firewalld防火墙 则主、备都运行下面的命令
centos7 默认防火墙firewall
开启vrrp 协议
主备都运行下面的命令
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --protocol vrrp -j ACCEPT
firewall-cmd --reload
6.5 重新启动服务
高可用配置完成后,重新启动服务
# systemctl restart keepalived
# systemctl stop keepalived
# systemctl status keepalived
# journalctl -xe
# 查看进程情况
ps -aux |grep keepalived
7 高可用测试
7.1 Keepalived+Nginx高可用测试
(1)首先验证vip在主节点生效
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LlS5WtVV-1609917447905)(assets/image-20201202201622262.png)]
关闭192.168.66.8中的Nginx,Keepalived会将它重新启动。验证master上的nginx关闭,master自动执行检查脚本并启动nginx
# /usr/local/nginx/sbin/nginx -s stop
或
# systemctl stop nginx
查看nginx进程
ps -ef | grep nginx
查看keepalived进程
ps -ef | grep keepalived
验证故障切换,通过修改配置文件模拟nginx挂了起不来。
脚本①脚本执行返回错误,执行优先级-20,VIP转移到从节点。可以修改nginx脚本引发nginx错误,让nginx无法启动进行测试,看是否会切换过来。
# vim /usr/local/nginx/conf/nginx.conf
再杀死 nginx 服务
# killall nginx
(2)脚本②检查脚本将停掉keepalived,vip转移到从节点
关闭192.168.66.8中的Keepalived,VIP会切换到192.168.66.9中
# systemctl stop keepalived
# ip a
Keepalived停止后,该节点的网络接口中的VIP将消失
查看此时VIP对应的MAC,Windows下使用CMD命令查看:验证keepalived主从切换成功。
采用的检查脚本是当nginx状态异常后停主节点启用备节点。
说明此时VIP已经漂移到物理主机192.168.66.9上了
再通过VIP来访问Nginx集群,访问到的也是192.168.66.9
由此可见,当主机dowm掉的时候才会访问从机,当主机连进来的时候又回去访问主机
当主机正常运行通过ip addr命令的时候可以看到网络下多了个虚拟ip,而从机却没有,只要当主机挂了时候从机才会显示虚拟ip
7.2 抓包监测
- 主备都抢到了虚拟ip
采用tcpdump抓包定位问题,以下是在192.168.66.8 主节点的抓包结果
tcpdump -i ens160 vrrp -n
以下是在192.168.66.9 备节点的抓包结果
tcpdump -i ens160 vrrp -n
由上图可以看到,192.168.66.8和192.168.66.9两个IP在轮流发送组播信号。而正常的应该是由MASTER服务器发送组播,如果BACKUP收不到MASTER的组播信号了,那么判定MASTER宕机了,BACKUP就会接手VIP
8 卸载 keepalived
卸载keeplived工作路径
# cd /usr/local/src/keepalived #源码所在目录(根据实际情况进入对应目录)
# make uninstall
删除keepalived相关文件
# rm -f /usr/local/sbin/keepalived
# rm -f /usr/local/etc/rc.d/init.d/keepalived
# rm -f /usr/local/etc/sysconfig/keepalived
# rm -rf /usr/local/etc/keepalived
# rm -f /usr/local/bin/genhash
# rm -rf /usr/local/keepalived
# rm -rf /etc/keepalived
# rm -f /etc/rc.d/init.d/keepalived
# rm -f /usr/sbin/keepalived
# rm -f /etc/sysconfig/keepalived
# rm -f /etc/keepalived/
# rm -f /etc/init.d/keepalived
# rm -f /etc/sysconfig/keepalived
# 删除软链接只是少了一个“ / ” 删除的 就是链接文件, 也就是在文件的最后不要加上"/"
# rm -f /usr/sbin/keepalived
# rm -f /sbin/keepalived
# 删除系统启动服务文件
# rm -f /lib/systemd/system/keepalived.service
# 删除解压源码
# rm -rf /usr/local/src/keepalived
测试是否卸载成功
# serive keepalived satrt
或
# systemctl restart keepalived
ps aux|grep keepalived --查看进程
当命令无效时,证明卸载成功。
9 cmd中的arp指令
arp是地址解析协议
OSI模型把网络工作分为七层,IP地址在OSI模型的第三层,MAC地址在第二层,彼此不直接打交道。在通过以太网发送IP数据包时,需要先封装第三层(32位IP地址)、第二层(48位MAC地址)的报头,但由于发送时只知道目标IP地址,不知道其MAC地址,物理层是又不能跨第二、三层,所以需要使用地址解析协议。使用地址解析协议,可根据0网络层IP数据包包头中的IP地址信息解析出目标硬件地址(MAC地址)信息,以保证通信的顺利进行
(1)-a [InetAddr] [-N ifaceAddr]
查看所有ARP缓存表中的所有信息,显示的格式如下
接口: 接口地址— 一个十六进制数
Internet地址(IP) 物理地址(MAC) 类型
…
(2)-g [InetAddr] [-N IfaceAddr] 作用与-a相同
就是说,如果是arp -a将ARP缓存表内容全部输出来
Arp -a ip 将ARP缓存表中对应ip内容输出,输出的结果可能是无ARP信息,一个ARP信息,多个ARP内容,
Arp -a -n 接口地址 将ARP缓存表中该接口地址的信息全部输出,可能无ARP信息,可能是多个结果值
Arp -a 地址 -n 接口地址 将ARP缓存表指定接口地址下该ip地址内容输出,可能输出无ARP信息,或者输出一个ARP信息内容
(3)Arp -a -v 输出所有ARP信息,包括无用的信息
(4)-d InetAddr [IfaceAddr] 从arp缓存表中将指定ip删除
要删除所有项,请使用星号 (*) 通配符代替 InetAddr。或者直接arp -d
(5)-s InetAddr EtherAddr [IfaceAddr]
向 ARP 缓存添加可将 IP 地址 InetAddr 解析成物理地址 EtherAddr 的静态项。要向指定接口的表添加静态 ARP 缓存项,请使用 IfaceAddr 参数,此处的 IfaceAddr 代 表指派给该接口的 IP 地址。说明,IfaceAddr在ARP表中必须存在,如果失败了,就会显示ARP: 错误IP地址:所IfaceAddr地址
4、tracert命令
tracert IP地址
从左到右的5条信息分别代表了“生成时间”、“三次发送ICMP包返回时间”(共计3个,单位为毫秒ms)和“途径路由器的IP地址”(如果有主机名,还会包含主机名)
tracert 地址,相同地址,每次经过的路由器是不同的
如果在“tracert”命令后添加一个不存在的IP地址或域名,tracert程序则会报错
在“tracert”命令与IP地址或URL地址中间输入“-d”,可以不将IP地址解析到主机名称。
在“tracert”命令与IP地址或URL地址中间输入“-h”,并在之后添加一个数字,可以指定本次tracert程序搜索的最大跳数。
在“tracert”命令与IP地址或URL地址中间输入“-w”,并在之后添加一个数字,可以指定tracert为每次回复所指定的毫秒数。
10 Linux 系统日志
/var/log目录下的20个Linux日志文件 :
其中一些日志文件只有特定版本采用,如dpkg.log只能在基于Debian的系统中看到。
/var/log/messages #包括整体系统信息,其中也包含系统启动期间的日志。此外,mail,cron,daemon,kern和auth等内容也记录在var/log/messages日志中。
/var/log/dmesg` ` #内核缓冲信息(kernel ring buffer)。在系统启动时,会在屏幕上显示许多与硬件有关的信息。可以用dmesg查看它们。
/var/log/auth.log #系统授权信息,包括用户登录和使用的权限机制等。
/var/log/boot.log #系统启动日志。
/var/log/daemon.log #包含各种系统后台守护进程日志信息。
/var/log/dpkg.log #包括安装或dpkg命令清除软件包的日志。
/var/log/kern.log #包含内核产生的日志,有助于在定制内核时解决问题。
/var/log/lastlog #记录所有用户的最近信息。这不是一个ASCII文件,因此需要用lastlog命令查看内容。
/var/log/maillog/var/log/mail.log #邮件信息。例如,sendmail日志信息就全部送到这个文件中。
/var/log/user.log #用户信息的日志。
/var/log/Xorg.x.log #来自X的日志信息。
/var/log/alternatives.log #更新替代信息都记录在这个文件中。
/var/log/btmp #记录所有失败登录信息。使用last命令可以查看btmp文件。例如,”last -f /var/log/btmp | more“。
/var/log/cups #涉及所有打印信息的日志。
/var/log/anaconda.log #在安装Linux时,所有安装信息都储存在这个文件中。
/var/log/yum.log #包含使用yum安装的软件包信息。
/var/log/cron #每当cron进程开始一个工作时,就会将相关信息记录在这个文件中。
/var/log/secure #包含验证和授权方面信息。例如,sshd会将所有信息记录(其中包括失败登录)在这里。
/var/log/wtmp 或 /var/log/utmp #包含登录信息。使用wtmp可以找出谁正在登陆进入系统,谁使用命令显示这个文件或信息等。
/var/log/faillog – 包含用户登录失败信息。此外,错误登录命令也会记录在本文件中。
除了上述Log文件以外, /var/log还基于系统的具体应用包含以下一些子目录:
/var/log/httpd/ 或 /var/log/apache2 #包含服务器access_log和error_log信息。
/var/log/lighttpd/ #包含light HTTPD的access_log和error_log。
/var/log/mail/ #这个子目录包含邮件服务器的额外日志。
/var/log/prelink/ #包含.so文件被prelink修改的信息。
/var/log/audit/ #包含被 Linux audit daemon储存的信息。
/var/log/samba/ #包含由samba存储的信息。
/var/log/sa/ #包含每日由sysstat软件包收集的sar文件。
/var/log/sssd/ #用于守护进程安全服务。
除了手动存档和清除这些日志文件以外,还可以使用logrotate在文件达到一定大小后自动删除。可以尝试用vi,tail,grep和less等命令查看这些日志文件。
11 参考资料
keepalived之vrrp_script总结:http://my.oschina.net/hncscwc/blog/158746
keepalived双机热备实现故障时发送邮件通知:http://www.2cto.com/os/201407/317795.html
基于keepalived 实现VIP转移,lvs,nginx的高可用:http://www.tuicool.com/articles/eu26Vz
ar/log/btmp #记录所有失败登录信息。使用last命令可以查看btmp文件。例如,”last -f /var/log/btmp | more“。
/var/log/cups #涉及所有打印信息的日志。
/var/log/anaconda.log #在安装Linux时,所有安装信息都储存在这个文件中。
/var/log/yum.log #包含使用yum安装的软件包信息。
/var/log/cron #每当cron进程开始一个工作时,就会将相关信息记录在这个文件中。
/var/log/secure #包含验证和授权方面信息。例如,sshd会将所有信息记录(其中包括失败登录)在这里。
/var/log/wtmp 或 /var/log/utmp #包含登录信息。使用wtmp可以找出谁正在登陆进入系统,谁使用命令显示这个文件或信息等。
/var/log/faillog – 包含用户登录失败信息。此外,错误登录命令也会记录在本文件中。
除了上述Log文件以外, /var/log还基于系统的具体应用包含以下一些子目录:
```shell
/var/log/httpd/ 或 /var/log/apache2 #包含服务器access_log和error_log信息。
/var/log/lighttpd/ #包含light HTTPD的access_log和error_log。
/var/log/mail/ #这个子目录包含邮件服务器的额外日志。
/var/log/prelink/ #包含.so文件被prelink修改的信息。
/var/log/audit/ #包含被 Linux audit daemon储存的信息。
/var/log/samba/ #包含由samba存储的信息。
/var/log/sa/ #包含每日由sysstat软件包收集的sar文件。
/var/log/sssd/ #用于守护进程安全服务。
除了手动存档和清除这些日志文件以外,还可以使用logrotate在文件达到一定大小后自动删除。可以尝试用vi,tail,grep和less等命令查看这些日志文件。
11 参考资料
keepalived之vrrp_script总结:http://my.oschina.net/hncscwc/blog/158746
keepalived双机热备实现故障时发送邮件通知:http://www.2cto.com/os/201407/317795.html
基于keepalived 实现VIP转移,lvs,nginx的高可用:http://www.tuicool.com/articles/eu26Vz
cmd arp 指令:https://baike.baidu.com/item/ARP/609343?fr=aladdin