集群接管与资源配置(SAPHanaSR-angi)

更新时间:
复制 MD 格式

重要

适用版本(执行前请确认)

  • 操作系统:SLES for SAP Applications 15 SP4 及以上(推荐 SP5 及以上)——SAPHanaSR-angi 的系统门槛(SUSE 官方 angi 指南适用于 SLES for SAP 15 SP4 或更新版本);

  • SAP HANA:SAP HANA 2.0 SPS05 rev59.04 及以上——angi 资源代理支持的 HSR 最低版本。

不满足上述任一门槛时,请改用《集群接管与资源配置(SAPHanaSR 经典版)》;若同时低于经典版的 Hook 门槛(SAP HANA 2.0 SPS05 rev.059),Hook 组合无法配置,请按《不满足 Hook 版本门槛时的方案与限制》运行。选型依据见《选型与决策指引》1.2、1.3 节。

本文档承接《SAP HANA HSR 配置》完成后的环境:HSR 复制关系已建立并通过手动接管测试验证,但 HANA 实例仍由人工管理,尚未由集群接管。本阶段完成 HA/DR Hook 配置与 Pacemaker 集群资源定义,由集群接管 HANA 实例的启动、停止、监控与故障接管。

后续路径:第 2 章配置与实例状态联动的 HA/DR Hook 脚本;第 3 章定义集群资源(含与《集群初始化》选型一致的 STONITH 方案 A/B 变体),并由集群接管实例;第 4 章验证故障接管与受控切换;第 5 章说明关键参数;第 6 章为可选的 Active/Active(Read-Enabled)配置。若《选型与决策指引》选定的是 SAPHanaSR 经典版,请转入《集群接管与资源配置(SAPHanaSR 经典版)》。

开始前的检查

  • 集群已初始化、STONITH 已配置且隔离能力已验证(《集群初始化》第 1~3 章);

  • HSR 已建立并验证(《SAP HANA HSR 配置》第 1 章),且已完成集群接管前的手动接管测试、主备角色已恢复为初始状态:hana01 为主库(SiteA)、hana02 为备库(SiteB)(《SAP HANA HSR 配置》第 2 章);副本状态为同步(SOK);

  • 两节点已安装 SAPHanaSR-angi 资源代理包、未安装经典版 SAPHanaSR 包(《前置准备》6.2 节),HANA 版本不低于 2.0 SPS05 rev59.04(《选型与决策指引》1.3 节);

  • 两节点 SAP HANA 实例的系统级自启动保持关闭(《前置准备》第 1 章)——systemd 风格下 saphostagent.service 与 SAP<SID>_<INO>.service 保持 enabled,自启动关闭由实例 profile 的 Autostart = 0 实现;集群接管后实例启停由集群控制。

说明
  • 本文档中:<SID> 表示大写 SAP 系统 ID(如 HA1),对应小写形式记作 <sid>(如 ha1);<INO> 表示两位实例号(如 10)。例如 SID=HA1、实例号=10 时,资源 mst_SAPHanaCon_<SID>_HDB<INO> 即 mst_SAPHanaCon_HA1_HDB10。

  • 站点名沿用 SiteA(hana01)与 SiteB(hana02);VIP 沿用《Infra 选型》4.2 节规划值(10.0.100.20,虚拟主机名 vhanadb)。

  • 命令用户约定:HANA 命令以 <sid>adm 执行;集群命令(crm、cs_wait_for_idle 等)以 root 执行;Hook 检查命令在 <sid>adm 的 cdtrace 环境中执行。

  • 第 2 章的 Hook 配置与 sudoers 需在两个节点分别执行。本系列 Scale-Up 部署的文件系统均为节点本地盘(《Infra 选型》3.2 节),global.ini 位于各节点本地路径 /hana/shared/<SID>/global/hdb/custom/config/global.ini。


1. 前置条件

本节确认集群与 HSR 均处于可接管状态:

# 集群状态(root,任一节点):两节点 online、无失败资源;STONITH 已配置
crm status

# HSR 复制状态(<sid>adm,主库节点 hana01):应为 ACTIVE
HDBSettings.sh systemReplicationStatus.py --sapcontrol=1
# overall_replication_status=ACTIVE

# 资源代理包(root,两个节点):应输出 SAPHanaSR-angi,且无经典版包
rpm -qa | grep SAPHanaSR

# Hook 脚本存在性(root,两个节点):应包含 susHanaSR.py、susTkOver.py、susChkSrv.py(及 susCostOpt.py)
ls /usr/share/SAPHanaSR-angi/

# SAP 服务状态(root,两个节点):saphostagent 与实例服务保持 enabled(systemd 风格)
systemctl list-unit-files | grep -E "saphostagent|SAP<SID>_<INO>"
# 预期 saphostagent.service enabled、SAP<SID>_<INO>.service enabled

# 实例自启动已关闭(<sid>adm,两个节点):实例 profile 中 Autostart = 0
grep -i 'Autostart' /usr/sap/<SID>/SYS/profile/<SID>_HDB<INO>_<hostname>
# 预期 Autostart = 0

同时确认:

  • 操作模式已在两个节点检查完毕([system_replication] operation_mode = logreplay,见《SAP HANA HSR 配置》1.6 节);

  • Cost Optimized 场景:备库的内存限制与表预加载设置已完成(《SAP HANA HSR 配置》1.4 节),本章 2.5 节与 3.6 节还需追加 Hook 与非复制实例配置。


2. HA/DR Hook 配置

2.1 Hook 脚本概述

SAPHanaSR-angi 通过 SAP HANA 的 HA/DR provider 接口实现集群联动。需要配置的 Hook 脚本均随 SAPHanaSR-angi 包提供,位于 /usr/share/SAPHanaSR-angi/:

Hook 脚本

HA/DR 方法

作用

必要性

susHanaSR.py

srConnectionChanged()

复制连接状态变化(同步/失去同步)时立即写入集群属性

必需(SUSE 官方指南)

susTkOver.py

preTakeover()

阻止集群正常运行期间的手动接管;仅在多状态资源处于维护模式或集群停止时放行

推荐

susChkSrv.py

srServiceStateChanged()

indexserver 进程故障时加速接管(action_on_lost=fence 时触发节点隔离)

推荐

susCostOpt.py

postTakeover()

Cost Optimized 专用:接管后解除新主库内存限制、恢复表预加载

仅 Cost Optimized(仅备库,见 2.5 节)

说明
说明
  • Hook 脚本必须直接使用包内文件,不要拷贝或移动——脚本被移动或拷贝后,SUSE 包的常规更新将不会生效。

  • 修改 global.ini 需要先停止 HANA,使 HANA 在启动时加载 Hook;也可使用 SAPHanaSR-manageProvider 在不停机的情况下管理 provider 段(以 <sid>adm 运行,--reconfigure 等效于 hdbnsutil -reloadHADRProviders),详见 manpage SAPHanaSR-manageProvider(8)。本文按停库修改文件的常规流程撰写。

2.2 修改 global.ini(两个节点)

步骤 1:停止两个节点的 HANA

# 分别在 hana01、hana02 以 <sid>adm 执行
sapcontrol -nr <INO> -function StopSystem

步骤 2:在两个节点分别编辑各自的 global.ini(路径 /hana/shared/<SID>/global/hdb/custom/config/global.ini),添加以下三个 provider 段:

[ha_dr_provider_sushanasr]
provider = susHanaSR
path = /usr/share/SAPHanaSR-angi/
execution_order = 1

[ha_dr_provider_sustkover]
provider = susTkOver
path = /usr/share/SAPHanaSR-angi/
execution_order = 2

[ha_dr_provider_suschksrv]
provider = susChkSrv
path = /usr/share/SAPHanaSR-angi/
execution_order = 3
action_on_lost = fence

[trace]
ha_dr_sushanasr = info
ha_dr_sustkover = info
ha_dr_suschksrv = info

各段说明:

  • susHanaSR 无需任何配置参数;execution_order 决定多个 provider 的执行顺序(本文按 1/2/3 设置)。

  • susTkOver 通常无需调整配置;超时参数 sustkover_timeout 默认 30 秒,适用于大多数环境。

  • susChkSrv 采用渐进式配置:action_on_lost = fence 表示 indexserver 进程丢失时由 Hook 发起节点隔离(crm node fence)以加速接管——该隔离动作即使集群处于维护模式也会发出,请求会排队至集群恢复运行后执行。任何调优应与 SAP 专家确认。

  • 若 global.ini 中已存在 [trace] 段,将上述 trace 行合并进已有段即可,不要重复定义同名段。

  • Cost Optimized 场景还需按 2.5 节在备库添加 susCostOpt 段——请在本步骤停库期间一并完成,避免再次停机。

2.3 配置 sudo 权限(两个节点)

Hook 脚本以 <sid>adm 运行,并使用 sudo 访问集群属性。<sid>adm 用户必须能设置 hana_<sid>_site_srHook_* 集群属性且免密码。以下条目写入新文件 /etc/sudoers.d/SAPHanaSR(无需编辑原 /etc/sudoers):

基础版(权限范围最小化,满足全部 Hook 需要):

# SAPHanaSR-ScaleUp entries for writing srHook cluster attribute and SAPHanaSR-hookHelper
<sid>adm ALL=(ALL) NOPASSWD: /usr/sbin/crm_attribute -n hana_<sid>_*
<sid>adm ALL=(ALL) NOPASSWD: /usr/bin/SAPHanaSR-hookHelper --sid=<SID> *

高安全级别版(逐命令限定):

# SAPHanaSR-ScaleUp entries for writing srHook cluster attribute
Cmnd_Alias SOK_SITEA    = /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_SiteA -v SOK   -t crm_config -s SAPHanaSR
Cmnd_Alias SFAIL_SITEA  = /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_SiteA -v SFAIL -t crm_config -s SAPHanaSR
Cmnd_Alias SOK_SITEB    = /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_SiteB -v SOK   -t crm_config -s SAPHanaSR
Cmnd_Alias SFAIL_SITEB  = /usr/sbin/crm_attribute -n hana_<sid>_site_srHook_SiteB -v SFAIL -t crm_config -s SAPHanaSR
Cmnd_Alias HOOK_HELPER  = /usr/bin/SAPHanaSR-hookHelper --sid=<SID> --case=checkTakeover

<sid>adm ALL=(ALL) NOPASSWD: SOK_SITEA, SFAIL_SITEA, SOK_SITEB, SFAIL_SITEB, HOOK_HELPER
说明
说明
  • 将 <sid> 替换为小写 SID(如 ha1)、<SID> 替换为大写 SID;站点名使用实际站点名(本例 SiteA/SiteB)。

  • 高安全版中每条 Cmnd_Alias 必须是单行,别名标识符必须为大写。

  • 文件创建后建议用 visudo -cf /etc/sudoers.d/SAPHanaSR 校验语法;确认无报错后检查文件权限为 0440。

2.4 启动 HANA 并验证 Hook 加载

# 分别在 hana01、hana02 以 <sid>adm 启动
HDB start

启动后以 <sid>adm 检查各 Hook 是否加载并初始化成功:

cdtrace

# susHanaSR
grep HADR.*load.*susHanaSR nameserver_*.trc
grep susHanaSR.init nameserver_*.trc

# susTkOver
grep HADR.*load.*susTkOver nameserver_*.trc
grep susTkOver.init nameserver_*.trc

# susChkSrv
grep HADR.*load.*susChkSrv nameserver_*.trc
grep susChkSrv.init nameserver_*.trc
egrep '(LOST:|STOP:|START:|DOWN:|init|load|fail)' nameserver_suschksrv.trc

事件级验证命令(在对应事件发生后才会有输出,配合第 4 章测试使用):

# susHanaSR 是否成功与集群交互(或落盘 fallback 文件)
grep susHanaSR.srConnection.*CRM nameserver_*.trc
grep susHanaSR.srConnection.*fallback nameserver_*.trc

# susTkOver 放行/阻止手动接管
grep susTkOver.preTakeover.*permit nameserver_*.trc

# sudo 权限是否生效(root)
grep "sudo.*SAPHanaSR-hookHelper" /var/log/messages

全部 Hook 加载无误后,继续第 3 章的集群资源配置。

2.5 仅 Cost Optimized:susCostOpt 与 keystore

Cost Optimized 场景中,备库配置了内存限制并关闭了表预加载(《SAP HANA HSR 配置》1.4 节)。接管发生时,susCostOpt.py 的 postTakeover() 方法通过 SQL 解除新主库的内存分配限制,并恢复表预加载。

配置位置:该 Hook 仅需配置在备库节点(本例 hana02)。在 2.2 节停库期间,将以下段追加到 hana02 的 global.ini:

[ha_dr_provider_suscostopt]
provider = susCostOpt
path = /usr/share/SAPHanaSR-angi/
userkey = saphanasr_<SID>_costopt
execution_order = 2

[trace]
ha_dr_suscostopt = info
  • execution_order = 2 为强制要求——该 Hook 必须晚于 susHanaSR.py 运行;

  • userkey(可省略):数据库用户密钥在 <sid>adm keystore 中的名称,默认为 saphanasr_<SID>_costopt;

  • 可选参数 costopt_primary_global_allocation_limit = <limit-in-mb>:接管后为新主库设置的 global_allocation_limit(MB)。不设置或设置为 0 表示不限制(不设置时 Hook 执行 UNSET 语句解除限制)。

创建数据库用户密钥(hana02 以 <sid>adm 执行):

hdbuserstore SET saphanasr_<SID>_costopt localhost:3<INO>13 SYSTEM <password>
hdbuserstore LIST saphanasr_<SID>_costopt
重要

示例使用 SYSTEM 用户仅为演示。生产环境必须创建仅具备修改内存限制与表预加载权限的专用数据库用户,并将其加入 <sid>adm 的 keystore。用户密钥只需创建在备库节点。

验证(hana02 以 <sid>adm):

cdtrace
grep HADR.*load.*susCostOpt nameserver_*.trc
grep susCostOpt.init nameserver_*.trc

# 发生接管事件后确认 postTakeover 已执行
grep susCostOpt.*postTakeover nameserver_*.trc
说明
  • postTakeover() 方法要求 SAP HANA 2.0 SPS04 及以上(angi 资源代理包整包门槛见《选型与决策指引》1.3 节);仅支持 Scale-Up;

  • 不得为 postTakeover() 方法配置其他 Hook,但本系列配置的其他方法(susHanaSR/susTkOver/susChkSrv)可与其并行使用;

  • postTakeover() 会同时修改 HANA 的内存配置与持久化配置(global.ini),接管后如需将角色回退到原始状态,须按恢复流程操作——概要见第 5 章 5.2 节,完整步骤见 manpage susCostOpt.py(7)。


3. 集群资源配置

3.1 加载方式与命名约定

本章给出 SAPHanaSR-angi 的完整集群资源配置脚本。推荐将 3.2 节脚本保存为本地文件(如 /root/crm-angi.txt,替换其中所有 <...> 占位符),然后加载到集群:

# 在任一集群节点以 root 执行
crm configure load update /root/crm-angi.txt
  • load update 为增量更新:只新增/修改脚本中出现的对象,未在脚本中出现的其他对象不受影响;重复加载为幂等更新。

  • 脚本中的「集群全局属性」与「STONITH」两段与《集群初始化》保持一致——按《Infra 选型》第 6 章的选型:方案 A(fence_aliyun)直接使用 3.2 节脚本;方案 B(SBD)请按 3.3 节替换对应两段。

  • 脚本与 angi 包内附的完整样例(/usr/share/SAPHanaSR-angi/samples/crm_cfg/angi-ScaleUp/)结构等效,区别在于:VIP 使用阿里云 aliyun-vpc-move-ip 资源代理,且按上述方案并入 STONITH 段。

3.2 完整集群资源配置脚本(方案 A 变体)

# vi crm-angi.txt
# ============================================================
# SAP HANA 集群资源配置 — SAPHanaSR-angi(SID=<SID>,实例号=<INO>)
# 加载前请替换所有 <...> 占位符
# ============================================================

# === 集群全局属性与默认值(与《集群初始化》一致) ===
property cib-bootstrap-options: \
    stonith-enabled="true" \
    stonith-action="reboot" \
    stonith-timeout="150"
rsc_defaults rsc-options: \
    resource-stickiness="1000" \
    migration-threshold="5000"
op_defaults op-options: \
    timeout="600" \
    record-pending=true

# === STONITH(方案 A:fence_aliyun;方案 B 见 3.3 节替换块) ===
# 与《集群初始化》1.2 节完全相同
primitive res_ALIYUN_STONITH_1 stonith:fence_aliyun \
        op monitor interval=120 timeout=60 \
        params filter="InstanceIds=[\"<ECS Id1>\", \"<ECS Id2>\"]" plug=<ECS Id1> ram_role=SAP-HA-ROLE region=<region ID> \
        meta target-role=Started

primitive res_ALIYUN_STONITH_2 stonith:fence_aliyun \
        op monitor interval=120 timeout=60 \
        params filter="InstanceIds=[\"<ECS Id1>\", \"<ECS Id2>\"]" plug=<ECS Id2> ram_role=SAP-HA-ROLE region=<region ID> \
        meta target-role=Started

# STONITH位置约束:节点不运行自己的STONITH资源
location loc_stonith1_not_on_hana01 res_ALIYUN_STONITH_1 -inf: hana01
location loc_stonith2_not_on_hana02 res_ALIYUN_STONITH_2 -inf: hana02

# === SAPHanaTopology(收集并发布 HANA 拓扑与复制状态) ===
primitive rsc_SAPHanaTop_<SID>_HDB<INO> ocf:suse:SAPHanaTopology \
    op start interval=0 timeout=600 \
    op stop interval=0 timeout=300 \
    op monitor interval=50 timeout=600 \
    params SID=<SID> InstanceNumber=<INO>
clone cln_SAPHanaTop_<SID>_HDB<INO> rsc_SAPHanaTop_<SID>_HDB<INO> \
    meta clone-node-max=1 interleave=true

# === SAPHanaFilesystem(监控 /hana/shared/<SID> 可读写,不负责挂载) ===
primitive rsc_SAPHanaFil_<SID>_HDB<INO> ocf:suse:SAPHanaFilesystem \
    op start interval=0 timeout=10 \
    op stop interval=0 timeout=20 \
    op monitor interval=120 timeout=120 \
    params SID=<SID> InstanceNumber=<INO> ON_FAIL_ACTION=fence
clone cln_SAPHanaFil_<SID>_HDB<INO> rsc_SAPHanaFil_<SID>_HDB<INO> \
    meta clone-node-max=1 interleave=true

# === SAPHanaController(主备实例控制与接管决策;以维护状态加载,3.5 节激活) ===
primitive rsc_SAPHanaCon_<SID>_HDB<INO> ocf:suse:SAPHanaController \
    op start interval=0 timeout=3600 \
    op stop interval=0 timeout=600 \
    op promote interval=0 timeout=900 \
    op demote interval=0 timeout=320 \
    op monitor interval=60 role=Promoted timeout=700 \
    op monitor interval=61 role=Unpromoted timeout=700 \
    params SID=<SID> InstanceNumber=<INO> PREFER_SITE_TAKEOVER=true \
        DUPLICATE_PRIMARY_TIMEOUT=7200 AUTOMATED_REGISTER=false \
        ON_FAIL_ACTION=fence \
    meta priority=100
clone mst_SAPHanaCon_<SID>_HDB<INO> rsc_SAPHanaCon_<SID>_HDB<INO> \
    meta clone-node-max=1 promotable=true interleave=true maintenance=true

# === 虚拟IP(阿里云 vpc-move-ip;SAP 应用通过 vhanadb 连接主库) ===
# routing_table 参数的值为 ECS 所在 VPC 对应的默认路由表 ID
primitive rsc_ip_<SID>_HDB<INO> ocf:aliyun:vpc-move-ip \
    params address=10.0.100.20 \
           routing_table=<routing-table-id> \
           endpoint=vpc-vpc.<region-id>.aliyuncs.com \
           interface=eth0 \
    op monitor interval=10s timeout=20s

# === 约束 ===
# VIP 跟随 Promoted(主库)
colocation col_saphana_ip_<SID>_HDB<INO> 2000: rsc_ip_<SID>_HDB<INO>:Started \
    mst_SAPHanaCon_<SID>_HDB<INO>:Promoted
# Topology 先于 Controller 启动
order ord_saphana_<SID>_HDB<INO> Optional: cln_SAPHanaTop_<SID>_HDB<INO> \
    mst_SAPHanaCon_<SID>_HDB<INO>
说明
  • Cost Optimized 场景:将 Controller 参数 PREFER_SITE_TAKEOVER=true 改为 false(理由见 5.1 节),并在加载本脚本后按 3.6 节追加非复制实例资源与约束。

  • 为增加加载过程的安全性,可先执行 crm configure property maintenance-mode=true,加载完成后再执行 crm configure property maintenance-mode=false(Controller 自身带有 maintenance=true,在 3.5 节激活前不会对实例执行任何操作)。

3.3 方案 B(SBD)替换块

若《集群初始化》第 2 章采用方案 B(SBD),将 3.2 节脚本中的两段内容替换如下(其余部分保持不变):

  1. 「集群全局属性」段的 property 行替换为:

# === 集群全局属性(方案 B)===
property cib-bootstrap-options: \
    stonith-enabled="true" \
    stonith-action="reboot" \
    stonith-timeout="150" \
    priority-fencing-delay="60"

(rsc_defaults、op_defaults 两段保持不变。)

  1. 「STONITH」段(两个 fence_aliyun 资源与两条位置约束)整体替换为:

# === STONITH资源(SBD) ===
primitive stonith-sbd stonith:external/sbd \
    params pcmk_delay_max="30s"

SBD 资源无需位置约束——它由所有节点共同参与,不存在「节点隔离自己」的问题。相关超时参数取值与约束关系见《集群初始化》2.2 节。

与《集群初始化》的关系:按《集群初始化》2.1 节(ha-cluster-init -s)初始化的集群已创建同名的 stonith-sbd 资源;load update 按对象 ID 就地更新,不会产生第二个 STONITH 资源。本段加载后实际生效的变化是把 stonith-timeout 从初始化自动值(83s)统一为 150s;pcmk_delay_max、priority-fencing-delay 已在初始化时自动配置(取值一致)。若按《集群初始化》2.3 节手动配置,则为幂等重复加载。

3.4 资源与约束说明

资源 / 对象

作用

关键说明

res_ALIYUN_STONITH_1/2 + location(方案 A)/ stonith-sbd(方案 B)

节点隔离

与《集群初始化》配置相同,重复加载为幂等更新;位置约束保证节点不隔离自己(方案 A)

rsc_SAPHanaTop_<SID>_HDB<INO> + clone

收集 HANA 拓扑、复制与站点状态,写入集群属性供其他组件使用

两节点均运行

rsc_SAPHanaFil_<SID>_HDB<INO> + clone

监控 /hana/shared/<SID> 的可读写性(通过创建子目录并写文件校验)

只监控、不挂载/卸载文件系统(挂载由 /etc/fstab 负责);默认监控目录即 /hana/shared/$SID/

rsc_SAPHanaCon_<SID>_HDB<INO> + mst

控制主备实例的启动/停止/提升/降级与接管决策

以 maintenance=true 加载,3.5 节激活;参数说明见第 5 章

rsc_ip_<SID>_HDB<INO>

主库虚拟 IP(vhanadb),随主库漂移

阿里云上通过 VPC 路由表实现(Overlay IP);启动时创建 <VIP>/32 路由,漂移时改写路由

col_saphana_ip_<SID>_HDB<INO> / ord_saphana_<SID>_HDB<INO>

VIP 跟随 Promoted;Topology 先于 Controller 启动

顺序约束为可选(Optional),不阻塞其他资源

说明

SAPHanaFilesystem 的监控行为(官方定义):主库节点上监控失败(且 srHook=SOK)时,集群先尝试停止并重启该监控资源;若停止失败则隔离节点,从而触发接管;srHook=SFAIL 时则重试直到成功或达到 migration-threshold。备库节点上监控失败不会通知集群。使用本资源代理的依据之一是其可用于本地文件系统(Scale-Up 场景),且其监控与动作超时远小于 SAPHanaController,有利于加快接管。

3.5 激活多状态资源(集群接管)

Controller 克隆以 meta maintenance=true 加载,在激活前不会对 HANA 执行任何操作。按以下顺序激活(任一节点以 root 执行):

crm resource refresh mst_SAPHanaCon_<SID>_HDB<INO>
cs_wait_for_idle -s 5
crm resource maintenance mst_SAPHanaCon_<SID>_HDB<INO> off
  • crm resource refresh:让集群重新探测多状态资源状态(丢弃历史角色信息);

  • cs_wait_for_idle -s 5:等待集群进入空闲状态(ClusterTools2 包提供,已在《前置准备》6.1 节安装);

  • crm resource maintenance ... off:退出维护状态,集群开始接管实例——正常情况下 hana01 成为 PROMOTED(主库)、hana02 为 DEMOTED(备库),VIP 在 hana01 上启动。

激活完成后进入第 4 章,使用 crm status 与 SAPHanaSR-showAttr 确认接管状态。

3.6 仅 Cost Optimized:非复制实例的集群资源

Cost Optimized 场景下,hana02 同时运行一个非复制的 HANA 实例(如 DEV/TST/QAS 系统)。为避免接管时两个实例争抢节点内存,集群必须在提升备库为主库之前自动关闭该非复制实例——这由 SAPInstance 资源代理与反亲和约束实现。

将以下内容保存为 /root/crm-costopt.txt(<NPSID> 为非复制实例的 SID、<NPINO> 为其实例号;该实例运行在 hana02),在 3.2/3.3 节脚本加载后追加加载:

# vi crm-costopt.txt
# === 非复制实例资源(通过 sapstartsrv API 管理,无需 secure store 配置) ===
primitive rsc_SAP_<NPSID>_HDB<NPINO> ocf:heartbeat:SAPInstance \
    params InstanceName="<NPSID>_HDB<NPINO>_hana02" \
        MONITOR_SERVICES="hdbindexserver|hdbnameserver" \
        START_PROFILE="/usr/sap/<NPSID>/SYS/profile/<NPSID>_HDB<NPINO>_hana02" \
    op start interval=0 timeout=600 \
    op monitor interval=120 timeout=700 \
    op stop interval=0 timeout=300

# === 非复制实例的反亲和与联动约束 ===
# 非复制实例固定运行在 hana02,不允许在 hana01 上运行
location loc_<NPSID>_never_on_hana01 rsc_SAP_<NPSID>_HDB<NPINO> -inf: hana01
# 非复制实例不得与已提升的主库同节点
location loc_<NPSID>_never_on_promoted_node \
    rsc_SAP_<NPSID>_HDB<NPINO> rule -inf: hana_<SID>_clone_state eq PROMOTED
# 非复制实例不得与主库 VIP 同节点
colocation col_<NPSID>_never_with_<SID>_ip -inf: rsc_SAP_<NPSID>_HDB<NPINO>:Started \
    rsc_ip_<SID>_HDB<INO>
# 接管顺序:先优雅停止非复制实例,再提升备库
order ord_<NPSID>_stop_before_<SID>_promote mandatory: rsc_SAP_<NPSID>_HDB<NPINO>:stop \
    mst_SAPHanaCon_<SID>_HDB<INO>:promote
# 在任一集群节点以 root 执行
crm configure load update /root/crm-costopt.txt
说明
  • 运行效果:正常情况下非复制实例运行在 hana02(备库节点);当生产主库被提升到 hana02 时(接管场景),非复制实例先被优雅停止(order 为 mandatory),随后备库才提升为主库;主备角色恢复后,再由管理员按需启动非复制实例。

  • 接管过程因需优雅停止非复制实例、且新主库表无预加载而耗时更长,这是 Cost Optimized 场景为节省资源付出的代价(因此建议 PREFER_SITE_TAKEOVER=false 优先本地重启,见 5.1 节)。

  • 非复制实例的自启动口径与主数据库一致(服务保持 enabled,自启动关闭由实例 profile 的 Autostart = 0 实现),由集群统一管理。


4. 接管验证

4.1 接管就绪状态检查

激活完成后,集群接管的正常状态如下:

# 集群状态(root):两节点 online;mst 在 hana01 为 Promoted、hana02 为 Unpromoted
crm status

# 资源代理内部状态(root):优先使用 SAPHanaSR-showAttr 查询
SAPHanaSR-showAttr
# SAPHanaSR-showAttr 输出示例
Global cib-time  prim  sec   sid   topology
----------------------------------------------
global ...       SiteA SiteB <SID> ScaleUp

Resource                         maintenance
---------------------------------------------
mst_SAPHanaCon_<SID>_HDB<INO>    false

Sites lpt lss mns    opMode    srHook srMode srPoll srr
---------------------------------------------------------
SiteB ... ... hana02 logreplay SOK    sync   SOK    S
SiteA ... ... hana01 logreplay PRIM   sync   PRIM   P

Hosts  clone_state roles                        score site srah
----------------------------------------------------------------
hana01 PROMOTED    master1:master:worker:master 150   SiteA -
hana02 DEMOTED     master1:master:worker:master 100   SiteB -
说明
  • 请使用 SAPHanaSR-showAttr 查询资源代理内部值——不要用 crm_attribute 等集群命令直接读取(属性的存储位置与参数名可能随版本变化,showAttr 会从正确位置取值);SAPHanaSR-showAttr 不适用于自动化系统监控。

  • 官方测试前提(SUSE 官方 angi 指南:两节点已启动、为集群成员,HANA RDBMS 运行,系统复制同步(SOK)。

4.2 故障接管测试:停止主库(官方用例 STOP_PRIMARY_DB_SITE_A)

在业务窗口外执行(会停止主库服务)。步骤如下:

步骤 1:停止主库(hana01)

# 在 hana01 以 <sid>adm 执行
HDB stop

步骤 2:观察集群自动接管,预期结果:

  • 集群检测到主库停止并将其标记为失败;

  • 集群提升备库(hana02)为新的主库;

  • VIP 自动迁移到新主库(hana02);

  • 一段时间后,停止的原主库(hana01)的 srHook 显示为 SFAIL;

  • 由于 AUTOMATED_REGISTER=false,集群不会自动重启原主库实例,也不会自动注册到新主库。

步骤 3:恢复——将原主库注册为新备库并交回集群管理

# 在 hana01 以 <sid>adm 执行(站点名沿用 SiteA)
hdbnsutil -sr_register --remoteHost=hana02 --remoteInstance=<INO> \
    --replicationMode=sync --operationMode=logreplay \
    --name=SiteA
# 在任一节点以 root 执行:让集群重新监测并启动该资源
crm resource refresh rsc_SAPHanaCon_<SID>_HDB<INO> hana01

等待复制恢复同步后验证:

# 在 hana02(新主库)以 <sid>adm 执行
HDBSettings.sh systemReplicationStatus.py --sapcontrol=1
# overall_replication_status=ACTIVE

# root
SAPHanaSR-showAttr
# Hosts 中 hana02 roles 以 4:P 开头(新主库)、hana01 roles 以 4:S 开头(新备库)
说明
  • 本测试会互换主备角色(测试后 hana02 为主库)。如需将角色恢复为初始状态(hana01 主库),按 4.3 节受控切换流程执行。

  • 若已将 AUTOMATED_REGISTER 改为 true,恢复步骤(手动注册 + refresh)由集群自动完成,可跳过(见第 5 章)。

  • Cost Optimized 场景(PREFER_SITE_TAKEOVER=false)的预期结果不同:集群会优先在原节点重启主库(本例中重启会成功,不发生接管);只有本地重启失败或整节点故障时才触发接管路径。验证接管需模拟节点级故障,或参考上述预期结果调整测试方法。

  • SUSE 官方 angi 指南给出的测试用例还包括:停止备库站点主库(STOP_PRIMARY_DB_SITE_B)、崩溃主库(HDB kill-9,站点 A/B 各一例)等,恢复流程同理。上线前应结合业务需求补充测试用例(如节点掉电、网络隔离)并全部通过。

4.3 受控切换(计划内主备互换)

计划内维护(如硬件升级)时,用以下两种方式之一互换主备角色(假设当前 hana01 为主库、hana02 为备库,目标为互换)。注意:系统复制处于失去同步状态(SFAIL)时不应执行切换。

方式一:SAP 工具集(手工接管,全程受控)

# 1) 将多状态资源置入维护模式(任一节点 root)
crm resource maintenance mst_SAPHanaCon_<SID>_HDB<INO>

# 2) 停止主库(hana01,<sid>adm)
HDB stop

# 3) 在备库执行接管(hana02,<sid>adm);确认主库已完全停止后再执行
hdbnsutil -sr_takeover

# 4) 将原主库注册为新备库(hana01,<sid>adm)
hdbnsutil -sr_register --remoteHost=hana02 --remoteInstance=<INO> \
    --replicationMode=sync --operationMode=logreplay \
    --name=SiteA

# 5) 启动新备库(hana01,<sid>adm)
HDB start

等待 SAPHanaSR-showAttr 中两个实例均恢复在线(roles 以 4 开头;新备库角色为 S)之后:

# 6) 让集群重新监测(任一节点 root)
crm resource refresh mst_SAPHanaCon_<SID>_HDB<INO>

# 7) 退出维护模式(任一节点 root)
crm resource maintenance mst_SAPHanaCon_<SID>_HDB<INO> off
说明

多状态资源置入维护模式后,preTakeover() Hook(susTkOver)将放行手动接管请求;集群正常运行期间,手动接管会被阻止——这正是 susTkOver 的作用。

方式二:集群工具集(半自动,仅 force 受支持)

# 1) 创建 “move away + force” 规则:集群先停止当前主库,再将备库提升为主库(任一节点 root)
crm resource move mst_SAPHanaCon_<SID>_HDB<INO> force
重要

迁移必须使用 force 选项:不带 force 的迁移会在未停止原主库的情况下引发接管(双主风险),不受支持。系统复制未同步(SFAIL)时不应执行迁移。

等待新主库提升完成后再继续:

# root:确认新主库 roles 以 4:P 开头
SAPHanaSR-showAttr --format=script | grep "/roles="
# 2) 将原主库注册为新备库(原主库节点,<sid>adm;站点名沿用原站点名)
#    若已启用 AUTOMATED_REGISTER=true,注册由集群自动完成,可跳过本步骤
hdbnsutil -sr_register --remoteHost=hana02 --remoteInstance=<INO> \
    --replicationMode=sync --operationMode=logreplay \
    --name=SiteA

# 3) 清除 move 规则,允许集群启动新备库(任一节点 root)
crm resource clear mst_SAPHanaCon_<SID>_HDB<INO>

最后确认新备库启动并同步(roles 以 4:S 开头),复制状态回到 ACTIVE。


5. 关键参数说明

5.1 资源代理参数

Controller 资源的关键参数与官方推荐值:

参数

Performance Optimized

Cost Optimized

说明

PREFER_SITE_TAKEOVER

true

false

是否优先切换到备站(而非在原节点重启故障主库)。Cost Optimized 场景建议 false:备库配置了内存限制且表预加载关闭(《SAP HANA HSR 配置》1.4 节),接管代价高,优先本地重启

AUTOMATED_REGISTER

false / true

false / true

是否自动将原主库注册为新主库的备库。设为 false 时原主库必须人工注册,集群不会启动未注册实例——避免双主。初始配置 false,上线验证通过后可按需改为 true

DUPLICATE_PRIMARY_TIMEOUT

7200

7200

双主场景下两个主库时间戳所需的差值(秒)。差值不足时集群将其中一个或两个实例保持 WAITING 状态,给管理员处置时间;若原主节点整体崩溃,超过该时间后原主库将被自动注册(数据由系统复制覆盖);若仅 RDBMS 崩溃则立即注册

ON_FAIL_ACTION

fence

fence

主库监控失败时的升级动作:srHook=SOK 时可触发节点隔离(加快接管);srHook=SFAIL 时照常重启

补充说明:

  • 验证通过后再启用自动化:建议保持 AUTOMATED_REGISTER=false 完成第 4 章全部测试,确认接管行为符合预期后,再执行 crm resource param rsc_SAPHanaCon_<SID>_HDB<INO> set AUTOMATED_REGISTER true。启用后,接管测试的恢复步骤由集群自动完成。

  • 操作超时:start=3600、stop=600、promote=900、demote=320、monitor=700 为官方模板值。HANA 的启动/停止/提升操作耗时较长,不建议调小;如需调优请对照 manpage ocf_suse_SAPHanaController(7)。

  • 默认值与粘性:resource-stickiness=1000 防止资源在节点间非必要漂移;migration-threshold=5000、op_defaults timeout=600 与 record-pending=true 均为官方模板值,直接沿用。

  • 维护状态机制:Controller 克隆加载时带 maintenance=true,只有执行 3.5 节的激活序列后才开始接管实例;后续维护操作(如端口/实例级调整)也应先将多状态资源置入维护模式,操作序列示例见 manpage SAPHanaSR_maintenance_examples(7)。

  • priority 与隔离竞速:Controller 设 meta priority=100,方案 B 下配合 priority-fencing-delay=60,让承载主库的节点在隔离竞速中占先(机制见《集群初始化》2.2 节)。

5.2 Cost Optimized 补充说明

  • 接管时的行为:susCostOpt.py 的 postTakeover() 在新主库上执行 SQL,解除 global.ini 中 [memorymanager] global_allocation_limit 限制并恢复 [system_replication] preload_column_tables(同时修改内存与持久化配置)。接管并发 SQL 的过程会延长接管时间。

  • 回退到原始状态的恢复流程(概要,完整命令示例见 manpage susCostOpt.py(7)):

  1. 将 HANA 多状态资源置入维护模式;

  2. 清理 HANA primitive 资源;

  3. 原主库站点:将原主库注册为新备库;

  4. 原主库站点:启动新备库,等待 SR 同步完成;

  5. 现主库站点:停止主库;

  6. 原主库站点:在备库上执行 hdbnsutil -sr_takeover;

  7. 现主库站点(已停止的原主库):修改 global.ini,恢复备库的内存限制与预加载设置;

  8. 现主库站点:将原主库注册为新备库;

  9. 现主库站点:启动新备库,等待 SR 同步完成;

  10. 刷新 HANA 多状态资源(crm resource refresh);

  11. 将 HANA 多状态资源退出维护模式。

说明
  • 第 7 步也可以在现主库停止之前预先对该节点完成(即提前按“备库参数”准备好 global.ini);

  • 若已启用 AUTOMATED_REGISTER=true,注册相关步骤可由集群自动完成;

  • 操作前后都应检查 Linux 集群与 HANA 系统复制的状态,站点名必须与集群已知的名称一致。


6. 可选:Active/Active(Read-Enabled)

仅 Performance Optimized 场景适用:备库以 logreplay_readaccess 操作模式运行(《SAP HANA HSR 配置》1.6 节),为其追加一个只读虚拟 IP,供报表类查询连接。Cost Optimized 场景不得启用。

# vi crm-re.txt
# === 只读虚拟IP(绑定到备库,Unpromoted 角色) ===
primitive rsc_ip_<SID>_HDB<INO>_readenabled ocf:aliyun:vpc-move-ip \
    params address=10.0.100.21 \
           routing_table=<routing-table-id> \
           endpoint=vpc-vpc.<region-id>.aliyuncs.com \
           interface=eth0 \
    op monitor interval=10s timeout=20s
colocation col_saphana_ip_<SID>_HDB<INO>_readenabled 2000: \
    rsc_ip_<SID>_HDB<INO>_readenabled:Started mst_SAPHanaCon_<SID>_HDB<INO>:Unpromoted
# 在任一集群节点以 root 执行
crm configure load update crm-re.txt
说明
  • 只读 VIP(10.0.100.21,虚拟主机名 vhanadbro)通过 colocation 绑定到 Unpromoted(备库)角色:接管发生后主备角色互换,该 IP 自动跟随新的备库;

  • 虚拟主机名与 /etc/hosts 的规划见《Infra 选型》4.2 节与《前置准备》4.2 节;客户端使用 vhanadbro 建立只读连接;

  • 版本一致性、备库 sizing 等要求见《SAP HANA HSR 配置》1.6 节。


至此,SAPHanaSR-angi 的集群接管与资源配置完成:HANA 主备实例由 Pacemaker 集群接管,具备故障自动接管与受控切换能力。日常维护操作(计划内停机、维护模式进入/退出、接管后的角色回退等)请参考 manpage SAPHanaSR_maintenance_examples(7);如《选型与决策指引》选定的是 SAPHanaSR 经典版,请转《集群接管与资源配置(SAPHanaSR 经典版)》。