在Oracle Linux 7上使用双主DRBD和OCFS2设置O2CB集群
我们将使用O2CB和DRBD构建两个节点的主动/主动HA集群。
在我们开始之前
o2cb是OCFS2文件系统的默认群集堆栈。
它是一个内核内集群堆栈,包括用于跟踪集群中节点的节点管理器(o2nm),用于检测节点活动性的磁盘心跳代理(o2hb),用于集群内的网络代理(o2net)节点通信和分布式锁管理器(o2dlm)来跟踪锁资源。
它还包括一个合成文件系统dlmfs,以允许应用程序访问内核内dlm。
该群集堆栈具有两个配置文件,'/etc/ocfs2/cluster.conf'和'/etc/sysconfig/o2cb'。
前者跟踪群集布局,而后者跟踪群集超时。
仅在群集联机时才读取两个文件。
本文遵循的约定是[ALL]表示需要在所有群集节点上运行的命令。
软件
本文使用的软件:
- Oracle Linux Server 7.2版(Maipo)
- 内核-uek-3.8.13
- ocfs2-tools 1.8.6
- drbd-8.4
网络和防火墙配置
我们在VirtualBox上有两个Oracle Linux 7虚拟机,分别名为ora1和ora2.
联网
将使用以下网络:
- 10.8.8.0/24-可以访问Internet的LAN,
- 172.16.21.0/24-适用于o2cb的不可路由群集心跳线vlan,
- 172.16.22.0/24-DRBD的不可路由群集心跳线VLAN。
在“/etc/hosts”文件中定义的主机名和IP:
10.8.8.55 ora1 10.8.8.56 ora2 172.16.21.55 ora1-clust 172.16.21.56 ora2-clust 172.16.22.55 ora1-drbd 172.16.22.56 ora2-drbd
我们设置了以下主机名:
[ora1]# hostnamectl set-hostname ora1 [ora2]# hostnamectl set-hostname ora2
SELinux
SELinux设置为强制模式。
防火墙功能
o2cb群集堆栈要求禁用或者修改iptables,以允许专用网络接口上的网络流量。
这些是我们正在使用的iptables规则:
# iptables -S -P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -s 10.0.0.0/8 -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT -A INPUT -s 172.16.21.0/24 -d 172.16.21.0/24 -p tcp -m tcp --dport 7777 -j ACCEPT -A INPUT -s 172.16.21.0/24 -d 172.16.21.0/24 -p udp -m udp --dport 7777 -j ACCEPT -A INPUT -s 172.16.22.0/24 -d 172.16.22.0/24 -m comment --comment DRBD -j ACCEPT -A INPUT -p udp -m multiport --dports 67,68 -m state --state NEW -j ACCEPT -A INPUT -p udp -m multiport --dports 137,138,139,445 -j DROP -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -j LOG --log-prefix "iptables_input " -A INPUT -j REJECT --reject-with icmp-port-unreachable
我们还禁用了IPv6,打开“ /etc/sysctl.conf”进行编辑,然后放置以下内容:
net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1
[ALL]# sysctl -p
广播电视
DRBD是指被设计为构成高可用性集群的构建块的块设备。
这可以通过分配的网络镜像整个块设备来完成。
DRBD可以理解为基于网络的RAID-1.
DRBD安装
导入ELRepo软件包签名密钥,启用存储库并使用实用程序安装DRBD内核模块:
[ALL]# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org [ALL]# rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm [ALL]# yum install -y kmod-drbd84 drbd84-utils
为了避免SELinux出现问题直到解决,我们将免除SELinux控制中的DRBD流程:
[ALL]# yum install -y policycoreutils-python [ALL]# semanage permissive -a drbd_t
DRBD的LVM卷
我们为DRBD创建一个新的1GB逻辑卷:
[ALL]# lvcreate --name lv_drbd --size 1024M vg_oracle7
DRBD配置
当我们要使用作为共享群集文件系统的OCFS2(期望来自所有群集节点的并发读/写存储访问)时,必须在双主模式下配置用于存储OCFS2文件系统的DRBD资源。
在初始配置时,建议不要将allow-two-primaries选项设置为yes。
初始资源同步完成后,我们应该这样做。
[ALL]# cat /etc/drbd.d/ocfsdata.res resource ocfsdata { protocol C; meta-disk internal; device /dev/drbd0; disk /dev/vg_oracle7/lv_drbd; handlers { split-brain "/usr/lib/drbd/notify-split-brain.sh root"; } startup { wfc-timeout 20; become-primary-on both; } net { allow-two-primaries yes; after-sb-0pri discard-zero-changes; after-sb-1pri discard-secondary; after-sb-2pri disconnect; rr-conflict disconnect; csums-alg sha1; } disk { on-io-error detach; resync-rate 10M; # 100Mbps dedicated link # All cluster file systems require fencing fencing resource-and-stonith; } syncer { verify-alg sha1; } on ora1 { address 172.16.22.55:7789; } on ora2 { address 172.16.22.56:7789; } }
为DRBD资源创建本地元数据:
[ALL]# drbdadm create-md ocfsdata
确保已加载DRBD内核模块,调出DRBD资源:
[ALL]# modprobe drbd [ALL]# drbdadm up ocfsdata
我们应该有不一致的数据:
[ora1]# drbdadm dstate ocfsdata Inconsistent/Inconsistent
[ora1]# cat /proc/drbd version: 8.4.2 (api:1/proto:86-101) srcversion: D2C09D2CF4CCB8C91B02D14 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r---- ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:1048508
我们看到状态为“已连接”,这意味着两个DRBD节点正在正常通信,并且两个节点都处于“辅助”角色且数据不一致。
强制ora1成为主节点:
[ora1]# drbdadm primary --force ocfsdata
[ALL]# drbdadm dstate ocfsdata UpToDate/UpToDate
也强制ora2成为主节点:
[ora2]# drbdadm primary --force ocfsdata
这两个节点都是主节点,并且是最新的:
[ora1]# cat /proc/drbd version: 8.4.2 (api:1/proto:86-101) srcversion: D2C09D2CF4CCB8C91B02D14 0: cs:Connected ro:Primary/Primary ds:UpToDate/UpToDate C r---- ns:0 nr:0 dw:0 dr:1049420 al:0 bm:64 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
[ora1]# drbd-overview 0:ocfsdata/0 Connected Primary/Primary UpToDate/UpToDate
在启动时启用DRBD,因为我们不使用Pacemaker:
[ALL]# systemctl enable drbd
集群配置
OCFS2群集软件
每个节点都应运行相同版本的OCFS2软件和兼容版本的Oracle Linux Unbreakable Enterprise Kernel(UEK)。
[ALL]# yum install -y ocfs2-tools
为群集堆栈创建配置文件
集群应该处于离线状态,因为我们尚未创建集群:
[ora1]# o2cb cluster-status offline
创建集群定义:
[ora1]# o2cb add-cluster tclust
上面的命令创建配置文件“ /etc/ocfs2/cluster.conf”(如果尚不存在)。
核实:
[ora1]# o2cb list-cluster tclust cluster: node_count = 0 heartbeat_mode = local name = tclust
我们需要定义每个群集节点。
IP地址是节点将用于集群中的专用通信的IP地址。
[ora1]# o2cb add-node tclust ora1 --ip 172.16.21.55 [ora1]# o2cb add-node tclust ora2 --ip 172.16.21.56
核实:
[ora1]# o2cb list-cluster tclust node: number = 0 name = ora1 ip_address = 172.16.21.55 ip_port = 7777 cluster = tclust node: number = 1 name = ora2 ip_address = 172.16.21.56 ip_port = 7777 cluster = tclust cluster: node_count = 2 heartbeat_mode = local name = tclust
现在,将集群配置文件“ /etc/ocfs2/cluster.conf”复制到集群中的每个节点。
配置集群堆栈
如果遵循“ Oracle Linux发行版7管理员教程”,则会看到定义了以下命令来配置集群堆栈:
# /etc/init.d/o2cb configure
但是,在Oracle Linux 7.2上,不再找到o2cb init.d脚本。
因此,打开文件“/etc/sysconfig/o2cb”并手动配置集群堆栈。
# O2CB_ENABLED: 'true' means to load the driver on boot. O2CB_ENABLED=true # O2CB_STACK: The name of the cluster stack backing O2CB. O2CB_STACK=o2cb # O2CB_BOOTCLUSTER: If not empty, the name of a cluster to start. O2CB_BOOTCLUSTER=tclust # O2CB_HEARTBEAT_THRESHOLD: Iterations before a node is considered dead. O2CB_HEARTBEAT_THRESHOLD=21 # O2CB_IDLE_TIMEOUT_MS: Time in ms before a network connection is considered dead. O2CB_IDLE_TIMEOUT_MS=15000 # O2CB_KEEPALIVE_DELAY_MS: Max time in ms before a keepalive packet is sent O2CB_KEEPALIVE_DELAY_MS=2000 # O2CB_RECONNECT_DELAY_MS: Min time in ms between connection attempts O2CB_RECONNECT_DELAY_MS=2000
将集群配置文件“/etc/sysconfig/o2cb”复制到集群中的每个节点。
配置o2cb和ocfs2服务,以便它们在启用网络后在启动时启动:
[ALL]# systemctl enable o2cb [ALL]# systemctl enable ocfs2
使用configfs注册集群:
[ALL]# o2cb register-cluster tclust
启动集群:
[ALL]# systemctl start o2cb
[ora1]# systemctl status o2cb o2cb.service - Load o2cb Modules Loaded: loaded (/usr/lib/systemd/system/o2cb.service; enabled; vendor preset: disabled) Active: active (exited) since Sat 2015-03-12 15:37:06 GMT; 8s ago Process: 1223 ExecStop=/sbin/o2cb.init disable (code=exited, status=0/SUCCESS) Process: 1288 ExecStart=/sbin/o2cb.init enable (code=exited, status=0/SUCCESS) Main PID: 1288 (code=exited, status=0/SUCCESS) CGroup: /system.slice/o2cb.service └─1335 o2hbmonitor Mar 12 15:37:06 ora1 o2cb.init[1288]: checking debugfs... Mar 12 15:37:06 ora1 o2cb.init[1288]: Loading filesystem "configfs": OK Mar 12 15:37:06 ora1 o2cb.init[1288]: Loading stack plugin "o2cb": OK Mar 12 15:37:06 ora1 o2cb.init[1288]: Loading filesystem "ocfs2_dlmfs": OK Mar 12 15:37:06 ora1 o2cb.init[1288]: Mounting ocfs2_dlmfs filesystem at /dlm: OK Mar 12 15:37:06 ora1 o2cb.init[1288]: Setting cluster stack "o2cb": OK Mar 1 15:37:06 ora1 o2cb.init[1288]: Registering O2CB cluster "tclust": OK Mar 12 15:37:06 ora1 o2cb.init[1288]: Setting O2CB cluster timeouts : OK Mar 12 15:37:06 ora1 systemd[1]: Started Load o2cb Modules. Mar 12 15:37:06 ora1 o2hbmonitor[1335]: Starting
为集群配置内核
为了使o2cb正常运行,需要设置两个sysctl值。
必须启用第一个panic_on_oops才能将内核oops变成紧急情况。
如果o2cb运行所需的内核线程崩溃,则必须重置系统以防止集群挂起。
如果未设置,则另一个节点可能无法区分一个节点无法响应还是响应缓慢。
另一个相关的sysctl参数是panic,它指定在紧急情况后系统将自动重置的秒数。
在每个节点上,打开文件“ /etc/sysctl.conf”,并为panic和panic_on_oops设置建议值:
kernel.panic = 30 kernel.panic_on_oops = 1
重新加载:
[ALL]# sysctl -p
创建并填充OCFS2文件系统
请注意,创建OCFS2卷后,我们无法更改其块大小和群集大小。
[ora1]# mkfs.ocfs2 --cluster-size 8K -J size=32M -T mail \ --node-slots 2 --label ocfs2_fs --mount cluster \ --fs-feature-level=max-features \ --cluster-stack=o2cb --cluster-name=tclust \ /dev/drbd0 mkfs.ocfs2 1.8.6 Cluster stack: o2cb Cluster name: tclust Stack Flags: 0x0 NOTE: Feature extended slot map Jan be enabled Overwriting existing ocfs2 partition. Proceed (y/N): y Filesystem Type of mail Label: ocfs2_fs Features: sparse extended-slotmap backup-super unwritten inline-data strict-journal-super metaecc xattr indexed-dirs usrquota grpquota refcount discontig-bg Block size: 2048 (11 bits) Cluster size: 8192 (13 bits) Volume size: 1073668096 (131063 clusters) (524252 blocks) Cluster groups: 9 (tail covers 4087 clusters, rest cover 15872 clusters) Extent allocator size: 4194304 (1 groups) Journal size: 33554432 Node slots: 2 Creating bitmaps: done Initializing superblock: done Writing system files: done Writing superblock: done Writing backup superblock: 0 block(s) Formatting Journals: done Growing extent allocator: done Formatting slot map: done Formatting quota files: done Writing lost+found: done mkfs.ocfs2 successful Filesystem can be checked with fsck.ocfs2 and tuned with tunefs.ocfs2. Detect all OCFS2 volumes on a system:
[ora1]# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/mapper/vg_oracle7-lv_drbd o2cb tclust Not mounted /dev/drbd0 o2cb tclust Not mounted
显示OCFS2文件系统信息:
[ora1]# o2info --fs-features /dev/drbd0 backup-super strict-journal-super sparse extended-slotmap inline-data metaecc xattr indexed-dirs refcount discontig-bg clusterinfo unwritten usrquota grpquota
[ora1]# o2info --volinfo /dev/drbd0 Label: ocfs2_fs UUID: 30F0A6E6705249FF9F9E39231772C1FE Block Size: 2048 Cluster Size: 8192 Node Slots: 2 Features: backup-super strict-journal-super sparse extended-slotmap Features: inline-data metaecc xattr indexed-dirs refcount discontig-bg Features: clusterinfo unwritten usrquota grpquota
我们可以将元数据块从“/dev/drbd0”设备复制到drbd0.out文件(对于debugfs.ocfs2很方便):
[ora1]# o2image /dev/drbd0 drbd0.out
创建一个安装点:
[ALL]# mkdir -p /cluster/storage
在所有节点上添加到fstab:
/dev/drbd0 /cluster/storage ocfs2 rw,noatime,nodiratime,_netdev 0 0
山:
[ALL]# mount -a
除非我们在网络启动后启用了o2cb和ocfs2服务,否则文件系统将不会挂载。
确认已安装该卷。
[ora1]# mount -l|grep ocfs ocfs2_dlmfs on /dlm type ocfs2_dlmfs (rw,relatime) /dev/drbd0 on /cluster/storage type ocfs2 (rw,relatime,seclabel,_netdev,heartbeat=local,nointr,data=ordered,errors=remount-ro,atime_quantum=60,cluster_stack=o2cb,coherency=buffered,user_xattr,acl) [ocfs2_fs]
[ora1]# drbd-overview 0:ocfsdata/0 Connected Primary/Primary UpToDate/UpToDate /cluster/storage ocfs2 1.0G 82M 943M 8%
[ora1]# mounted.ocfs2 -f Device Stack Cluster F Nodes /dev/mapper/vg_oracle7-lv_drbd o2cb tclust ora1, ora2 /dev/drbd0 o2cb tclust ora1, ora2
处理SELinux
应用的默认安全上下文应为无标签的:
[ora1]# ls -dZ /cluster/storage drwxr-xr-x. root root system_u:object_r:unlabeled_t:s0 /cluster/storage/
应当加载OCFS2的xattr部分:
[ora1]# dmesg|grep xattr [11426.378173] SELinux: initialized (dev dm-3, type ext4), uses xattr [11432.780965] SELinux: initialized (dev sda1, type ext2), uses xattr [11804.273746] SELinux: initialized (dev drbd0, type ocfs2), uses xattr
我们将把安全性上下文更改为公共内容,每个文件系统仅一个安全性上下文。
在所有群集节点上相应地配置fstab并重新安装OCFS2卷:
/dev/drbd0 /cluster/storage ocfs2 rw,noatime,nodiratime,_netdev,context=system_u:object_r:public_content_t:s0 0 0
安全上下文应更改:
[ora1]# ls -dZ /cluster/storage drwxr-xr-x. root root system_u:object_r:public_content_t:s0 /cluster/storage/
重新启动系统并检查内核消息缓冲区,不应再加载xattr部分:
[ora1]# systemctl reboot
[ora1]# dmesg|grep xattr [12133.780006] SELinux: initialized (dev dm-3, type ext4), uses xattr [12139.991193] SELinux: initialized (dev sda1, type ext2), uses xattr
一些测试
手动DRBD裂脑恢复
根据DRBD文档,在检测到裂脑后,一个节点将始终具有处于StandAlone连接状态的资源。
另一个可能也处于StandAlone状态(如果两个节点同时检测到裂脑),或者处于WFConnection(如果对等方在另一个节点有机会检测到裂脑之前断开连接)。
为了测试裂脑式DRBD方案,我们可以简单地在集群节点之一上关闭用于DRBD通信的网络接口(172.16.22.0/24)。
让我们看看之后资源是什么状态。
[ora1]# drbd-overview 0:ocfsdata/0 StandAlone Primary/Unknown UpToDate/DUnknown /cluster/storage ocfs2 1.0G 186M 839M 19%
[ora2]# drbd-overview 0:ocfsdata/0 WFConnection Primary/Unknown UpToDate/DUnknown /cluster/storage ocfs2 1.0G 186M 839M 19%
我们将选择ora1节点作为裂脑受害者:
[ora1]# umount /cluster/storage/ [ora1]# drbdadm disconnect ocfsdata [ora1]# drbdadm secondary ocfsdata
[ora1]# drbd-overview 0:ocfsdata/0 StandAlone Secondary/Unknown UpToDate/DUnknown
[ora1]# drbdadm connect --discard-my-data ocfsdata
在另一个节点(裂脑幸存者)上,如果其连接状态也为StandAlone,我们将输入:
[ora2]# drbdadm connect ocfsdata
但是,由于该节点已经处于WFConnection状态,因此我们可以省略此步骤。
然后它将自动重新连接。
[ora1]# drbdadm primary ocfsdata [ora1]# mount -a
O2CB Fencing
根据Oracle文档,如果节点未能在((O2CB_HEARTBEAT_THRESHOLD 1)* 2)秒内更新其时间戳,则该节点会自行隔离。
每次写入时间戳后,内核线程都会设置一个计时器,以在该持续时间后使系统崩溃。
如果在该持续时间之内写入了下一个时间戳,则应先取消该计时器,然后再设置一个新的时间戳。
这样,如果内核线程由于某种原因无法更新时间戳并因此被集群中的其他节点视为已死,它可以确保系统自动隔离。
若要测试o2cb防护,请在群集节点之一上关闭用于o2cb通信的网络接口(172.16.21.0/24)。