Pacemaker 高可用集群
核心模块深度解析
面向系统工程师与运维人员的体系化培训文档。从 Corosync 消息层到 Pacemaker 资源编排,逐层拆解 RHEL 10 High Availability Add-On 的每一个核心组件、它们的协作关系,以及背后的设计取舍。
00课程说明与学习路径
本课程的目标不是让你记住几十条 pcs 命令,而是让你理解集群在每一次故障中到底做了什么决策、为什么这么决策。只有理解了模块边界,排障时才知道该看哪个日志、该调哪个参数。
基础与架构
第 1–2 章。建立 HA 的概念地图与四层架构模型。
核心引擎
第 3–6 章。Corosync、Pacemaker 守护进程、CIB、决策流程。本课程重点。
配置对象
第 7–9 章。资源、资源代理、约束、集群属性。
数据完整性
第 10–11 章。Fencing 与 Quorum —— 生产集群的生死线。
工具与扩展
第 12–14 章。pcs 命令地图、高级特性、RHEL 10 变化。
实践
第 15–16 章。速查表、动手实验与自测题。
文中所有技术点标注了信息来源:RHEL10 官方 表示直接来自 Red Hat RHEL 10《Configuring and managing high availability clusters》;RHEL9 官方 表示 RHEL 10 文档未单列、由 RHEL 9 同名文档补充;社区 表示来自 ClusterLabs 上游文档或 man page。所有引用链接见第 17 章。
01高可用集群基础概念
Red Hat High Availability Add-On 是一套集群系统,通过消除单点故障(SPOF)并在节点失效时把服务故障转移(failover)到其他节点,来为关键生产服务提供可靠性、可扩展性与可用性。RHEL10 官方
1.1 必须先分清的四个词
| 术语 | 含义 | 在 Pacemaker 中的体现 |
|---|---|---|
| 高可用 (HA) | 服务在节点故障后能快速在别处恢复,客户端感知不到节点级失效 | failover 集群,本课程主题 |
| 负载均衡 (LB) | 请求分发到多个后端,提升吞吐 | 另一个产品:Load Balancer Add-On(haproxy/keepalived),不是 Pacemaker |
| 容灾 (DR) | 跨站点、跨地域的业务连续性 | Booth 多站点票据管理(第 13 章) |
| 脑裂 (Split-brain) | 网络分区导致两边都认为自己是"活的",同时写共享数据 → 数据损坏 | 用 Quorum + Fencing 双保险防止(第 10–11 章) |
1.2 HA 集群要解决的核心矛盾
集群随时面临一个两难:节点 A 联系不上节点 B 时,B 究竟是宕机了,还是只是网络断了?
- 如果 B 宕机了,A 必须立刻接管服务 —— 否则业务中断。
- 如果 B 只是网络断了但仍在运行,A 贸然接管就会导致两个节点同时挂载同一个文件系统、同时持有同一个 VIP —— 数据必然损坏。
集群无法区分"对端宕机"与"网络分区"。因此 Pacemaker 采取的策略是:与其猜测,不如强制确定状态 —— 通过 Fencing(STONITH)主动把对端断电/隔离,把"不确定"变成"确定的死亡",然后才敢接管资源。这就是为什么生产环境永远不能关闭 fencing。
1.3 一次典型故障转移的时间线
| # | 阶段 | 负责组件 | 发生了什么 |
|---|---|---|---|
| 1 | 心跳丢失 | corosync | token 超时(默认约 1s 级别,可调),成员关系变更 |
| 2 | 成员重算 | corosync / votequorum | 形成新 membership,判断本分区是否有 quorum |
| 3 | 通知 | pacemaker-controld | DC 收到 membership 变更事件 |
| 4 | 决策 | pacemaker-schedulerd | 基于 CIB 计算新的目标状态,生成 transition graph |
| 5 | 隔离 | pacemaker-fenced | 对失联节点执行 STONITH,确认其已死 |
| 6 | 启动资源 | pacemaker-execd → RA | 按依赖顺序在存活节点上拉起资源 |
| 7 | 状态回写 | pacemaker-based (CIB) | 更新 status 段,集群收敛 |
请特别注意第 5 步的位置:fencing 发生在启动资源之前。如果 fencing 设备不可用,集群会停在这里等待,资源不会被接管 —— 这是新手最常见的"集群卡住不切换"的根因。
02整体架构:四层模型
把 Pacemaker 集群理解成自下而上的四层,是掌握它最有效的心智模型。每一层只关心自己的职责,向上提供抽象。
2.1 各层职责边界(面试/考试高频)
| 层 | 组件 | 回答"我知道什么" | 不负责什么 |
|---|---|---|---|
| L2 | Corosync | 集群里现在有哪些节点在线?我这个分区有没有 quorum?消息怎么可靠地广播给所有成员? | 不知道有哪些"服务",完全不理解资源概念 |
| L3 | Pacemaker | 有哪些资源、应该跑在哪个节点、依赖顺序是什么、故障了该怎么办 | 不知道怎么"具体"启动一个 Apache |
| L4 | Resource Agent | 怎么 start/stop/monitor 这个具体的应用 | 不知道集群拓扑,只管本机这一个服务 |
| L1 | Fence 设备 | 怎么把某台机器强行断电或隔离 | 不参与任何决策 |
Corosync 是"为高可用集群提供核心成员关系与成员间通信"的组件与同名守护进程,是 High Availability Add-On 运行的必要前提;它同时管理 quorum 规则与判定,为跨成员协同的应用提供消息能力,并使用 kronosnet (knet) 库作为网络传输,从而提供多条冗余链路与自动故障切换。RHEL10 官方 Ch.1
03Corosync:消息与成员层
Corosync 是集群的"神经系统"。Pacemaker 完全构建在它之上 —— 没有 Corosync,Pacemaker 连"集群里有几台机器"都不知道。
3.1 Corosync 的四项职责
成员管理
基于 Totem 单环协议维护"当前在线节点列表",节点加入/离开时触发 membership 变更事件。
可靠有序消息
通过 CPG(Closed Process Group)为上层提供"全序、可靠"的组播消息,保证所有节点看到相同的事件顺序。
法定票数判定
votequorum 模块计算当前分区票数,回答"我这一半有没有资格提供服务"。
knet 多链路传输
kronosnet 支持最多 8 条冗余链路、自动故障切换、链路优先级与加密。
3.2 corosync.conf 解剖
配置文件位于 /etc/corosync/corosync.conf。官方明确要求:不要直接编辑此文件,应通过 pcs、RHEL Web 控制台的 HA Cluster Management 插件,或 ha_cluster RHEL 系统角色来管理。RHEL10 官方 Ch.1
totem {
version: 2
cluster_name: my_cluster
transport: knet # RHEL 8+ 默认传输,支持多链路
crypto_cipher: aes256 # 链路加密
crypto_hash: sha256 # 消息完整性校验
# token: 3000 # token 超时(ms),判定节点失联的关键阈值
# token_retransmits_before_loss_const: 4
}
nodelist {
node {
ring0_addr: 192.168.10.11 # link0:心跳主链路
ring1_addr: 192.168.20.11 # link1:心跳备链路(强烈建议)
name: node1.example.com
nodeid: 1
}
node {
ring0_addr: 192.168.10.12
ring1_addr: 192.168.20.12
name: node2.example.com
nodeid: 2
}
}
quorum {
provider: corosync_votequorum
two_node: 1 # 双节点集群自动写入!见第 11 章
# wait_for_all: 1 # two_node:1 时自动隐式启用
}
logging {
to_logfile: yes
logfile: /var/log/cluster/corosync.log
to_syslog: yes
timestamp: on
}
3.3 关键段落说明
| 段 / 参数 | 作用 | 调优提示 |
|---|---|---|
totem.transport | 传输方式:knet(默认,多链路)/ udpu(单播)/ udp(组播) | 虚拟化或云环境组播常被禁,保持 knet 即可 |
totem.token | token 超时(毫秒)。超时未收到 token 即认为节点失联 | 负载极高或网络抖动的环境可适当增大;不要盲目调小,会误判 |
totem.crypto_cipher/hash | 心跳链路加密与完整性 | RHEL 8+ 默认启用;跨机房时务必保留 |
nodelist.node.ringN_addr | 第 N 条链路的地址 | knet 最多 8 条链路;至少配 2 条避免单网络故障触发误切换 |
nodelist.node.nodeid | 节点唯一 ID | 由 pcs 自动分配,不要手工冲突 |
quorum.provider | 固定为 corosync_votequorum | — |
quorum.two_node | 双节点特殊模式 | 详见第 11 章,是双节点集群最重要的参数 |
3.4 多链路(redundant link)配置
创建集群时用多个 addr= 即声明多条链路,出现顺序对应 link0、link1……RHEL10 官方 Ch.3
# 语法
pcs cluster setup cluster_name \
node1_name addr=node1_link0_address addr=node1_link1_address \
node2_name addr=node2_link0_address addr=node2_link1_address
# 官方示例
pcs cluster setup my_twolink_cluster \
rh80-node1 addr=192.168.122.201 addr=192.168.123.201 \
rh80-node2 addr=192.168.122.202 addr=192.168.123.202
# 指定优先级:让 link1 优先、link0 作备(link_mode 默认 passive)
pcs cluster setup my_twolink_cluster \
rh80-node1 addr=192.168.122.201 addr=192.168.123.201 \
rh80-node2 addr=192.168.122.202 addr=192.168.123.202 \
transport knet link link_priority=1 link link_priority=0
3.5 Corosync 层常用排查命令
corosync-quorumtool -s # 查看票数、期望票数、当前 quorum 状态
corosync-cfgtool -s # 查看各 link 的健康状态(ring status)
corosync-cmapctl | grep members # 查看运行时成员表
pcs cluster config # 以 pcs 视角查看 corosync 配置
pcs quorum status # quorum 详细状态(推荐)
journalctl -u corosync -f # 实时日志
04Pacemaker 守护进程详解
Pacemaker 不是一个进程,而是一组各司其职的守护进程。官方描述为:"由若干独立的组件守护进程构成,它们监控集群成员关系、管理服务的脚本,以及监控各类资源的资源管理子系统。"RHEL10 官方 Ch.1
4.1 官方命名 vs 实际进程名(重要)
RHEL 官方文档在概念章节沿用了 CIB / CRMd / LRMd / STONITH 这套经典命名,但从 Pacemaker 2.0(RHEL 8)起,实际的二进制与进程名已经全部改名。培训时必须把两套名字对上,否则看日志会一头雾水。
| 经典名(文档/老资料) | 实际进程名(RHEL 8/9/10) | 职责 |
|---|---|---|
| — | pacemakerd | 主控进程。启动并监管下列所有子守护进程,异常退出时负责拉起 |
| CIB | pacemaker-based | 集群信息库守护进程,内部用 XML 存储并在全集群同步配置与状态 |
| CRMd | pacemaker-controld | 集群控制器,所有资源动作经它路由;负责 DC 选举与状态机 |
| PEngine / policy engine | pacemaker-schedulerd | 调度/策略引擎,根据 CIB 计算"理想状态"并生成 transition graph |
| LRMd | pacemaker-execd | 本地资源执行器,作为 controld 与资源代理之间的接口,实际调用 RA |
| STONITHd | pacemaker-fenced | 隔离守护进程,处理 fence 请求,调用 fence agent |
| attrd | pacemaker-attrd | 节点属性管理,维护并同步各节点的瞬时/永久属性(如 failcount) |
| — | pacemaker-remoted | 运行在 Pacemaker Remote 节点上,让非集群成员也能承载资源 |
CIB:"Pacemaker 信息守护进程,内部使用 XML,将当前的配置与状态信息从 DC(Designated Coordinator,指定协调者)—— 一个由 Pacemaker 指派、用于存储和分发集群状态与动作的节点 —— 通过 CIB 分发并同步到所有其他集群节点。"
CRMd:"Pacemaker 的集群资源动作都经此守护进程路由。由 CRMd 管理的资源可以被客户端系统查询、移动、实例化和按需变更。每个集群节点还包含一个本地资源管理守护进程 LRMd,作为 CRMd 与资源之间的接口;LRMd 把 CRMd 的命令(如 start/stop)传给代理,并回传状态信息。"RHEL10 官方 Ch.1
4.2 守护进程协作关系图
4.3 DC(Designated Coordinator)机制
什么是 DC?集群会选举出一个节点作为 DC。DC 上的 pacemaker-schedulerd 是唯一做决策的地方 —— 其他节点的 schedulerd 处于待命状态。这样保证了"同一时刻只有一个大脑",避免决策冲突。
- DC 不是"主节点",资源不一定跑在 DC 上,DC 只负责计算和编排。
- DC 宕机后集群会立即重新选举,业务不受影响。
- 用
pcs status输出中的Current DC:一行查看当前 DC。
ps -ef | grep pacemaker # 看到 pacemakerd 及其 6~7 个子进程
systemctl status pacemaker # 服务级状态
pcs status | grep -i "Current DC" # 当前 DC 是谁
crm_mon -1 # 一次性快照(不进入交互界面)
crm_mon -1 -A # 附带显示节点属性
05CIB:集群信息库
CIB(Cluster Information Base)是整个集群唯一的事实来源(single source of truth)。它同时存放两类东西:你写的配置,和集群观测到的状态。
5.1 存储与同步
| 项目 | 说明 |
|---|---|
| 磁盘文件 | /var/lib/pacemaker/cib/cib.xml(官方称配置文件为 cib.xml) |
| 内容 | 一个 XML 文件,同时表示集群配置与所有资源的当前状态RHEL10 官方 Ch.1 |
| 同步方式 | 由 pacemaker-based 自动在全集群保持同步,无需手工分发 |
| 版本控制 | 通过 admin_epoch / epoch / num_updates 三元组做版本比较,防止旧配置覆盖新配置 |
| 禁止操作 | 不要直接编辑 cib.xml。必须通过 pcs、Web 控制台 HA 插件或 ha_cluster 系统角色修改RHEL10 官方 |
5.2 CIB 的 XML 结构
<cib admin_epoch="0" epoch="37" num_updates="12" validate-with="pacemaker-3.x"
have-quorum="1" dc-uuid="1">
<configuration> <!-- ① 管理员写的:期望状态 -->
<crm_config> <!-- 集群全局属性 -->
<cluster_property_set id="cib-bootstrap-options">
<nvpair name="stonith-enabled" value="true"/>
<nvpair name="no-quorum-policy" value="stop"/>
</cluster_property_set>
</crm_config>
<nodes> <!-- 节点清单与永久节点属性 -->
<node id="1" uname="node1.example.com"/>
<node id="2" uname="node2.example.com"/>
</nodes>
<resources> <!-- 资源定义:primitive / group / clone / bundle -->
<primitive id="VirtualIP" class="ocf" provider="heartbeat" type="IPaddr2">
<instance_attributes id="VirtualIP-ia">
<nvpair name="ip" value="192.168.10.100"/>
</instance_attributes>
<operations>
<op name="monitor" interval="30s"/>
</operations>
</primitive>
</resources>
<constraints> <!-- location / colocation / order / ticket -->
</constraints>
<fencing-topology/> <!-- 多级 fencing -->
<acls/> <alerts/> <!-- 访问控制 / 告警 -->
</configuration>
<status> <!-- ② 集群自动写的:实际状态,只读,勿动 -->
<node_state id="1" in_ccm="true" crmd="online" join="member">
<!-- 每个资源的最近一次操作结果、rc-code、failcount 等 -->
</node_state>
</status>
</cib>
<configuration> = 你想要的样子(desired state);<status> = 现在实际的样子(observed state)。pacemaker-schedulerd 的全部工作,就是计算"从 status 走到 configuration 需要执行哪些动作"。这与 Kubernetes 的调谐(reconcile)思想完全一致。
5.3 操作 CIB 的正确姿势
# —— 查看 ——
pcs cluster cib # 输出完整 CIB XML
pcs cluster cib > /root/cib_backup.xml
cibadmin --query # 底层等价命令
cibadmin --query --scope resources # 只看资源段
pcs config # 人类可读的完整配置摘要(推荐)
pcs status --full # 状态 + 资源 + failcount
# —— 离线批量修改(沙箱模式,强烈推荐用于复杂变更)——
pcs cluster cib my_cfg # ① 导出到本地文件
pcs -f my_cfg resource create VIP IPaddr2 ip=192.168.10.100 cidr_netmask=24
pcs -f my_cfg resource create Web apache configfile=/etc/httpd/conf/httpd.conf
pcs -f my_cfg constraint colocation add Web with VIP INFINITY
pcs cluster cib-push my_cfg --config # ② 一次性原子提交
# —— 备份与恢复整个集群配置 ——
pcs config backup cluster_backup # 生成 cluster_backup.tar.bz2
pcs config restore cluster_backup.tar.bz2
任何涉及多条命令的配置变更(例如新建一组资源 + 约束),都应使用 pcs -f <file> 沙箱方式,最后一次性 cib-push。否则中间态可能触发集群把资源启动在错误位置,产生不必要的抖动。
06集群决策流程剖析
理解这条链路,等于掌握了 Pacemaker 的全部运行逻辑。
6.1 用命令观察决策过程
# 干跑:告诉我"如果现在重新计算,集群会做什么",但不真正执行
crm_simulate -SL
# 从当前 CIB 模拟并显示动作图
pcs cluster cib > /tmp/cib.xml
crm_simulate -x /tmp/cib.xml -S -s # -s 显示各资源在各节点的分数
# 查看资源为什么跑在这个节点:打印分配分数
crm_simulate -sL | grep -i "native_color"
# 集群日志(决策细节都在这里)
journalctl -u pacemaker --since "10 min ago"
grep -Ei "pengine|schedulerd|Transition|fence" /var/log/pacemaker/pacemaker.log
07资源与资源代理 (RA)
7.1 资源的三段式命名
每个资源由 standard(class) : provider : type 三段唯一确定:
ocf : heartbeat : IPaddr2
│ │ └── type 具体的资源代理名
│ └───────────── provider 提供者(仅 ocf 标准有此段)
└────────────────────── standard 标准/类别
| standard | 说明 | 示例 | 建议 |
|---|---|---|---|
ocf | Open Cluster Framework 标准脚本,支持参数、支持 monitor、返回码规范 | ocf:heartbeat:IPaddr2 | 首选 |
systemd | 直接托管一个 systemd unit | systemd:httpd | 无 OCF RA 时使用 |
service | 自动判定走 systemd 还是 lsb | service:httpd | 兼容用 |
lsb | 传统 /etc/init.d 脚本 | lsb:myapp | 遗留 |
stonith | 隔离设备资源 | stonith:fence_ipmilan | fencing 专用 |
把服务交给 Pacemaker 管理后,必须在所有节点 systemctl disable 该服务。否则节点重启时 systemd 和 Pacemaker 会争抢,可能导致服务在两个节点同时启动。
7.2 常用资源代理速查
| 资源代理 | 用途 | 关键参数 |
|---|---|---|
ocf:heartbeat:IPaddr2 | 浮动 IP / VIP | ip, cidr_netmask, nic |
ocf:heartbeat:Filesystem | 挂载文件系统 | device, directory, fstype, options |
ocf:heartbeat:LVM-activate | 激活 LVM 卷组(HA-LVM / 共享 VG) | vgname, vg_access_mode |
ocf:heartbeat:apache | Apache HTTP Server | configfile, statusurl |
ocf:heartbeat:nfsserver | NFS 服务 | nfs_shared_infodir, nfs_no_notify |
ocf:heartbeat:exportfs | NFS 导出目录 | directory, clientspec, fsid |
ocf:heartbeat:mysql / pgsql | 数据库 | binary, datadir, config |
ocf:pacemaker:ping | 探测外部网关连通性,写入节点属性驱动 location 约束 | host_list, multiplier |
ocf:pacemaker:controld | DLM 控制守护进程(GFS2 场景) | — |
ocf:heartbeat:azure-lb / aws-vpc-move-ip | 公有云环境的 VIP 替代方案 | 随云平台不同 |
pcs resource standards # 支持的 standard 列表
pcs resource providers # 支持的 provider 列表
pcs resource agents ocf:heartbeat # 列出所有 ocf:heartbeat 代理
pcs resource describe ocf:heartbeat:IPaddr2 # 查看参数说明(最常用!)
pcs resource list | grep -i nfs # 关键字搜索
7.3 资源操作(operations)
| 操作 | 作用 | 常用属性 |
|---|---|---|
start | 启动资源 | timeout, on-fail |
stop | 停止资源 | timeout, on-fail=fence(默认,停不掉就 fence) |
monitor | 周期健康检查 —— 没有它集群就是"瞎的" | interval, timeout, on-fail |
promote/demote | 提升/降级(主从资源) | promotable 资源专用 |
migrate_to/migrate_from | 在线迁移(如 KVM 虚机) | 需 RA 支持 |
创建资源时忘记配置 monitor 操作。没有 monitor,集群只会在启动时检查一次,之后服务挂掉集群完全不知道 —— 你以为有 HA,其实没有。务必显式指定:op monitor interval=30s。
7.4 资源 meta 属性
| meta 属性 | 默认 | 含义 |
|---|---|---|
resource-stickiness | 0 | 资源"黏性"。>0 表示原节点恢复后不自动漂回,避免二次中断 |
migration-threshold | INFINITY | 在当前节点失败多少次后强制迁走 |
failure-timeout | 0(永不过期) | 失败计数多久后自动清零 |
target-role | Started | Stopped 即等价于 pcs resource disable |
is-managed | true | false = 集群只监控不干预(维护单个资源) |
priority | 0 | 资源不足时优先保谁;也影响 priority-fencing-delay |
multiple-active | stop_start | 发现资源在多处运行时的处置策略 |
7.5 复合资源类型
资源组
一组资源按顺序启动、逆序停止,且必须在同一节点。等价于自动创建 order + colocation 约束。最常用的简化手段。
克隆资源
同一资源在多个节点同时运行。用于 dlm、clvmd、GFS2 挂载、监控类资源。
可提升克隆(主从)
克隆的特例,实例分 Promoted/Unpromoted 两种角色。用于 DRBD、PostgreSQL 流复制等。旧称 master/slave。
容器 bundle
把容器(podman/docker)作为集群资源编排,自动处理网络与存储映射。
# 资源组:apachegroup 内按声明顺序 启动 lvm → fs → vip → web
pcs resource create my_lvm ocf:heartbeat:LVM-activate vgname=my_vg \
vg_access_mode=system_id --group apachegroup
pcs resource create my_fs Filesystem device="/dev/my_vg/my_lv" \
directory="/var/www" fstype="xfs" --group apachegroup
pcs resource create VirtualIP IPaddr2 ip=192.168.10.100 cidr_netmask=24 \
--group apachegroup
pcs resource create Website apache configfile="/etc/httpd/conf/httpd.conf" \
statusurl="http://127.0.0.1/server-status" --group apachegroup
# 克隆:每个节点都跑一份
pcs resource create dlm ocf:pacemaker:controld op monitor interval=30s on-fail=fence \
clone interleave=true ordered=true
# 可提升克隆(主从)
pcs resource promotable my_db promoted-max=1 promoted-node-max=1 \
clone-max=2 clone-node-max=1
08约束 Constraints
约束是你向 scheduler 表达"业务规则"的唯一手段。Pacemaker 用分数(score)模型统一处理所有约束。
8.1 三大类约束
| 类型 | 回答的问题 | 命令 |
|---|---|---|
| Location(位置) | 这个资源能/倾向于跑在哪些节点? | pcs constraint location |
| Colocation(共置) | A 必须/倾向和 B 跑在同一个节点吗? | pcs constraint colocation |
| Order(顺序) | A 必须在 B 之前启动吗? | pcs constraint order |
| Ticket(票据) | 多站点场景,本站点是否持有运行权? | pcs constraint ticket(配合 Booth) |
8.2 分数(score)语义 —— 必须理解
| 分数 | 含义 | 典型用途 |
|---|---|---|
INFINITY (= 1000000) | 强制,必须满足 | "数据库和 VIP 必须在一起" |
-INFINITY | 强制禁止 | "绝不能跑在这个节点" |
| 正数(如 100) | 倾向,越大越倾向 | "优先跑 node1,但 node1 挂了也可以去 node2" |
| 负数(如 -100) | 不倾向 | "尽量别跑这里" |
| 0 | 中立 | — |
任何值 + INFINITY = INFINITY;任何值 + -INFINITY = -INFINITY;INFINITY + -INFINITY = -INFINITY(禁止优先)。这解释了为什么一个 -INFINITY 的 location 约束会让资源无论如何都不上那个节点。
8.3 约束命令实操
# ——— Location ———
pcs constraint location Website prefers node1.example.com=100 # 倾向
pcs constraint location Website avoids node2.example.com=INFINITY # 禁止
pcs constraint location Website prefers node1.example.com # 不写分数=INFINITY
# ——— Colocation:把 Website 放到 VirtualIP 所在的节点 ———
# 注意方向:colocation add <源> with <目标>,先决定目标位置,再放源
pcs constraint colocation add Website with VirtualIP INFINITY
# ——— Order:先起 VirtualIP,再起 Website ———
pcs constraint order start VirtualIP then start Website
pcs constraint order VirtualIP then Website kind=Mandatory # Mandatory/Optional/Serialize
# ——— 查看 / 删除 ———
pcs constraint # 概览
pcs constraint --full # 含约束 id(删除时要用)
pcs constraint location config
pcs constraint delete <constraint_id>
pcs constraint colocation add A with B 的语义是"A 跟着 B 走":集群先决定 B 放哪,再把 A 放到同一节点。如果写反了,当 A 无法启动时会把 B 也拖住。经验法则:把"依赖别人的那个"写在前面。
09集群属性与行为控制
集群属性(cluster properties)存放在 CIB 的 crm_config 段,控制集群的全局行为。RHEL10 官方 Ch.23
| 属性 | 默认值 | 说明与建议 |
|---|---|---|
stonith-enabled | true | 生产环境必须保持 true。设为 false 相当于放弃数据完整性保护,Red Hat 不支持 |
stonith-action | reboot | reboot 或 off。共享存储场景常用 off 更安全 |
no-quorum-policy | stop | 失去 quorum 时:stop(停资源,默认) / freeze(保持但不接管,GFS2 用) / ignore(危险) / suicide(自我 fence) |
symmetric-cluster | true | true=资源默认可在任意节点运行;false=必须显式 location 允许("白名单"模式) |
cluster-recheck-interval | 15min | 周期性重新评估集群状态的间隔 |
default-resource-stickiness | 0 | 建议设为正值(如 100),避免故障节点恢复后资源自动漂回造成二次中断 |
start-failure-is-fatal | true | 启动失败即视为致命,直接迁走。设 false 则受 migration-threshold 控制 |
priority-fencing-delay | 0 | 双节点关键参数:脑裂时让运行资源更少/优先级更低的节点延迟 fence,从而更可能被"先干掉" |
maintenance-mode | false | true = 集群停止管理所有资源(只监控不动作),用于计划内维护 |
concurrent-fencing | true (较新版本) | 允许并行 fence 多个节点 |
batch-limit | 0(自动) | 一次 transition 中并行执行的动作数上限 |
pcs property config # 查看已显式设置的属性
pcs property config --all # 查看全部属性(含默认值)
pcs property describe no-quorum-policy # 查看某属性的说明与可选值
pcs property set stonith-enabled=true
pcs property set no-quorum-policy=freeze
pcs property set priority-fencing-delay=15s
pcs resource defaults update resource-stickiness=100 # 资源默认 meta
pcs property set maintenance-mode=true # 进入维护模式
pcs property set maintenance-mode=false # 退出
10Fencing / STONITH
STONITH = Shoot The Other Node In The Head。官方定义:"STONITH 是 Pacemaker 的 fencing 实现。它在 Pacemaker 中作为一种集群资源存在,处理 fence 请求,强制关闭节点并把它从集群中移除,以确保数据完整性。STONITH 在 CIB 中配置,并可像普通集群资源一样被监控。"RHEL10 官方 Ch.1
10.1 为什么 fencing 不可协商
没有配置可用 fencing 的集群,Red Hat 不提供生产支持。原因很简单:一旦发生脑裂,共享存储上的数据会被两个节点同时写入而不可逆损坏。fencing 是把"不确定"变为"确定"的唯一手段。
10.2 Fence Agent 选型
| Fence Agent | 适用场景 | 机制 | 关键参数 |
|---|---|---|---|
fence_ipmilan | 物理服务器(Dell iDRAC / HP iLO / 通用 IPMI) | 带外管理口下电/重启 | ip, username, password, lanplus=1 |
fence_idrac / fence_ilo5 | 厂商专用封装 | 同上 | 同上 |
fence_vmware_rest | VMware vSphere 虚机 | 调 vCenter REST API 强制关机 | ip(vCenter), username, password, ssl_insecure |
fence_rhevm / fence_ovirt | RHV / oVirt 虚机 | 管理 API | — |
fence_apc_snmp | APC 智能 PDU | 切断插座供电 | ipaddr, pcmk_host_map |
fence_scsi | 共享 SCSI 存储 | SCSI-3 持久预留(PR),剥夺写权限 | devices, pcmk_host_list |
fence_sbd | 无带外管理的场景 | 共享块设备"毒丸" + watchdog 自复位 | devices;需 sbd 服务 |
fence_kdump | 配合 kdump 采集崩溃转储 | 检测节点是否在 dump 中社区 | 通常作为 fencing topology 的第一级 |
fence_virt / fence_xvm | KVM 实验环境 | 宿主机 fence_virtd | pcmk_host_list |
fence_aws / fence_gce / fence_azure_arm | 公有云 | 云 API 停止实例 | 随平台 |
10.3 SBD(Storage-Based Death)+ Watchdog
当环境没有可靠的带外管理(如某些虚拟化平台或刀片),SBD 是最常用的替代方案。RHEL10 官方 Ch.10
- watchdog-only 模式:不需要共享存储。节点失去 quorum 或自检异常时,硬件/软件 watchdog 超时未被喂狗 → 自动复位本机。安装
sbd包。 - poison-pill 模式:需要 1~3 个共享块设备(SBD 分区,约 8MB 即可)。其他节点往目标节点的 slot 里写"毒丸"消息,目标节点的 sbd 进程读到后主动自杀。安装
sbd+fence-agents-sbd。 - 关键前提:必须有可用的 watchdog 设备(
/dev/watchdog,硬件 watchdog 优先;虚机可用softdog,但可靠性较低)。
10.4 Fencing Topology(多级隔离)
当单一 fence 设备可能失效(例如 PDU 与服务器共用一路电源)时,可配置多级 fencing:第 1 级失败后自动尝试第 2 级。
# 级别 1:先试 IPMI;失败则级别 2:切 PDU 电源
pcs stonith level add 1 node1.example.com ipmi-node1
pcs stonith level add 2 node1.example.com apc-pdu
# 典型组合:kdump 优先(保留崩溃转储),再走 IPMI
pcs stonith level add 1 node1.example.com kdump-node1
pcs stonith level add 2 node1.example.com ipmi-node1
pcs stonith level config # 查看
pcs stonith level remove 2 node1.example.com
10.5 STONITH 常用命令
pcs stonith list # 列出本机可用的 fence agent
pcs stonith list ipmi # 关键字过滤
pcs stonith describe fence_ipmilan # 查看参数(配置前必看)
# 创建(官方 APC SNMP 示例)
pcs stonith create myapc fence_apc_snmp \
ipaddr="zapc.example.com" \
pcmk_host_map="z1.example.com:1;z2.example.com:2" \
login="apc" passwd="apc"
pcs stonith config # 查看已配置的 stonith 资源
pcs stonith status
pcs stonith fence node2.example.com # ⚠ 真的会把 node2 打掉(测试用)
pcs stonith confirm node2.example.com # 手工确认节点已死(仅在确实已断电时使用!)
stonith_admin --history="*" # fencing 历史
pcs stonith history show
| 关键参数 | 作用 |
|---|---|
pcmk_host_list | 该 fence 设备能隔离哪些节点(名称列表) |
pcmk_host_map | 集群节点名 → 设备端口/插座 的映射,如 "node1:1;node2:2" |
pcmk_delay_base | 固定延迟。双节点上给两台设不同值(如 node1=0s、node2=10s)可确定性地决出胜者 |
pcmk_delay_max | 随机延迟上限,用于打破 fence 竞态 |
pcmk_reboot_action | 覆盖默认动作 |
pcmk_monitor_timeout | fence 设备自身的监控超时 |
双节点网络断开时,两边会同时尝试 fence 对方,可能导致两台机器互相打死(双双下线)。解决方案:① 给两个 stonith 资源配置不同的 pcmk_delay_base;② 或使用集群属性 priority-fencing-delay,让承载资源较少的节点延迟动手。详见配套的《双节点配置文档》。
11Quorum 法定票数
Quorum 回答一个问题:"我这个分区,有没有资格代表整个集群提供服务?"由 Corosync 的 votequorum 模块负责。RHEL10 官方 Ch.27
11.1 基本规则
默认规则:一个分区必须拥有 超过总票数一半(> 50%)的票,才算有 quorum。
- 3 节点集群:需 ≥2 票 → 可容忍 1 节点故障 推荐
- 5 节点集群:需 ≥3 票 → 可容忍 2 节点故障
- 2 节点集群:需 ≥2 票 → 理论上任何一个节点故障都会失去 quorum! 所以必须特殊处理(见下)
- 4 节点集群:需 ≥3 票 → 只能容忍 1 节点故障,性价比不如 3 节点。集群节点数建议为奇数
11.2 votequorum 关键参数
| 参数 | 作用 | 注意 |
|---|---|---|
two_node: 1 | 双节点专用。使 quorum 计算变为"只要有 1 票就算有 quorum" | 由 pcs cluster setup 在双节点时自动写入。此时完全依赖 fencing 防脑裂 |
wait_for_all: 1 | 集群首次启动时必须所有节点都可见才获得 quorum | two_node: 1 时自动隐式启用社区/votequorum(5),防止冷启动脑裂 |
last_man_standing: 1 | 允许集群随节点逐个退出而动态下调 expected_votes | 需配合 last_man_standing_window;与 two_node 互斥 |
auto_tie_breaker: 1 | 票数刚好对半时,包含指定节点(默认最小 nodeid)的分区获胜 | 偶数节点集群可用 |
expected_votes | 期望总票数 | 一般由节点数自动推导,不建议手改 |
11.3 Quorum Device(qdevice)—— 双节点的正解
| 组件 | 装在哪 | 包名 |
|---|---|---|
corosync-qnetd | 集群外部的第三方主机(可以是一台很小的虚机,甚至可为多个集群共用) | corosync-qnetd + pcs |
corosync-qdevice | 每个集群节点 | corosync-qdevice |
算法选择:ffsplit(fifty-fifty split,默认,对半分裂时投给节点数相同则由 qnetd 裁决)与 lms(last man standing,允许只剩最后一个能连上 qnetd 的节点继续运行)。
pcs quorum status # 当前票数与 quorum 状态(最常用)
pcs quorum config # quorum 配置
corosync-quorumtool -s # 底层视图
pcs quorum device status # qdevice 客户端状态
pcs qdevice status net --full # 在 qnetd 主机上查看服务端状态
12管理工具链
RHEL 10 官方提供三种集群部署、监控与管理工具。RHEL10 官方 Ch.1
pcs 命令行
控制并配置 Pacemaker 与 corosync。可创建配置集群、在线修改配置、启动/停止/查看状态。本培训主要使用。
HA Cluster Management
RHEL web console 插件
图形化创建与配置集群,安装 cockpit-ha-cluster 包后通过 RHEL Web 控制台使用。
ha_cluster RHEL 系统角色
用 Ansible 系统角色声明式配置与管理 Pacemaker 集群,适合批量与标准化交付。
过去大家熟悉的 pcsd Web UI(https://node:2224)在 RHEL 10 文档中已被 cockpit-ha-cluster 取代作为官方推荐 GUI。但 pcsd 服务本身仍然必需(节点间通信与认证,TCP 2224)。
12.1 pcs 命令地图
| 子命令 | 管什么 | 高频用法 |
|---|---|---|
pcs host | 节点认证 | pcs host auth node1 node2 |
pcs cluster | 集群生命周期 | setup / start / stop / enable / destroy / cib / status / report |
pcs status | 状态总览 | pcs status --full |
pcs resource | 资源 | create / config / enable / disable / move / clear / cleanup / group |
pcs constraint | 约束 | location / colocation / order / delete |
pcs stonith | 隔离 | list / describe / create / level / fence / history |
pcs property | 集群属性 | config / set / describe |
pcs quorum | 法定票数 | status / config / device add |
pcs qdevice | 仲裁服务端 | setup model net / status net --full |
pcs node | 节点操作 | standby / unstandby / maintenance / attribute |
pcs config | 配置导出/备份 | pcs config / backup / restore |
pcs alert | 告警 | create path=... / recipient add |
pcs acl | 访问控制 | role create / user create |
12.2 底层工具(排障时很有用)
| 命令 | 用途 |
|---|---|
crm_mon -1 / -A / -r | 状态快照 / 显示节点属性 / 显示未运行资源 |
cibadmin --query [--scope X] | 直接读写 CIB(谨慎) |
crm_simulate -SL | 模拟决策,看集群"打算做什么" |
crm_resource --locate -r <rsc> | 某资源当前在哪个节点 |
crm_verify -L -V | 校验 CIB 配置合法性 |
crm_attribute / attrd_updater | 节点属性读写 |
stonith_admin | fencing 底层管理与历史 |
pcs cluster report --from "YYYY-MM-DD H:M" | 一键打包全集群日志与配置,提交 Red Hat Support 必备 |
13高级特性
Pacemaker Remote
通过 pacemaker-remoted 让节点承载资源但不参与 corosync 成员与选举,突破 corosync 的节点数上限(通常 32)。分两类:remote node(独立主机)与 guest node(由集群管理的虚机)。需放行 TCP 3121。
Booth 多站点集群
跨机房/跨地域场景。由 booth arbitrator 管理 ticket,只有持票站点才能运行资源,配合 pcs constraint ticket。需放行 TCP/UDP 9929。
GFS2 + DLM + 共享 LVM
需要多节点同时读写同一文件系统时使用。依赖 dlm(分布式锁管理,clone 资源)、lvmlockd、gfs2-utils。此场景 no-quorum-policy 应设为 freeze,并放行 TCP 21064。属于 Resilient Storage Add-On。
单节点独占 LVM
只需主备独占访问时用 LVM-activate + system_id 方式,比 GFS2 简单得多。大多数主备场景应选这个。
集群告警 Alerts
pcs alert create path=/path/to/script,在资源/节点/fencing 事件发生时调用外部脚本(发邮件、推 IM、写监控系统)。
ACL 访问控制
pcs acl 定义角色与权限,让运维人员只能查看或只能操作特定资源,避免误操作。
14RHEL 10 变化要点
| 主题 | RHEL 8 / 9 | RHEL 10 |
|---|---|---|
| 官方 GUI | pcsd Web UI(https://node:2224)为主 | HA Cluster Management RHEL web console 插件(cockpit-ha-cluster 包)成为文档推荐 GUI |
| 自动化 | ha_cluster 系统角色已存在 | 在概览章节被正式列为三大官方工具之一,推荐用于标准化交付 |
| 传输层 | RHEL 8 起默认 knet | 延续 knet,官方明确写明 corosync 使用 kronosnet 库提供多冗余链路与自动故障切换 |
| 软件仓库 | rhel-9-for-x86_64-highavailability-rpms | rhel-10-for-x86_64-highavailability-rpms |
| 认证命令 | RHEL 8 起 pcs host auth 取代 pcs cluster auth | 沿用 pcs host auth |
| rgmanager / CMAN | RHEL 7 起已废弃 | 完全不存在,只有 Pacemaker 栈 |
| Booth 端口 | 9929 | 9929 TCP/UDP(官方端口表已列出) |
从 RHEL 8/9 升级到 RHEL 10 时,集群配置(CIB、corosync.conf)通常可平滑继承,但请务必:① 确认所用 fence agent 在 RHEL 10 中仍受支持;② 若依赖 pcsd Web UI,改为部署 cockpit-ha-cluster;③ 采用滚动升级(一次一节点:standby → 升级 → 重启 → unstandby → 验证),不要两台同时升。
15速查表:包 / 服务 / 端口
15.1 软件包
| 包 | 作用 | 装在哪 |
|---|---|---|
pcs | 命令行管理工具 + pcsd 守护进程 | 所有集群节点、qnetd 主机 |
pacemaker | 集群资源管理器核心 | 所有集群节点 |
corosync | 消息与成员层(作为依赖自动安装) | 所有集群节点 |
fence-agents-all | 全部 fence agent;也可只装 fence-agents-<model> | 所有集群节点 |
resource-agents | OCF 资源代理集合(依赖自动安装) | 所有集群节点 |
corosync-qnetd | 仲裁服务端 | 第三方仲裁主机 |
corosync-qdevice | 仲裁客户端 | 所有集群节点 |
sbd / fence-agents-sbd | SBD watchdog-only / poison-pill | 按需 |
cockpit-ha-cluster | Web 控制台 HA 管理插件 | 按需 |
pcp-zeroconf | 性能数据采集(官方建议安装,便于事后分析) | 可选 |
dlm / lvm2-lockd / gfs2-utils | 共享集群文件系统(Resilient Storage) | 仅 GFS2 场景 |
15.2 系统服务
| 服务 | 说明 |
|---|---|
pcsd.service | 必须 enable + start。节点间认证与 pcs 远程操作的基础 |
corosync.service | 由 pcs cluster start 拉起,一般不手工操作 |
pacemaker.service | 同上 |
corosync-qdevice.service | 使用 qdevice 时 |
corosync-qnetd.service | 仲裁主机上 |
sbd.service | 使用 SBD 时 |
15.3 防火墙端口(官方 Table 3.1)RHEL10 官方
| 端口 | 协议 | 用途 |
|---|---|---|
| 2224 | TCP | pcsd 默认端口,所有节点必须开放(含 Booth、qdevice 主机) |
| 3121 | TCP | 集群包含 Pacemaker Remote 节点时需要 |
| 5403 | TCP | 使用 corosync-qnetd 仲裁设备的主机需开放 |
| 5404–5412 | UDP | corosync 节点间通信(必需) |
| 21064 | TCP | 集群含 DLM 资源(如 GFS2)时需要 |
| 9929 | TCP/UDP | Booth 多站点票据管理器(所有节点及 arbitrator) |
firewall-cmd --permanent --add-service=high-availability
firewall-cmd --add-service=high-availability
firewall-cmd --list-services
15.4 重要文件路径
| 路径 | 内容 |
|---|---|
/etc/corosync/corosync.conf | Corosync 配置(勿手改) |
/var/lib/pacemaker/cib/cib.xml | CIB 主文件(勿手改) |
/var/lib/pacemaker/cib/cib-*.raw | CIB 历史版本备份 |
/usr/lib/ocf/resource.d/<provider>/ | OCF 资源代理脚本所在目录 |
/usr/sbin/fence_* | fence agent 可执行文件 |
/var/log/pacemaker/pacemaker.log | Pacemaker 主日志 |
/var/log/cluster/corosync.log | Corosync 日志 |
/var/log/messages | 汇总日志(含集群关键事件) |
/etc/sysconfig/sbd | SBD 配置 |
16动手实验与自测
16.1 建议的实验序列
| # | 实验 | 验收标准 |
|---|---|---|
| 1 | 搭建双节点集群并观察 corosync.conf | 能指出 two_node: 1 出现在哪一段,并解释含义 |
| 2 | 用 ps -ef | grep pacemaker 找出全部守护进程 | 能逐个说出每个进程的职责,并定位当前 DC |
| 3 | 导出 CIB 并找到 configuration 与 status 两段 | 能说明二者区别 |
| 4 | 创建 VIP 资源,用 ip a 观察它在哪台机器上 | VIP 可 ping 通,pcs status 显示 Started |
| 5 | pcs node standby 触发切换,观察日志 | 能在日志中找到 transition 与资源迁移记录 |
| 6 | 故意杀掉资源进程,观察 monitor 触发恢复 | 理解 failcount 与 migration-threshold 的关系 |
| 7 | 配置 fencing 并执行 pcs stonith fence | 目标节点确实被重启,集群正确接管 |
| 8 | 断开心跳网模拟脑裂 | 观察 quorum 变化与 fencing 行为;再加 qdevice 重做一遍对比 |
16.2 自测题(点击展开答案)
集群里的 DC 节点是不是"主节点"?资源会优先跑在 DC 上吗?
不是。DC 只是被选出来做决策计算的节点(它的 pacemaker-schedulerd 是唯一工作的调度器)。资源放在哪完全由约束与分数决定,与 DC 身份无关。DC 宕机后会立即重选,不影响业务。
为什么双节点集群 pcs cluster setup 会自动写入 two_node: 1?带来什么风险?
因为标准 quorum 规则下 2 节点需要 2 票,任一节点故障就会失去 quorum,集群直接停摆,失去 HA 意义。two_node: 1 让 1 票即算有 quorum。风险:网络分区时两边都认为自己有 quorum → 脑裂。因此必须依赖 fencing(并推荐加 qdevice)来兜底。同时 two_node: 1 会自动隐式启用 wait_for_all,防止冷启动时两边各自成群。
集群"卡住不切换",资源既不启动也不报错,最应该先查什么?
查 fencing。Pacemaker 在 fence 未成功确认前绝不会在其他节点启动资源(否则可能双写)。依次检查:pcs stonith status、pcs stonith history show、fence 设备网络/凭据是否可达、pcs property config stonith-enabled。日志里搜 fence、Requesting fencing、pending。
pcs constraint colocation add A with B INFINITY 到底谁跟着谁?
A 跟着 B。集群先为 B 选节点,再把 A 放到同一节点。副作用:如果 A 因故无法在 B 所在节点启动,可能连带影响 B 的放置决策。写约束时把"从属方"放在 with 前面。
为什么不建议在生产上设置 stonith-enabled=false?实验环境可以吗?
生产上禁止:没有 fencing 就无法确认失联节点是否真的停止访问共享资源,脑裂时会造成不可逆的数据损坏;Red Hat 也不为此类集群提供支持。实验环境(无共享存储、纯功能演示)可临时关闭,但要清楚这时集群的故障切换行为与生产完全不同,不能作为验证依据。
resource-stickiness 设为 0 和 100 有什么实际差别?
为 0 时,故障节点修复回归集群后,如果它的 location 分数更高,资源会自动漂回去 —— 这意味着第二次业务中断。设为正值(如 100)后,资源倾向留在当前节点,只有必要时才迁移,避免"来回抖动"。多数生产集群都应该设置一个正的默认黏性。
OCF、systemd、lsb 三种资源类型该怎么选?
优先 OCF:支持传参、有规范的返回码、monitor 语义完整,集群能准确判断"运行中/已停止/失败"。没有合适 OCF RA 时用 systemd,但必须在所有节点 systemctl disable 该服务,避免与集群抢管理权。lsb 仅用于遗留脚本,返回码不规范容易误判。
qdevice 和"再加一个集群节点"相比,优势是什么?
qnetd 主机不运行 pacemaker、不承载任何资源、不需要访问共享存储、不需要 fence 设备,可以是一台很轻量的虚机,甚至被多个集群共用。它只提供投票仲裁。相比之下,增加第三个真正的集群节点意味着完整的软件栈、存储连接与 fencing 配置,成本高得多。
17官方参考资料
17.1 RHEL 10 官方文档(主要来源)
- Configuring and managing high availability clusters(RHEL 10 文档首页)
- 同上 · 单页 HTML 全文版(便于全局检索)
- Ch.1 High Availability Add-On overview(架构组件 / 工具 / 配置文件)
- Ch.3 Creating a Red Hat High-Availability cluster with Pacemaker(安装/端口/setup)
- Ch.4 Configuring an active/passive Apache HTTP server
- Ch.9 Configuring fencing in a Red Hat High Availability cluster
- Ch.10 Configuring SBD fencing
- Ch.23 Controlling cluster behavior(集群属性)
- Ch.27 Configuring cluster quorum
- Ch.28 Configuring quorum devices
- Ch.32 Performing cluster maintenance
17.2 补充来源
- RHEL 9《Configuring and managing high availability clusters》单页版(用于 pcs 语法差异对照)RHEL9 官方
- Red Hat High Availability Add-On Documentation Guide(文档导航)
- ClusterLabs · Pacemaker 上游官方文档社区(守护进程实际命名、CIB 内部结构、score 运算规则)
man 5 votequorum、man 5 corosync.conf、man 8 pcs、man 8 crm_simulate社区
本培训文档的实操篇为 《RHEL 10 双节点 Pacemaker 高可用集群部署配置文档》(pacemaker-two-node-cluster-setup.html),包含从零到可用的完整命令、qdevice 与 fencing 实操、验证测试用例与运维排错清单。建议配合阅读。