使用Puppet在Pacemaker群集上配置主动/被动NFS服务器

时间:2020-03-21 11:42:29  来源:igfitidea点击:

我们将使用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选项的列表。