概念
简介
- 块级别的同步方案
- 热备, 理解为网络 Raid 1
- 可支持双主复制模式, 需要使用集群文件系统
支持的类型
- 磁盘, 或磁盘分区
- 软 Raid 设备
- LVM 逻辑卷
- 任何块设备, 包括 内存盘RAMDISK
角色
- Primary - 主
- Secondary - 从
IO 请求流程 和 协议
- 用户向 FileSystem 发送 IO 请求
- FileSystem 接收 IO 请求后, 经过 buffer/cache 发送给 DRBD
- DRBD 将 IO 发送给本机存储
- 本机 IO 完成后, 通过 TCP 发送给对端 DRBD - 配置协议 A, 这步完成, 视为同步完成
- 收到 Secondary 确认接收消息 - 配置协议 B, 这步完成, 视为同步完成
- 收到 Secondary 写入完成消息 - 配置协议 C, 这步完成, 视为同步完成
日常同步逻辑
基于 IO 流
- 利用 Gituple 保证两端属于同一"代", 根据 Primary 此"代"的 IO 流, 在 Secondary 重复执行
- 常规同步
基于块做文件检查
- 拆分块文件, 并计算校验和, 传输校验和并找到不同步的块
- 查漏补缺
安装
准备工作
配置 hosts 文件
# 编辑 /etc/hosts 文件, 加入 DRBD 集群机器 IP 和 hostname 的对应关系
192.168.248.79 node-01
192.168.248.80 node-02
配置时间同步
# crontab -l
*/5 * * * * ntpdate ntp1.aliyun.com
配置互信
# 为了方便, 不配置不影响集群功能
ssh-keygen
ssh-copy-id dm1/dm2
部署
安装
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
yum install -y kmod-drbd84 drbd84-utils
配置文件
- /etc/drbd.conf
# 入口文件, 不用修改
# You can find an example in /usr/share/doc/drbd.../drbd.conf.example
include "drbd.d/global_common.conf";
include "drbd.d/*.res";
- /etc/drbd.d/global_common.conf
# 全局配置信息
global {
# 不汇报信息
usage-count no;
}
common {
net {
# 协议
protocol C;
# 在线设备验证加密算法
verify-alg md5;
# tcp buffer 设置, 影响同步速度
sndbuf-size 512K;
max-buffers 8192;
max-epoch-size 8192;
}
}
- dt.res(资源文件)
# 资源名 dt
resource dt {
# 生成设备 /dev/drbd1
device /dev/drbd1;
# 使用底层设备 /dev/thc_vg/datacube_lv
disk /dev/thc_vg/datacube_lv;
# 使用内部 metadata
meta-disk internal;
disk {
# 出现 io 错误的策略, 默认, 丢弃备份设备, 以无盘模式运行
on-io-error detach;
# 活动日志大小
al-extents 6433;
# 同步速率大小
resync-rate 1000M;
}
# 节点信息: 主机名, IP, PORT
on 192-168-248-79 {
address 192.168.248.79:7789;
}
on 192-168-248-80 {
address 192.168.248.80:7789;
}
}
启动(首次初始化)
# 创建元数据
drbdadm create-md dt
# 启动资源
drbdadm up dt
# 新盘上可以执行, 执行后即认为两端为同步状态
drbdadm new-current-uuid --clear-bitmap dt
# 指定一端为 Primary
drbdadm primary dt
# Primary 格式化文件系统
mkfs.xfs /dev/drbd1
# 挂载使用
mount /dev/drbd1 /thc/datacube
维护
常用命令
# 开/关<res>, 关闭后只能操作 wipe-md
drbdadm up/down dt
# 从网络层面连接/断开<res>
drbdadm connect/disconnect dt
# 切换主从角色, 必须先降级再卸载
drbdadm primary/secondary dt
# 创建/删除<res>的元数据
drbdadm create-md/wipe-md dt
# 基于块文件校验和检查一致性
drbdadm verify dt
# 重读配置文件
drbdadm adjust dt
# 查看过程
cat /proc/drbd
# 查看角色
drbdadm role dt
检查
-
drbdadm verify dt
会将块文件拆分为校验和去对端进行对比, 并记录不同步的地方, 日志打印在/var/log/messages
-
cat /proc/drbd
查看检查进度 -
tailf /var/log/message
查看日志 - 日志示例
# 如果完全一致, 应当如下
Feb 4 19:37:49 192-168-248-80 kernel: block drbd1: conn( Connected -> VerifyS )
Feb 4 19:37:49 192-168-248-80 kernel: block drbd1: Starting Online Verify from sector 41921096
Feb 4 19:37:49 192-168-248-80 kernel: block drbd1: Online verify done (total 1 sec; paused 0 sec; 10296 K/sec)
Feb 4 19:37:49 192-168-248-80 kernel: block drbd1: conn( VerifyS -> Connected )
Feb 4 19:38:17 192-168-248-80 kernel: block drbd1: conn( Connected -> VerifyS )
Feb 4 19:38:17 192-168-248-80 kernel: block drbd1: Starting Online Verify from sector 0
Feb 4 19:44:34 192-168-248-80 kernel: block drbd1: Online verify done (total 376 sec; paused 0 sec; 55772 K/sec)
Feb 4 19:44:34 192-168-248-80 kernel: block drbd1: conn( VerifyS -> Connected )
# 如果有不一致, 会出现类似如下信息
Feb 4 18:46:16 192-168-248-80 kernel: block drbd1: conn( Connected -> VerifyS ) disk( Inconsistent -> UpToDate ) pdsk( Inconsistent -> UpToDate )
Feb 4 18:46:16 192-168-248-80 kernel: block drbd1: Starting Online Verify from sector 0
Feb 4 18:46:16 192-168-248-80 kernel: block drbd1: Out of sync: start=0, size=8 (sectors)
Feb 4 18:46:16 192-168-248-80 kernel: block drbd1: Out of sync: start=24, size=8 (sectors)
Feb 4 18:46:16 192-168-248-80 kernel: block drbd1: Out of sync: start=64, size=8 (sectors)
Feb 4 18:46:16 192-168-248-80 kernel: block drbd1: Out of sync: start=96, size=32 (sectors)
Feb 4 18:47:22 192-168-248-80 kernel: block drbd1: Out of sync: start=10485424, size=32 (sectors)
Feb 4 18:48:39 192-168-248-80 kernel: block drbd1: Out of sync: start=20970848, size=40 (sectors)
Feb 4 18:48:39 192-168-248-80 kernel: block drbd1: Out of sync: start=20970896, size=16 (sectors)
切换(正常状态)
- Primary 卸载:
umount /dev/drbd1
- Primary 降级:
drbdadm secondary dt
- Secondary 升级:
drbdadm primary dt
- Secondary 挂载:
mount /dev/drbd1 /thc/datacube
恢复
方式 1 - 推荐
# 如果无法找到对端, 考虑重建元数据, 如果只是数据不同步, 可以跳过本步骤
# [在两台上执行]
umount /dev/drbd1
drbdadm secondary dt
drbdadm create-md dt
# 将两端断开资源链接
# [在两台上执行]
drbdadm disconnect dt
# 声明自己为 syncTarget, 同步对端数据
# [在 slave 执行]
drbdadm connect --discard-my-data dt
# 声明 Primary 角色
# [在 master 执行]
drbdadm primary dt
# 此时会开始全盘同步, 查看进度
cat /proc/drbd
方式 2 - 相当于手动检查手动触发同步
# 重建元数据
# [在两台上执行]
umount /dev/drbd1
drbdadm secondary dt
drbdadm create-md dt
# 将作为同步源的节点 bitmap 置零, 执行后状态为"同步"
drbdadm new-current-uuid --clear-bitmap dt
# 将作为同步源的节点升级, 挂载使用即可
drbdadm primary dt
mount /dev/drbd1 /thc/datacube
# 如果挂载碰到文件系统 superblock 报错
xfs_repair -L /dev/drbd1
# 检查
drbdadm verify dt
# 手动触发同步
drbdadm disconnect dt
drbdadm connect dt
# 再检查, 没有不同
drbdadm verify dt
# 执行切换即可
扩容(基于 LVM)
- Primary & Secondary 对 LVM 进行扩容:
lvextend -L +10G /dev/vg_test/lv_test
- Primary 系统调整空间大小:
xfs_growfs /thc/datacube
- Primary DRBD 调整空间大小:
drbdadm resize dt
- 检查是否同步:
df -Th
问题记录
无法挂载
- 由于同步未完成, 可通过
cat /proc/drbd
查看进度, 等待同步完成后, 即可 - 由于绑定了 lvm 的挂载, 执行
systemctl daemon-reload
脑裂
- 解决脑裂的核心就是, 使元数据中的 GI tuple 相同
# 能找到对端的情况下
umount /dev/drbd1
drbdadm secondary dt
drbdadm disconnect dt
# Secondary 执行
drbdadm connect --discard-my-data dt
# Primary 执行
drbdadm connect dt
drbdadm primary dt
- 如果以上操作不能解决, 重新创建元数据再执行
- 切勿格式化文件系统
补充
状态
dstate 状态
Inconsistent/Inconsistent 数据不一致, 同步期间属于正常状态
UpToDate:一致的最新的数据状态,这个状态为正常状态
DUnknown:当对等节点网络连接不可用时出现这种状态
Outdated:数据资源是一致的,但是已经过时
Diskless 无盘:本地没有块设备分配给DRBD使用,这表示没有可用的设备,或者使用drbdadm命令手工分离或是底层的I/O错误导致自动分离
Attaching:读取无数据时候的瞬间状态
Failed 失败:本地块设备报告I/O错误的下一个状态,其下一个状态为Diskless无盘
Negotiating:在已经连接的DRBD设置进行Attach读取无数据前的瞬间状态
Consistent:一个没有连接的节点数据一致,当建立连接时,它决定数据是UpToDate或是Outdated
cstate 状态
Connected 连接:DRBD已经建立连接,数据镜像现在可用,节点处于正常状态
WFConnection:等待和对等节点建立网络连接
StandAlone 独立的:网络配置不可用;资源还没有被连接或是被管理断开(使用 drbdadm disconnect 命令),或是由于出现认证失败或是脑裂的情况
Disconnecting 断开:断开只是临时状态,下一个状态是StandAlone独立的 modprobe drbd
Unconnected 悬空:是尝试连接前的临时状态,可能下一个状态为WFconnection和WFReportParams
Timeout 超时:与对等节点连接超时,也是临时状态,下一个状态为Unconected悬空
BrokerPipe:与对等节点连接丢失,也是临时状态,下一个状态为Unconected悬空
NetworkFailure:与对等节点推动连接后的临时状态,下一个状态为Unconected悬空
ProtocolError:与对等节点推动连接后的临时状态,下一个状态为Unconected悬空
TearDown 拆解:临时状态,对等节点关闭,下一个状态为Unconected悬空
WFReportParams:已经建立TCP连接,本节点等待从对等节点传来的第一个网络包
StartingSyncS:完全同步,有管理员发起的刚刚开始同步,未来可能的状态为SyncSource或PausedSyncS
StartingSyncT:完全同步,有管理员发起的刚刚开始同步,下一状态为WFSyncUUID
WFBitMapS:部分同步刚刚开始,下一步可能的状态为SyncSource或PausedSyncS
WFBitMapT:部分同步刚刚开始,下一步可能的状态为WFSyncUUID
WFSyncUUID:同步即将开始,下一步可能的状态为SyncTarget或PausedSyncT
SyncSource:以本节点为同步源的同步正在进行
SyncTarget:以本节点为同步目标的同步正在进行
PausedSyncS:以本地节点是一个持续同步的源,但是目前同步已经暂停,可能是因为另外一个同步正在进行或是使用命令(drbdadm pause-sync)暂停了同步
PausedSyncT:以本地节点为持续同步的目标,但是目前同步已经暂停,这可以是因为另外一个同步正在进行或是使用命令(drbdadm pause-sync)暂停了同步
VerifyS:以本地节点为验证源的线上设备验证正在执行
VerifyT:以本地节点为验证目标的线上设备验证正在执行
同步的其他方式
# 用于首次同步, 强制设置本机为 Primary, 会扫全盘, 检查同步状态
drbdadm primary --force dt
# 用于处理数据不同步时, 声明本机数据为脏数据, 同步对端数据
drbdadm connect --discard-my-data dt
# 将 DRBD 的 bitmap 清零, 让 DRBD 认为此时是同步状态, 设置一端为 Primary, 写数据即开始同步
# 执行前提, 两节点有连接, 且数据未同步
drbdadm new-current-uuid --clear-bitmap dt
元数据
- 在关闭的状态下可以导出元数据,
d dump-md dt >> /root/metadata
- 元数据有两种存放方式
internally
和externally
, 在资源配置文件中指定, 默认为internally
- Internal
- DRBD把它的 metadata 和实际生产数据存储于相同的底层物理设备中, 在设备的最后位置留出一个区域来存储 metadata
- 优点: 因为 metadata 是和实际生产数据紧密联系在一起的, metadata 会随实际生产数据的丢失和恢复, 不需要人为操作
- 缺点: 写操作会触发 metadata 更新, 导致额外两次磁头读写移动, 对吞吐量有负面影响
- external
- 把 metadata 和生产数据分开存储
- 优点: 对某些写操作, 提供某些潜在的改进
- 缺点: 恢复需要人工干预
- 推荐设备中已经存有数据, 而该设备不支持扩容和缩容
GI Tuple
- d dump-md dt >> /root/metadata
- 如果遇到报错
报错: Found meta data is "unclean", please apply-al first
, 可执行d apply-al dt
- 参考链接
- 参考链接 1
- 参考链接 2
同步速度
官方提示, 速率的设定最好设为网络带宽和磁盘读写速度中的最小者的 30%. 有两个示例
- 如果I/O能维持的读写速度为180MB/s, 而千兆网络所能维持的网络吞吐速度为110MB/s, 那么有效可用带宽为110MB/s, 该选项的推荐值为110 x 0.3 = 33MB/s
- 如果I/O速度为80MB/s,而网络连接速度可达千兆,那么有效可用带宽为80MB/s,推荐的rate速率应该为80 x 0.3 = 24MB/s