首先需要明白我们准备使用keepalived来做什么,今天这里只是给大家简单安装和配置下keepalived实现vip对外服务,防止单点故障。keepalived是高可用高可用高可用 而非负载非负载非负载。
下面我将使用keepalived部署双主模模式,实现方式,利用脚本检测某个服务,当服务宕机的时候,停止keepalived,vip漂移到另一个主机上。
VIP1: 192.168.80.136 eth0:10.0.0.11 em1:10.0.0.67
VIP2: 192.168.80.139 eth1:10.0.0.12 em2:10.0.0.68 #vip/主机1网卡对应ip/主机2对应网卡ip
1.安装keepalived
yum install -y glibc openssl-devel wget http://www.keepalived.org/software/keepalived-1.2.24.tar.gz tar zxf keepalived-1.2.24.tar.gz cd keepalived-1.2.24 mkdir /usr/local/keepalived ./configure --prefix=/usr/local/keepalived && make && make install
2.将keepalived配置为系统服务
mkdir /etc/keepalived cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/rc.d/init.d/keepalived cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/keepalived chmod +x /etc/init.d/keepalived ln /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived chkconfig --add keepalived
3.配置keepalived服务
cd /etc/keepalived/
cat keepalived.conf (主机1配置)
! Configuration File for keepalived global_defs { router_id NODE_B } vrrp_script checkALL { script "/etc/keepalived/script/check_nginx.sh" #检测nginx服务脚本 interval 5 } vrrp_instance VIP136 { state MASTER #VIP1的master 主机2的时候改为BACKUP interface eth0 mcast_src_ip 10.0.0.11 virtual_router_id 136 #虚拟路由id 2个主机需要一样 priority 100 #优先级 数值越大优先级越大,第二个主机设置比她它小 advert_int 1 authentication { auth_type PASS auth_pass masterbrian #双方认证使用的密码 } virtual_ipaddress { 192.168.80.136 #vip1虚拟ip } track_script { checkALL #检测脚本 } notify_master "/etc/keepalived/script/notify.sh master 10.0.0.11 192.168.80.136" #变为主的时候触发的脚本 notify_backup "/etc/keepalived/script/notify.sh backup 10.0.0.11 192.168.80.136" notify_fault "/etc/keepalived/script/notify.sh fault 10.0.0.11 192.168.80.136" } vrrp_instance VIP139 { state BACKUP #VIP2的slave 主机改为MASTER nopreempt #备机不抢占模式,当备机的优先级高于主机的时候不抢占 interface eth1 mcast_src_ip 10.0.0.12 virtual_router_id 139 priority 90 advert_int 1 authentication { auth_type PASS auth_pass masterrobinson } virtual_ipaddress { 192.168.80.139 } track_script { checkALL } notify_master "/etc/keepalived/script/notify.sh master 10.0.0.12 192.168.80.139" notify_backup "/etc/keepalived/script/notify.sh backup 10.0.0.12 192.168.80.139" notify_fault "/etc/keepalived/script/notify.sh fault 10.0.0.12 192.168.80.139" }
cat keepalived.conf (主机2配置)
! Configuration File for keepalived global_defs { router_id LVS_DEVEL } vrrp_script checkALL { script "/etc/keepalived/script/check_nginx.sh" interval 5 } vrrp_instance VIP136 { state BACKUP interface em1 nopreempt mcast_src_ip 10.0.0.67 virtual_router_id 136 priority 90 advert_int 1 authentication { auth_type PASS auth_pass masterbrian } virtual_ipaddress { 192.168.80.136 } track_script { checkALL } notify_master "/etc/keepalived/script/notify.sh master 10.0.0.67 192.168.80.136" notify_backup "/etc/keepalived/script/notify.sh backup 10.0.0.67 192.168.80.136" notify_fault "/etc/keepalived/script/notify.sh fault 10.0.0.67 192.168.80.136" } vrrp_instance VIP139 { state MASTER interface em2 mcast_src_ip 10.0.0.68 virtual_router_id 139 priority 100 advert_int 1 authentication { auth_type PASS auth_pass masterrobinson } virtual_ipaddress { 192.168.80.139 } track_script { checkALL } notify_master "/etc/keepalived/script/notify.sh master 10.0.0.68 192.168.80.139" notify_backup "/etc/keepalived/script/notify.sh backup 10.0.0.68 192.168.80.139" notify_fault "/etc/keepalived/script/notify.sh fault 10.0.0.68 192.168.80.139" }
4.使用到的其他脚本文件
4.1监控nginx服务脚本,当nginx服务不存在的时候停止keepalived服务
这个脚本可以根需要使用高可用的服务来做相应的调整。
cat /etc/keepalived/script/check_nginx.sh
#!/bin/bash checknginx=$(ps -C nginx --no-header | wc -l) checkkeepalived=$(ps -C keepalived --no-header | wc -l) TIME=$(date +%Y-%m-%d\ %H:%M:%S) if [ ${checknginx} -eq 0 ];then service nginx restart sleep 3 fi checknginx_two=$(ps -C nginx --no-header | wc -l) if [ ${checknginx_two} -eq 0 ];then killall -TERM keepalived fi
4.2状态变化的时候的触发的脚本
cat /etc/keepalived/script/notify.sh
#!/bin/bash status=${1} hostip=${2} vip=${3} TIME=$(date +%Y-%m-%d\ %H:%M:%S) HOST_NAME=$(hostname) subject="${HOST_NAME} to be ${status}: ${vip} floating" send_user="xxxxx" send_contant="${TIME} ${HOST_NAME}[${hostip}] 主机keepalived的VIP:${vip} 状态改变为${status},请检查相关服务。" python /etc/keepalived/script/send_mail.py "${send_user}" "${subject}" "${send_contant}"
4.3 notify.sh中触发的发送邮件的python脚本
这个脚本最下面需要修改 用户名和密码,邮件服务器和收件人等相关信息
cat /etc/keepalived/script/send_mail.py
#!/usr/bin/env python # -*- coding:utf-8 -*- """ 纯文本文件发送 """ import sys import smtplib from email.header import Header from email.mime.text import MIMEText from abc import abstractmethod class Mail(object): """dohost, user_name, pwd, context, Subject, To, filename, file_path, port, nick_name, mail_adressring for Mail""" def __init__(self, host, user_name, pwd, context, Subject, To, port, nick_name, mail_adress): """ :param host: 邮件服务器地址 :param user_name: 邮件登陆名 :param pwd: 邮箱登陆密码 :param context: 邮箱正文 :param Subject: 邮箱主题 :param To: 收件人 :param From: 发件人 """ self.host=host self.user_name=user_name self.pwd=pwd self.context=context self.Subject=Subject self.To=To self.port=port self.nick_name=nick_name self.mail_adress=mail_adress @abstractmethod def send(self,**kwargs): """ send mail to account :param file: :return: """ pass class TextMail(Mail): """ 只有文本信息的邮件 """ def __init__(self,**kwargs): super(TextMail,self).__init__(**kwargs) self.mail_type='TEXT' @abstractmethod def send(self): #print("send_start") server=smtplib.SMTP(self.host,self.port) server.set_debuglevel(0) server.login(self.user_name,self.pwd) msg=MIMEText(self.context,'html','utf-8') msg['From']='{0}<{1}>'.format(self.nick_name,self.mail_adress,'utf-8') msg['Subject']=Header(self.Subject,'utf-8').encode() msg['To']=','.join(self.To) try: server.sendmail(self.mail_adress,self.To,msg.as_string()) print("mail has been successfully") except smtplib.SMTPException as e: print('邮件发送失败') print(e) def send_mail(fromstmp,fromuser,frompwd,content,subject,touser): host=fromstmp fromuser=fromuser pwd=frompwd scontent=content subject=subject touser=touser nick_name="运维监控" b=TextMail(host=host,user_name=fromuser,pwd=pwd,context=content,Subject=subject,To=touser,port=25,nick_name=nick_name,mail_adress=fromuser) b.send() if __name__ == '__main__': """ 设置发送邮箱信息 """ fromuser="XXX" #发送邮箱的 123456@qq.com frompwd="XXX" #邮箱密码 xxxx fromstmp="XXX" #邮件服务stmp smtp.qq.com touser = [str(sys.argv[1])] #传过来的第一个参数 subject = str(sys.argv[2]) #传过来的第二个参数 content = str(sys.argv[3]) #传过来的第三个参数 touser='xxx@126.com','xxxx@123.com' #收邮件的人 send_mail(fromstmp,fromuser,frompwd,content,subject,touser)