DRBD + Pacemaker + Corosync 实现 GitLab 高可用
本文介绍基于 DRBD + Pacemaker + Corosync 实现 GitLab 高可用(High Availability, HA)的经典架构。该架构通常是一个 Active/Passive (主/备) 架构。只有一台机器(主节点)运行 GitLab 服务并挂载存储,另一台机器(备节点)实时同步数据。当主节点宕机,备节点会自动接管 VIP(虚拟IP)、挂载存储并启动服务。
介绍
DRBD
DRBD (Distributed Replicated Block Device) 是 Linux 平台下一种基于软件的、无共享(Shared-Nothing)的存储复制解决方案。可以把它理解为 “通过网络实现的 RAID 1(镜像)”。
DRBD 作为一个 内核模块 工作在 Linux 的 I/O 栈中。它位于 文件系统(如 XFS, ext4)和 物理磁盘(如 /dev/sdb)之间。
-
正常流程: 应用写数据 -> 文件系统 -> 物理硬盘。
-
DRBD 流程: 应用写数据 -> 文件系统 -> DRBD -> (同时写入:本地物理硬盘 + 通过网络发给对端 DRBD)。
-
RAID 1: 两块硬盘插在同一台电脑上,数据同时写两份。
-
DRBD: 两块硬盘插在两台不同的电脑上,通过网线连接,数据同时写两份。
DRBD 支持三种复制协议 (Replication Protocols),决定了数据的一致性和性能平衡。在高可用(HA)场景中,绝大多数情况使用协议 C。
-
Protocol C (同步复制 - Synchronous):
- 机制: 当本地磁盘写入成功,且收到远程节点的
写入确认后,才告诉应用程序写操作完成。 - 特点: 数据绝对安全(两边数据时刻一致)。但写入速度受网络延迟影响(写速度 = 磁盘速度 + 网络往返时间)。
- 场景: 高可用集群(如 GitLab HA, MySQL HA)。
- 机制: 当本地磁盘写入成功,且收到远程节点的
-
Protocol A (异步复制 - Asynchronous):
- 机制: 数据写入本地磁盘并发送到发送缓冲区后,立即告诉应用程序
完成。不等待对方确认。 - 特点: 写入速度快(接近本地磁盘),但如果主节点突然断电,可能丢失最近几秒的数据。
- 场景: 跨长距离的异地容灾(网络延迟大)。
- 机制: 数据写入本地磁盘并发送到发送缓冲区后,立即告诉应用程序
-
Protocol B (内存同步 - Memory Synchronous):
- 机制: 数据到达远程节点的内存后,即视为完成。
- 特点: 介于 A 和 C 之间,风险在于远程节点如果断电且数据未落盘,数据会丢失。
- 场景: 极少使用。
架构规划
本文是基于 CentOS 7/Rocky Linux 8 或 Ubuntu 20.04/22.04 通用的完整实施指南。
- Node1 (Primary): 192.168.1.101 (
gitlab-node1) - Node2 (Secondary): 192.168.1.102 (
gitlab-node2) - VIP (Virtual IP): 192.168.1.100 (用户访问此IP)
- 专用磁盘/分区:
/dev/sdb1(用于 DRBD 数据同步,两台机器需大小一致)
环境准备 (两台节点执行)
-
修改主机名与 Hosts
bash# /etc/hosts 192.168.1.101 gitlab-node1 192.168.1.102 gitlab-node2 -
关闭防火墙和 SELinux (生产环境建议配置规则)
bashsystemctl stop firewalld && systemctl disable firewalld setenforce 0 sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config -
时间同步 (非常重要)
bashyum install -y chrony systemctl enable --now chronyd -
配置 SSH 互信 确保 Node1 可以无密码 SSH 登录 Node2,反之亦然(用于文件拷贝和集群通信)。
部署 DRBD (数据镜像)
我们需要将 /var/opt/gitlab(GitLab 数据目录)放在 DRBD 设备上。
-
安装 DRBD CentOS:
yum install -y elrepo-release && yum install -y kmod-drbd90 drbd90-utilsUbuntu:apt install -y drbd-utils -
配置资源文件 在两台节点创建
/etc/drbd.d/gitlab.res: textresource gitlab { protocol C; # 同步复制协议,最安全 on gitlab-node1 { device /dev/drbd0; disk /dev/sdb1; # 你的实际物理分区 address 192.168.1.101:7788; meta-disk internal; } on gitlab-node2 { device /dev/drbd0; disk /dev/sdb1; # 你的实际物理分区 address 192.168.1.102:7788; meta-disk internal; } } -
初始化 DRBD (两台节点执行)
bashdrbdadm create-md gitlab drbdadm up gitlab -
设置主节点 (仅在 Node1 执行)
bashdrbdadm primary --force gitlab mkfs.xfs /dev/drbd0 # 格式化 DRBD 设备
安装 GitLab
-
安装依赖与软件包 (两台节点) 按照 GitLab 官网安装社区版 (CE) 或企业版 (EE)。
bashcurl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash yum install -y gitlab-ce -
挂载数据并迁移 (仅在 Node1 执行) 先将 DRBD 挂载到临时目录,把初始数据放进去。
bashmkdir -p /var/opt/gitlab mount /dev/drbd0 /var/opt/gitlab # 初次配置,生成配置文件 gitlab-ctl reconfigure gitlab-ctl stop # 此时 /var/opt/gitlab 中已有数据 umount /var/opt/gitlab -
同步配置文件 (重要) 将 Node1 的
/etc/gitlab/gitlab.rb和/etc/gitlab/gitlab-secrets.json拷贝到 Node2。注意:gitlab-secrets.json必须一致,否则加密数据无法在 Node2 解密。 bash# 在 Node1 执行 scp /etc/gitlab/gitlab.rb root@gitlab-node2:/etc/gitlab/ scp /etc/gitlab/gitlab-secrets.json root@gitlab-node2:/etc/gitlab/ -
修改 GitLab 配置 (两台节点) 编辑
/etc/gitlab/gitlab.rb: ruby# 设置为 VIP external_url 'http://192.168.1.100' # 禁用开机自启 (交由 HA 集群管理) # 注意:GitLab 的 systemd 服务名通常是 gitlab-runsvdir在两台机器上执行命令禁用自启:
bashsystemctl disable gitlab-runsvdir
部署 Pacemaker 集群
使用 Pacemaker 来管理 VIP、挂载 DRBD 和启动 GitLab 服务。
-
安装集群软件 (两台节点)
bashyum install -y pcs pacemaker corosync fence-agents-all systemctl enable --now pcsd passwd hacluster # 设置集群用户密码,两台需一致 -
创建集群 (仅在 Node1 执行)
bash# 认证 pcs cluster auth gitlab-node1 gitlab-node2 -u hacluster -p <你的密码> # 创建并启动集群 pcs cluster setup --name gitlab_cluster gitlab-node1 gitlab-node2 pcs cluster start --all pcs cluster enable --all # 禁用 STONITH (仅测试环境,生产环境强烈建议配置 STONITH/Fencing 设备以防脑裂) pcs property set stonith-enabled=false # 设置忽略 Quorum (因为只有2个节点,防止单节点无法工作) pcs property set no-quorum-policy=ignore
配置集群资源
我们需要定义三个资源:
- DRBD 数据资源 (Master/Slave 模式)
- 文件系统挂载
- GitLab 服务
- VIP
在 Node1 执行以下 PCS 命令:
-
配置 DRBD 资源
bashpcs resource create DrbdData ocf:linbit:drbd \ drbd_resource=gitlab op monitor interval=60s # 设置为主从克隆资源 pcs resource master DrbdDataClone DrbdData \ master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true -
配置文件系统资源
bashpcs resource create FsData Filesystem \ device="/dev/drbd0" directory="/var/opt/gitlab" fstype="xfs" -
配置 GitLab 服务资源 GitLab 启动较慢,需调大超时时间。
bashpcs resource create GitlabService systemd:gitlab-runsvdir \ op monitor interval=60s timeout=100s \ op start timeout=300s \ op stop timeout=300s -
配置 VIP 资源
bashpcs resource create VirtualIP IPaddr2 ip=192.168.1.100 cidr_netmask=24 -
配置资源约束 (顺序和组合) 必须按照顺序启动:DRBD主 -> 挂载文件系统 -> 绑定VIP -> 启动GitLab。
bash# 组合约束:FS、VIP、GitLab 必须在同一台机器运行 pcs constraint colocation add FsData with DrbdDataClone INFINITY with-rsc-role=Master pcs constraint colocation add VirtualIP with FsData INFINITY pcs constraint colocation add GitlabService with VirtualIP INFINITY # 顺序约束:先 Promote DRBD,再 Mount,再 VIP,最后 Start GitLab pcs constraint order promote DrbdDataClone then start FsData pcs constraint order start FsData then start VirtualIP pcs constraint order start VirtualIP then start GitlabService
验证与测试
-
查看状态
bashpcs status正常情况下,所有资源应该都在 Node1 上运行,Node2 为 Standby/Slave。
-
访问测试 浏览器访问
http://192.168.1.100,应能看到 GitLab 登录页。 -
故障模拟 (手动切换)
bash# 将 Node1 设为待机 pcs node standby gitlab-node1观察
pcs status,你会看到资源依次停止,DRBD 在 Node2 变为 Primary,服务在 Node2 启动。这通常需要几分钟时间(GitLab 启动较慢)。 -
脑裂恢复 (DRBD Split Brain) 如果两个节点都变成 Standalone 或数据不一致,需要手动恢复:
- 在从节点 (数据不要的那个) 执行:
bashdrbdadm secondary gitlab drbdadm connect --discard-my-data gitlab - 在主节点 (数据保留的那个) 执行:
bashdrbdadm connect gitlab
- 在从节点 (数据不要的那个) 执行:
关键注意事项
- GitLab 版本一致性: 升级 GitLab 时,必须先冻结集群,在两台机器升级相同版本,再恢复集群。
- GitLab 启动慢: GitLab 包含 Postgres、Redis、Unicorn 等多个组件,
gitlab-runsvdir启动后,内部服务还需要时间初始化。Pacemaker 的timeout设置一定要足够长。 - Fencing (STONITH): 在生产环境中,必须配置 Fencing 设备(如 IPMI 卡或 VMware 接口)。如果没有 Fencing,当心跳网络中断时,两台机器可能同时抢占 VIP 和 DRBD Primary,导致数据损坏(脑裂)。
- 日志: 故障排查查看
/var/log/messages和/var/log/cluster/corosync.log。