keepalived 使用纯 C 语言写成。软件围绕中心的 I/O 多路复用器设计提供实时的网络。它的设计重点是在各个元素之间实现模块化,为了保证稳定性和健壮性,守护进程被分成三个独立的进程。整体设计基于一个简单的父进程,父进程负责 fork 并监控子进程。两个子进程,一个负责 VRRP 框架,另一个负责健康检查。每个子进程有自己的 I/O 调度多路复用器,这样可以优化 VRRP 调度,因为 VRRP 调度比健康检查更敏感。另一方面,这个分开的设计使得健康检查机制对外部函数库的使用最小化,最小化自身的动作并且让主循环空闲来避免自身引起的故障。父进程的监控框架叫做 watchdog,它的设计是:每个子进程打开一个 UNIX 套接字等待请求,当守护进程启动后,父进程连接这些 UNIX 套接字并周期性(5s)地发送 hello 包到子进程。如果父进程无法发送 hello 包到远程连接的 UNIX 套机字,它会简单地重启子进程。watchdog 的设计有两个好处,首先 hello 包从父进程发送到远程连接的子进程是通过 I/O 多路复用器调度,这样它就能够检测子进程调度框架中的死循环。第二个好处是可以使用 sysV 信号检测子进程是否死掉。当启动服务的时候,进程列表:
global_defs {
notification_email {
admin@example.com
}
notification_email_from admin@example.com
smtp_server 127.0.0.1
stmp_connect_timeout 30
router_id LVS_DEVEL
}
global_defs:全局配置标识
notification_email:表示 keepalived 在发生诸如切换时需要发送 email 通知,以及 email 发送给哪些邮件地址,邮件地址可以是多个,每行一个
notification_email_from:表示发送通知邮件时,邮件的发送者
smtp_server:表示发送邮件时 smtp 服务器地址,这里可以使用本地的 sendmail 来实现
smtp_connect_timeout:连接 smtp 的超时时间
router_id:机器标识
static_ipaddress {
192.168.1.1/24 brd + dev eth0 scope global
192.168.1.2/24 brd + dev eth1 scope global
}
static_routes {
src $SRC_IP to $DST_IP dev $SRC_DEVICE
src $SRC_IP to $DST_IP via $GW dev $SRC_DEVICE
}
这里的配置实际上和系统里面命令配置 IP 地址和路由一样,例如:192.168.1.1/24 brd + dev eth0 scope global 相当于 ip addr add 192.168.1.1/24 brd + dev eth0 scope global。就是给 eth0 配置 IP 地址,路由同理。一般这个区域不需要配置
这里实际上就是给服务器配置真实的 IP 地址和路由,在复杂环境下可能需要配置,一般不会用这个来配置
vrrp_sync_group VG_1 {
group {
http
mysql
}
notify_master /path/to/to_master.sh
notify_backup /path_to/to_backup.sh
notify_fault "/path/fault.sh VG_1"
notify /path/to/notify.sh
smtp_alert
}
group:VRRP 组。http 和 mysql 是实例名,和下面的实例名一致
notify_master:表示当切换到 Master 状态时要执行的脚本
notify_backup:表示当切换到 Backup 状态时要执行的脚本
notify_fault:错误时要执行的脚本
smtp_alert:表示切换时给 global_defs 中定义的邮件地址发送邮件通知
vrrp_instance http {
state MASTER
interface eth0
dont_track_primary
track_interface {
eth0
eth1
}
mcast_src_ip <IPADDR>
garp_master_delay 10
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
autp_pass 1234
}
virtual_ipaddress {
#<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPT> label <LABEL>
192.168.200.17/24 dev eth1
192.168.200.18/24 dev eth2 label eth2:1
}
virtual_routes {
# src <IPADDR> [to] <IPADDR>/<MASK> via|gw <IPADDR> dev <STRING> scope <SCOPE> tab
src 192.168.100.1 to 192.168.109.0/24 via 192.168.200.254 dev eth1
192.168.110.0/24 via 192.168.200.254 dev eth1
192.168.111.0/24 dev eth2
192.168.112.0/24 via 192.168.100.254
}
notify_master /path/to/to_master.sh
notify_backup /path_to/to_backup.sh
notify_fault "/path/fault.sh VG_1"
nopreempt
preemtp_delay 300
debug
}
state:指定 Instance 的初始状态,但是启动之后还是要通过优先级竞选选定 Master
interface:实例绑定的网卡,因为在配置虚拟 IP 的时候必须是在已有的网卡上添加的
dont_track_primary:忽略 VRRP 的 interface 错误
track_interface:跟踪接口,设置额外的监控,里面任意一块网卡出现问题,都会进入故障(FAULT)状态,例如,用 nginx 做负载均衡的时候,内外网必须工作正常,如果内网出了问题,这个 LB 也无法运作,所以必须对内外网同时做健康检查
mcast_src_ip:发送多播数据包时的源 IP 地址,这里实际上就是在哪个地址上发送 VRRP 通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于 heartbeat 的心跳端口。如果没有设置就使用默认的绑定的网卡的 IP,也就是 interface 指定的地址
garp_master_delay:在切换到 Master 状态后,延迟进行 gratuitous ARP 请求
virtual_router_id:设置 VRID,相同的 VRID 为一组,它将决定多播的 MAC 地址
priority 100:设置本节点的优先级
advert_int:检查间隔,默认为 1 秒
virtual_ipaddress:LVS 的 VIP
virtual_routes:虚拟路由
lvs_sync_daemon_interface:LVS syncd 绑定的网卡
authentication:设置认证
auth_type:认证方式,可以是 PASS 或 AH 两种方式
auth_pass:认证密码
nopreempt:设置不抢占,这里只能设置在 state 为 BACKUP 的节点上,而且这个节点的优先级必须比其他节点高
preempt_delay:抢占延迟
debug:debug 级别
notify_master:和 synchorization group 里设置的含义一样,可以单独设置
vrrp_script check_running {
script "/usr/local/bin/check_running" # 执行的脚本
interval 10 # 执行脚本的时间间隔
weight 10 # 检测失败优先级操作 10 表示优先级 +10,-10 表示优先级 -10
fall 2 # 检测尝试次数,也就是认定服务器 down 的检测次数
rise 1 # 认定服务器 up 的次数
}
vrrp_instance http {
state BACKUP
smtp_alert
interface eth0
virtual_router_id 101
priority 90
advert_int 3
authentication {
auth_type PASS
auth_pass whatever
}
virtual_ipaddress {
1.1.1.1
}
track_script {
check_running weight 20
}
}
首先在 vrrp_script 区域定义脚本名字、脚本执行间隔和脚本执行的优先级变更,然后在实例里面引用。注意:VRRP 脚本和 VRRP 实例属于同一级别
virtual_server_group <STRING> {
# VIP port
<IPADDR> <PORT>
<IPADDR> <PORT>
fwmark <INT>
}
2.虚拟主机配置
virtual server 可以用下面三种的任意一种来配置:
1. virtual server IP port 2. virtual server fwmark int 3. virtual server group string
virtual_server 172.16.100.1 80 { # 设置一个 virtual server:VIP:PORT
delay_loop 6 # 服务轮询的时间间隔
lb_algo rr|wrr|lc|wlc|lblc|sh|sh # LVS 调度算法
lb_kind NAT|DR|TUN # LVS 集群模式
nat_mask 255.255.255.0
persistent_timeout 50 # 会话保持时间(秒)
persistent_granularity <NETMASK> # LVS 会话保持粒度,ipvsadm 中的 -M 参数,默认是 0xffffffff,即每个客户端都会话保持
protocol TCP # 协议
sorry_server <IPADDR> <PORT> # 备用机,就是当所有后端 realserver 节点都不可用时,就用这里的设置
real_server <IPADDR> <PORT> { # 后端真实节点主机的权重等设置
weight 1
inhibit_on_failure # 表示在节点失败后,把它权重设置为 0 而不是从 IPVS 中删除
notify_up <STRING>|<QUOTED-STRING> # 检查服务器正常(up)后要执行的脚本
notify_down <STRING>|<QUOTED-STRING> # 检查服务器失败(down)后要执行的脚本
HTTP_GET|SSL_GET { # 健康检查的方式
url { # 要检测的 url,可以有多个
path <STRING> # 测试页面的 URI 路径
digest <STRING> # 摘要码
status_code <INT> # 返回状态码
}
connect_port <PORT> # realserver 提供服务的端口
bindto <IPADDR> # realserver 提供服务的地址
connect_timeout <INT> # 连接超时时间
nb_get_retry <INT> # 重试次数
delay_before_retry <INT> # 重试间隔
}
TCP_CHECK {
connect_port <PORT>
bindto <IPADDR>
connect_timeout <INT>
}
SMTP_CHECK {
host {
connect_ip <IP ADDRESS>
connect_port <PORT>
bindto <IP ADDRESS>
}
connect_timeout <INT>
retry <INT>
delay_before_retry <INT>
helo_name <STRING>|<QUOTED-STRING>
}
MISC_CHECK {
misc_path <STRING>|<QUOTED-STRING> # 外部程序或脚本
misc_timeout <INT> # 脚本或程序执行超时时间
misc_dynamic # 通过执行的程序或脚本返回的状态码动态调整 weight 值,使权重根据真实的后端压力来适当调整
} # 返回 0:健康检查没问题,不修改权重
} # 返回 1:健康检查失败,权重设置为 0
} # 返回 2-255:健康检查没问题,但是权重修改为返回代码-2
原文:http://my.oschina.net/JerryBaby/blog/408390