Vertica 集群节点操作系统升级最佳实践¶
编译:JiangChong
原文:Best Practices for Upgrading the Operating System on Nodes in a Vertica Cluster(2023-06-28)
📝 文章说明:本文基于 Vertica 官方 KB 原文翻译整理。原文仅讨论了三种通用方案(Copy Cluster、全集群停机升级、升级后恢复备份),未区分 Enterprise / Eon 两种运行模式,也未涉及 Eon 模式下的子集群滚动升级。译者根据当前 Vertica 技术架构(v26.2),补充了 Eon 子集群逐组滚动升级、Enterprise 逐节点升级、Enterprise 分批次升级 三种新方案,并新增了方案对比总表、选型决策框架和升级前参数调整指南。新增内容位于「Eon 模式下的滚动升级方案」至「选型决策框架」章节。
在某些时候,您可能需要升级 Vertica 集群节点上的操作系统或 Linux 内核。本文档说明了完成升级应遵循的步骤。
注意: 本文档不讨论升级 Vertica 版本。它仅涉及操作系统或内核升级。您的数据库版本不会改变。
开始之前¶
在准备系统升级时,应考虑以下常见约束:
- 确认计划升级的操作系统受您当前运行的 Vertica 版本支持。
- 您可能需要在升级期间保持集群运行。
- 操作系统升级可能需要重启一个或多个节点。
在升级操作系统或内核之前,执行以下任务:
- 备份 Vertica 数据库和操作系统。
- 始终将操作系统升级到 Vertica 支持的版本。
- 在生产环境应用之前,先在预演系统上测试升级步骤。
- 在升级操作系统之前,按照准备 Vertica 数据库进行维护中的步骤操作。虽然这些步骤侧重于为数据库升级做准备,但它们同样适用于操作系统的升级。
操作系统升级选项¶
原文描述了三种操作系统升级选项:
- 使用 Copy Cluster 双集群方案
- 停机期间升级所有节点
- 升级集群并恢复备份
使用 Copy Cluster 双集群方案¶
当需要复制现有 Vertica 集群时,可使用 copy cluster。在此场景中,复制源集群的目标集群运行已升级的操作系统。
使用 copy cluster 是最快的选项,您可以在复制目标期间保持现有集群运行。但是,将用户应用程序从源集群切换到目标集群可能需要重置连接,带来短暂停机。
Copy cluster 方案需要搭建一个全新的集群,运行新的操作系统。您必须有可用的硬件来短期运行两个集群。如果您运行在虚拟化基础设施上,copy cluster 可能是最佳选择。
要执行 copy cluster 操作,请按照在相似的 Vertica 集群之间复制数据中的步骤操作。
停机期间升级所有节点¶
在系统停机期间升级所有节点是升级到新操作系统的传统方式。但是,关闭整个集群进行升级可能不方便。步骤如下:
- 备份数据库和操作系统。
- 关闭 Vertica 集群。
- 升级所有节点上的操作系统。
- 重启节点。
- 重新启动 Vertica 集群。
升级集群并恢复备份¶
前两个选项的变体:您可以升级集群,然后将数据库备份恢复到同一集群。当 Vertica 与操作系统位于同一文件系统时,使用此选项。按照以下步骤操作:
- 备份数据库和操作系统。
- 关闭 Vertica 集群。
- 升级所有节点上的操作系统。
- 重启节点。
- 从备份恢复 Vertica 集群,如从 Vertica 集群复制和恢复数据到备份中所述。
此选项的效率不如前两个选项,但如果在操作系统升级后出现错误、意外损坏或节点丢失,则可能需要这样做。在这些情况下,必须依靠备份来恢复数据库。
Eon 模式下的滚动升级方案¶
Eon 模式计算与存储分离的架构特性使得可以在不关闭整个数据库的前提下,逐子集群排空连接后升级操作系统。但升级过程中集群内短暂存在不同 OS 版本的节点,建议在维护窗口内执行,非官方推荐的不停业务方案。
Eon 架构优势¶
| 特性 | Enterprise 模式 | Eon 模式 |
|---|---|---|
| 数据存储位置 | 各节点本地磁盘 | 公共存储(S3/MinIO/HDFS) |
| 计算与存储 | 耦合 | 分离 |
| 升级时数据恢复方式 | buddy projection 补齐(网络传输) | Catalog 从公共存储同步,Depot 数据持久在磁盘直接可用 |
| 子集群隔离 | 不适用 | 支持(工作负载隔离 + 维护隔离) |
| Sandbox 隔离测试 | 不适用 | 支持(独立演进、可回退) |
升级前参数调整¶
在开始滚动升级前,建议调整以下参数以避免节点因 OS 重启时间过长被集群误判为故障而驱逐:
-- 1. 增大 Spread Token 超时(单位:毫秒),防止 OS 重启期间被误判为网络故障
-- 建议值:预计最长节点重启时间 + 5 秒缓冲
SELECT SET_SPREAD_OPTION('TokenTimeout', '35000'); -- 35 秒(默认 8-25 秒)
-- 2. 增大心跳间隔(单位:秒),防止节点在重启期间被自动驱逐
-- 节点连续 5 次心跳失败后会被驱逐,即驱逐时间 = DatabaseHeartBeatInterval × 5
SELECT SET_CONFIG_PARAMETER('DatabaseHeartBeatInterval', 300); -- 300 秒(默认 120 秒)
-- 3. 确认 K-safety 状态和节点依赖关系
SELECT GET_NODE_DEPENDENCIES();
SELECT current_fault_tolerance FROM system;
升级完成后记得恢复:将上述参数恢复为原值,避免正常故障检测延迟。
参考:Spread 超时和心跳机制详见 Vertica 26.2.x 官方文档(TokenTimeout 和 DatabaseHeartBeatInterval 小节)。
Eon 子集群逐组滚动升级方案¶
适用场景:Eon 模式集群,希望避免全集群停机、改为分阶段升级。相比全集群停机,此方案只需逐子集群排空连接,数据库本身不关闭。但升级窗口内集群节点会短暂运行不同 OS 版本,建议安排在维护窗口,排空目标子集群的业务连接后再执行。
前置条件:
- 集群至少有两个子集群(否则无法在关闭一个子集群时由其他子集群继续服务)
- 目标子集群上的所有会话可以被排空(drain)或迁移
- 关闭目标子集群不会导致分片订阅丢失(所有分片仍有其他节点订阅)
💡 只有单个子集群怎么办? 如果集群只有一个子集群(如仅有
default_subcluster),无法按子集群粒度逐组升级,但仍可利用 Eon 架构做节点级滚动升级:不关闭整个子集群,而是逐个停止节点 → 升级 OS → 重启,也可参照分片订阅关系分批次并行升级(与 Enterprise 按节点依赖关系分批逻辑类似,但约束是分片订阅而非 buddy projection)。与 Enterprise 逐节点升级相比,Eon 节点重启后数据直接从公共存储恢复(无需 buddy projection 网络传输),恢复更快。具体步骤参考下方 Enterprise 模式下的不停库升级章节,但数据恢复路径不同(公共存储 vs buddy projection)。
操作步骤:
-- 第 0 步:确认 Primary 子集群数量。如果目标子集群是 Primary 且是唯一的 Primary,
-- 必须先提升一个 Secondary 为 Primary,确保降级后集群仍有 Primary 可写入
SELECT DISTINCT subcluster_name, is_primary FROM nodes ORDER BY subcluster_name;
-- 第 1 步(如需要):提升一个 Secondary 为 Primary,作为接替
-- 仅当目标子集群是唯一的 Primary 时需要此步
SELECT PROMOTE_SUBCLUSTER_TO_PRIMARY('another_secondary_sc');
-- 第 2 步:如果目标子集群仍是 Primary,降级为 Secondary
SELECT DEMOTE_SUBCLUSTER_TO_SECONDARY('target_sc');
-- 第 3 步:排空目标子集群的连接(Eon 专属功能)
-- timeout > 0:等待该秒数后强制关闭剩余连接
-- timeout = 0:立即关闭所有活跃会话
-- timeout < 0:标记为 draining,无限等待所有会话自然结束
SELECT SHUTDOWN_WITH_DRAIN('target_sc', 300);
-- 第 4 步:在目标子集群的所有节点上执行 OS 升级
-- (SSH 到各节点,执行 yum update / apt upgrade / 内核升级等)
-- 第 5 步:重启目标子集群
-- 节点从公共存储同步 Catalog,Depot 数据持久在磁盘,重启后直接可用
-- 停机期间发生的写入/更新会导致部分 Depot 数据过期,需从公共存储补齐变更
$ admintools -t restart_subcluster -d <dbname> -c target_sc -p <password>
-- 第 6 步:验证
-- 逐节点运行 vertica.local_verify 检查 OS 参数兼容性
$ /opt/vertica/oss/python/bin/python -m vertica.local_verify
-- 第 7 步(如需要):恢复原始 Primary 拓扑
-- 如果在第 1 步提升了替代 Primary,视需要将原目标子集群重新提升
SELECT PROMOTE_SUBCLUSTER_TO_PRIMARY('target_sc');
-- 第 8 步:对下一个子集群重复上述步骤
关键注意事项:
- ⚠️ 双主集群关闭前必须先降级:直接
SHUTDOWN_SUBCLUSTER()或admintools -t stop_subcluster关闭主子集群会导致整个数据库变为只读(READONLY),详见 Eon双主子集群的注意事项。 - ⚠️ 分片订阅覆盖:Eon 模式中,每个分片(shard)必须有至少一个订阅节点处于 UP 状态。关闭子集群前确认:
SELECT * FROM v_monitor.shard_subscriptions WHERE subscription_state = 'ACTIVE';—— 如果目标子集群的节点是某些分片的唯一订阅者,关闭后将导致数据库 READONLY。 - ⚠️ Depot 数据持久化在磁盘:子集群重启后 Depot 数据不会丢失(存储在本地磁盘,非内存),无需重新从公共存储全量拉取。但重启期间集群上发生的写入/更新会导致部分 Depot 数据过期,重启后需要从公共存储补齐变更部分。监控 Depot 命中率:
SELECT * FROM v_internal.dc_depot_fetches; - ⚠️ 逻辑相邻节点:Eon 模式中同一分片的订阅节点被称为「逻辑相邻」。如果逻辑相邻节点同时宕机,集群进入 READONLY。因此不要同时升级同一分片的所有订阅节点。
Enterprise 模式下的不停库升级¶
适用场景:Enterprise 模式集群,K-safety ≥ 1,希望减少停机窗口但不能接受全集群停机。
原理:Enterprise 模式下,K-safety 决定了集群可容忍的同时故障节点数。K-safety=1 时,可以逐节点(每次一个)或逐批次(每次一批)停止、升级、重启,如果操作过程中没有停业务,则由 buddy projection 在节点恢复时自动补齐停机时新增数据。
数据量与恢复时间的关系¶
Enterprise 逐节点升级的恢复时间由两个阶段构成:
- 节点启动时间:取决于节点本地数据量(ROS 容器数)和 Catalog 大小,数据越多启动越慢
- 数据恢复时间:仅当升级期间未停业务时产生——停机期间集群上发生的写入/更新/删除,需要在节点重启后从 buddy projection 补齐。停业务则无此阶段
| 场景 | 恢复耗时 = | 影响因素 |
|---|---|---|
| 停业务升级 | 节点启动时间 | 节点数据量 + Catalog 大小 |
| 不停业务升级 | 节点启动时间 + 停机期间新增数据的恢复时间 | 上述 + 停机期间的写入量 |
不停业务时,写入量越大、停机越久,恢复时间越长。这也是大数据量场景下建议停业务全量升级的另一个原因——不仅启动慢,还要追增量。
数据规模参考(停业务场景,仅启动时间):
| 单节点数据量 | 启动耗时(估算) | 3 节点集群串行总耗时 | 建议 |
|---|---|---|---|
| < 1 TB | 分钟级 | < 1 小时 | 逐节点滚动升级可行 |
| 1-10 TB | 数十分钟 | 2-4 小时 | 建议维护窗口内执行 |
| 10-50 TB | 1-3 小时 | 4-10 小时 | 考虑分批次升级 |
| > 50 TB | 3 小时以上 | > 10 小时 | 建议停业务全量并行升级 |
不停业务时还需叠加增量数据恢复时间。数据量大且写入频繁的场景,逐节点串行耗时极易失控。
分批次升级(按节点依赖关系)¶
不能停业务且数据量较大时,可以利用 GET_NODE_DEPENDENCIES() 识别哪些节点组合不能同时停止,分批并行升级以缩短总耗时。
原理:输出采用位图编码,每一位代表一个节点。1 表示该节点持有对应 segment 的副本。多节点组合(如 000011)的 cnt 表示刚好由该组节点覆盖的 segment 数量——同时停掉这些节点会丢失 cnt 个 segment。
⚠️ 关键约束:单批停止节点数必须远少于半数,否则存在脑裂风险。
示例:6 节点集群,K-safety=1
SELECT GET_NODE_DEPENDENCIES();
-- 输出(位图从右到左对应 node0001 ~ node0006):
Deps:
000011 - cnt: 30
000110 - cnt: 30
001100 - cnt: 30
011000 - cnt: 30
110000 - cnt: 30
100001 - cnt: 30
111111 - cnt: 13
000001 - name: v_db_node0001
000010 - name: v_db_node0002
000100 - name: v_db_node0003
001000 - name: v_db_node0004
010000 - name: v_db_node0005
100000 - name: v_db_node0006
解读 — 环形拓扑:
6 个两节点组合(每个 cnt:30)恰好构成一个环:node1 ↔ node2 ↔ node3 ↔ node4 ↔ node5 ↔ node6 ↔ node1。每个节点与环上前后两个邻居都有共享 segment——即每个节点同时是两个 buddy pair 的成员:
关键结论:停止任意一个节点,它的两个邻居都不能同时停。比如停 node0001 后,node0002 和 node0006 都不能加入同一批。
111111(cnt:13)是 UNSEGMENTED projection,6 个节点各自持有完整副本,停任意节点不影响。
规划分批:6 节点环,每次停 2 个(保留 4 个 UP),需确保每批内的两个节点在环上不相邻。一种可行的分割是 {1,4} → {2,5} → {3,6}:
# ===== 第 1 批:node0001 + node0004 =====
# 环上不相邻(1的邻居是2和6,4的邻居是3和5),且不在任何两节点组合中
$ admintools -t stop_node -s node0001_IP,node0004_IP
$ ssh node0001 "yum update -y && reboot"
$ ssh node0004 "yum update -y && reboot"
$ admintools -t restart_node -s node0001_IP,node0004_IP
-- 等待两个节点全部恢复为 UP
SELECT node_name, node_state FROM nodes WHERE node_name IN ('node0001','node0004');
# ===== 第 2 批:node0002 + node0005 =====
$ admintools -t stop_node -s node0002_IP,node0005_IP
# ... 同上步骤 ...
# ===== 第 3 批:node0003 + node0006 =====
$ admintools -t stop_node -s node0003_IP,node0006_IP
# ... 同上步骤 ...
每批节点数规律:每批最多 = (N-1)/2 取整数部分(法定人数约束:停节点数必须小于总数的一半)。依赖关系方面,GET_NODE_DEPENDENCIES() 中 cnt > 0 的两节点组合不能同时出现在同一批内。
| 节点总数 | 每批最多(安全值) | 批次数 | 说明 |
|---|---|---|---|
| 3 | 1 | 3 | 单节点串行,最安全 |
| 4 | 1 | 4 | 不能同时停2个节点,会脑裂 |
| 5 | 2 | 3 | 每批最多 2 个,3 个 UP 保持法定人数 |
| 6 | 2 | 3 | 每批最多 2 个,4 个 UP 保持法定人数 |
| 7 | 3 | 3 | 每批最多 3 个,4 个 UP 保持法定人数 |
| 8 | 3 | 3 | 每批最多 3 个,5 个 UP 保持法定人数 |
| 9 | 4 | 3 | 每批最多 4 个,5 个 UP 保持法定人数 |
| 10 | 4 | 3 | 每批最多 4 个,6 个 UP 保持法定人数 |
| N | (N-1)/2 取整数部分 | N≤4 时为 N 批,N≥5 时为 3 批 | 停节点数必须小于总数的一半,即不超过 (N-1)/2 |
逐节点升级操作步骤¶
前置条件:
- K-safety ≥ 1(检查:
SELECT current_fault_tolerance FROM system;) - 每个节点有足够的磁盘空间容纳恢复期间的数据变更
- 升级前完成全量备份(见 Vertica 备份与恢复方案总览)
操作步骤:
-- 第 0 步(升级前):全量备份 + 维护准备
-- 第 1 步:调整 Spread 超时和心跳间隔(同上 Eon 方案)
SELECT SET_SPREAD_OPTION('TokenTimeout', '35000');
SELECT SET_CONFIG_PARAMETER('DatabaseHeartBeatInterval', 300);
-- 第 2 步:对每个节点依次执行以下子步骤
-- 假设集群有 3 个节点,按 node01 → node02 → node03 顺序执行:
-- 2a. 停止目标节点上的 Vertica
$ admintools -t stop_node -s <node_IP>
-- 2b. 确认节点状态为 DOWN,集群仍在运行
SELECT node_name, node_state FROM nodes;
-- 2c. 升级该节点的操作系统(yum update / 内核升级等)
-- 2d. 重启节点(OS 重启完成后,继续下一步)
-- 2e. 重新启动该节点的 Vertica
$ admintools -t restart_node -s <node_IP>
-- 节点自动从 buddy projection 恢复数据
-- 2f. 等待该节点恢复完成,状态变为 UP
SELECT node_name, node_state FROM nodes WHERE node_name = '<node_name>';
-- 2g. 验证该节点
$ ssh <node_IP> "/opt/vertica/oss/python/bin/python -m vertica.local_verify"
-- 2h. 等待下一个节点前确认集群健康
SELECT node_name, node_state FROM nodes WHERE node_state != 'UP';
-- 应返回 0 行(所有节点 UP)
关键注意事项:
- ⚠️ K-safety=0 不可用:如果集群 K-safety=0,任何节点宕机都会导致数据库关闭。此时只能使用原文的「停机期间升级所有节点」方案。
- ⚠️ 逐节点/逐批等待恢复完成:必须在上一节点(或上一批)完全恢复后才能开始下一轮,否则可能突破 K-safety 容忍度。
- 恢复耗时估算见上方「数据量与恢复时间的关系」表格;节点恢复机制详见 Vertica 节点恢复过程。
方案对比总表¶
| 维度 | Copy Cluster (双集群) |
全集群停机升级 | 升级 + 恢复备份 | Eon 子集群 滚动升级 |
Enterprise 逐节点升级 |
Enterprise 分批次升级 |
|---|---|---|---|---|---|---|
| 适用模式 | 通用 | 通用 | 通用 | 仅 Eon | 仅 Enterprise | 仅 Enterprise |
| 停机时间 | 极短(连接切换) | 完全停机 | 完全停机 | 逐子集群排空(数据库不关闭,不建议承载业务) | 部分停机(每次一个节点) | 逐批排空(每批 ≤ (N-1)/2 取整数部分,保持法定人数) |
| 硬件需求 | 2 倍(两套集群) | 1 倍 | 1 倍 | 1 倍 | 1 倍 | 1 倍 |
| 数据复制/迁移 | 需要 copy cluster | 无 | 需要恢复备份 | 无(数据在公共存储) | 节点自动恢复 | 节点自动恢复 |
| 风险等级 | 低(可提前验证目标集群) | 高(无回退能力) | 中(有备份兜底) | 低(逐子集群、可回滚) | 中(依赖 K-safety) | 中(依赖节点依赖关系分析准确性) |
| 总耗时 | 中(copy cluster 耗时) | 短(并行升级) | 中(+ 恢复耗时) | 中(串行子集群) | 长(串行逐节点) | 中(并行批次,N≥5 时约 3 批) |
| 需要 rebalance | 否 | 否 | 否 | 否 | 否 | 否 |
| 回滚方案 | 切回源集群 | 从备份恢复 | 从备份恢复 | 恢复升级前快照 / 子集群回退 | 从备份恢复 / 逐节点回退 | 从备份恢复 / 逐批回退 |
| 重启后存储恢复 | 不涉及(新集群独立存储) | Catalog 同步 + Depot 验证(磁盘持久,无全量拉取) | 从备份恢复(取决于备份大小) | Catalog 同步 + Depot 验证(仅补齐停机期间变更) | buddy projection 补齐(网络传输) | buddy projection 补齐(网络传输) |
| K-safety 要求 | 不适用 | 不适用 | 不适用 | 所有分片有订阅 | 必须 ≥ 1 | 必须 ≥ 1 |
选型决策框架¶
按以下决策树选择最适合的升级方案:
您需要升级集群节点的操作系统
│
├─ 集群是 Eon 模式?
│ ├─ 是 →
│ │ ├─ 有硬件搭建第二套集群?→ Copy Cluster(最稳妥)
│ │ ├─ 有多个子集群、可逐组升级?
│ │ │ └─ 是 → Eon 子集群逐组滚动升级(数据库不关、建议维护窗口执行)
│ │ └─ 只有单个子集群?
│ │ ├─ 能接受逐节点升级?→ Eon 节点级滚动升级(逐节点或按分片订阅关系分批次,数据从公共存储恢复)
│ │ └─ 不能 → 全集群停机升级(最简单)
│ │
│ └─ 否(Enterprise 模式)→
│ ├─ 能停业务 →
│ │ └─ 全集群停机并行升级(总耗时最短,最简单)
│ ├─ 不能停业务 →
│ │ ├─ K-safety = 0?→ 无法不停库升级,只能 Copy Cluster 或接受停机
│ │ ├─ 有硬件搭建第二套集群?→ Copy Cluster(最稳妥)
│ │ ├─ 数据量小(< 10TB)→ 逐节点滚动升级(恢复耗时短,可行)
│ │ ├─ 数据量大(> 50TB)→ 分批次升级(按依赖关系分组并行)
│ │ └─ 数据量中等 → 逐节点或分批次均可,按维护窗口灵活选择
│ │
└─ 核心原则:1、能停业务就全量并行,不能停则根据数据量和节点数选择逐节点或分批次;2、操作前做好备份。
升级后¶
升级操作系统后,检查是否存在需要根据 Vertica 安装要求实施的操作系统变更。执行此检查的命令:
# 单节点
$ /opt/vertica/oss/python/bin/python -m vertica.local_verify
# 批量检查所有节点
$ for host in $(grep -P "^v_" /opt/vertica/config/admintools.conf | awk '{print $3}' | awk -F, '{print $1}'); do
echo "==== $host ===="
ssh $host "/opt/vertica/oss/python/bin/python -m vertica.local_verify"
done
vertica.local_verify会检查内核参数(vm.dirty_ratio、vm.min_free_kbytes等)、文件系统挂载选项、SELinux 状态等是否符合 Vertica 安装要求。
升级后必做项:
- ✅ 恢复 Spread TokenTimeout 和 DatabaseHeartBeatInterval 为原值
- ✅ 逐节点运行
vertica.local_verify - ✅ 检查
vertica.log无异常报错 - ✅ 运行代表性业务查询,确认性能正常
- ✅ 监控 Depot 命中率(Eon 模式):
SELECT * FROM v_internal.dc_depot_fetches;
更多信息¶
- 安装操作系统前的准备 — Vertica 官方安装指南
- 准备 Vertica 数据库进行维护 — 维护前完整准备流程
- 在相似的 Vertica 集群之间复制数据 — Copy Cluster 操作细节
- Vertica 26.2.x Eon 模式文档 — 子集群管理、drain 章节
- Vertica 26.2.x 管理员指南 — 节点启停、替换、故障恢复
扩展阅读¶
- Vertica 维护前准备 Checklist — 升级前必做的维护准备步骤
- Vertica 备份与恢复方案总览 — 备份策略与恢复方案
- Vertica 弹性伸缩功能介绍与配置 — Eon 子集群管理、弹性伸缩
- Vertica 节点恢复过程 — Enterprise 模式节点自动恢复机制
- Eon双主子集群的注意事项 — 双主子集群关闭前必须降级