资讯动态

DRBD+Pacemaker+Corosync:MySQL高可用集群搭建与避坑指南

发布时间:2026/10/16 13:39:59 来源:尧图企业网站定制
1. 为什么在高可用方案里我最终选了 DRBD 这条路线做数据库高可用这些年MySQL 的主备方案我前后搭过不下十套。早期用主从复制加脚本探活后来试过 MHA、Orchestrator 这类中间件方案再往后接触到基于共享存储和块设备同步的思路。绕了一圈之后在中小规模、对数据一致性要求高、又不想引入太多组件的场景里我最终稳定下来的方案是DRBD Pacemaker Corosync这套组合。先把这套方案是什么讲清楚。DRBD 负责的是块设备级别的数据同步它把两台机器上的磁盘分区做成一个镜像关系主节点写入的数据会同步到备节点从操作系统角度看就是一块随时可以切换主人的网络磁盘。Pacemaker 是集群资源管理器它决定谁现在是主、谁持有这块盘、MySQL 跑在哪台机器上。Corosync 则是底层的集群通信层负责节点之间的心跳和消息传递让 Pacemaker 知道每台机器是死是活。这三者分工非常清晰Corosync 管活着没Pacemaker 管该谁干活DRBD 管数据在不在。MySQL 本身不需要做任何主从复制的配置它只是跑在 DRBD 提供的那块盘上谁挂载了这块盘、谁启动 MySQL谁就是当前的主库。这套方案能解决什么问题核心是自动故障切换。当主节点宕机、网络中断或者 MySQL 进程挂掉时Pacemaker 会检测到资源异常自动把 DRBD 提升到备节点、挂载文件系统、启动 MySQL整个过程通常在一分钟内完成业务侧只需要重连即可。相比主从复制方案它最大的优势是数据强一致——因为只有一份数据在写不存在主从延迟导致的数据丢失窗口。适合谁来参考我觉得有三类人最合适一是中小团队里负责数据库运维的工程师手头就两三台机器想要一个不依赖云厂商的高可用方案二是已经用过主从复制、被延迟和脑裂问题折磨过的同行三是对集群资源管理感兴趣、想搞明白 Pacemaker 到底怎么调度资源的技术爱好者。这套方案不算轻量但一旦跑通稳定性非常让人放心。需要提前说明的是下面所有操作我都是在两台配置相同的服务器上完成的操作系统用的是主流的 Linux 发行版MySQL 用的是社区版。具体版本号我会在涉及兼容性的地方点出来其余不重要的地方就不啰嗦了。整个搭建过程我会把每一步为什么这么做讲透因为这套东西的坑基本都藏在细节里光抄命令很容易在某个环节卡住。2. 动手之前必须想清楚的几个底层机制2.1 DRBD 的主从角色和谁说了算很多人第一次接触 DRBD 会有一个误解以为它像 MySQL 主从那样两边都能写。不是的。DRBD 在任意时刻只有一个 Primary 节点可以读写另一个是 Secondary只负责接收同步数据。这个 Primary/Secondary 的角色切换就是整个高可用方案的核心动作。那谁来决定谁是 Primary答案是 Pacemaker。DRBD 自己有一个drbdadm primary命令可以手动提升但在集群里我们不会手动敲而是通过 Pacemaker 的 DRBD 资源代理resource agent来管理。Pacemaker 会根据资源约束、节点优先级、当前健康状态来决定把 Primary 角色放在哪台机器上。这里有个关键点DRBD 的 Primary 角色和 MySQL 的运行位置必须绑定在一起。也就是说DRBD 提升为 Primary 的那台机器才应该挂载文件系统、才应该启动 MySQL。如果这两者错位了比如 DRBD 在 A 机是 PrimaryMySQL 却在 B 机跑那 B 机根本读不到数据直接报错。所以后面配置 Pacemaker 约束时我们要用资源组或者顺序约束 位置约束把它们牢牢绑在一起。2.2 脑裂是怎么发生的以及怎么防脑裂split-brain是 DRBD 最需要警惕的问题。简单说就是两台机器都认为对方挂了于是各自把自己提升为 Primary两边都开始写数据。等网络恢复两份数据已经分叉DRBD 无法自动合并只能人工介入处理起来非常麻烦。脑裂的触发场景通常是心跳网络中断但机器本身还活着。比如 Corosync 用的那条网线断了或者交换机抽风两台机器互相 ping 不通但各自都在正常运行。这时候如果没有额外的防护机制Pacemaker 可能两边都尝试提升资源。防脑裂有几个层次的手段。第一层是冗余心跳链路Corosync 支持配置多条通信链路一条断了还有另一条。第二层是STONITHShoot The Other Node In The Head也就是爆头机制——当集群判定某个节点失联时通过带外管理比如 IPMI、电源管理接口直接把对方强制断电确保它不可能继续写数据。第三层是 DRBD 自身的自动降级策略可以配置成失去对端连接一段时间后自动放弃 Primary 角色。我在实际生产里STONITH 是必须配的。没有 STONITH 的 Pacemaker 集群在真正发生网络分区时行为是不可预测的官方文档也明确说不建议在生产环境关闭它。测试环境里可以临时关掉方便调试但上线前一定要补上。2.3 Corosync 的心跳和 Pacemaker 的决策是两回事新手容易把 Corosync 和 Pacemaker 混为一谈其实它们是两层。Corosync 只负责传递消息和判断节点存活它不关心你上面跑的是 MySQL 还是别的什么。Pacemaker 才是那个大脑它订阅 Corosync 提供的节点状态然后根据你定义的资源、约束、策略来做决策。这个分层理解很重要因为它决定了排查问题的方向。如果集群整个失去联系先查 Corosync 的通信如果节点都在但资源没切换那要查 Pacemaker 的配置和约束。我见过有人资源不切换就去重启 Corosync方向完全错了白折腾半天。Corosync 判断节点存活靠的是心跳超时。它会周期性地在节点间发送心跳包如果连续多个周期收不到某个节点的回应就判定它离线。这个超时时间可以调但调太短容易误判网络抖动就触发切换调太长切换又慢。经验值是一秒一次心跳、大概三到五次收不到就判定离线具体要看网络质量。2.4 文件系统选型为什么我不用普通 ext4DRBD 提供的是块设备上面还要建文件系统。这里有个坑普通文件系统在切换后可能因为日志回放导致挂载缓慢甚至失败。因为主节点宕机时文件系统可能处于已写入但日志未提交的状态备节点挂载时要做日志恢复。我的做法是用GFS2 或者直接上 XFS但更稳妥的方案是配合LVM使用并且在切换脚本里做好文件系统检查。实际上在单主同一时刻只有一个节点挂载的场景下ext4 也能用只是要在 Pacemaker 的资源里配置好fstype和挂载参数确保卸载干净。我个人的习惯是用 LVM 管理逻辑卷文件系统用 XFS因为 XFS 在大文件和并发写入场景下表现更稳而且挂载速度相对快。还有一个细节DRBD 设备上建文件系统之前必须先确保 DRBD 已经同步完成。如果两块盘数据不一致就建文件系统等于把不一致的状态固化下来后面切换必然出问题。所以初次搭建时一定要等drbdadm status显示两个节点都是UpToDate再往下走。3. 从裸机到集群分阶段搭建的完整链路3.1 基础环境准备和主机名解析两台机器我分别叫它们node-a和node-b这是集群里必须做好的第一步。Pacemaker 和 Corosync 都依赖主机名来识别节点如果主机名解析不稳定集群会莫名其妙地出问题。具体操作上先在两台机器的/etc/hosts里写死对方的 IP 和主机名不要依赖 DNS。因为集群启动早期 DNS 可能还没就绪用 hosts 文件最可靠。同时用hostnamectl把主机名设置成node-a和node-b确保hostname命令输出和 hosts 文件里一致。# 两台机器都执行注意 IP 换成你自己的 cat /etc/hosts EOF 192.168.1.10 node-a 192.168.1.11 node-b EOF hostnamectl set-hostname node-a # node-b 上改成 node-b时间同步也要做。集群节点之间时间差太大会导致日志时间戳混乱排查问题时非常痛苦。用系统自带的时间同步服务把两台机器对齐即可这个不用多说。然后是关闭防火墙或者放行必要端口。Corosync 默认用 UDP 5405 端口做心跳Pacemaker 和 DRBD 也有各自的通信端口。测试环境我一般直接关掉防火墙减少干扰生产环境则精确放行。这里提醒一句心跳网络最好和业务网络分开用独立的网卡或者 VLAN避免业务流量把心跳挤掉导致误判。3.2 DRBD 的资源配置和初次同步DRBD 的配置分两部分全局配置和资源定义。全局配置里我关注的是同步速率和协议。资源定义里则是具体的设备名、磁盘分区、节点地址。先看资源定义的核心结构。假设我用/dev/sdb1这块分区做数据盘DRBD 设备名用/dev/drbd0配置大概是这样# /etc/drbd.d/mysql.res resource mysql { protocol C; meta-disk internal; device /dev/drbd0; disk /dev/sdb1; on node-a { address 192.168.1.10:7789; } on node-b { address 192.168.1.11:7789; } }这里有几个关键选择要解释。protocol C是同步复制协议意思是主节点写入必须等到备节点确认收到才算完成。这是数据安全性最高的模式代价是写延迟受网络影响。对于数据库场景我强烈建议用 protocol C因为丢数据的代价远大于那点延迟。如果对性能极度敏感且能接受少量数据丢失可以考虑 protocol B半同步但数据库我不用。meta-disk internal表示元数据存在数据盘内部这样不用额外分区简单。缺点是元数据占用的空间会稍微减少可用容量但影响很小。配置写好后两台机器都要执行初始化drbdadm create-md mysql drbdadm up mysqlcreate-md是创建元数据区up是启动资源。这时候 DRBD 会尝试连接对端但两边都还没有 Primary数据也还没同步。接下来要在其中一台比如 node-a上强制把它设为 Primary 并开始初次同步drbdadm primary --force mysql这条命令会触发全量同步把 node-a 的数据复制到 node-b。同步时间取决于数据量和网络带宽几十 GB 的数据在千兆网下大概十几分钟。同步期间不要做任何写操作等drbdadm status显示两个节点都是UpToDate再继续。注意初次同步完成后node-a 是 Primarynode-b 是 Secondary。但这是手动状态后面交给 Pacemaker 管理时我们要先把 DRBD 资源停掉让 Pacemaker 重新接管避免状态冲突。3.3 在 DRBD 设备上建文件系统和挂载测试同步完成后在 Primary 节点node-a上对/dev/drbd0建文件系统。我前面说了用 XFSmkfs.xfs /dev/drbd0 mkdir -p /data/mysql mount /dev/drbd0 /data/mysql挂载后可以写个测试文件然后卸载把 DRBD 降级为 Secondary再在 node-b 上提升为 Primary、挂载看看文件在不在。这一步是验证数据同步是否真的生效非常关键别跳过。# node-a 上 umount /data/mysql drbdadm secondary mysql # node-b 上 drbdadm primary mysql mount /dev/drbd0 /data/mysql ls /data/mysql # 应该能看到刚才写的测试文件确认无误后把 node-b 也降回 Secondary、卸载让两边回到干净状态准备交给 Pacemaker。这一步做完DRBD 层面就算通了。3.4 Corosync 和 Pacemaker 的安装与集群初始化接下来装集群软件。不同发行版包名略有差异核心是corosync、pacemaker、pcs或者crmsh这几个。pcs是配置管理工具比直接编辑 XML 友好太多我强烈建议用它。装好后先启动 Corosync 的配置。用pcs初始化集群pcs cluster auth node-a node-b -u hacluster -p 你的密码 pcs cluster setup --name mysql_cluster node-a node-b pcs cluster start --all pcs cluster enable --allauth是配置节点间的认证setup是生成集群配置start是启动。启动后可以用pcs status看集群状态正常的话两个节点都应该是Online。这里有个很容易踩的坑hacluster用户的密码在两台机器上必须一致否则认证会失败。有些发行版安装后这个用户是锁定的需要先passwd hacluster设置密码。我第一次搭的时候就在这里卡了半天报错信息还不明显。集群起来后先别急着加资源用corosync-cfgtool -s确认心跳链路正常用pcs status corosync看成员节点。这些都正常了再往下走。3.5 把 DRBD、文件系统、MySQL 串成资源栈这是整个方案最核心的部分。我们要在 Pacemaker 里定义几个资源然后用约束把它们绑在一起形成一个要么全在这台、要么全在那台的整体。资源清单如下资源名类型作用drbd_mysqlocf:linbit:drbd管理 DRBD 主从角色fs_mysqlocf:heartbeat:Filesystem挂载 DRBD 设备mysql_serviceocf:heartbeat:mysql管理 MySQL 进程vip_mysqlocf:heartbeat:IPaddr2提供浮动 IP 供业务连接先创建 DRBD 的主从资源。DRBD 资源代理有个特殊之处它需要定义成master/slave 类型新版本叫 promotable因为要区分 Primary 和 Secondarypcs resource create drbd_mysql ocf:linbit:drbd \ drbd_resourcemysql \ op monitor interval15s roleMaster \ op monitor interval30s roleSlave pcs resource promotable drbd_mysql \ promoted-max1 promoted-node-max1 \ clone-max2 clone-node-max1 notifytruepromoted-max1是关键它保证同一时刻只有一个节点是 Primary。notifytrue让资源代理在角色变化时通知其他资源这是实现顺序联动的关键。然后创建文件系统、MySQL、VIP 资源pcs resource create fs_mysql ocf:heartbeat:Filesystem \ device/dev/drbd0 directory/data/mysql fstypexfs pcs resource create mysql_service ocf:heartbeat:mysql \ binary/usr/sbin/mysqld \ config/etc/my.cnf \ datadir/data/mysql \ op monitor interval20s pcs resource create vip_mysql ocf:heartbeat:IPaddr2 \ ip192.168.1.100 cidr_netmask24注意 MySQL 资源里的datadir要指向 DRBD 挂载点config指向配置文件。这里有个细节MySQL 的配置文件和数据目录都要放在 DRBD 盘上或者至少配置文件在两台机器上完全一致否则切换后可能因为配置差异启动失败。我习惯把配置也放到/data/mysql下通过软链接引用。3.6 约束配置让资源同生共死资源建好了但它们现在是各自为政的。Pacemaker 可能把 DRBD 放 A 机、MySQL 放 B 机那就乱套了。所以要用约束把它们绑起来。首先是顺序约束规定启动顺序DRBD 先提升为 Primary然后挂文件系统然后起 MySQL最后配 VIP。停止时反过来。pcs constraint order promote drbd_mysql-clone then fs_mysql pcs constraint order fs_mysql then mysql_service pcs constraint order mysql_service then vip_mysql然后是位置约束规定这些资源必须和 DRBD 的 Primary 在同一台机器上pcs constraint colocation add fs_mysql with master drbd_mysql-clone INFINITY pcs constraint colocation add mysql_service with fs_mysql INFINITY pcs constraint colocation add vip_mysql with mysql_service INFINITYINFINITY表示强制绑定不允许分开。这样配置下来整个资源栈就变成了一个整体DRBD Primary 在哪其他资源就跟到哪。最后可以设置节点优先级让集群默认倾向于在 node-a 上运行。比如给 node-a 设个更高的优先级这样正常状态下主库就在 node-anode-b 待命。这个用pcs node attribute配置即可。配置完成后用pcs status看整体状态应该能看到所有资源都起来了DRBD 在某个节点是Promoted其他资源都在同一节点。这时候用 VIP 连 MySQL能正常读写说明集群跑通了。4. 切换测试和那些让我熬夜的坑4.1 手动切换和自动切换的验证方法集群搭好不测试等于没搭。我一般分两步验证先手动切换再模拟故障自动切换。手动切换用pcs resource move或者pcs node standby。比如让 node-a 进入待命pcs node standby node-a这时候 Pacemaker 会把所有资源迁移到 node-b。观察pcs status应该看到 DRBD 在 node-b 变成 Promoted文件系统挂载、MySQL 启动、VIP 漂移。整个过程通常几十秒。切换完成后用 VIP 连上去数据应该完整。自动切换测试更狠一点直接在 Primary 节点上强制关机或者 kill 掉 MySQL 进程。如果是 kill MySQLPacemaker 的监控会发现进程没了触发重启或迁移如果是关机Corosync 检测到节点离线触发资源迁移。两种场景都要测。我建议测试时开着另一个终端持续 ping VIP这样能直观看到切换期间业务中断了多久。一般来说进程级故障恢复快一些节点级故障因为要等心跳超时会慢一点。4.2 切换后 MySQL 起不来的几种典型原因这是我最常遇到的问题切换动作完成了但 MySQL 启动失败集群进入降级状态。原因通常有这么几类。第一类是数据目录权限问题。DRBD 设备挂载后挂载点的属主属组可能不对MySQL 用户没有写权限。解决办法是在文件系统资源里配置好挂载后的权限或者用 Pacemaker 的Filesystem资源的options参数指定。我一般会在初始化时就把/data/mysql的属主设成mysql:mysql并且确保 DRBD 同步时这个权限也同步过去。第二类是PID 文件或 socket 文件残留。主节点宕机时MySQL 的 PID 文件可能还留在数据目录里备节点启动时看到 PID 文件以为已经有实例在跑就拒绝启动。这个要在 MySQL 配置里把pid-file和socket指向一个切换时会清理的位置或者在资源代理的启动脚本里加清理逻辑。第三类是InnoDB 日志恢复失败。如果主节点是非正常关闭InnoDB 需要做崩溃恢复。大多数情况能自动完成但如果数据文件损坏就会卡住。这也是为什么我强调要用 XFS 并且做好文件系统检查。遇到这种情况只能人工介入用innodb_force_recovery尝试拉起导出数据重建。4.3 脑裂的真实案例和恢复步骤我遇到过一次脑裂原因是心跳网线被误拔。当时两台机器都活着但互相收不到心跳结果两边都尝试提升 DRBD。好在 STONITH 配置生效了集群通过电源管理把其中一台强制断电避免了双写。但如果没有 STONITH或者 STONITH 也失效就会真的脑裂。恢复步骤是这样的先确认哪边的数据是更完整的通常选那个一直作为 Primary 的节点。然后在另一个节点上执行drbdadm disconnect mysql drbdadm secondary mysql drbdadm connect --discard-my-data mysql--discard-my-data表示丢弃本节点数据以对端为准重新同步。这一步非常危险一定要确认清楚哪边是要保留的选错了数据就没了。恢复后重新同步等两边一致再交回 Pacemaker 管理。注意脑裂恢复期间务必确保 MySQL 没有在任何一个节点上运行否则同步过程中数据还在变永远同步不完。4.4 STONITH 配置里那些不起眼但要命的细节STONITH 是防脑裂的最后一道防线但配置起来坑不少。我用的是 IPMI 电源管理每台机器通过带外网口控制对方电源。配置大概是这样pcs stonith create fence_node_a fence_ipmilan \ pcmk_host_listnode-a \ ipaddr192.168.2.10 \ loginadmin passwdxxx \ lanplus1 pcs stonith create fence_node_b fence_ipmilan \ pcmk_host_listnode-b \ ipaddr192.168.2.11 \ loginadmin passwdxxx \ lanplus1几个细节pcmk_host_list必须和集群里的节点名完全一致大小写都不能错。lanplus1表示用 IPMI 2.0 协议老版本可能不支持。密码里如果有特殊字符要注意转义。配置完一定要测试。用pcs stonith fence node-a手动触发一次看 node-a 是不是真的断电了。测试前确保业务已经切走不然就是生产事故。我见过有人配了 STONITH 但从来没测过真出事的时候发现密码错了防线形同虚设。5. 让这套方案在生产里跑得更稳的调优经验5.1 DRBD 同步速率和网络参数的取舍DRBD 的同步速率默认是不限制的初次全量同步时会把网络带宽吃满可能影响业务。可以在资源配置里加限速resource mysql { ... disk { resync-rate 100M; } net { max-buffers 8000; sndbuf-size 1M; } }resync-rate限制同步带宽生产环境我一般设成网络带宽的一半左右留出余量给业务。max-buffers和sndbuf-size影响同步吞吐调大能提升性能但吃内存要平衡。还有一个参数c-plan-ahead和c-fill-target是 protocol C 的延迟控制参数默认值在大多数场景够用网络延迟高的时候可以调。这个我一般不轻易动除非确实观察到同步延迟影响业务。5.2 Pacemaker 资源监控间隔的平衡监控间隔设太短频繁检查增加系统负担设太长故障发现慢。我的经验值是DRBD 的 Master 角色监控 15 秒一次Slave 30 秒一次MySQL 进程监控 20 秒一次VIP 监控 10 秒一次。这样在故障发现速度和系统开销之间比较平衡。另外可以配置资源的失败处理策略。比如 MySQL 启动失败后是重启几次还是直接迁移到另一节点。用op monitor的on-fail参数控制op monitor interval20s on-failrestartrestart表示先尝试重启重启几次还不行再迁移。这个比直接迁移更温和避免因为临时抖动就切换。5.3 日常巡检该看哪些指标集群跑起来不是就完事了日常要盯着几个关键点。我列一下自己的巡检清单检查项命令关注点集群整体状态pcs status有无 failed 资源DRBD 同步状态drbdadm status是否 UpToDate有无延迟心跳链路corosync-cfgtool -s链路是否正常资源位置pcs status --full资源是否在预期节点磁盘空间df -hDRBD 盘是否快满其中 DRBD 的同步状态最需要关注。如果看到Inconsistent或者SyncTarget说明正在同步或者数据不一致这时候切换是有风险的。正常情况下两个节点都应该是UpToDate。5.4 版本兼容性这个隐形杀手DRBD、Pacemaker、Corosync 这三个组件的版本兼容性非常重要而且不同发行版的打包版本差异很大。我踩过的坑是升级了 Corosync 但 Pacemaker 没跟着升结果集群通信协议不匹配节点起不来。我的建议是用发行版官方仓库里的版本组合不要自己混装。如果一定要升级先在测试环境验证。另外 DRBD 有内核模块和用户态工具两部分内核模块版本要和内核版本匹配升级内核后记得重新编译或安装对应的 DRBD 模块否则 DRBD 直接起不来。还有一点DRBD 从 8 到 9 有比较大的变化配置语法和资源代理都有调整。网上很多老教程是 DRBD 8 的照抄到 DRBD 9 上会报错。看文档时注意版本我一般直接看官方对应版本的文档。6. 写在最后的一点个人体会这套 DRBD Pacemaker Corosync 的方案我从第一次搭到稳定运行前后折腾了大概两周中间踩的坑基本都写在上面了。它不像云厂商的托管数据库那样点几下就能用但胜在完全自主可控、数据强一致、不依赖外部服务。对于数据量在几百 GB 以内、机器数量不多的场景我觉得性价比很高。如果让我给准备上手的人一句建议那就是先把 DRBD 单独跑通再叠 Pacemaker最后加 MySQL。不要一上来就把所有组件堆在一起调出了问题根本不知道是哪一层的锅。分层验证每层都确认无误再往上走这是最省时间的路径。另外STONITH 和脑裂恢复演练一定要做而且要定期做。高可用方案的价值只有在真出事的时候才体现出来平时不演练关键时刻手忙脚乱那这套集群就白搭了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑