亚马逊AWS官方博客
亚马逊云科技VPC中的keepalived配置指南
![]() |
前言
Keepalived是在Linux操作系统中比较流行的基于网络的高可用组件,常用于包含主备节点的高可用集群,例如数据库、DNS服务器、网络防火墙等。
在决定使用keepalived之前,我们建议您首先评估是否可以使用云原生的网络高可用服务替代keepalived。AWS VPC常用的云原生高可用服务包括负载均衡器(应用负载均衡器:Application Load Balancer, ALB或者网络负载均衡器:Network Load Balancer, NLB,网关负载均衡器:Gateway Load Balancer, GWLB),和基于DNS(AWS Route 53 )的负载均衡/故障切换。采用云原生服务构建的高可用系统,可靠性更高,配置、维护也更加简单便捷,同时系统架构设计也大为简化,进一步降低了系统故障的可能性。
Keepalived在AWS VPC中部署时,需要根据AWS VPC网络的特点进行相应的配置调整。本文将详细介绍如何在 AWS VPC上部署基于keepalived的高可用应用。
AWS VPC与keepalived
AWS VPC与传统网络的区别
与传统网络不同,AWS VPC网络是完全的软件定义网络(Software Defined Networking, SDN)。AWS VPC更加注重网络的安全性,并且根据软件定义网络的能力和特点,对网络转发行为进行了优化。具体表现为:
- VPC内的IP转发依据子网路由表
- 子网路由表预置目标为VPC CIDR的本地路由,并且不可修改(例如CIDR为100.0.0/16的VPC内的所有路由表都预置前缀为10.100.0.0/16,下一跳为local的路由)
- 不支持二层/三层广播
- ARP请求的响应由VPC网络代答,实际上报文并未在VPC网络内传递
在这里有必要对VPC的路由行为进行详细的说明,因为路由行为对keepalived的配置有直接的影响,并且充分理解VPC路由的转发行为对正确设计VPC网络十分关键。VPC路由转发遵循以下几个原则:
原则1:对于VPC内的一个子网,子网路由表仅作用在出子网方向。子网路由表对入方向的流量不起作用[注1]。
原则2:子网路由表依照最长前缀匹配方式查找。这种查找方式与传统网络的路由查找方式一致。
原则3:在投递IP报文到VPC内的网络接口时,除非另有子网路由配置,VPC网络仅会投递到已分配的IP地址。已分配的IP地址包括ENI接口的主IP、从IP(可以有多个)和委托的前缀(Prefix Delegation)。VPC网络不支持中转,从VPC外投递报文到VPC内时,报文的目标必须为上述已分配IP地址,否则报文会被丢弃[注2]。
在VPC中的EC2实例允许绑定多个网卡(ENI: Elastic Network Interface),除了主网卡外,其余网卡均可与EC2实例动态绑定或解绑(主网卡不支持解绑,仅支持选择在实例删除时是否保留)。每个网卡会在所在子网分配一个主IP (Primary IP),这个主IP的生命周期与ENI相同,并且不允许修改。每个ENI可选绑定多个辅助IP (Secondary IP) 或委托前缀 (Prefix Delegation)。辅助IP/IP前缀同样可以动态绑定/解绑。ENI主IP通常是由DHCP动态配置到实例中,通常不需要干预即可在实例内部生效;而DHCP不支持对辅助IP/IP前缀的配置,所以必须依赖实例内部的额外配置才能在实例内部生效。EC2实例可以绑定ENI的数量以及辅助IP/IP前缀的数量与实例规格相关,请参照相关EC2文档。EC2在关联ENI和添加辅助IP/IP前缀的时候,有以下要求:
- EC2实例可以绑定不同子网、不同VPC的ENI,但是这些ENI需要与EC2实例处于相同的可用区
- ENI绑定的辅助IP或前缀IP必须与该ENI的主IP位于同一子网
AWS VPC中keepalived的网络设计
keepalived 是一个基于 VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)的,运行于Linux系统上的高可用组件。VRRP允许多个物理节点组成一个虚拟路由器组,并共享同一个虚拟IP地址(VIP: Virtual IP)。在正常运行状态下,整个集群会基于配置中设定的优先级自动选举出主节点,由主节点绑定并响应该VIP,处理所有流向VIP的数据流量,而其余节点作为备用。集群内部通过定时发送心跳报文进行状态同步,一旦主节点故障或宕机时,备节点就会触发自动选举逻辑,由优先级最高的节点接管VIP,从而实现故障切换。
基于前述对AWS VPC及EC2网络的理解,在AWS VPC中配置keepalived时,需要考虑以下方面:
- AWS VPC中不支持VRRP组播,需要配置keepalived使用单播模式
- AWS VPC的安全机制不支持使用免费ARP的方式来实现VRRP VIP的动态漂移,必须通过AWS API,将VIP与keepalived master节点绑定
在 VPC 中,VIP的实现方式主要有两个选择。1) 由于ENI可以动态绑定/解绑,我们可以选择使用ENI的主IP承担VIP的角色。2) 实现VIP的另外一个选择是利用辅助IP的动态绑定和解绑能力,来实现VIP在不同节点之间的漂移。这两种方式实现VIP的主要区别如下:
- ENI的绑定/解绑涉及操作系统中网卡的热插拔,流程相对复杂
- ENI需要先完成解绑,然后才能执行绑定操作
- 不是所有的操作系统都支持网卡热插拔
- 即使是支持网卡热插拔的操作系统,在异常情况下可能无法响应热插拔事件;而在触发keepalived主从切换时,操作系统有一定可能处于异常状态
- 虽然EC2 API支持强制绑定解绑ENI(无需通知操作系统),但是这种操作无法确保网卡在操作系统中正常工作
- ENI绑定/解绑操作不具有幂等性,重复解绑/绑定操作API会调用失败
- 辅助IP的绑定/解绑操作较为简单
- 只需一个API调用即可完成辅助IP的重新绑定
- 辅助IP的解绑/绑定API不依赖操作系统的配合
- 辅助IP的绑定操作是幂等的,重复操作不会导致API调用失败
基于以上原因,在本文中我们使用辅助IP的方式来为keepalived提供VIP[注3]。
接下来我们要解决的问题是如何将VIP漂移与keepalived的状态转换联动。我们需要一种触发机制来实现在keepalived节点发生状态变化的同时进行相应的VIP漂移操作。
keepalived可以配置在发生状态转换时执行特定的脚本(参考keepalived文档)。我们只需要在keepalived节点成为VRRP master时将VIP绑定到该节点,这可以通过如下配置实现:
在上面的/path/to_master.sh文件中,我们通过AWS EC2 CLI命令来实现VIP的漂移:
在上面的命令中,我们需要将<eni id>
替换为本节点的ENI ID。并且,该节点需要有访问 EC2 AssignPrivateIpAddresses
API的IAM权限。
使用EC2基于辅助IP实现VIP漂移的配置流程
![]() |
图1 基于辅助IP漂移实现keepalived
我们用一个最小环境来演示使用EC2实例在AWS VPC中配置keepalived的具体操作。在这个例子里面,我们用两台EC2实例运行keepalived,分别作为主、备节点。我们在这两台实例上配置nginx提供一个简单的web页面,用于验证VIP是否成功漂移。我们另外创建一台EC2服务器作为客户端,通过这台EC2服务器来访问VIP。完整的配置包括以下几个部分:
- 创建2个EC2实例用于运行keepalived和nginx web服务器,这两个实例使用相同的子网
- 为keepalived实例的instance profile添加IAM权限,用于绑定/解绑辅助IP
- 创建一个EC2实例用于模拟客户端
- 创建安全组规则,用于keepalived实例之间互相通信和客户端访问keepalived实例web服务。将安全组绑定到各个实例
- 启动keepalived服务,并触发主备切换。分别从客户端访问VIP,验证VIP绑定到了正确的节点
⚠️ 本文中所有示例基于Amazon Linux 2023操作系统,其它发行版请根据实际情况调整相关命令。
一、环境准备
我们将启动两台t3.micro EC2实例,分别作为Master和Backup节点,实现通过虚拟IP (VIP) 的主备切换。
⚠️ 请确认两台实例位于同一子网。
安装keepalived, AWS CLI和nginx
在两台 EC2 实例上分别执行以下命令:
我们另外启动一台t3.micro实例,用于模拟客户端。客户端使用的curl命令已经包含在Amazon Linux 2023系统镜像中,无需额外安装操作。
二、IAM权限配置
在本例中,我们使用EC2 instance profile来为keepalived实例配置操作辅助VIP的权限。您也可以使用其它方式来为keepalived实例提供必要的IAM权限,例如使用AK/SK。要使 EC2 实例具备动态分配 VIP 的能力,需要为两台实例绑定一个包含以下权限的 IAM 角色:
该角色的信任关系需要包含EC2服务,才可以允许绑定到EC2实例上。我们为该角色添加如下信任关系:
⚠️ 请在AWS控制台为Master和Backup实例分别绑定该IAM角色。
三、添加安全组规则
keepalived集群节点之间需要使用VRRP协议进行通信。VRRP协议是独立于TCP/UDP的IP协议,IP协议号为112。我们可以添加安全组入站规则以放行相应的keepalived协议。在VPC中,我们也可以通过使用default安全组实现节点之间的无限制通信,这也是我们在本文中所使用的方式。在VPC中的default安全组中包含一条入站规则,该规则允许来自本安全组的所有流量。这意味着绑定了default安全组的所有网络接口之间的通信不受限制,同时并未开放来自其它源地址或其它安全组的访问。default安全组的这个设计特别适用于集群节点间的相互通信。
⚠️ 我们为Master、Backup节点和客户端节点分别添加绑定default安全组,同时保留原有安全组。
四、创建 VIP 分配脚本
在两台 EC2 实例上分别执行以下命令:
执行以下脚本生成VIP切换脚本文件,并根据你的实际VIP和ENI ID修改:
赋予脚本可执行权限:
sudo chmod +x /etc/keepalived/scripts/vip_master.sh
⚠️ keepalived Master、Backup节点上都需要执行上述操作,并替换ENI ID为该节点的ENI ID
五、创建keepalived配置文件
Master节点配置
执行脚本内容如下:
Backup 节点配置
执行脚本内容如下:
分别在keepalived Master和Backup节点启动keepalived服务和nginx服务:
六、验证VIP漂移
- 验证 VIP 当前绑定在 Master 节点
在 Master 节点上执行以下命令,确认 VIP 10.0.1.100
已绑定到网卡 ens5
:
ip addr show ens5 | grep 10.0.1.100
输出如下,表示 VIP 当前处于 Master 节点:
inet 10.0.1.100/32 scope global ens5
- 创建简单的web页面
在Master节点创建一个简单的页面:
在Backup节点创建一个简单的页面:
- 验证服务访问正常
在客户端节点,使用curl命令向两个keepalived节点分别发起HTTP请求:
curl 10.0.1.101 10.0.1.102
输出如下:
Hello from node 101
Hello from node 102
在客户端节点,使用curl命令向VIP发起HTTP请求:
curl 10.0.1.100
输出如下:
Hello from node 101
以上输出表明VIP目前绑定在节点101上,即Master节点。
- 模拟主节点故障切换
我们可以有多种方式模拟Master节点的故障。keepalived提供多种配置选项用于监控系统的健康情况,比如使用track_script
自定义健康检查脚本。本文中通过停止Master节点的 keepalived服务来模拟Master节点的故障。
在 Master 节点执行:
sudo systemctl stop keepalived
在客户端节点,使用curl命令再次向VIP发起HTTP请求:
curl 10.0.1.100
输出如下:
Hello from node 102
以上输出表明VIP已经成功漂移,目前绑定在节点102上,即Backup节点。
通过以上步骤,成功验证了keepalived在Master节点故障时,能够将VIP漂移到Backup节点,确保服务高可用。
总结与讨论
本博客介绍了如何在AWS VPC内通过辅助IP的方式配置keepalived实现EC2间的VIP漂移,完成主备切换。该方案适用于内网流量高可用需求,配置简单。成为Master的节点会执行脚本,将辅助IP分配到自己的网卡。
讨论
- keepalived集群节点位于同一可用区的不同子网
由于辅助IP漂移仅限同一子网,当keepalived集群节点位于不同子网时,无法直接使用辅助IP作为VIP。在这种情况下,可以通过添加ENI弹性网络接口的方式,使所有集群节点在某个特定子网中都有关联的弹性网络接口,然后修改keepalived配置文件使用该网络接口来实现本文中描述的方案。
- 通过VPC对等连接 (VPC Peering) 、VGW和TGW从VPC外部访问keepalived VIP
由于辅助IP由AWS VPC分配,使用辅助IP作为keepalived VIP时,可以通过VPC Peering、VGW或TGW从外部访问。在必要的网络路由配置之外无需针对VIP进行特殊路由配置。
- 面向公网服务的keepalived集群
通过将Elastic IP关联到用于VIP的辅助IP,我们很容易用以上配置来实现keepalived集群同时对公网提供服务。在辅助IP漂移的同时,Elastic IP会保持与辅助IP关联,同步漂移到新的网卡。需要注意的是 1) keepalived节点需要位于公开子网; 2) keepalived节点安全组入站规则需要允许相应的服务访问。
- 跨可用区的高可用keepalived集群
无论是使用辅助IP还是ENI弹性网卡实现keepalived的VIP,都要求集群节点位于同一个可用区。在一些场景下,业务可能要求VIP可以跨可用区漂移,以实现更高级别的可用性。在VPC网络中,可以使用更新路由表的方式实现跨可用区的VIP漂移。在这种方式下,我们需要在路由表中创建一条路由,目的前缀为VIP,下一跳为keepalived master节点。具体配置方式我们将在另外一个博客中描述。
注释
[注1] 本文不展开讨论路由表的边缘关联 (Edge Association),并且边缘关联仅针对VPC入方向的流量,对子网内流量没有影响。
[注2] VPC边缘网关所关联的路由表仅在报文进入VPC后才会被索引,所以对报文是否能进入VPC没有影响。使用隧道方式实现网络中转(例如中转网关 (Transit Gateway) 的Connect Attachment)没有直接使用VPC路由,并不违反VPC网络不支持中转的原则。
[注3] 在之前的另外一个亚马逊云科技博客文章中有关keepalived的部分使用了ENI弹性网卡作为配置示例,基于本文描述的理由,我们推荐优先考虑使用辅助IP的实现方案。