实例升级¶
Trove 需要解决客户实例如何更新其数据库软件、Trove 客体代理以及底层操作系统的问题。本蓝图提出了一种技术,允许通过将数据卷迁移到基于更新的客体镜像的新实例来更新客体实例。
Launchpad 蓝图:https://blueprints.launchpad.net/trove/+spec/instance-upgrade
问题描述¶
Trove 通过从提供的操作系统镜像创建 nova 实例并将一个卷附加到该实例以保存用户的数据来创建数据库实例。通过使用预配置了数据库软件的已知镜像,操作员可以确保用户获得已知版本的数据库软件,并配置了与该数据库软件版本兼容的操作系统。这种技术消除了许多应用程序配置的歧义,允许操作员向数据库用户提供已发布的的服务级别。
不幸的是,运行中的数据库实例在其生命周期内并非静态的。随着时间的推移,可能需要升级实例以应用安全补丁、新的数据库软件或 Trove 客体代理的更新。云操作员和最终用户必须提供一种将他们的数据库迁移到新的操作环境的方法。
总而言之,数据库实例可能会随着时间的推移受到多种变化的影响,本规范解决了应用这些类型变化的问题。这些包括(但不一定限于):
操作系统安全补丁
数据库安全补丁
数据库版本升级
Trove 客体代理升级
OpenStack 版本升级
操作系统升级
提议的变更¶
系统升级的传统方法是简单地执行系统实用程序,例如“apt-get upgrade”来升级正在运行的系统中的所有或部分内容。对于大型安装,可以使用 Ansible 或 Salt 等工具自动将更改应用于许多系统。这种方法对于数据库即服务来说并不理想,因为它对要升级的组件及其版本控制不足;更新可能会导致数据库实例处于数据库无法正常运行的状态,甚至可能导致数据本身损坏。
至关重要的是,Trove 必须开发一种更新实例的方法,该方法能够高度保证数据库处于安全、一致和可用状态。
为了确保安全一致的状态,本蓝图提出了一种升级实例的技术,该技术使其从一个已知镜像过渡到运行更新软件的新镜像。每个实例状态的完整状态都将被知道。从本质上讲,这种技术涉及分离包含数据库数据的卷,并将其附加到基于不同(更新)镜像的新实例。
Trove 实例的大部分“可变”数据存在于附加的卷上,数据库在其上存储其数据。在这次转换过程中,还需要保留一些操作系统状态,主要包括网络数据(实例名称和 IP 地址)、一些 Trove 配置数据(guest_info.conf 和 trove-guestagent.conf)以及数据库配置数据(例如 /etc/mysql)。
该技术的核心将基于 Nova 提供的 rebuild API。Nova rebuild 函数将正在运行的实例升级到新镜像,确保将网络配置应用于新实例。新创建的实例将使用与从中创建的实例相同的网络配置(ip、主机名和 Neutron 配置)。将添加 Trove 客体功能,以允许客体捕获有关实例的其他状态(主要数据库配置),并在重建后将该状态重新应用于系统。结果将是在运行更新软件的新实例上配置的、可连接的数据库。
升级到哪个镜像的选择将基于当前 datastore_version 机制。本质上,用户将被允许将其实例升级到其数据存储的较新的 datastore_version。将采取保障措施以确保用户选择合适的 datastore_version 进行升级;例如,用户只能将 mysql 实例从 datastore_version 5.5 升级到 5.6,而不能升级到 5.0 或 6.7。
配置¶
不计划进行任何配置更改。
数据库¶
未来的蓝图将概述支持 datastore_versions 上升级约束所需的更改;本规范将仅限于实现升级功能,而不包括约束。
公共 API¶
将添加一个新的 REST API 调用以支持此功能。
REST API:PATCH /instances/<instance id> REST body
{
"instance": {
"datastore_version": "<datastore_version_uuid>"
}
}
REST 结果
{}
REST 返回代码
202 - Accepted。400 - BadRequest。服务器无法理解请求。404 - Not Found。未找到 <datastore_version_id>。
公共 API 安全¶
没有预见的安全性影响。
Python API¶
将在 trove API 中实现一种新方法。此方法将升级实例到由提供的 datastore_version 指定的镜像。
upgrade(instance, datastore_version)
- 实例
要升级的实例
- datastore_version
trove 实例将升级到的数据存储版本,或其 ID
CLI (python-troveclient)¶
将实现一个新的 CLI 调用。此新调用将升级实例到由提供的 datastore_version 指定的镜像。
trove upgrade <instance> <datastore_version>
- 实例
要升级的实例
- datastore_version
实例将升级到的数据存储版本
内部 API¶
将添加一种新方法以支持此功能。
def upgrade(self, instance_id, datastore_version_id):
LOG.debug("Making async call to upgrade guest to %s "
% datastore_version_id)
cctxt = self.client.prepare(version=self.version_cap)
cctxt.cast(self.context, "upgrade", instance_id=instance_id,
datastore_version_id=datastore_version_id)
Guest Agent¶
将在客体代理 API 中实现两个新的操作。预计每个数据存储将(可选地)覆盖这些方法以实现镜像升级之前和之后所需的任何功能。例如,Mysql 将使用这些方法将配置数据从 /etc/mysql 复制到数据卷,并在镜像升级后将其复制回去并重新启动 mysql 服务器。
预计 pre_upgrade 方法将验证是否可以执行请求的升级;例如,实例可能指定了与新的 datastore_version 不兼容的配置覆盖。如果无法执行升级,pre_upgrade 方法将引发异常 - 任何异常都将导致任务管理器中止该实例的升级过程。
def pre_upgrade(self):
"""Prepare the guest for upgrade."""
LOG.debug("Sending the call to prepare the guest for upgrade.")
return self._call("pre_upgrade", AGENT_HIGH_TIMEOUT, self.version_cap)
def post_upgrade(self, upgrade_info):
"""Recover the guest after upgrading the guest's image."""
LOG.debug("Recover the guest after upgrading the guest's image.")
self._call("post_upgrade", AGENT_HIGH_TIMEOUT, self.version_cap)
有两种机制可供 pre_upgrade 与 post_upgrade 通信信息。首先,从 pre_upgrade 步骤返回的值将作为 *upgrade_info* 参数传递给 post_upgrade 步骤;客体可以根据需要自由使用此值,但通常用于交换配置数据字典。客体将使用的第二个机制是通过将配置数据存储在数据卷上来传递信息;这通常用于大型配置文件。
预计如果 Nova rebuild 命令在开始重建过程之前没有返回异常,则重建将成功。如果重建失败,实例将被移动到 ERROR 状态,并且不会尝试恢复实例;需要操作员干预。如果 post_upgrade 返回异常,实例将过渡到 ERROR 状态。
备选方案¶
升级镜像的替代方法是通过 apt-get 或 yum 在正在运行的实例中进行升级。虽然这是升级实例的正常过程,但它对 Trove 具有不良影响。Trove 旨在提供已知的服务级别,但升级正在运行的实例可能会导致实例处于未知状态。还可能存在有关不允许 Trove 实例直接访问互联网的安装问题,因为 Trove 将不得不提供一种机制来传递更新实例所需的所有 deb/rpm 包。
Dashboard 影响 (UX)¶
待定
实现¶
负责人¶
- 主要负责人
6-morgan
里程碑¶
- 完成目标里程碑
Newton
工作项¶
此功能已经过原型验证。将原型与本规范保持一致的工作包括:
原型使用镜像 ID 而不是 datastore_version
添加 trove.upgrade.start/end/error 通知
实现单元测试
调查是否需要更新此功能的集成测试
记录升级过程
升级影响¶
依赖项¶
n/a
文档影响¶
“trove upgrade”命令及其相应的 python API 需要进行记录。
参考资料¶
n/a
附录¶
n/a