Report HA Router Master¶
https://blueprints.launchpad.net/neutron/+spec/report-ha-router-master
高可用路由器是一个新的功能,它被合并到 l3-high-availability 蓝图中。HA 路由器被调度到多个 L3 代理上,但是云操作员无法知道哪个实例是活动的。
问题描述¶
云操作员可以知道哪些 L3 代理正在提供路由器,但不知道哪个实例是活动的。传统路由器可以手动从一个代理移动到另一个代理。对于 HA 路由器,相当于移动活动实例,但目前这还不可能。第一步是知道活动实例的位置,这将在本蓝图中解决,但是设置活动实例的位置不在本范围之内,将在未来解决。
操作员可能希望执行节点维护,这可以通过手动将路由器从节点上移动来协助完成。同样,操作员可能希望在故障转移后查看路由器的状态(活动实例是否真的发生了故障转移?)。
提议的变更¶
l3-agent-list-hosting-router <router_id>
当前显示托管路由器的所有 L3 代理。现在它还将显示所述路由器在每个代理上的 HA 状态(活动、待机或故障)。
+-----------+------+----------------+-------+----------+
| id | host | admin_state_up | alive | ha_state |
+-----------+------+----------------+-------+----------+
| 534c4b37- | net1 | True | :-) | active |
| da2730c6- | net2 | True | :-) | standby |
| 7abcd991- | net3 | True | xxx | fault |
+-----------+------+----------------+-------+----------+
Keepalived 不支持查询当前 VRRP 状态的方式。因此,唯一的方法是使用通知脚本。这些脚本在状态转换发生时执行,并接收新的状态(主、备份、故障)。
每次我们重新配置 keepalived(当路由器被创建或更新时),我们都会告诉它执行一个 Python 脚本(该脚本作为仓库的一部分维护)。
该脚本将
将新的状态写入到 $state_path/ha_confs/router_id/state 中的一个文件
通过 Unix 域套接字通知代理发生了转换。之所以第一步会在脚本中发生,而不是在代理收到通知后发生,是因为我们希望记录下每次状态转换,这样即使代理关闭也不会丢失。keepalived 不提供查询当前状态的方式,因此,如果发生了状态转换但我们未能将其写入,那么该信息将永久丢失。
L3 代理将在收到通知时启动和停止元数据代理。这样可以节省内存使用量,仅在活动实例上启用代理。这在规模化时非常重要,因为每个代理占用 20+ MB 的内存。
L3 代理将在 T 秒内批量处理这些状态更改通知。当 T 秒过去且没有收到新的通知时,它将向服务器发送一个 RPC 消息,其中包含路由器 ID 到该特定代理上的 VRRP 状态的映射。其工作方式是,一旦代理收到事件,它就会将所有未来的事件在 T 秒内批量处理。当定时器触发时,它会将所有状态更改以单个消息发送到控制器。此外,每次代理启动时,它都会获取调度到代理上的路由器列表。代理现在将循环遍历所述路由器,从磁盘收集它们的 HA 状态并更新服务器。这是为了捕获代理关闭时可能发生的状态更改。如果路由器在批量处理期间多次更改状态,代理将仅发送最新的状态。
如果管理网络暂时中断,或者代理与管理网络断开连接,则将重试发送的 RPC 消息。
服务器将在收到 RPC 消息后持久化此信息:表已经为此设置好了。每个路由器在其被调度的每个代理上都有一个 HA 绑定表中的条目,并且该记录包含该特定代理上的 VRRP 状态。控制器还将持久化上次接收到状态更改的时间,以便在分脑情况下,管理员可以通过观察时间戳来了解哪个是“真正的”主节点。
可选地*,服务器将查找已死代理(一段时间内没有发送心跳),并将它们的 HA 路由器标记为关闭。这将有助于主要用例,即超visor 死亡(当然无法报告任何状态更改),并且另一个超visor 托管所有路由器。在这种情况下,API 将在服务器注意到第一个代理死亡并将其路由器标记为关闭之前,为两个机器上的所有路由器返回“活动”。
这是一个可选的增强功能,如果我们在发现它正确之后可以添加。
数据模型影响¶
每个路由器到代理绑定的 HA 状态都持久化在 L3HARouterAgentPortBinding 表中。当前未使用。为了添加时间戳以及“故障”状态,需要进行数据库迁移,因为当前只能持久化“活动”和“待机”。
REST API 影响¶
l3-agent-list-hosting-router 现在将返回一个额外的列,对于 HA 路由器可以是“活动”、“待机”或“故障”,对于其他类型的路由器可以是 None。
安全影响¶
keepalived 以 root 身份运行,它调用的转换脚本也以 root 身份运行。转换脚本通过 Unix 域套接字与代理通信。
通知影响¶
无。
其他最终用户影响¶
python-neutronclient 将支持新的 ha_state 列。当收到适当的响应时,它将显示“活动”、“待机”或“故障”。如果旧服务器收到 None 或对于非 HA 路由器,将显示“-” 。
性能影响¶
假设有两个 L3 代理和每个代理托管 1,000 个路由器,从节点 1 到节点 2 的故障转移应该只会引起从节点 2 到服务器的一个 RPC 调用,以及一个数据库事务。
IPv6 影响¶
无。
其他部署者影响¶
无。
开发人员影响¶
无。
社区影响¶
无。
备选方案¶
与其让 neutron-keepalived-state-change 通过 Unix 域套接字通知代理,不如让代理每 T 秒轮询所有 HA 路由器的状态。然后它将比较新的状态与缓存的副本,并通知服务器任何更改。有人可能会认为这更容易实现和维护,但性能较差。
实现¶
负责人¶
- 主要负责人
Assaf Muller <amuller>
工作项¶
当前的 keepalived 通知 bash 脚本是内联生成的。现在它们将是作为仓库的一部分维护的 Python 脚本。该脚本将作为 neutron-keepalived-state-change 提供,并由 keepalived 调用。
首先,该脚本将复制现有 bash 脚本的行为:将新的状态写入磁盘并启动或关闭元数据代理。
该脚本还必须通过 Unix 域套接字通知代理状态更改。启动和停止元数据代理将被移动到代理。
更新 HA 路由器状态的 RPC 消息将被实现(它实际上已经存在,但没有更改格式就无法使用)。
代理会将状态更改通知批量处理到一个 RPC 消息中。Nova 通知机制会批量处理通知,并且代码将被重用。
API 必须暴露新的 ha_state 列。
L3 代理必须在启动后报告 HA 状态。
通过数据库迁移补丁添加故障状态和状态更改时间戳。
可选:控制器将查找已死代理并将它们的 HA 路由器移动到故障状态。
依赖项¶
无。
测试¶
Tempest 测试¶
L3 HA 无法在 Tempest 中进行测试,除非有对多节点的支持。L3 HA 是在引入树内集成测试时首先要测试的候选对象,通过 integration-tests 蓝图。
功能测试¶
L3 代理已经有功能测试。将添加两个新的测试
当发生状态更改时,确认通知到达代理。
当发生多个状态更改时,确认 RPC 调用以预期的参数发送到服务器。
API 测试¶
RPC 和 DB 方法将使用单元测试进行测试。
文档影响¶
API 和 CLI 的更改需要文档。
用户文档¶
CLI 客户端文档必须更新。
开发人员文档¶
Neutron API 更改必须记录下来。