keepalived实现双vip部署
首先至少需要准备:
两台主机
四个IP:
192.168.100.226
192.168.100.224
192.168.100.201(VIP)
192.168.100.202(VIP)
keepalived的安装方式有两种:
一种是通过yum源进行安装,另一种是通过源码安装。
使用yum装比较简单省事,还能自动解决依赖问题。华为、阿里的网络yum源镜像都有keepalived的yum安装包;
~]# yum -y install keepalived
源码安装
一、官网下载源码
首先我们需要下载keepalived的一个源码包
二、安装
两台做一样的操作
安装依赖
如果不安装依赖在编译时回报,无法完成编译
~]# yum install -y libnfnetlink-devel zlib zlib-devel gcc gcc-c++ openssl openssl-devel openssh
解压、编译安装源码包,将keeplived纳管到systemctl中
~]# tar -xf keepalived-2.1.0 # 解压安装包
~]# cd keepalived-2.1.0 # 进入安装包
keepalived-2.1.0]# ./config --prefix=/usr/local/keepalived # 编译指定安装路径
keepalived-2.1.0]# make && make install # 编译完成后进行安装
~]# ln -s /usr/local/keepalived/sbin/keepalived /usr/sbin/ # 创建软连接
~]# ls /usr/sbin/ | grep keepalived
keepalived
~]# cd /usr/local/keepalived/etc/
etc]# cp -r keepalived /etc/keepalived
etc]# cp sysconfig/keepalived /etc/sysconfig/keepalived
三、修改配置
在安装中指定了安装路径,所有配置问件在/usr/local/keepalived目录下
修改配置
~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
script_user root
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_http_port {
script "/data/shell/check.sh httpd"
interval 0
weight -2
vrrp_instance VI_1 {
state BACKUP # BACKUP为备
interface eth0
virtual_router_id 101
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.100.201 dev eth0 label eth0:1
}
vrrp_instance VI_2 { # 当有两个VIP时vrrp_instance应当区分开
state MASTER # MASTER为主
interface eth0 # 工作接口
virtual_router_id 102 # 虚拟路由ID,如果是一组虚拟路由就定义一个ID,如果是多组就要定义多个;
# 而且这个虚拟ID还是虚拟MAC最后一段地址的信息,取值范围0-255
priority 100 # 定义优先级,数值越高,优先级越高
advert_int 1 # 通告频率,秒
track_interface { # 监听的网卡,网卡故障马上切换vip
eth0
ens33
}
authentication { # 通信机制,这里是明文,还有加密
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 配置虚拟VIP,这里配置在网卡eth0,别名是eth0:2
192.168.100.202 dev eth0 label eth0:2
}
}
这是主机1的配置文件,主机2的配置文件,只需要在主机1的配置文件是那个修改参数
state BACKUP # 主机1为MASTER时,主机2为BACKUP
priority 80 # 这里配置坚持master的优先级大于backup即可,根据state属性定义
启动keepalived
~]# systemctl restart keepalived
两一台是没有vip
停掉主机
查看备机
报错处理
注意:
安装keepalived源码包过程中可能会遇到的报错,在make时提示:
make: *** No targets specified and no makefile found. Stop
这可能是因为是一开始的依赖没有装,导致编译失败,安装依赖后再用:
./config --prefix=/usr/local/keepalived 进行编译
启动失败处理
启动失败可查看keepalived日志
log]# tail -f /var/log/messages
报错1
keepalived.service: Can't open PID file /var/lib/keepalived.pid (yet?) after start: No such file or directory
这是pid文件无法写入,这是之前修改过默认的pid文件路径,修改回默认的路径即可
usr]# vim /lib/systemd/system/keepalived.service # 修改配置文件
PIDFile=run/keepalived.pid
usr]# systemctl daemon-reload # 重新加载
usr]# systemctl restart keepalived # 重新启动keepalived
报错2
Mar 16 22:42:20 tang Keepalived_vrrp[3511655]: (Line 1) Unknown keyword '~]'
Mar 16 22:42:20 tang Keepalived_vrrp[3511655]: (Line 28) (VI_2) tracked interface ens33 doesn't exist
为配置文件配置错误,日志中有错误的行数,检查配置文件配置既可
/etc/keepalived/keepalived.conf
报错3
Mar 16 23:04:32 tang Keepalived_vrrp[3584514]: WARNING - default user 'keepalived_script' for script execution does not exist - please create.
这是keepalived的默认用不不存在,创建用户keepalived_script即可
useradd keepalived_script
配置监控脚本
shell]# vim check.sh
#!/bin/bash
Date=$(date "+%Y-%m-%d %H:%M:%S")
log_file="/var/log/keepalived.log"
check_process() {
if [ -z "$1" ]; then
echo "进程名为空........"
echo "[$Date] 执行脚本无参数......" >> $log_file
exit
fi
process_status=`pidof $1`
if [ "$process_status" != "" ]; then
return 10
else:
return 11
fi
}
check_process $1
if [ $? -eq 10 ]; then
echo 0
exit 0
else
echo "[$Date] 进程[$1]异常,正在准备重启....." >> $log_file
count=0
while (($count < 3))
do
((count++))
echo "[$Date] 尝试第$count次拉起进程$1......" >> $log_file
systemctl restart $1 2&> /dev/null
check_process $1
if [ $? -eq 10 ]; then
echo "[$Date] 进程$1已拉起......." >> $log_file
echo 0
exit 0
fi
done
echo 1
echo "[$Date] 尝试拉起进程$1三次均失败......" >> $log_file
systemctl stop keepalived
exit 1
fi
调试脚本,脚本需要传参,传参为进程名
/bin/bash check_process.sh nginx
报错4
keepalived配置的监控脚本执行错误
出现下面的这种错误可能是用户执行的权限不够,讲执行的权限修改为root即可
在配置文件keepalived.conf中添加一行,在global_defs下面添加script_user root,然后重启keepalived即可
如:
global_defs {
script_user root
基于以上的keepalived安装步骤的python的一键部署py脚本,从下载源码包到修改配置启动服务
如有疑问欢迎留言!!!!
使用注意:
1、需要将上面的检查脚本保存为/data/shell/check.sh
监控的进程需要为system管理的进程,否则在检测到进程故障时无法重新拉起,将会直接ip漂移
2、使用时可以将一下代码保存为install_keepalived.py
3、配置文件中的基本参数可在脚本开头配置,如(安装路径、源码包存储路径、安装的软件包版本、VIP、是否为主等)
4、使用 python install_keepalived.py 命令执行
模块在centos系统自带python中有无需安装模块
# encoding: utf-8
import sys
import os
version = '2.2.2' # keepalived版本号
tar_name = "keepalived-{}.tar.gz".format(version) # 源码包名
download_file = "https://www.keepalived.org/software/{}".format(tar_name) # keepalived的官网下载地址
instanll_path = "/usr/local/keepalived" # 安装路径
file_path = '/tmp/keepalived' # 源码包存储位置
MASTER = 0 # 0表示为主,非0表示为从
network = 'ens33' # 监听的网卡名
network_bn = "ens33:02" # 网卡别名
virtual_router_id = 52 # 路由id,两个keepalived的需要一致
priority = 99 # 权重,master的要大于从的
advert_int = 1
Vip = "192.168.43.111" # 虚拟ip
chk_http_port = 'chk_http_port'
httpd = "httpd" # 监控的进程名(需要依赖上面的监控脚本,将上面的监控脚本复制一份保存为/data/shell/check.sh)
def mkdir_path(files_path):
if not os.path.exists(files_path):
os.makedirs(files_path)
def wget_tar():
s = os.system("which wget")
if s != 0:
print("主机无wget命令,正在尝试安装.....")
install_wget = "yum -y install wget"
w = os.system("install_wget")
if w == 0:
print("安装wget成功!!")
return "ok"
else:
print("wget命令安装失败,请检查网络或yum源!!!")
exit(0)
else:
return "ok"
def sed_file(file):
s = '\ script_user root'
s1 = '\ vrrp_script chk_http_port {'
s2 = '\ script "/data/shell/check.sh {} "'.format(httpd)
s3 = '\ interval 0'
s4 = '\ weight -2'
s5 = '}'
s6 = '\ vrrp_instance VI_2 {'
if MASTER == 0:
s7 = '\ state MASTER'
else:
s7 = '\ state BACKUP'
s8 = '\ interface {}'.format(network)
s9 = '\ virtual_router_id {}'.format(virtual_router_id)
s10 = '\ priority {}'.format(priority)
s11 = '\ advert_int {}'.format(advert_int)
s12 = '\ track_interface {'
s13 = '\ {}'.format(network)
s14 = '\ }'
s15 = '\ authentication {'
s16 = '\ auth_type PASS'
s17 = '\ auth_pass 1111'
s18 = '\ }'
s19 = '\ virtual_ipaddress {'
s20 = '\ {} dev {} label {}'.format(Vip, network, network_bn)
s21 = '\ }'
s22 = '\ track_script {'
s23 = '\ chk_http_port'
s24 = '\ }'
s25 = '}'
cmd_list = [s, s1, s2, s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s20,s21,s22,s23,s24,s25]
os.system("sed -i '18,$d' {}".format(file))
for cmd in cmd_list:
os.system("echo {} >> {}".format(cmd, file))
def download_tar():
install_yl = os.system('yum install -y libnfnetlink-devel zlib zlib-devel gcc gcc-c++ openssl openssl-devel openssh')
if install_yl == 0:
print("依赖安装完成!!!")
else:
print("依赖安装失败!!!")
exit(0)
d_status = os.system('cd {} && wget {}'.format(file_path, download_file))
#d_status = 0
if d_status ==0:
if os.path.exists(file_path + '/' + tar_name):
mkdir_path(instanll_path)
tar_cmd = 'cd {} &&tar -xf {} && cd {}/keepalived-{} && ./configure --prefix={} && make && make install'.format(file_path, tar_name,file_path, version, instanll_path)
tar_s = os.system(tar_cmd)
if tar_s ==0:
print("安装编译成功!!!")
ln_cmd = "ln -s {}/sbin/keepalived /usr/sbin/"
ln_s = os.system(ln_cmd)
if ln_s == 0:
print("软连接创建成功!!")
cp_cmd = "cp -r {}/etc/keepalived /etc/ && cp -r {}/etc/sysconfig/keepalived /etc/sysconfig/".format(instanll_path, instanll_path)
cp_s = os.system(cp_cmd)
if cp_s == 0:
add_cmd = "useradd keepalived_script"
os.system(add_cmd)
print("配置文件copy完毕!!")
sed_file('/etc/keepalived/keepalived.conf')
# os.system("sed -i '/PIDFile/d' /lib/systemd/system/keepalived.service")
# os.system("sed -i '7iPIDFile=run/keepalived.pid' /lib/systemd/system/keepalived.service")
os.system("systemctl daemon-reload")
start_cmd = "systemctl restart keepalived"
start_s = os.system(start_cmd)
if start_s == 0:
print("keepalived安装完毕,已启动!!!")
else:
print("keepalived启动失败!!!")
else:
print("配置文件copy失败!!")
else:
print("软连接创建失败!!")
else:
print("安装编译失败!!!")
exit(0)
def main():
mkdir_path(file_path)
status = wget_tar()
if status == "ok":
download_tar()
else:
print("退出安装!!")
if __name__ == '__main__':
main()