使用Puppet在Pacemaker群集上配置主动/被动NFS服务器
我们将使用Puppet安装Pacemaker/Corosync并配置NFS群集。
有关如何在CentOS 7上编译fence_pve的说明,请滚动至页面底部。
本文是KVM,Katelo和Puppet系列测试环境项目的一部分。
测试环境
我们安装了两个要配置的CentOS 7服务器,如下所示:
storage1.hl.local(10.11.1.15)– Pacemaker群集节点
storage2.hl.local(10.11.1.16)– Pacemaker群集节点
SELinux设置为强制模式。
集群要求
要配置集群,我们将需要以下内容:
- NFS服务器所需的虚拟IP地址。
- 群集中NFS节点的共享存储。
- 群集中每个节点的电源防护设备。
虚拟IP为10.11.1.31(DNS名称为nfsvip.hl.local)。
关于共享存储,虽然我同意iSCSI是理想的选择,但事实是“我们没有那种钱”。
我们将不得不使用同一Proxmox主机上不同VM之间的共享磁盘来实现它。
在防护方面,如前所述,Proxmox不使用libvirt,因此,不能通过使用fence-agents-virsh对Pacemaker群集进行防护。
有可用的fence_pve,但我们在CentOS/RHEL中找不到它。
我们需要从源代码编译它。
Proxmox和磁盘共享
我无法找到将现有磁盘添加到另一个VM的WebUI方法。
Proxmox论坛有所帮助,由于WebUI不允许我将相同的磁盘分配给两个VM,因此我最终手动编辑了VM的配置文件。
看一下下图,该图显示了连接到storage1.hl.local节点的两个磁盘:
我们要为NFS使用较小的磁盘(2GB)。
storage2.hl.local节点的VM ID为208(请参见此处),因此我们可以通过编辑节点的配置文件来添加磁盘。
# cat /etc/pve/qemu-server/208.conf boot: cn bootdisk: scsi0 cores: 1 hotplug: disk,cpu memory: 768 name: storage2.hl.local net0: virtio=00:22:FF:00:00:16,bridge=vmbr0 onboot: 1 ostype: l26 scsi0: data_ssd:208/vm-208-disk-1.qcow2,size=32G scsi1: data_ssd:207/vm-207-disk-3.qcow2,size=2G scsihw: virtio-scsi-pci smbios1: uuid=030e28da-72e6-412d-be77-a79f06862351 sockets: 1 startup: order=208
我们添加的磁盘是scsi1.
请注意,它如何引用VM ID 207.
该磁盘将在两个节点上均显示为'/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi1'。
用Puppet配置
Puppet Master 在Katello服务器上运行。
Puppet模块
我们使用puppet-corosync Puppet模块来配置服务器。
我们还使用puppetlabs-accounts创建Linux帐户。
请参阅模块文档以获取支持的功能和可用的配置选项。
配置防火墙
确保Pacemaker服务器可以相互通信非常重要。
以下需求适用于两个群集节点:
firewall { '007 accept HA cluster requests': dport => ['2224', '3121', '5403', '21064'], proto => 'tcp', source => '10.11.1.0/24', action => 'accept', }-> firewall { '008 accept HA cluster requests': dport => ['5404', '5405'], proto => 'udp', source => '10.11.1.0/24', action => 'accept', }-> firewall { '009 accept NFS requests': dport => ['2049'], proto => 'tcp', source => '10.11.1.0/24', action => 'accept', }-> firewall { '010 accept TCP mountd requests': dport => ['20048'], proto => 'tcp', source => '10.11.1.0/24', action => 'accept', }-> firewall { '011 accept UDP mountd requests': dport => ['20048'], proto => 'udp', source => '10.11.1.0/24', action => 'accept', }-> firewall { '012 accept TCP rpc-bind requests': dport => ['111'], proto => 'tcp', source => '10.11.1.0/24', action => 'accept', }-> firewall { '013 accept UDP rpc-bind requests': dport => ['111'], proto => 'udp', source => '10.11.1.0/24', action => 'accept', }
创建Apache用户和NFS挂载点
在配置集群之前,我们需要确保已安装nfs-utils软件包,并且已禁用nfs-lock服务,它将由心脏起搏器进行管理。
创建Apache用户是为了匹配所有权并允许Web服务器写入NFS共享。
以下需求适用于两个群集节点:
package { 'nfs-utils': ensure => 'installed' }-> service { 'nfs-lock': enable => false }-> accounts::user { 'apache': comment => 'Apache', uid => '48', gid => '48', shell => '/sbin/nologin', password => '!!', home => '/usr/share/httpd', home_mode => '0755', locked => false, }-> file {'/nfsshare': ensure => 'directory', owner => 'root', group => 'root', mode => '0755', }
在storage1.hl.local上配置Pacemaker/Corosync
我们最初禁用STONITH是因为围列代理fence_pve尚不可用。
我们将在以后进行编译,但是,它不是使集群进入运行状态所必需的。
我们使用主机代管将原语保持在一起。
虽然共置定义了一组原语必须在同一节点上一起生活,但是顺序定义将定义每个原语的启动顺序。
这很重要,因为我们要确保以正确的顺序启动群集资源。
请注意,我们如何将NFS导出配置为仅对两个特定的客户端可用:web1.hl.local和web2.hl.local。
实际上,不需要任何其他homelab服务器访问NFS共享。
我们使apache用户成为NFS共享的所有者,并使用no_all_squash将其导出。
class { 'corosync': authkey => '/etc/puppetlabs/puppet/ssl/certs/ca.pem', bind_address => $::ipaddress, cluster_name => 'nfs_cluster', enable_secauth => true, enable_corosync_service => true, enable_pacemaker_service => true, set_votequorum => true, quorum_members => [ 'storage1.hl.local', 'storage2.hl.local' ], } corosync::service { 'pacemaker': ## See: https://wiki.clusterlabs.org/wiki/Pacemaker version => '1.1', }-> cs_property { 'stonith-enabled': value => 'false', }-> cs_property { 'no-quorum-policy': value => 'ignore', }-> cs_primitive { 'nfsshare': primitive_class => 'ocf', primitive_type => 'Filesystem', provided_by => 'heartbeat', parameters => { 'device' => '/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi1', 'directory' => '/nfsshare', 'fstype' => 'ext4' }, }-> cs_primitive { 'nfsd': primitive_class => 'ocf', primitive_type => 'nfsserver', provided_by => 'heartbeat', parameters => { 'nfs_shared_infodir' => '/nfsshare/nfsinfo' }, require => Cs_primitive['nfsshare'], }-> cs_primitive { 'nfsroot1': primitive_class => 'ocf', primitive_type => 'exportfs', provided_by => 'heartbeat', parameters => { 'clientspec' => 'web1.hl.local', 'options' => 'rw,async,no_root_squash,no_all_squash', 'directory' => '/nfsshare', 'fsid' => '0' }, require => Cs_primitive['nfsd'], }-> cs_primitive { 'nfsroot2': primitive_class => 'ocf', primitive_type => 'exportfs', provided_by => 'heartbeat', parameters => { 'clientspec' => 'web2.hl.local', 'options' => 'rw,async,no_root_squash,no_all_squash', 'directory' => '/nfsshare', 'fsid' => '0' }, require => Cs_primitive['nfsd'], }-> cs_primitive { 'nfsvip': primitive_class => 'ocf', primitive_type => 'IPaddr2', provided_by => 'heartbeat', parameters => { 'ip' => '10.11.1.31', 'cidr_netmask' => '24' }, require => Cs_primitive['nfsroot1','nfsroot2'], }-> cs_colocation { 'nfsshare_nfsd_nfsroot_nfsvip': primitives => [ [ 'nfsshare', 'nfsd', 'nfsroot1', 'nfsroot2', 'nfsvip' ], }-> cs_order { 'nfsshare_before_nfsd': first => 'nfsshare', second => 'nfsd', require => Cs_colocation['nfsshare_nfsd_nfsroot_nfsvip'], }-> cs_order { 'nfsd_before_nfsroot1': first => 'nfsd', second => 'nfsroot1', require => Cs_colocation['nfsshare_nfsd_nfsroot_nfsvip'], }-> cs_order { 'nfsroot1_before_nfsroot2': first => 'nfsroot1', second => 'nfsroot2', require => Cs_colocation['nfsshare_nfsd_nfsroot_nfsvip'], }-> cs_order { 'nfsroot2_before_nfsvip': first => 'nfsroot2', second => 'nfsvip', require => Cs_colocation['nfsshare_nfsd_nfsroot_nfsvip'], }-> file {'/nfsshare/uploads': ensure => 'directory', owner => 'apache', group => 'root', mode => '0755', }
在storage2.hl.local上配置Pacemaker/Corosync
class { 'corosync': authkey => '/etc/puppetlabs/puppet/ssl/certs/ca.pem', bind_address => $::ipaddress, cluster_name => 'nfs_cluster', enable_secauth => true, enable_corosync_service => true, enable_pacemaker_service => true, set_votequorum => true, quorum_members => [ 'storage1.hl.local', 'storage2.hl.local' ], } corosync::service { 'pacemaker': version => '1.1', }-> cs_property { 'stonith-enabled': value => 'false', }
集群状态
如果一切顺利,我们应该在此时启动集群并运行它。
[Hyman@theitroad ~]# pcs status Cluster name: nfs_cluster Stack: corosync Current DC: storage2.hl.local (version 1.1.16-12.el7_4.8-94ff4df) - partition with quorum Last updated: Sun Apr 29 17:04:50 2016 Last change: Sun Apr 29 16:56:25 2016 by root via cibadmin on storage1.hl.local 2 nodes configured 5 resources configured Online: [ storage1.hl.local storage2.hl.local ] Full list of resources: nfsshare (ocf::heartbeat:Filesystem): Started storage1.hl.local nfsd (ocf::heartbeat:nfsserver): Started storage1.hl.local nfsroot1 (ocf::heartbeat:exportfs): Started storage1.hl.local nfsroot2 (ocf::heartbeat:exportfs): Started storage1.hl.local nfsvip (ocf::heartbeat:IPaddr2): Started storage1.hl.local Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: inactive/disabled
[Hyman@theitroad ~]# pcs status Cluster name: nfs_cluster Stack: corosync Current DC: storage2.hl.local (version 1.1.16-12.el7_4.8-94ff4df) - partition with quorum Last updated: Sun Apr 29 17:05:04 2016 Last change: Sun Apr 29 16:56:25 2016 by root via cibadmin on storage1.hl.local 2 nodes configured 5 resources configured Online: [ storage1.hl.local storage2.hl.local ] Full list of resources: nfsshare (ocf::heartbeat:Filesystem): Started storage1.hl.local nfsd (ocf::heartbeat:nfsserver): Started storage1.hl.local nfsroot1 (ocf::heartbeat:exportfs): Started storage1.hl.local nfsroot2 (ocf::heartbeat:exportfs): Started storage1.hl.local nfsvip (ocf::heartbeat:IPaddr2): Started storage1.hl.local Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: inactive/disabled
通过将活动节点置于备用状态来测试集群故障转移:
[Hyman@theitroad ~]# pcs node standby
服务应在另一个群集节点上变得可用:
[Hyman@theitroad ~]# pcs status Cluster name: nfs_cluster Stack: corosync Current DC: storage2.hl.local (version 1.1.16-12.el7_4.8-94ff4df) - partition with quorum Last updated: Sun Apr 29 17:06:36 2016 Last change: Sun Apr 29 16:56:25 2016 by root via cibadmin on storage1.hl.local 2 nodes configured 5 resources configured Node storage1.hl.local: standby Online: [ storage2.hl.local ] Full list of resources: nfsshare (ocf::heartbeat:Filesystem): Started storage2.hl.local nfsd (ocf::heartbeat:nfsserver): Started storage2.hl.local nfsroot1 (ocf::heartbeat:exportfs): Started storage2.hl.local nfsroot2 (ocf::heartbeat:exportfs): Started storage2.hl.local nfsvip (ocf::heartbeat:IPaddr2): Started storage2.hl.local Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: inactive/disabled
在虚拟IP地址上执行showmount:
[Hyman@theitroad ~]# showmount -e 10.11.1.31 Export list for 10.11.1.31: /nfsshare web1.hl.local,web2.hl.local
在CentOS 7上编译fence_pve
恐怕这就是自动化部分结束的地方,但是,没有什么可以阻止我们将下面的手动步骤放入Puppet列表中。
安装套件
# yum install git gcc make automake autoconf libtool \ pexpect python-requests
下载源代码并进行编译
# git clone https://github.com/ClusterLabs/fence-agents.git
请注意配置部分,我们只希望编译一种隔离代理fence_pve。
# cd fence-agents/ # ./autogen.sh # ./configure --with-agents=pve # make && make install
核实:
# fence_pve --version 4.1.1.51-6e6d
配置起搏器以使用fence_pve
非常感谢Igor Cicimov的教程 文章,该文章帮助我轻松完成了工作。
要测试防护代理,请执行以下操作:
[Hyman@theitroad ~]# fence_pve --ip=10.11.1.5 --nodename=pve \ Hyman@theitroad --password=passwd \ --plug=208 --action=off
其中10.11.1.5是Proxmox系统管理程序的IP,pve是Proxmox节点的名称,而插件是VM ID。
在这种情况下,我们隔离了storage2.hl.local节点。
要配置Pacemaker,我们可以创建两个STONITH配置,每个我们想要能够隔离的节点一个。
[Hyman@theitroad ~]# pcs stonith create my_proxmox_fence207 fence_pve \ ipaddr="10.11.1.5" inet4_only="true" vmtype="qemu" \ login="Hyman@theitroad" passwd="passwd" \ node_name="pve" delay="15" \ port="207" \ pcmk_host_check=static-list \ pcmk_host_list="storage1.hl.local"
[Hyman@theitroad ~]# pcs stonith create my_proxmox_fence208 fence_pve \ ipaddr="10.11.1.5" inet4_only="true" vmtype="qemu" \ login="Hyman@theitroad" passwd="passwd" \ node_name="pve" delay="15" \ port="208" \ pcmk_host_check=static-list \ pcmk_host_list="storage2.hl.local"
核实:
[Hyman@theitroad ~]# stonith_admin -L my_proxmox_fence207 my_proxmox_fence208 2 devices found
[Hyman@theitroad ~]# pcs status Cluster name: nfs_cluster Stack: corosync Current DC: storage1.hl.local (version 1.1.16-12.el7_4.8-94ff4df) - partition with quorum Last updated: Sun Apr 29 17:50:59 2016 Last change: Sun Apr 29 17:50:55 2016 by root via cibadmin on storage1.hl.local 2 nodes configured 7 resources configured Online: [ storage1.hl.local ] OFFLINE: [ storage2.hl.local ] Full list of resources: nfsshare (ocf::heartbeat:Filesystem): Started storage1.hl.local nfsd (ocf::heartbeat:nfsserver): Started storage1.hl.local nfsroot1 (ocf::heartbeat:exportfs): Started storage1.hl.local nfsroot2 (ocf::heartbeat:exportfs): Started storage1.hl.local nfsvip (ocf::heartbeat:IPaddr2): Started storage1.hl.local my_proxmox_fence207 (stonith:fence_pve): Started storage1.hl.local my_proxmox_fence208 (stonith:fence_pve): Started storage1.hl.local Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: inactive/disabled
请注意storage2.hl.local节点如何关闭,因为我们已对其进行了防护。
如果决定使用测试配置,请不要忘记在集群节点上停止Puppet代理,因为它将禁用STONITH(我们在列表中将stonith-enabled设置为false)。
有关更多信息,请执行以下操作:
# pcs stonith describe fence_pve
这将为我们提供其他可用的STONITH选项的列表。