跳转到主要内容

【未完成】使用 Pacemaker 实现 MySQL 高可用

假设我们有一个 3 节点 MySQL 集群,显然我们需要有一个负载均衡/反向代理/自动故障转移服务,来将访问路由到可用的节点上。

传统上我们通常使用一个或一组负载均衡服务器来部署 HAProxy 或是 ProxySQL,访问该节点的 IP 就行了。

但要是部署 HAProxy 或是 ProxySQL 的负载均衡单个服务器挂了呢?
这就叫 SPOF,Single Point of Failure 单点故障。显然负载均衡也是需要高可用的。

那要是我们使用一组服务器部署负载均衡呢?
我想这样成本太高了。而且在流量不是太高和 Mysql 服务器性能不是太弱的情况下,完全可以和 Mysql 部署在同一台服务器上。

因此我觉得,我们可以在每一个 MySQL 节点上都部署一个  Pacemaker 来提供 VIP(Virural IP / 虚拟 IP) 来管理要路由到哪一个 MySQL 上,客户端始终访问 VIP 即可。
这样我们就可以保证只要有 MySQL 节点存活,就始终可以访问。
当然这就要求 MySQL 节点有多余的性能可以部署 Pacemaker。

如果你的应用场景需要网络层面的负载均衡,比如分散读取请求到多个节点,则你可能需要使用 Pacemaker 使 HAProxy 或  ProxySQL 高可用,然后再由它们转发到 MySQL 服务器,原理是一样的。

你也可以使用 Keepalived 来简单配置一个 VIP,只是功能上不如 Pacemaker 强大。

组件介绍与前言

Pacemaker 堆栈 PCS

pacemaker 是一个高可用的集群资源管理器,它的核心是一个能够协调一组机器上相互关联的服务的启动和恢复的分布式有限状态机(指 CRMd / Cluster Resource Management daemon)。
Pacemaker 支持多种资源代理标准(LSB 初始化脚本、OCF 资源代理、systemd 单元文件等)来管理任何服务,并且可以对它们之间的复杂关系(托管、排序等)进行建模。
Pacemaker 支持高级服务配置,例如依赖资源组、必须在多台机器上处于活动状态的克隆资源、可以在两个不同角色之间切换的资源以及容器化服务。

Pacemaker 堆栈包括以下组件:

名称

功能

libQB

 libqb 是一个库,其主要目的是为客户端/服务器应用程序提供高性能、可重用的功能,包括高性能日志记录、跟踪、IPC 和轮询

Corosync 消息层组件,管理成员关系、消息与仲裁,为高可用环境中提供通讯服务,位于高可用集群架构的底层,为各节点之间提供心跳信息
Resource agents  资源代理,在节点上接收 CRM 的调度,一般通过脚本对资源进行管理
Fencing agents 关闭不稳定或无答复的节点,以保障集群的其它资源,其主要功能是消除脑裂
Pacemaker 资源管理器,负责启停服务,位于集群架构中资源管理、资源代理层

这里有一点点迷惑,Pacemaker 堆栈是一组组件,其中包括 Pacemaker 本身。
在过去,Pacemaker 还支持 Corosync 1(有或没有 CMAN 的区别)以及 Heartbeat。
不同的发行版支持不同的集群层,需要不同的设置。我们将 Pacemaker 和集群层的每个组合称为“堆栈”。
真心希望 clusterlabs 能给它改个名字。 然而就是在 2.0 中全改成 pacemaker-xxxxx 的。

详情见:

说人话就是:

Pacemaker 是一个开源的集群资源管理器,用于监视和控制集群中的资源和服务。它可以管理各种资源,如虚拟 IP 地址、文件系统、数据库、应用程序等,以确保它们在集群节点之间实现高可用性。Pacemaker 提供了一个策略引擎,可以根据定义的资源约束和策略来自动调整资源的分配,以处理故障情况和负载均衡。

Corosync 是一个开源的通信框架,用于在集群节点之间提供高可用性集群通信。它提供了可靠的消息传递和集群成员检测机制,以确保节点之间的协调和同步。Corosync 负责维护集群成员的状态信息,以便 Pacemaker 可以基于此信息做出决策。它通常与Pacemaker 一起使用,作为 Pacemaker 的底层通信基础设施。

总之,Pacemaker 负责管理和监视集群资源,Corosync 则负责在集群节点之间提供通信和协同工作的能力,以确保高可用性和故障容忍性。它们共同构成了一个完整的高可用性解决方案,通常用于关键业务应用程序和服务的部署,以确保系统在面临硬件或软件故障时保持可用。

HAProxy

HAProxy 是一种开源、非常快速且可靠的反向代理,可为基于 TCP 和 HTTP 的应用程序提供高可用性、负载均衡和代理。

ProxySQL

ProxySQL 是一个开源的数据库代理服务器,主要用于数据库负载均衡、路由、缓存查询、读写分离、故障转移和监控等任务,可以自动故障转移,但没有 VIP 功能。

MySQL 集群选择

Percona XtraDB Cluster

在 MySQL 集群方面我选择了 Percona XtraDB Cluster (PXC),这是一种自由的使用 Galera Cluster 的多主集群,可以自动确保节点间数据一致性等(不支持 XA 事务)。

将普通 MySQL 服务器迁移至 PXC 很简单,只需卸载 Mysql 包(不会删除数据,但最好备份),然后安装 PXC 包,安装文档说明以引导方式启动第一个节点,添加其他节点后数据会自动同步,非常省心。
详见:https://docs.percona.com/percona-xtradb-cluster/8.0/install-index.html

注:当集群第一次启动或集群所有节点都离线的情况,需要以引导方式启动节点(systemctl start mysql@bootstrap.service),即该节点作为数据提供节点,以该节点的数据为基准同步到其他节点,同步完毕后可以 systemctl stop mysql@bootstrap.service 然后以普通方式启动数据库(systemctl start mysql.service)。如果所有节点都离线过则启动时所有节点都可能认为自己不是最后一个离开集群的节点而拒绝启动,此时需要查看 mysql 日志文件,里面大概会提到需要修改 /var/lib/mysql/grastate.dat 中的 safe_to_bootstrap1,修改后再次以引导方式启动节点即可。
崩溃恢复详见:https://docs.percona.com/percona-xtradb-cluster/8.0/crash-recovery.html

Galera Arbitrato (garb)

如果你不幸拥有偶数个节点且不想再添加一个相同性能的节点,那么可以添加一个轻量级 Galera Arbitrato(Galera 仲裁器),仲裁器作为集群普通成员参与投票(不储存数据,但集群同步数据时都会发它一份,所以你也需要考虑该节点的网络),此外 Galera Arbitrato 还可以充当节点之间的数据中继服务器,或是从此节点请求复制数据用来备份。
详见:https://docs.percona.com/percona-xtradb-cluster/8.0/garbd-howto.html

注:my.conf 中的 wsrep_cluster_address 无需填写 garb 节点地址,garb 配置文件中的 GALERA_NODES 无需填写本机地址。
garb 中的地址可以不与 wsrep_cluster_address 中的地址相同,garb 可以配置在不同网络中。
当 garb 正确加入节点后,你应该能看到 MySQL 中的 wsrep_cluster_size 数值增加。
(可通过 mysql> show status like 'wsrep%'; 查询)

Corosync Qnetd

既然 Galera Cluster 有仲裁器,那么 Pacemaker 堆栈有没有呢?
Corosync Qnetd 就是 Corosync 的仲裁器,它提供投票给 Corosync-qdevice,以共同决定群集的法定人数(Quorum)状态。

  • corosync-qdevice:是一个在集群的每个节点上运行的守护进程。它通过依据第三方仲裁者的决定向集群的仲裁子系统提供投票,以帮助集群在节点故障时维持仲裁。

  • corosync-qnetd:是一个运行在集群外部的守护进程,它提供投票给 corosync-qdevice 的网络模型。Corosync-qnetd 设计用来支持多个集群,运行时几乎不需要配置和维护状态,新的集群可以动态处理,无需配置文件。它还可以作为非 root 用户运行。qnetd 主要作为第三方仲裁,配合 qdevice 来提供投票仲裁服务,不属于集群内节点,不承担任何集群节点功能。

即需要在每个 Corosync 节点上安装 Corosync-qdevice,然后使用一台单独的节点部署 Corosync-qnetd,一个 Corosync-qnetd 可以为多个集群提供服务。

架构图可参考:https://www.ibm.com/docs/en/db2/11.5?topic=option-install-configure-qdevice-quorum


搭建

本文以 RHEL 8.9 为例,其它系统除包不同和配置文件路径可能不同外基本一致。

使用 2 节点 PXC (Percona XtraDB Cluster) 兼 Pacemaker 堆栈+ 1 节点 corosync-qnetd 兼 garb。

PXC 与 garb 已预先搭建完成注意事项在上文中,本文将关注 Pacemaker 堆栈。

以下操作默认需要在每个 Pacemaker 节点上执行,需要在 qnetd 节点上部署的另外说明。

 

启用储存库

Pacemaker 堆栈相关包都在 Red Hat Enterprise Linux High Availability Add-On 里,它很可能已经在你的订阅里了,但需要先启用。

如果你是 RHEL

查看储存库列表:

subscription-manager repos --list

EL 8:

subscription-manager repos --enable=rhel-8-for-x86_64-highavailability-rpms

EL 9:

subscription-manager repos --enable=rhel-9-for-x86_64-highavailability-rpms

如果你是 AlmaLinux、Rocky Linux 等克隆版

查看储存库列表:

访问各发行版官网,例如

EL 8:

dnf config-manager --set-enabled ha

EL 9:

dnf config-manager --set-enabled highavailability
安装并启用包
yum install corosync pacemaker pcs

如果你打算使用 Corosync Qnetd

那么需要在每个集群成员节点上安装 corosync-qdevice

yum install corosync-qdevice

然后在单独的节点上安装 corosync-qnetd

yum install corosync-qnetd

检查版本

# crmadmin --version
Pacemaker 2.1.6-9.1.el8_9
Written by Andrew Beekhof and the Pacemaker project contributors
# corosync -v
Corosync Cluster Engine, version '3.1.7'
Copyright (c) 2006-2021 Red Hat, Inc.

Built-in features: dbus systemd xmlconf vqsim nozzle snmp pie relro bindnow
Available crypto models: nss openssl
Available compression models: zlib lz4 lz4hc lzo2 lzma bzip2

其他版本可能有略微差异。

启用包

systemctl enable --now pcsd.service

验证状态

systemctl status pcsd.service

 

 

配置主机名解析和防火墙

请根据你的防火墙实现配置。

协议 方向 端口范围 用途
TCP 入站 2224 用于 pcsd、Web UI 和节点到节点通信。
TCP 入站 3121 用于和远程 Pacemaker 节点通讯。
TCP 入站 5403 用于 corosync-qnetd 和 corosync-qnetd 通讯。
UDP 入站 5404 用于 corosync 通讯(如果配置为多播 UDP)。
UDP 入站 5405 用于 corosync 通讯。

在 /etc/hosts 中或你的 DNS 中配置主机名解析。

10.100.100.101   server1
10.100.100.102   server2
10.100.100.200   qnetd

 

配置用户

安装包时已自动添加 Linux 用户 hacluster ,现在你需要为其设置密码。红帽建议每个节点上 hacluster 用户的密码都相同。

passwd hacluster

创建集群

在任意一个节点上执行

为每个节点进行身份验证。

执行后会要求输入用户名密码,用户名为 hacluster,密码则为你刚刚设置的密码。

pcs cluster auth [节点主机名] [...] [-u 用户名] [-p 密码]

例如

pcs host auth server1 server2

 

 

在任意一个节点上执行

创建集群并将设置文件同步到配置的节点

 

pcs cluster setup [--start] [--local] --name <集群名称> <节点1主机名> [节点2主机名] [...]
pcs cluster setup my_cluster --start server1 server2


待续

主要参考