1. 简介
负载平衡是一种在一组真实服务器之间分配 IP 流量的方法,可提供一种或多种高度可用的虚拟服务。在设计负载平衡拓扑结构时,必须考虑到负载平衡器本身及其背后实际服务器的可用性。
Keepalived 为负载平衡和高可用性提供了框架。负载平衡框架依赖于著名的、广泛使用的 Linux 虚拟服务器(IPVS)内核模块,该模块提供第 4 层负载平衡。Keepalived 实现了一套健康检查器,可根据服务器池的健康状况动态、自适应地维护和管理负载平衡服务器池。高可用性由虚拟冗余路由协议(VRRP)实现。VRRP 是路由器故障转移的基础。此外,keepalived 还为 VRRP 有限状态机实现了一组钩子,提供低级和高速的协议交互。每个 Keepalived 框架可单独使用,也可一起使用,以提供弹性基础设施。
在这种情况下,负载平衡器也可被称为 Director 或 LVS 路由器。
简而言之,Keepalived 提供两大功能:
- LVS 系统的健康检查
- 实施 VRRPv2 协议栈以处理负载平衡器故障切换
2. 软件设计
Keepalived 采用纯 ANSI/ISO C 语言编写。软件围绕一个中央 I/O 多路复用器展开,提供实时网络设计。主要设计重点是在所有元素之间提供同质模块化。因此,创建了一个核心库,以消除代码重复。目标是生成安全可靠的代码,确保生产的稳健性和稳定性。
为确保稳健性和稳定性,守护进程被分为 3 个不同的进程:
- 一个最小化的父进程,负责分叉子进程的监控。
- 两个子进程,一个负责 VRRP 框架,另一个负责健康检查。
每个子进程都有自己的调度 I/O 多路复用器,这样可以优化 VRRP 调度抖动,因为 VRRP 调度比健康检查器更合理/更关键。这种拆分设计可以最大限度地减少健康检查对外来库的使用,并最大限度地减少自身的运行,使主循环处于空闲状态,以避免自身引起的故障。
父进程监控框架被称为看门狗,其设计是每个子进程打开一个接受 unix 域的套接字,然后在守护进程启动时,父进程连接到这些 unix 域套接字,并定期(5 秒)向子进程发送 hello 包。如果父进程无法向远程连接的 unix 域套接字发送你好数据包,它就会重新启动子进程。
这种看门狗设计有两个好处:首先,父进程向远程连接的子进程发送 hello 数据包是通过 I/O 多路复用器调度器完成的,这样它就能检测到子进程调度框架中的死循环。第二个好处是使用 sysV 信号检测死循环子进程。运行时,你会在进程列表中看到
PID 111 Keepalived <-- Parent process monitoring children
112 _ Keepalived <-- VRRP child
113 _ Keepalived <-- Healthchecking child
内核组件
Keepalived 使用四个 Linux 内核组件:
- LVS 框架:使用 getsockopt 和 setsockopt 调用来获取和设置套接字上的选项。
- Netfilter 框架:支持 NAT 和伪装的 IPVS 代码。
- 网联接口:在网络接口上设置和删除 VRRP 虚拟 IP。
- 组播:VRRP 广告会发送到保留的 VRRP MULTICAST 组 (224.0.0.18)。
原子组件
控制平面
Keepalived 配置通过 keepalived.conf 文件完成。编译器设计用于解析。解析器通过关键字树层次结构将每个配置关键字与具体处理程序进行映射。中央多级递归函数读取配置文件并遍历关键字树。在解析过程中,配置文件被转换为内部存储器表示法。
调度器 - I/O 复用器
所有事件都安排在同一个进程中。Keepalived 是一个单一进程。Keepalived 是一个网络路由软件,因此与 I/O 无关。这里使用的设计是一个中央选择(......),负责调度所有内部任务。没有使用 POSIX 线程库。该框架提供了自己的线程抽象,并针对网络目的进行了优化。
内存管理
该框架提供了一些通用的内存管理功能,如分配、重新分配、释放等。该框架有两种使用模式:正常模式和调试模式。使用调试模式时,它提供了消除和跟踪内存泄漏的强大方法。这个底层 env 通过跟踪分配内存和释放内存来提供缓冲区欠运行保护。所有使用的缓冲区长度都是固定的,以防止缓冲区溢出。
核心组件
该框架定义了一些通用的全局库,所有代码都会用到。这些库包括:html 解析、链接列表、定时器、矢量、字符串格式化、缓冲区转储、网络工具、守护进程管理、pid 处理、底层 TCP layer4。我们的目标是最大限度地精简代码,尽可能减少代码重复,从而提高模块化程度。
看门狗
该框架提供子进程监控(VRRP 和健康检查)功能。每个子进程接受与自己的看门狗 unix 域套接字的连接。父进程向子进程的 unix 域套接字发送 "你好 "信息。父进程使用 I/O 多路复用器发送 "你好 "信息,子进程使用 I/O 多路复用器接受/处理 "你好 "信息。如果父进程检测到管道断裂,它会使用 sysV 信号测试子进程是否还活着,并重新启动它。
校验器
这是 Keepalived 的主要功能之一。检查器负责 realserver 的健康检查。检查器测试 realserver 是否存活,测试结束后做出二进制决定:将 realserver 从 LVS 拓扑中移除或添加到 LVS 拓扑中。内部检查器设计为实时网络软件,采用全多线程 FSM 设计(有限状态机)。该检查堆栈根据第 4 层到第 5/7 层的测试结果提供 LVS 拓扑操作。它在一个独立进程中运行,由父进程监控。
VRRP 堆栈
另一个最重要的 Keepalived 功能是 VRRP(虚拟路由器冗余协议:RFC2338)。VRRP(虚拟路由器冗余协议:RFC2338)的重点是路由器接管,它为路由器备份提供了底层设计。它实现了完整的 IETF RFC2338 标准,并为 LVS 和防火墙设计提供了一些规定和扩展。它实现了 vrrp_sync_group 扩展,确保协议接管后路由路径的持久性。它使用 MD5-96 位加密规定实现了 IPSEC-AH,以确保协议广告交换的安全。有关 VRRP 的更多信息,请阅读 RFC。重要事项:VRRP 代码可以在没有 LVS 支持的情况下使用,它是为独立使用而设计的。
系统调用
该框架提供启动额外系统脚本的功能。它主要用于 MISC 检查器。在 VRRP 框架中,它提供了在协议状态转换时启动额外脚本的功能。系统调用是在一个分叉进程中完成的,这样就不会干扰全局调度计时器。
Netlink 反射器
与 IPVS 封装器相同。Keepalived 使用自己的网络接口表示。IP 地址和接口标志通过内核 Netlink 通道进行设置和监控。Netlink 消息传递子系统用于设置 VRRP VIP。另一方面,Netlink 内核消息广播功能用于向用户空间 Keepalived 内部数据表示反映与接口相关的任何事件。因此,任何其他用户空间(其他程序)的网络链接操作都会通过 Netlink 内核广播(RTMGRP_LINK 和 RTMGRP_IPV4_IFADDR)反映到我们的 Keepalived 数据表示中。
SMTP
SMTP 协议用于管理通知。它使用多线程 FSM 设计实现了 IETF RFC821。管理通知用于发送健康检查器活动和 VRRP 协议状态转换。SMTP 非常常用,可与任何其他通知子系统(如 GSM-SMS、寻呼机等)连接。
IPVS 封装器
该框架用于向内核 IPVS 代码发送规则。它提供 Keepalived 内部数据表示与 IPVS 规则用户表示之间的转换。它使用 IPVS libipvs 来保持与 IPVS 代码的通用集成。
IPVS
Wensong 从 LinuxVirtualServer.org 开源项目中提供的 Linux 内核代码。IPVS(IP 虚拟服务器)在 Linux 内核中实现了传输层负载均衡,也称为第四层交换。
NETLINK
由 Alexey Kuznetov 提供的 Linux 内核代码,具有非常出色的高级路由框架和子系统功能。Netlink 用于在内核和用户空间进程之间传输信息。它包括一个用于用户空间进程的基于套接字的标准接口和一个用于内核模块的内核应用程序接口。
Syslog
所有 keepalived 守护进程的通知信息都使用 syslog 服务记录。
健康检查框架
每个健康检查都在全局调度框架中注册。这些健康检查工作线程执行以下类型的健康检查:
- TCP_CHECK
在第 4 层工作。为确保这一检查,我们使用非阻塞/超时 TCP 连接进行 TCP 检查。如果远程服务器没有回复该请求(超时),则测试错误,服务器将从服务器池中删除。
- HTTP_GET
在第 5 层工作。对指定 URL 执行 HTTP GET。然后使用 MD5 算法对 HTTP GET 结果求和。如果总和与预期值不符,则测试错误,服务器将从服务器池中删除。该模块实现了对同一服务的多 URL 获取检查。如果您使用的服务器托管多个应用服务器,该功能将非常有用。该功能可让您检查应用服务器是否正常工作。MD5 摘要使用 genhash 实用程序(包含在 keepalived 软件包中)生成。
- SSL_GET
与 HTTP_GET 相同,但使用 SSL 连接到远程网络服务器。
- MISC_CHECK
该检查允许将用户定义的脚本作为健康检查器运行。结果必须为 0 或 1。脚本在引导盒上运行,是测试内部应用程序的理想方式。可以使用完整路径(即 /path_to_script/script.sh)调用无需参数即可运行的脚本。需要参数的脚本需要用双引号括起来(例如:"/path_to_script/script.sh arg 1 ... arg n ")
Keepalived 的目标是定义一个易于扩展的通用框架,以便添加新的校验模块。如果你有兴趣开发现有的或新的校验模块,请查看源代码中的 keepalived/check 目录:github.com/acassen/kee…
故障切换 (VRRP) 框架
Keepalived 实现了 VRRP 协议,以进行导向器故障切换。在已实施的 VRRP 堆栈中,VRRP 数据包分配器负责为每个 VRRP 实例解复用特定的 I/O。
该框架独立于 LVS,因此可用于 LVS 主任故障切换,甚至可用于需要热备协议的其他 Linux 路由器。出于设计和稳健性考虑,该框架已完全集成到 Keepalived 守护进程中。
该框架提供的主要功能有:
- 故障转移:基于一组漫游 VRRP VIP 的本地 VRRP 协议目的。
- VRRP 实例同步:我们可以指定 2 个 VRRP 实例之间的状态监控,也称为 VRRP 同步组。它保证 2 个 VRRP 实例保持相同的状态。同步实例相互监控。
- 漂亮的回退
- 广告数据包完整性:使用 IPSEC-AH ICV。
- 系统调用:在 VRRP 状态转换期间,可能会调用外部脚本/程序。
使用带虚拟 MAC 地址的 VRRP 注意事项
为了减少接管影响,某些网络环境需要使用带有 VMAC 地址的 VRRP。为了实现这一目标,Keepalived VRRP 框架通过在配置文件中调用 "use_vmac "关键字来实现 VMAC 支持。
在内部,Keepalived 代码将调用虚拟接口,每个接口专用于特定的 virtual_router。Keepalived 使用 Linux 内核 macvlan 驱动程序来定义这些接口。因此,必须使用编译了 macvlan 支持的内核。
此外,我们还可以指出,VRRP VMAC 模式,只能在包含以下补丁的内核中运行: git.kernel.org/?p=linux/ke…
默认情况下,MACVLAN 接口处于 VEPA 模式,它会过滤掉 MAC 源地址与 MACVLAN 接口匹配的接收数据包。将 MACVLAN 接口设置为专用模式将不会根据 MAC 源地址进行过滤。
或者,您也可以指定 "vmac_xmit_base",这将导致在底层接口上传输和接收 VRRP 信息,而 ARP 将在 VMAC 接口上进行。
您可能还需要调整物理接口,以解决众所周知的 ARP 问题。如果有问题,请尝试以下配置:
-
- 全局配置:
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 1
net.ipv4.conf.all.arp_filter = 0
-
- 物理接口配置
对于运行 VRRP 实例的物理以太网接口,使用
net.ipv4.conf.eth0.arp_filter = 1
-
- VMAC 接口 请考虑以下 VRRP 配置:
vrrp_instance instance1 {
state BACKUP
interface eth0
virtual_router_id 250
use_vmac
vmac_xmit_base # Transmit VRRP adverts over physical interface
priority 150
advert_int 1
virtual_ipaddress {
10.0.0.254
}
}
use_vmac 关键字将驱动 keepalived 代码创建一个名为 vrrp.250 的 macvlan 接口(默认内部范例为 vrrp.{virtual_router_id},您可以为 "use_vmac "关键字提供一个参数,例如:use_vmac vrrp250)。
然后,您需要用
net.ipv4.conf.vrrp.250.arp_filter = 0
net.ipv4.conf.vrrp.250.accept_local = 1 (this is needed for the address owner case)
net.ipv4.conf.vrrp.250.rp_filter = 0
您可以创建 notify_master 脚本来自动执行这一配置步骤:
vrrp_instance instance1 {
state BACKUP
interface eth0
virtual_router_id 250
use_vmac
priority 150
advert_int 1
virtual_ipaddress {
10.0.0.254
}
notify_master "/usr/local/bin/vmac_tweak.sh vrrp.250"
}
3. 负载均衡技术
通过 NAT 的虚拟服务器
当负载平衡器(或 LVS 路由器)有两个网络接口卡(NIC),其中一个分配了面向外部的 IP 地址,另一个分配了面向内部的专用 IP 地址时,就会使用 NAT 路由。在这种方法中,负载平衡器接收来自公共网络用户的请求,并使用网络地址转换(NAT)将这些请求转发给位于专用网络的真正服务器。当真正的服务器回复用户请求时,回复也会被反向转换。
这样做的好处是,真实服务器隐藏在负载平衡器后面,不受公共网络的影响。另一个优点是可以保护 IP 地址,因为专用网络可以使用专用地址范围。
主要缺点是负载平衡器成为瓶颈。它不仅要为公共用户的请求提供服务,还要为公共用户的回复提供服务,同时还要转发私人真实服务器的请求。
通过直接路由(DR)的虚拟服务器
在直接路由中,用户向负载平衡器上的 VIP 发出请求。负载平衡器使用其预定义的调度(分配)算法,将请求转发给相应的真实服务器。与使用 NAT 路由不同,真实服务器直接响应公共用户,无需通过负载平衡器路由。
这种路由选择方法的主要优势在于可扩展性,因为负载平衡器不需要额外负责将发出的数据包从真实服务器路由到公共用户。
这种路由方法的缺点在于其 ARP 限制。为了让真实服务器直接响应公共用户的请求,每台真实服务器在发送回复时都必须使用 VIP 作为源地址。因此,VIP 和 MAC 地址组合在负载平衡器本身和每个真实服务器之间共享,这可能导致真实服务器直接接收请求,而绕过负载平衡器接收传入请求。有一些方法可以解决这个问题,但会增加配置的复杂性和可管理性。
4. 安装 KeepAlived
yum install keepalived
apt-get install keepalived
5. Keepalived 配置概要
Keepalived 配置文件使用以下概要
global_defs {
notification_email {
email
email
}
notification_email_from email
smtp_server host
smtp_connect_timeout num
lvs_id string
}
| Keyword | Definition | Type |
|---|---|---|
| global_defs | 表明这是一个全局配置 | |
| notification_email | 将接收通知邮件的电子邮件帐户 | List |
| notification_email_from | 处理 "MAIL FROM: "SMTP 命令时使用的电子邮件 | List |
| smtp_server remote SMTP | 用于发送邮件通知的服务器 | alphanum |
| smtp_connection_timeout | 指定 SMTP 流处理的超时时间 | numerical |
| lvs_id | specify the name of the LVS director | alphanum |
Email type: Is a string using charset as specified into the SMTP RFC eg: “user@domain.com”
Virtual Server 定义概要
virtual_server (@IP PORT)|(fwmark num) {
delay_loop num
lb_algo rr|wrr|lc|wlc|sh|dh|lblc
lb_kind NAT|DR|TUN
(nat_mask @IP)
persistence_timeout num
persistence_granularity @IP
virtualhost string
protocol TCP|UDP
sorry_server @IP PORT
real_server @IP PORT {
weight num
TCP_CHECK {
connect_port num
connect_timeout num
}
}
real_server @IP PORT {
weight num
MISC_CHECK {
misc_path /path_to_script/script.sh
(or misc_path “ /path_to_script/script.sh <arg_list>”)
}
}
}
real_server @IP PORT {
weight num
HTTP_GET|SSL_GET {
url { # You can add multiple url block
path alphanum
digest alphanum
}
connect_port num
connect_timeout num
retry num
delay_before_retry num
}
}
| Keyword | Definition | Type | |||
|---|---|---|---|---|---|
| virtual_server | identify a virtual server definition block | ||||
| fwmark | specify that virtual server is a FWMARK | ||||
| delay_loop | specify in seconds the interval between checks | numerical | |||
| lb_algo | select a specific scheduler (rr | wrr | lc | wlc...) | string |
| lb_kind | select a specific forwarding method (NAT | DR | TUN) | string | |
| persistence_timeout | specify a timeout value for persistent connections | numerical | |||
| persistence_granularity | specify a granularity mask for persistent connections | ||||
| virtualhost | specify a HTTP virtualhost to use for HTTP | SSL_GET | alphanum | ||
| protocol | specify the protocol kind (TCP | UDP) | numerical | ||
| sorry_server | server to be added to the pool if all real servers are down | ||||
| real_server | specify a real server member | ||||
| weight | specify the real server weight for load balancing decisions | numerical | |||
| TCP_CHECK | check real server availability using TCP connect | ||||
| MISC_CHECK | check real server availability using user defined script | ||||
| misc_path | identify the script to run with full path | path | |||
| HTTP_GET | check real server availability using HTTP GET request | ||||
| SSL_GET | check real server availability using SSL GET request | ||||
| url | identify a url definition block | ||||
| path | specify the url path | alphanum | |||
| digest | specify the digest for a specific url path | alphanum | |||
| connect_port | connect remote server on specified TCP port | numerical | |||
| connect_timeout | connect remote server using timeout | numerical | |||
| retry | maximum number of retries | numerical | |||
| delay_before_retry | delay between two successive retries | numerical |
VRRP 实例定义概要
最常用的就是该模式
vrrp_sync_group string {
group {
string
string
}
notify_master /path_to_script/script_master.sh
(or notify_master “ /path_to_script/script_master.sh <arg_list>”)
notify_backup /path_to_script/script_backup.sh
(or notify_backup “/path_to_script/script_backup.sh <arg_list>”)
notify_fault /path_to_script/script_fault.sh
(or notify_fault “ /path_to_script/script_fault.sh <arg_list>”)
}
vrrp_instance string {
state MASTER|BACKUP
interface string
mcast_src_ip @IP
lvs_sync_daemon_interface string
virtual_router_id num
priority num
advert_int num
smtp_alert
authentication {
auth_type PASS|AH
auth_pass string
}
virtual_ipaddress { # Block limited to 20 IP addresses
@IP
@IP
@IP
}
virtual_ipaddress_excluded { # Unlimited IP addresses
@IP
@IP
@IP
}
notify_master /path_to_script/script_master.sh
(or notify_master “ /path_to_script/script_master.sh <arg_list>”)
notify_backup /path_to_script/script_backup.sh
(or notify_backup “ /path_to_script/script_backup.sh <arg_list>”)
notify_fault /path_to_script/script_fault.sh
(or notify_fault “ /path_to_script/script_fault.sh <arg_list>”)
}
| Keyword | Definition | Type | |
|---|---|---|---|
| vrrp_instance | identify a VRRP instance definition block | ||
| state | specify the instance state in standard use | ||
| Interface | specify the network interface for the instance to run on | string | |
| mcast_src_ip | specify the src IP address value for VRRP adverts IP header | ||
| lvs_sync_daemon_inteface | specify the network interface for the LVS sync_daemon to run on | string | |
| virtual_router_id | specify to which VRRP router id the instance belongs | numerical | |
| priority | specify the instance priority in the VRRP router | numerical | |
| advert_int | specify the advertisement interval in seconds (set to 1) | numerical | |
| smtp_alert | Activate the SMTP notification for MASTER state transition | ||
| authentication | identify a VRRP authentication definition block | ||
| auth_type | specify which kind of authentication to use (PASS | AH) | |
| auth_pass | specify the password string to use | string | |
| virtual_ipaddress | identify a VRRP VIP definition block | ||
| virtual_ipaddress_excluded | identify a VRRP VIP excluded definition block (not protocol VIPs) | ||
| notify_master | specify a shell script to be executed during transition to master state | path | |
| notify_backup | specify a shell script to be executed during transition to backup state | path | |
| notify_fault | specify a shell script to be executed during transition to fault state | path | |
| vrrp_sync_group | Identify the VRRP synchronization instances group | string |
Path type: A system path to a script eg: “/usr/local/bin/transit.sh <arg_list>”
注意这里没说明某些参数是否可以省略,那应该就是不能省略。 而且认证类型是强制二选一,AH 比 PASS 更安全。
5. Keepalived 程序简介
Keepalived 软件包包含 2 个程序:
- keepalived 服务端
- genhash 实用程序
keepalived 命令行参数为:
- -f, –use-file=FILE
- Use the specified configuration file. The default configuration file is “/etc/keepalived/keepalived.conf”.
- -P, –vrrp
- Only run the VRRP subsystem. This is useful for configurations that do not use IPVS load balancer.
- -C, –check
- Only run the healthcheck subsystem. This is useful for configurations that use the IPVS load balancer with a single director with no failover.
- -l, –log-console
- Log messages to the local console. The default behavior is to log messages to syslog.
- -D, –log-detail
- Detailed log messages.
- -S, –log-facility=[0-7]
- Set syslog facility to LOG_LOCAL[0-7]. The default syslog facility is LOG_DAEMON.
- -V, –dont-release-vrrp
- Don’t remove VRRP VIPs and VROUTEs on daemon stop. The default behavior is to remove all VIPs and VROUTEs when keepalived exits
- -I, –dont-release-ipvs
- Don’t remove IPVS topology on daemon stop. The default behavior it to remove all entries from the IPVS virtual server table on when keepalived exits.
- -R, –dont-respawn
- Don’t respawn child processes. The default behavior is to restart the VRRP and checker processes if either process exits.
- -n, –dont-fork
- Don’t fork the daemon process. This option will cause keepalived to run in the foreground.
- -d, –dump-conf
- Dump the configuration data.
- -p, –pid=FILE
- Use specified pidfile for parent keepalived process. The default pidfile for keepalived is “/var/run/keepalived.pid”.
- -r, –vrrp_pid=FILE
- Use specified pidfile for VRRP child process. The default pidfile for the VRRP child process is “/var/run/keepalived_vrrp.pid”.
- -c, –checkers_pid=FILE
- Use specified pidfile for checkers child process. The default pidfile for the checker child process is “/var/run/keepalived_checkers.pid”.
- -x, –snmp
- Enable SNMP subsystem.
- -v, –version
- Display the version and exit.
- -h, –help
- Display this help message and exit.
genhash 二进制文件用于生成摘要字符串。genhash 命令行参数为
- –use-ssl, -S
- Use SSL to connect to the server.
- –server <host>, -s
- Specify the ip address to connect to.
- –port <port>, -p
- Specify the port to connect to.
- –url <url>, -u
- Specify the path to the file you want to generate the hash of.
- –use-virtualhost <host>, -V
- Specify the virtual host to send along with the HTTP headers.
- –hash <alg>, -H
- Specify the hash algorithm to make a digest of the target page. Consult the help screen for list of available ones with a mark of the default one.
- –verbose, -v
- Be verbose with the output.
- –help, -h
- Display the program help screen and exit.
- –release, -r
- Display the release number (version) and exit.
6. IPVS 调度算法
IPVS 内核代码支持以下调度算法。
Round Robin
Weighted Round Robin
Least Connection
Weighted Least Connection
Locality-Based Least Connection
Locality-Based Least Connection with Replication
Destination Hashing
Source Hashing
Shortest Expected Delay
Never Queue
7. IPVS 支持的协议
IPVS 负载平衡 支持的传输协议
IPVS 支持以下传输协议的负载平衡:
- TCP
- UDP
- ESP(封装安全有效载荷)
- AH(验证头)
8. 配置 SNMP 支持
Keepalived 提供了一个 SNMP 子系统,可以收集有关 VRRP 堆栈和健康检查系统的各种指标。keepalived MIB 位于项目的 doc 目录中。MIB 的基本 SNMP OID 是 .1.3.6.1.4.1.9586.100.5,位于 IANA 分配的 Debian OID 空间下。
在系统中安装 SNMP 协议工具和库。这需要安装几个软件包:
yum install net-snmp net-snmp-utils net-snmp-libs
配置支持
在 SNMP 守护进程配置文件(如果通过 RPM 安装在 CentOS 机器上,通常为 /etc/snmp/snmpd.conf)中加入以下一行,即可启用 SNMP AgentX 支持:
master agentx
Adding the MIB
You can query keepalived SNMP managed objects by using the OID. For example:
snmpwalk -v2c -c public localhost .1.3.6.1.4.1.9586.100.5.1.1.0
SNMPv2-SMI::enterprises.9586.100.5.1.1.0 = STRING: "Keepalived v1.2.15 (01/10,2015)"
Alternatively, with the keepalived MIB, you can query using the MIB available from the project. First, copy the MIB to the system’s global MIB directory or to the user’s local MIB directory:
cp /usr/local/src/keepalived-1.2.15/doc/KEEPALIVED-MIB /usr/share/snmp/mibs
MIB Overview
There are four main sections to the keepalived MIB:
- global
- vrrp
- check
- conformance
9. 案例研究: 健康检查
举例来说,我们可以引入以下 LVS 拓扑:
首先,您需要一个配置良好的 LVS 拓扑。在本文的其余部分,我们将假设所有系统配置都已完成。这种拓扑一般在 DMZ 架构中实现。有关 LVS NAT 拓扑和系统配置的更多信息,请阅读 Joseph Mack LVS HOWTO。
主要架构组件
- LVS 路由器:拥有负载平衡 IP 类路由(192.168.100.0/24)。
- 网络路由器:整个内部网络的默认路由器。所有局域网工作站都通过该 IP 地址处理。
- 网络 DNS 服务器:参考内部网络 IP 拓扑。
- SMTP 服务器:接收邮件警报的 SMTP 服务器。
- 服务器池:承载负载均衡服务的服务器集。
服务器池规格
在此示例配置中,我们有 2 个服务器池:
- 服务器池 1:托管 HTTP 和 SSL 服务。每台服务器拥有两个应用程序服务器(IBM WEBSPHERE 和 BEA WEBLOGIC)
- 服务器池 2:托管 SMTP 服务。
配置 Keepalived
现在,您可以根据 LVS 拓扑配置 Keepalived 守护进程了。整个配置在 /etc/keepalived/keepalived.conf 文件中完成。在我们的案例研究中,该文件如下所示
# Configuration File for keepalived
global_defs {
notification_email {
admin@domain.com
0633225522@domain.com
}
notification_email_from keepalived@domain.com
smtp_server 192.168.200.20
smtp_connect_timeout 30
lvs_id LVS_MAIN
}
virtual_server 192.168.200.15 80 {
delay_loop 30
lb_algo wrr
lb_kind NAT
persistence_timeout 50
protocol TCP
sorry_server 192.168.100.100 80
real_server 192.168.100.2 80 {
weight 2
HTTP_GET {
url {
path /testurl/test.jsp
digest ec90a42b99ea9a2f5ecbe213ac9eba03
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
retry 3
delay_before_retry 2
}
}
real_server 192.168.100.3 80 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
retry 3
delay_before_retry 2
}
}
}
virtual_server 192.168.200.15 443 {
delay_loop 20
lb_algo rr
lb_kind NAT
persistence_timeout 360
protocol TCP
real_server 192.168.100.2 443 {
weight 1
TCP_CHECK {
connect_timeout 3
}
}
real_server 192.168.100.3 443 {
weight 1
TCP_CHECK {
connect_timeout 3
}
}
}
virtual_server 192.168.200.15 25 {
delay_loop 15
lb_algo wlc
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.100.4 25 {
weight 1
TCP_CHECK {
connect_timeout 3
}
}
real_server 192.168.100.5 25 {
weight 2
TCP_CHECK {
connect_timeout 3
}
}
}
根据这个配置示例,Keepalived 守护进程将使用以下信息驱动内核:
LVS 服务器将拥有以下名称:LVS_MAIN
通知:
- SMTP 服务器将是192.168.200.20
- SMTP 连接超时设置为:30 秒
- 通知电子邮件将为: admin@domain.com & 0633225522@domain.com
负载平衡服务:
HTTP:VIP 192.168.200.15 端口 80
负载平衡:
使用加权循环调度程序和 NAT 转发。每个 TCP 服务的连接持续时间设置为 50 秒。如果使用 Linux 内核 2.2,则需要指定 NAT 净掩码来定义 IPFW 伪装粒度(nat_mask 关键字)。延迟循环设置为 30 秒
-
对不起(究极备份)服务器:如果所有真实服务器都从 VS 的服务器池中移除,我们将添加 sorry_server 192.168.100.100 端口 80 来处理客户请求。
-
真实服务器 192.168.100.2 端口 80 的权重为 2。故障检测将基于 HTTP_GET over 2 URLS。服务连接超时设置为 3 秒。重试 3 次后,真实服务器将被视为宕机。守护进程将等待 2 秒后再重试。
-
真实服务器 192.168.100.3 端口 80 的权重为 1。故障检测将基于 1 个 URL 的 HTTP_GET。服务连接超时设置为 3 秒。重试 3 次后,真实服务器将被视为宕机。守护进程将等待 2 秒后再重试。
SSL: VIP 192.168.200.15 端口 443
-
负载平衡:使用带有 NAT 转发功能的循环罗宾调度程序。每个 TCP 服务的连接持续时间设置为 360 秒。延迟循环设置为 20 秒
-
真实服务器 192.168.100.2 端口 443 的权重为 2,故障检测基于 TCP_CHECK。连接超时 3 秒后,真实服务器将被视为宕机。
-
真实服务器 192.168.100.3 端口 443 的权重为 2。故障检测将基于 TCP_CHECK。真实服务器将在 3 秒连接超时后被视为宕机。
SMTP: VIP 192.168.200.15 端口 25
-
负载平衡:在 NAT 拓扑中使用加权最小连接调度算法,连接持续时间设置为 50 秒。延迟循环设置为 15 秒
-
真实服务器 192.168.100.4 端口 25 的权重为 1。故障检测将基于 TCP_CHECK。连接超时 3 秒后,真实服务器将被视为宕机。
-
真实服务器 192.168.100.5 端口 25 的权重为 2。故障检测将基于 TCP_CHECK。真实服务器将在 3 秒连接超时后被视为宕机。
对于 SSL 服务器健康检查,我们可以使用 SSL_GET 检查器。相应真实服务器的配置块如下所示
# virtual_server 即负载均衡器: 会调用 lvs 进行配置
virtual_server 192.168.200.15 443 {
delay_loop 20
lb_algo rr
lb_kind NAT
persistence_timeout 360
protocol TCP
real_server 192.168.100.2 443 {
weight 1
SSL_GET
{
url {
path /testurl/test.jsp
digest ec90a42b99ea9a2f5ecbe213ac9eba03
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
retry 3
delay_before_retry 2
}
}
real_server 192.168.100.3 443 {
weight 1
SSL_GET
{
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
retry 3
delay_before_retry 2
}
}
}
10. 案例研究:使用 VRRP 进行故障切换
举例来说,我们可以引入以下 LVS 拓扑:
架构规范 为使用 VRRPv2 协议创建虚拟 LVS 总监,我们定义了以下架构:
- 主-主配置中的 2 个 LVS directors。
- 每个 LVS director 有 4 个 VRRP 实例:2 个 VRRP 实例处于 MASTER 状态,2 个处于 BACKUP 状态。我们在每个 LVS director 上使用对称状态。
- 处于相同状态的 2 个 VRRP 实例必须同步,以定义持久的虚拟路由路径。
- 强身份验证:IPSEC-AH 用于保护我们的 VRRP 广告免受欺骗和回复攻击。
如果要保证安全的话,最好是默认使用强身份验证
VRRP 实例由以下 IP 地址组成:
- VRRP 实例 VI_1:拥有 VRRIP VIP VIP1 和 VIP2。该实例默认为 LVS director 1 的 MASTER 状态。它与 VI_2 保持同步。
- VRRP 实例 VI_2:拥有 DIP1。该实例默认处于 LVS director 1 的 MASTER 状态。它与 VI_1 保持同步。
- VRRP 实例 VI_3:拥有 VRRIP VIP VIP3 和 VIP4。该实例处于 LVS director 2 的默认 MASTER 状态。它与 VI_4 保持同步。
- VRRP 实例 VI_4:拥有 DIP2。该实例处于 LVS director 2 的默认 MASTER 状态。它与 VI_3 保持同步。
Keepalived 配置
整个配置在 /etc/keepalived/keepalived.conf 文件中完成。在我们的案例研究中,LVS director 1 上的该文件如下所示:
# 只有组内的成员会建立主主管理,建立 VRRP 检测同步
vrrp_sync_group VG1 {
VI_1
VI_2
}
vrrp_sync_group VG2 {
VI_3
VI_4
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type AH
auth_pass k@l!ve1
}
virtual_ipaddress {
192.168.200.10
192.168.200.11
}
}
vrrp_instance VI_2 {
state MASTER
interface eth1
virtual_router_id 52
priority 150
advert_int 1
authentication {
auth_type AH
auth_pass k@l!ve2
}
virtual_ipaddress {
192.168.100.10
}
}
vrrp_instance VI_3 {
state BACKUP
interface eth0
virtual_router_id 53
priority 100
advert_int 1
authentication {
auth_type AH
auth_pass k@l!ve3
}
virtual_ipaddress {
192.168.200.12
192.168.200.13
}
}
vrrp_instance VI_4 {
state BACKUP
interface eth1
virtual_router_id 54
priority 100
advert_int 1
authentication {
auth_type AH
auth_pass k@l!ve4
}
virtual_ipaddress {
192.168.100.11
}
}
然后,我们在 LVS director 2 上定义对称配置文件。这意味着,LVS 主控 2 上的 VI_3 和 VI_4 处于优先级较高的 MASTER 状态,优先级为 150,以便从稳定状态开始。对称地,LVS 设备 2 上的 VI_1 和 VI_2 处于默认的备份状态,优先级较低,为 100。| 该配置文件为每个物理网卡指定了 2 个 VRRP 实例。在 LVS 主任 1 上运行 Keepalived 而不在 LVS 主任 2 上运行时,LVS director 1 将拥有所有 VRRP VIP。因此,如果使用 ip 实用程序,您可能会看到如下内容:(在 Debian 上,ip 工具是 iproute 的一部分):
[root@lvs1 tmp]# ip address list
1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:00:5e:00:01:10 brd ff:ff:ff:ff:ff:ff
inet 192.168.200.5/24 brd 192.168.200.255 scope global eth0
inet 192.168.200.10/32 scope global eth0
inet 192.168.200.11/32 scope global eth0
inet 192.168.200.12/32 scope global eth0
inet 192.168.200.13/32 scope global eth0
3: eth1: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.5/24 brd 192.168.201.255 scope global eth1
inet 192.168.100.10/32 scope global eth1
inet 192.168.100.11/32 scope global eth1
Then simply start Keepalived on the LVS director 2 and you will see:
[root@lvs1 tmp]# ip address list
1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:00:5e:00:01:10 brd ff:ff:ff:ff:ff:ff
inet 192.168.200.5/24 brd 192.168.200.255 scope global eth0
inet 192.168.200.10/32 scope global eth0
inet 192.168.200.11/32 scope global eth0
3: eth1: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.5/24 brd 192.168.201.255 scope global eth1
inet 192.168.100.10/32 scope global eth1
Symmetrically on LVS director 2 you will see:
[root@lvs2 tmp]# ip address list
1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:00:5e:00:01:10 brd ff:ff:ff:ff:ff:ff
inet 192.168.200.5/24 brd 192.168.200.255 scope global eth0
inet 192.168.200.12/32 scope global eth0
inet 192.168.200.13/32 scope global eth0
3: eth1: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:00:5e:00:01:32 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.5/24 brd 192.168.201.255 scope global eth1
inet 192.168.100.11/32 scope global eth1
The VRRP VIPs are:
- VIP1 = 192.168.200.10
- VIP2 = 192.168.200.11
- VIP3 = 192.168.200.12
- VIP4 = 192.168.200.13
- DIP1 = 192.168.100.10
- DIP2 = 192.168.100.11
使用 VRRP 关键字 "sync_instance "意味着我们为每个 LVS director 定义了一对 MASTER VRRP 实例 ó (VI_1,VI_2) & (VI_3,VI_4)。这意味着,如果 LVS director 1 上的 eth0 出现故障,VI_1 就会进入 LVS director 2 上的 MASTER 状态,因此两个 director 上的 MASTER 实例分布将如下:(VI_2) on Director 1 & (VI_1,VI_3,VI_4) on Director 2。我们使用 "sync_instance",这样 VI_2 就会强制备份 LVS 主任 1 上的状态。最终的 VRRP MASTER 实例分布将是(在 LVS director 1 上为(无),在 LVS director 2 上为(VI_1,VI_2,VI_3,VI_4)。如果 LVS director 1 上的 eth0 可用,则分布将过渡回初始状态。
有关这种状态转换的更多详情,请参阅 "Linux Virtual Server High Availability using VRRPv2"(《使用 VRRPv2 的 Linux 虚拟服务器高可用性》)一文(可从 www.linux-vs.org/~acassen/ 获取),其中解释了该功能的实现。
使用此配置时,两个 LVS director 同时处于活动状态,从而共享全局总监的 LVS director。这样,我们就引入了一个虚拟 LVS director。