滚动升级的迁移命令¶
在 keystone-manage 中提供滚动升级步骤,以实现零停机数据库升级。
问题描述¶
OpenStack 服务正朝着支持滚动升级的方向发展,目前 nova、neutron 和 swift 已经声称支持。其他服务也在努力实现这一目标(例如 glance)。有关其他服务支持的更多信息,请参阅“参考”部分。在 Newton 之前,keystone 并没有声称支持任何此类功能,但我们决定添加此支持。
首先,重要的是要说明,当人们谈论滚动升级时,实际上涉及两个相互关联的功能:
在多节点服务中,能够逐个节点地滚动升级,同时整体服务保持运行的能力——因此,从定义上讲,允许同时运行新旧节点,并使用相同的数据库。
为服务提供零停机时间,包括在执行 (1) 时,大型数据库迁移期间不临时锁定用户。
在 Newton 中,我们计划支持 (1) 和 (2)。我们已经通过仅允许对数据库进行附加更改来启动对滚动升级的支持(这受到测试的保护)。
为了仅支持滚动升级部分,keystone 将允许(假设我们仅允许对数据库进行附加更改)以下序列
将 keystone 从服务中移除,并将其替换为新版本,但尚未运行它。执行 keystone-manage 命令以升级数据库。等待并确保所有旧节点正常运行。只有在您对情况满意时,才启动运行新版本的进程并逐个节点地将其在线。
通过将其从正在运行的任何代理配置中移除、升级 keystone 并将其重新上线,逐个节点地升级其他节点。由于这已经在 (1) 中完成,因此在这些步骤期间不会发生数据库更改。
为了支持此类滚动升级,一些迁移脚本不能将数据库保留在它们理想状态,例如添加一个新属性,该属性具有需要由代码手动写入的默认值(而不是服务器默认值)。如果在滚动升级期间,通过未迁移的节点创建新的实体,则此新属性将不会获得默认值。这会导致尝试清理此类数据与创建它的进程之间的竞争条件,并且需要新版本的 keystone 了解两种数据模式才能正常运行。请参阅:Bug 1496500。
支持无需服务中断的零停机时间升级,需要 keystone 支持在数据被修改时逐步地动态迁移数据,并支持最终的手动“迁移剩余内容”操作。这种动态支持由 Nova 和 Neutron 在数据库对象层实现,它们支持在旧位置和新位置查找数据。
为了解决这个问题,而无需编写和维护必要的 Python 代码,我们可以依赖数据库触发器。数据库触发器将使我们能够继续针对单个模式编写每个版本,而不管应用程序底层的实际模式如何(该模式至少必须是应用程序知道的模式的超集)。更具体地说,当以前的版本写入其知道的数据库模式时,数据库触发器也会更新新模式。当下一个版本写入其知道的数据库模式时,数据库触发器也会更新旧模式。
这种方法使我们能够消除
下一版本了解先前版本模式的需求(这将给开发人员带来复杂的维护负担,大大提高了新开发人员的入门门槛,并存在相对微妙的错误的风险)。
任何清理操作超出一次性数据迁移的需求。
应用程序在运行时发现模式状态的需求(这提出了许多可能的竞争条件)。
提议的变更¶
我们建议向 keystone-manage 添加新的功能,这些功能可以解决现有的滚动升级问题,并符合整个滚动升级和跨项目零停机时间计划的背景。
似乎其他服务 *-manage 工具用于完全零停机时间支持的实际命令没有太多共同点。为了了解我们提出的初始支持如何符合这种完全支持,以下是升级运行代码版本 X 到 X+1 的多节点配置所需的概念步骤,例如,X+1 将数据从一列移动到新列
一个节点的代码升级到 X+1。运行
<service>-manage db_sync --expand命令,该命令创建新的数据库结构,但不自行迁移任何数据。但是,它会创建数据库触发器以促进实时迁移数据在两种模式版本之间。
在 X+1 节点上,运行
<service>-manage db_sync --migrate以“强制”将所有数据从旧模式迁移到新模式。数据库触发器将继续在运行 X 版本的节点继续写入旧模式时保持旧模式和新模式之间的一致性。升级并重新启动所有剩余节点到 X+1 版本,一次一个。在此过程中,将有多个版本写入数据库,但数据库触发器将使其保持同步。
一旦所有节点都升级并写入新模式,使用
<service>-manage db_sync --contract删除旧模式和触发器。
对于 keystone 在此版本中,我们建议支持以上所有命令
keystone-manage db_sync --expand:通过纯粹的“附加”操作(例如创建新列、索引、表和触发器)扩展数据库模式。这可以在所有节点仍在运行 X 版本时运行。新模式将通过触发器在 X 版本继续写入旧模式时开始填充。
keystone-manage db_sync --migrate:将在所有节点仍在运行 X 版本时,在运行时将数据从旧模式迁移到新模式。keystone-manage db_sync --contract:一旦所有节点都运行 X+1,将删除任何旧模式和触发器。
该 keystone-manage db_sync 命令(没有选项)仍然受支持,首先是为了确保现有的工具和升级流程(不尝试执行滚动升级)将继续运行,其次是为了提供“强制数据库升级完成”的情况,以防部署者在滚动升级时遇到问题。但是,一旦执行了 keystone-manage db_sync 命令(没有选项),则运行旧代码的节点不再受支持。以这种方式运行 keystone-manage db_sync 将执行所有阶段(包括收缩阶段,如果安全的话),并设置数据库迁移状态。这确保了后续版本的滚动更新尝试是可行的。
在实施方面,keystone-manage db_sync --expand、keystone-manage db_sync --migrate 和 keystone-manage db_sync --contract 阶段将由 sqlalchemy-migrate 存储库驱动。
所提出的方法旨在支持在主要发布周期升级的部署者以及更紧密跟踪主分支的部署者。
另一个方面是,与服务一起,我们不支持跨 2 个版本的滚动升级。例如,一旦您正在运行 Newton,我们将不支持直接升级到 P 版本,您需要先升级到 Ocata。
备选方案¶
我们可以只使用 keystone-manage db_sync 作为 --expand 步骤,但由于这仍然会想要打印一个提醒,以运行其他命令,这意味着操作员将没有一组不打印警告的命令(这似乎不是一个好主意,用于生产环境)。
我们可以只使用完全不同的 keystone-manage 命令,而不尝试使其符合总体趋势。
keystone-manage db_sync --initial-migration
keystone-manage db_sync --complete-migration
安全影响¶
无
通知影响¶
无
其他最终用户影响¶
无
性能影响¶
无
其他部署者影响¶
无
开发人员影响¶
开发人员需要了解新的数据库迁移存储库以及每个存储库的要求。
实现¶
负责人¶
- 主要负责人
Henry Nash (henry-nash)
其他指派人:- Dolph Mathews (dolphm) - Dave Chen (davechen)
工作项¶
创建三个新的数据库迁移存储库(expand、migrate、contract)。
更新基础
keystone-manage db_sync(没有选项)以运行来自旧迁移存储库的任何未决迁移,所有--expand迁移,所有--migrate迁移,然后是所有--contract迁移。实施三个新的
keystone-manage db_sync选项,--expand、--migrate和--contract以运行其相应的迁移存储库。向操作员提供有关预期工作流程的文档。
依赖项¶
无。
文档影响¶
需要更新操作员指南。