滚动升级

本文档扩展了 Neo4j 操作手册中的条目 升级因果集群,其中包含有关在 Kubernetes 中滚动升级方法的信息。

开始之前

  1. 在尝试滚动升级之前,请阅读所有这些文档。并非所有相关概念都将在本文档中描述。将假定您熟悉其他页面。

  2. 在类似生产环境中执行测试升级,以获取有关可能需要任何停机时间(如果有)的持续时间的信息。

何时需要此操作?

  • 当您拥有 Neo4j 因果集群时(独立部署不适用)

  • 当您需要升级到 Neo4j 的新次要或修补程序版本时

  • 当您必须在升级过程中保持集群在线并具有读写功能时。

此方法不涵盖哪些内容

在 Neo4j 的主要版本之间移动(例如,3.5 和 4.0)。由于以下因素,这需要更多计划

  • 在 3.5 和 4.0 之间的 Pod 上需要进行大量配置更改

  • 产品功能的重大更改,这些更改会影响客户端可以依赖的内容。

  • 使用的 helm 图表及其结构的更改;如果您使用的是旧的 3.5 helm 图表,则您正在使用的图表与这个存储库之间的差异可能很大。

  • 需要存储升级操作来更改磁盘上 Neo4j 数据的格式

Neo4j 4.0 与 3.5 不向后兼容。建议进行额外的计划和离线升级。

如果您需要从 Neo4j 3.5 迁移到 4.0,请参阅 Neo4j 迁移指南

如果这无法满足您的约束条件,请查看本文档底部的“滚动升级的替代方案”。

高级方法

  1. 进行备份

  2. 扩展核心 StatefulSet,以维持高可用性。

  3. 选择并应用您的更新策略。

  4. 修补 StatefulSet 以应用新版 Neo4j

  5. 监控进程

  6. (可选/如果适用) 也对读取副本 StatefulSet 应用上述流程。

  7. 成功后缩减回原始大小。

我们现在将描述每个步骤、如何执行以及原因。

进行备份

在执行任何主要的系统维护操作之前,务必拥有最新的备份,以确保如果出现任何问题,数据库状态都有一个可以返回的时间点。

此外,所有操作都应在暂存或类似生产的环境中作为“预演”进行测试,然后再在应用程序关键系统上尝试此操作。执行备份在该存储库中的用户指南中进行了介绍。

扩展核心 StatefulSet

如果您通常在 StatefulSet 中拥有 3 个核心成员,它们提供了宝贵的 高可用性目的和仲裁

在滚动升级操作中,我们将依次关闭每个服务器。当一个服务器停止/重新启动时,我们(暂时)会损害集群的 HA 特性,降低其提供查询的能力。为了缓解这种情况,在进行滚动升级之前,我们将集群扩展,例如从 3 个核心扩展到 5 个。然后,我们将通过这些更改进行滚动 - 在任何给定时间,我们都会有 4 个中的 5 个核心可用。

给定一个名为“mygraph”的集群部署,您可以将其扩展到 5 个核心,如下所示

kubectl scale statefulsets mygraph-neo4j-core --replicas=5

这应该会立即安排两个具有相同配置(以及版 Neo4j)的新 Pod 启动并加入集群。建议您按 2 扩展,而不是按 1 扩展,以确保集群中的核心数量始终为奇数。

请记住,当新成员加入集群时,在集群稳定之前,它们需要拉取当前的事务状态。强烈建议首先从最近的备份中恢复成员,以最大程度地减少 追赶过程的负载。

如果您没有在每个 Pod 上从备份中恢复,它仍然可以工作,但集群可能需要大量时间才能让新成员追赶上来,尤其是在您拥有大量数据或事务历史记录的情况下。

有关更多信息,请参阅 Kubernetes 文档中的 扩展 StatefulSet

选择并应用您的更新策略

有关更多详细信息,请参阅 Kubernetes StatefulSet 的更新策略

在接下来的步骤中,我们将告诉 StatefulSet 更改它正在运行的 Neo4j 版本。在我们这样做之前,我们需要为其提供一个关于滚动升级如何进行的策略。您基本上有 2 个主要选项,RollingUpdateOnDelete。本文档假设使用 RollingUpdate 策略。在这种情况下,Kubernetes 执行以下操作

  • 从最后(最高核心编号)开始,它关闭一个 Pod 并重新启动它。因为我们将要修补版本,所以当该 Pod 重新启动时,它将以新版本启动。

  • Kubernetes 等待 Pod 进入 Ready 状态。

  • 滚动更新将继续下一个较低的索引。

就绪/存活性检查的重要性

Kubernetes 对 Neo4j 的了解不多。它需要提供一个关于 Neo4j“就绪”的含义的定义。如果新 Pod 在下一个 Pod 滚动之前没有准备好,您可能会遇到集群在失去更多成员之前没有时间稳定下来的情况。

用户手册中描述的就绪检查涵盖了此目的。在执行滚动升级之前,请检查它们是否适合您的部署,并在必要时进行修改。

修补 StatefulSet

到目前为止,我们所做的一切都只是准备工作,但此步骤实际上会影响更改。如果您运行此操作,那么根据您上面指定的UpdateStrategy,Kubernetes 将开始终止和重新启动 Pod。

NEW_VERSION=neo4j:4.1.0-enterprise
kubectl patch statefulset mygraph-neo4j-core --type='json' \
    -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"'$NEW_VERSION'"}]'

监控进程

我们正在寻找:* 每次只停止/重新启动一个 Pod * 在整个过程中始终能够保持与集群的连接,并具有读写功能。* 监控debug.log文件和容器输出,以确保进程正确进行

(可选) 将流程应用于只读副本

只读副本在第二个 StatefulSet 中处理。尽管如此,应用更新策略、修补 statefulset 和监控的过程是相同的。

建议:确保在处理只读副本之前,您的核心集群成员集已完全迁移并正常运行。不要同时滚动这两个集合。

缩减规模

如果一切正确完成,您最终应该会得到一个包含新版本、100% 在线状态的 5 个成员的集群。成功后,不再需要额外的成员,您可以将集群缩减回原始大小。

kubectl scale statefulsets mygraph-neo4j-core --replicas=3

滚动升级的替代方案

如果您可以在保持完全读取可用性的同时容忍一段时间的写入不可用,Kubernetes 提供了滚动升级的第二个选项。本文档将重点介绍如何进行滚动升级,但作为主要替代方案的概要。

  1. 将您当前的集群配置为由单个 DNS 记录(mycluster.company.com)支持。

  2. 备份您当前的集群。

  3. 启动一个运行新版 Neo4j 的第二个集群(mycluster-updated)。从 mycluster 的上次备份中恢复此集群。

  4. 热交换 DNS 记录以指向第二个集群(mycluster-updated)。

  5. 关闭原始集群(mycluster)。

如果您采用此方法,您将需要一个维护窗口,在此期间您不接受写入,从备份的那一刻开始。写入不可用期间应在步骤 2 和步骤 4 中 DNS 就绪之间。如果在此期间写入到达原始集群,则更新后的集群中将缺少这些写入。

此方法应始终保持读取可用性,并且相当安全;即,如果新集群未能正确迁移或存在数据问题,这不会影响正在运行的生产系统的可用性。