精华内容
下载资源
问答
  • ctdb是基于压缩特里的简单键/值数据库。 存储是仅追加的,写入的数据永远不会更改。 支持的操作: 将新的键/值对添加到数据库。 从数据库中删除现有密钥。 查询数据库中的特定密钥。 遍历数据库中的所有数据。...
  • 音乐脑-ctdb Musicbrainz CTDB用户脚本
  • CTDB入门

    2020-07-03 08:39:00
    CTDB是集群Samba中的集群数据库组件,可提供高可用性负载共享CIFS服务器集群。 CTDB的主要功能是: 提供TDB数据库的集群版本,并在节点发生故障时自动重建/恢复数据库。 监视集群中的节点以及在每个节点上运行的...

    引言

    CTDB是集群Samba中的集群数据库组件,可提供高可用性负载共享CIFS服务器集群。

    CTDB的主要功能是:

    • 提供TDB数据库的集群版本,并在节点发生故障时自动重建/恢复数据库。
    • 监视集群中的节点以及在每个节点上运行的服务。
    • 管理用于向客户端提供服务的公共IP地址池。 另外,CTDB可以与LVS一起使用。

    与集群文件系统结合使用CTDB为集群Samba,NFS和其他服务等服务提供了完整的高可用(HA)环境。

    设置CTDB

    设置集群文件系统后,可以设置CTDB集群。 要使用CTDB,必须为发行版安装ctdb-package。 安装完所有依赖包后,将找到目录/etc/ctdb。 在其目录中,需要一些CTDB的配置文件。

    配置CTDB所需的文件。

    文件内容
    /etc/ctdb/ctdb.conf基本配置
    /etc/ctdb/script.options设置事件脚本的选项
    /etc/ctdb/nodes所有节点的所有IP地址
    /etc/ctdb/public_addresses所有节点的动态IP地址

    ctdb.conf文件

    ctdb.conf文件与旧的配置样式(<Samba 4.9)相比发生了很大变化。 该文件不再用于配置CTDB管理的其它服务。 目前,在该文件中要做的唯一设置就是设置恢复锁文件。 所有节点都使用此文件来检查是否可以将文件锁在机器中以供排他使用。 如果不使用恢复锁文件,则集群可能会陷入混乱状态。 默认情况下,未设置“恢复锁”。 除非知道自己在做什么,否则不应使用没有恢复锁的CTDB。 该变量必须指向已挂载的gluster-volume中的文件。 要使用恢复锁,请在两个节点上的/etc/ctdb/ctdb.conf中输入以下行:

    recovery lock = /glusterfs/ctdb.lock
    

    script.options文件

    CTDB提供的所有服务会通过特殊脚本启动。 在此文件中,可以为脚本设置选项。 脚本中显示了一个示例。 服务脚本50.samba.options中名为CTDB_SAMBA_SKIP_SHARE_CHECK的选项,默认情况下设置为yes。 这意味着,每次创建新共享时,CTDB都会检查路径是否存在,如果不存在,则CTDB将停止。 但是,如果使用vfs-module glusterfs,则共享配置中将没有本地路径。 共享指向gluster卷上的目录,因此CTDB无法检查路径。 因此,如果要使用glusterfs,则必须将Samba的此选项设置为no。

    因为可以在这个文件中为所有服务脚本设置所有选项,所以不必更改任何服务脚本。可在手册man ctdb-script.options中找到有关所有选项的更多信息。

    nodes文件

    CTDB必须知道属于该集群的所有主机,在此文件中,必须放置所有节点的心跳网络中的所有IP。 该文件在所有节点上必须具有相同的内容。 只需将两个节点的两个IP放入文件中即可。 在这里,可以看到文件的内容。

    192.168.57.42
    192.168.57.43
    

    在大多数发行版中,该文件不存在,必须创建它。

    public_addresses文件

    每当CTDB启动时,它将为CTDB-Cluster中的所有节点提供IP地址,该地址必须是生产网络中的IP地址。

    启动集群后,CTDB将处理这些IP地址,并将此列表的IP地址提供给每个CTDB节点。 如果CTDB节点崩溃,则CTDB将从崩溃节点中分配IP地址给另一个CTDB节点。 因此,该文件中的每个IP地址始终分配给节点中的一个。

    CTDB正在对服务进行故障转移。 如果一个节点失效,则IP地址将切换到其余节点之一。 然后,所有客户端将重新连接到该节点。 这是可能的,因为所有节点都具有所有客户端的所有会话信息。

    对于每个节点,需要一个public_addresses文件。 节点上的文件可以不同,具体取决于要分配节点的子网。 该示例仅使用一个子网,因此两个节点都具有相同的public_addresses文件。 在这里,可以看到文件的内容:

    192.168.56.101/24 enp0s8
    192.168.56.102/24 enp0s8
    

    第一次启动CTDB

    现在,已经在两个节点上都配置了CTDB服务,那么就可以准备开始了。 要查看启动期间会发生什么,您可以打开另一个终端并启动tail -f /var/log/ctdb/ctdb.log以查看消息。 首先使用systemctl restart ctdb启动一个节点,查看日志消息,然后启动第二个节点,并继续关注日志。

    2020/02/11 17:32:53.778637 ctdbd[1926]: monitor event OK - node re-enabled
    2020/02/11 17:32:53.778831 ctdbd[1926]: Node became HEALTHY. Ask recovery master to reallocate IPs 
    2020/02/11 17:32:53.779152 ctdb-recoverd[1966]: Node 0 has changed flags - now 0x0  was 0x2
    2020/02/11 17:32:54.575970 ctdb-recoverd[1966]: Unassigned IP 192.168.56.102 can be served by this node
    2020/02/11 17:32:54.576047 ctdb-recoverd[1966]: Unassigned IP 192.168.56.101 can be served by this node
    2020/02/11 17:32:54.576254 ctdb-recoverd[1966]: Trigger takeoverrun
    2020/02/11 17:32:54.576780 ctdb-recoverd[1966]: Takeover run starting
    2020/02/11 17:32:54.594527 ctdbd[1926]: Takeover of IP 192.168.56.102/24 on interface enp0s8
    2020/02/11 17:32:54.595551 ctdbd[1926]: Takeover of IP 192.168.56.101/24 on interface enp0s8
    2020/02/11 17:32:54.843175 ctdb-recoverd[1966]: Takeover run completed successfully
    

    在这里,可以看到该节点已经使用了两个动态IP地址,可以使用ip a l enp0s8进行检查。

    不要使用ifconfig列出IP地址,ifconfig不会列出动态分配的IP地址。

    在启动第二个节点之前,请查看具有ctdb状态的CTDB状态。 将看到刚启动的第一个节点的状态为OK,另一个节点的状态为DISCONNECTED | UNHEALTHY | INACTIVE。

    root@cluster-01:~# ctdb status
    Number of nodes:2
    pnn:0 192.168.57.42    OK (THIS NODE)
    pnn:1 192.168.57.43    DISCONNECTED|UNHEALTHY|INACTIVE
    Generation:1636031659
    Size:1
    hash:0 lmaster:0
    Recovery mode:NORMAL (0)
    Recovery master:0
    

    现在,可以使用systemctl restart ctdb在第二个节点上启动CTDB。 在第一个节点的日志中,将看到以下消息:接管成功。 接下来,将看到日志的最后几行:

    2020/02/11 17:51:49.964668 ctdb-recoverd[6598]: Takeover run starting
    2020/02/11 17:51:50.004374 ctdb-recoverd[6598]: Takeover run completed successfully
    2020/02/11 17:51:59.061780 ctdb-recoverd[6598]: Reenabling recoveries after timeout
    2020/02/11 17:52:04.632267 ctdb-recoverd[6598]: Node 1 has changed flags - now 0x0  was 0x2
    2020/02/11 17:52:04.989395 ctdb-recoverd[6598]: Takeover run starting
    2020/02/11 17:52:05.008763 ctdbd[6554]: Release of IP 192.168.56.102/24 on interface enp0s8  node:1
    2020/02/11 17:52:05.154588 ctdb-recoverd[6598]: Takeover run completed successfully
    

    如果在下清单中看到很多消息,请检查是否正确安装了gluster-volume,以及/etc/ctdb/ctdb.conf中的recovery lock-option是否正确设置:

    2020/02/11 17:51:00.883523 ctdbd[6554]: CTDB_WAIT_UNTIL_RECOVERED
    2020/02/11 17:51:00.883630 ctdbd[6554]: ../../ctdb/server/ctdb_monitor.c:324 wait for pending recoveries to end. Wait one more second.
    

    查看状态将显示两个节点都正常,如在ctsdb status中所见

    root@cluster-01:~# ctdb status
    Number of nodes:2
    pnn:0 192.168.57.42    OK (THIS NODE)
    pnn:1 192.168.57.43    OK
    Generation:101877096
    Size:2
    hash:0 lmaster:0
    hash:1 lmaster:1
    Recovery mode:NORMAL (0)
    Recovery master:0
    

    每当停止一个节点时,另一个节点将接管CTDB分配的IP地址。 现在,CTDB正在运行,但是您尚未配置任何服务。 如果两个节点都正常,则应仅继续配置服务。

    作为测试,可以在一个节点上停止CTDB,然后会看到另一节点将从停止的节点获取IP。 重新启动节点后,会将其中一个IP地址分配给该节点,并且两个节点的状态都将再次变为OK。

    下一步将设置samba。

    配置Samba

    在这一部分中,可了解如何设置Samba集群以向Windows和Linux客户端提供文件服务。 该集群将加入Samba Active Directory域并创建共享。 将描述三种不同的技术来为客户提供共享:

    • 使用本地挂载的gluster-volume创建共享。
    • 使用vfs-module glusterfs直接指向gluster-cluster上的卷,而无需在本地系统上挂载该卷。
    • 使用新的vfs-module glusterfs_fuse。

    加入域

    要将集群加入域,必须执行以下步骤:

    • 创建DNS记录
    • 通过注册表配置Samba
    • 加入集群
    创建DNS记录

    要加入域,第一步应该是为集群创建DNS条目。 如果已经配置了反向区域,则可以跳过命令以创建反向区域。

    root@addc-01:~# kinit administrator
    administrator@EXAMPLE.NET's Password:********
    
    root@addc-01:~# samba-tool dns zonecreate addc-01 56.168.192.in-addr.arpa -k yes
    Zone 56.168.192.in-addr.arpa created successfully
    
    root@addc-01:~# systemctl restart samba-ad-dc
    

    如果正在使用来自Samba的内部DNS服务器,则只需重启DC

    root@addc-01:~# samba-tool dns add addc-01 example.net cluster A 192.168.56.101 
    Record added successfully
    
    root@addc-01:~# samba-tool dns add addc-01 example.net cluster A 192.168.56.102
    Record added successfully
    
    root@addc-01:~# samba-tool dns add addc-01 56.168.192.in-addr.arpa 101 PTR cluster.example.net
    Record added successfully
    
    root@addc-01:~# samba-tool dns add addc-01 56.168.192.in-addr.arpa 102 PTR cluster.example.net
    Record added successfully
    

    测试名称解析。

    root@addc-01:~# host cluster
    cluster.example.net has address 192.168.56.101
    cluster.example.net has address 192.168.56.102
    
    root@addc-01:~# host 192.168.56.101
    101.56.168.192.in-addr.arpa domain name pointer cluster.example.net.
    
    root@addc-01:~# host 192.168.56.102
    102.56.168.192.in-addr.arpa domain name pointer cluster.example.net.
    

    在清单中,看到两个动态IP地址都具有相同的DNS名称。 解析主机名将为您提供两个IP地址。 因此,客户端可以连接到这两个地址中的任意一个,并将始终到达集群节点之一。

    配置Samba

    如果将Samba与CTDB一起使用,则必须使用注册表来配置Samba。 原因是,配置的是集群,而不是每个主机。 集群的所有配置都可以在任一Samba主机上完成。 CTDB-Samba-主机将共享所有TDB文件。 这些文件将存储在本地,但将在所有节点之间提交。

    将设置写入注册表的最简单方法是以smb.conf样式写入文件,然后将文件导入注册表。

    如果启动Samba,Samba查找任何配置的第一个地方就是smb.conf文件。 这就是为什么用户始终拥有最低smb.conf的原因。 在下面的清单中,将看到配置设置。

    [global]
           workgroup = EXAMPLE
           realm = EXAMPLE.NET
           netbios name = CLUSTER
           security = ADS
           template shell = /bin/bash
           winbind use default domain = Yes
           winbind refresh tickets = Yes
           idmap config *:range = 10000-19999
           idmap config samba-ad:range = 1000000-1999999
           idmap config samba-ad:backend = rid
    

    下一步是创建smb.conf来告诉Samba应该使用集群,并且所有配置都来自注册表。

    [global]
           clustering = yes
           include = registry
    

    现在,使用命令net conf import /daten/smb.conf.first将配置文件导入注册表。 可以在两个节点上使用net conf list测试导入。 使用两个节点上的testparm测试所有设置。 如果没有错误消息,则可以将集群加入域:

    root@cluster-01:/etc/ctdb# net ads join -U administrator
    Enter administrator's password: *******
    
    Using short domain name -- EXAMPLE
    Joined 'CLUSTER' to dns domain 'example.net'
    Not doing automatic DNS update in a clustered setup.
    
    root@cluster-01:~# net ads testjoin
    Join is OK
    

    在加入期间无法对集群进行DNS更新,这就是为什么在加入集群之前创建DND记录的原因,但是可以看到使用net ads testjoin是有效的。 另一个测试是查看群集的帐户是否在AD中创建,以便在域控制器上执行 samba-tool computer list。

    现在,已将集群加入域。 到目前为止,还没有启动任何Samba服务。 启动和停止服务smbd,nmbd和winbind应该由CTDB而不是通过systemd完成。 因此,在配置CTDB来接管服务之前,必须停止并禁用systemd中的服务:

    root@cluster-01:~# systemctl stop smbd nmbd winbind
    root@cluster-01:~# systemctl disable smbd nmbd winbind
    
    root@cluster-02:~# systemctl stop smbd nmbd winbind
    root@cluster-02:~# systemctl disable smbd nmbd winbind
    

    必须在两个节点上都执行此操作。

    配置CTDB以接管samba服务

    完成Samba的配置并将群集加入域之后,就可以开始配置CTDB来接管Samba服务。 从Samba 4.9开始,配置CTDB的方式已经发生了很大变化,到目前为止,仅在配置恢复锁时才注意到这一点。 配置服务的旧方法是在ctdb.conf中激活服务。 从已更改的Samba 4.9开始,现在有一个命令来激活服务。

    每个服务将通过事件脚本启用。 要启用脚本,请使用命令ctdb。 我们需要Samba脚本和winbind脚本。 在下一个清单中,将看到启用脚本的命令:

    root@cluster-01:~# ctdb event script enable legacy 50.samba
    root@cluster-01:~# ctdb event script enable legacy 49.winbind
    
    root@cluster-02:~# ctdb event script enable legacy 50.samba
    root@cluster-02:~# ctdb event script enable legacy 49.winbind
    

    启用50.samba和49.winbind后,使用systemctl restart ctdb,并在两个节点上重新启动ctdb。

    一段时间后,两个CTDB节点再次变为“正常”。 用s | egrep 'mbd|winbind’和ss -tlpn表示Samba服务正在运行。 现在,您已经配置了CTDB以启动和停止所有Samba服务。

    当您执行命令时会发生什么? 如果激活脚本,所有事件脚本都位于/usr/share/ctdb/events/legacy中,该脚本将链接到/etc/ctdb/events/legacy/。 如果您看一下脚本,就会看到,它看起来像是服务的初始化脚本,仅此而已。

    检查CTDB集群

    在CTDB集群运行并且Samba服务处于活动状态之后,让我们看一下一些CTDB测试。

    ctdb status

    显示整个集群的实际状态。 列出了所有节点,可以看到所有节点的状态。

    root@cluster-02:~# ctdb status
    Number of nodes:2
    pnn:0 192.168.57.42    OK
    pnn:1 192.168.57.43    OK (THIS NODE)
    Generation:1823539022
    Size:2
    hash:0 lmaster:0
    hash:1 lmaster:1
    Recovery mode:NORMAL (0)
    Recovery master:1
    

    此处:

    • 集群中的节点数。
    • 所有节点的{pnn} -number,IP地址和状态的列表。
    • Generation只是一个数字,如果进行重新配置,则数字会发生变化。 没有特别的意义。
    • 集群的大小-这里是2个节点。
    • 行hash: lmaster:用于计算lmaster,它是通过哈希值计算的。
    • Recovery mode显示集群中的所有内容是否正常,或者是否正在进行恢复。
    • Recovery master是负责恢复的节点。

    如果只想查看所有节点或仅一个节点或某些主机的状态,则可以使用ctdb nodestatus。 使用nodestatus,可以查看实际节点的状态或主机列表:

    root@cluster-01:~# ctdb nodestatus
    pnn:0 192.168.57.42    OK (THIS NODE)
    
    root@cluster-01:~# ctdb nodestatus 1
    pnn:1 192.168.57.43    OK
    
    root@cluster-01:~# ctdb nodestatus 0,1
    pnn:0 192.168.57.42    OK (THIS NODE)
    pnn:1 192.168.57.43    OK
    
    root@cluster-01:~# ctdb nodestatus all
    Number of nodes:2
    pnn:0 192.168.57.42    OK (THIS NODE)
    pnn:1 192.168.57.43    OK
    

    还有更多检查集群的可能性:

    root@cluster-01:~# ctdb uptime
    Current time of node 0        :                Wed Feb 12 18:56:14 2020
    Ctdbd start time              : (000 04:53:49) Wed Feb 12 14:02:25 2020
    Time of last recovery/failover: (000 04:53:43) Wed Feb 12 14:02:31 2020
    Duration of last recovery/failover: 0.573115 seconds
    
    root@cluster-01:~# ctdb listnodes
    192.168.57.42
    192.168.57.43
    
    root@cluster-01:~# ctdb ping
    response from 0 time=0.000124 sec  (20 clients)
    
    root@cluster-01:~# ctdb ip
    Public IPs on node 0
    192.168.56.101 1
    192.168.56.102 0
    

    有关测试CTDB集群的更多信息,请参见ctdb的联机帮助页。

    检查所有服务

    接下来的重要检查是查看CTDB可以提供哪些服务以及实际配置了哪些服务。 可以使用命令ctdb scriptstatus列出所有正在运行的服务,但是不建议使用此命令。 从Samba 4.9开始,应该使用ctdb event status legacy monitor检查事件脚本。 然后,将看到所有正在运行的(受监视的)服务。 要查看所有服务的列表,请执行ctdb event script list legacy。

    root@cluster-01:~# ctdb event status legacy monitor
    00.ctdb              OK         0.005 Thu Feb 13 18:28:35 2020
    01.reclock           OK         0.023 Thu Feb 13 18:28:35 2020
    05.system            OK         0.017 Thu Feb 13 18:28:35 2020
    10.interface         OK         0.019 Thu Feb 13 18:28:35 2020
    49.winbind           OK         0.011 Thu Feb 13 18:28:35 2020
    50.samba             OK         0.101 Thu Feb 13 18:28:35 2020
    
    root@cluster-01:~#  ctdb event script list legacy  
    * 00.ctdb
    * 01.reclock
    * 05.system
      06.nfs
    * 10.interface
      11.natgw
      11.routing
      13.per_ip_routing
      20.multipathd
      31.clamd
      40.vsftpd
      41.httpd
    * 49.winbind
    * 50.samba
      60.nfs
      70.iscsi
      91.lvs
    

    第一条命令显示所有正在运行的服务。 第二个命令显示CTDB可以提供的所有服务,所有正在运行的服务都标有*。

    展开全文
  • 关于ctdb,有太多的想吐槽的地方了。。。我CentOS系统镜像版本 CentOS1908,应该是最后一版了。 然后 可以再直接安装的ctdb版本 是ctdb4.9 配置文件语法与之前差了好多,这个不重要的话,每次直接安装完成后,没有一...

    关于ctdb,有太多的想吐槽的地方了。。。我CentOS系统镜像版本 CentOS1908,应该是最后一版了。
    然后 可以再直接安装的ctdb版本 是ctdb4.9 配置文件语法与之前差了好多,这个不重要的话,每次直接安装完成后,没有一次成功启动过。

    然后根据官网指导,源码安装Samba 附带会安装ctdb。。。这能成也是好事啊。。。好不容易安装完毕。不能使用systemctl管理。好在有一个 ctdb.service 文件,修改一下后放在 /usr/lib/systemd/system/目录后 也能使用systemctl启停,但是,每次重启也会报错。 /usr/local/samba/var/lib/ctdb 目录 已存在一个db数据库。还要手动删除才行。。。这。。。

    最后找到了 gluster 提供的Samba+ctdb的rpm包下载地址。尽管版本低了点 4.2.4 也是可以用的。。。满怀期待安装完成。
    https://download.gluster.org/pub/gluster/glusterfs/samba/CentOS/
    终于可以使用 systemctl 启停 ctdb了。。。好激动,然而,通过这个库安装的Samba启动又会失败了。。。emmm可能就是版本太低。。。不过 先不使用Samba了,可以试一下ctdb 实现gluster 用户态高可用。。。(如果想使用这个ctdb4.2,然后安装Samba4.9的话,安装时会自动帮你吧ctdb也升级一下。。。然后ctdb就也变成4.9再次启动失败。。。)

    这可能只是我自己会遇到的问题(配置什么的可能设置错误了才导致这么坑爹,但是本博客主要是讲gluster+ctdb)

    首先,安装ctdb

    准备三个Centos主机,我使用的是虚拟机。。。ip分别是
    192.168.199.71
    192.168.199.72
    192.168.199.73
    确保三台主机之间可以相互ping 通

    然后三个节点全部执行下面几步

    关闭防火墙
    设置 SELINUX为permissive模式

    安装 wget

    yum -y install wget
    

    下载https://download.gluster.org/pub/gluster/glusterfs/samba/CentOS/glusterfs-samba-epel.repo 到 /etc/yum.repos.d/ 目录

     wget -O /etc/yum.repos.d/glusterfs-samba-epel.repo https://download.gluster.org/pub/gluster/glusterfs/samba/CentOS/glusterfs-samba-epel.repo
    

    重新生成缓存

    yum makecache
    

    然后就可以安装 ctdb4.2.4了
    4.2.4版本配置文件 是/etc/sysconfig/ctdb

    yum -y install ctdb-4.2.4
    

    测试ctdb 基本使用

    同样是三个节点都执行

    ctdb什么也不管理,单纯测试是否可用

    创建并编辑 nodes文件和 public_address 文件,本来应该是使用gluster挂载一个共享卷,然后设置文件在相应位置建立软链接的,暂时没安装gluster,先使用本地文件

    vim /etc/ctdb/nodes
    
    192.168.199.71
    192.168.199.72
    192.168.199.73
    
    
    vim /etc/ctdb/public_addresses
    
    192.168.199.70/24       ens33
    

    可以看做公共IP地址,是一个虚拟IP没有对应主机。

    修改 ctdb 配置文件 /etc/sysconfig/ctdb

    vim /etc/sysconfig/ctdb
    

    把这两行注释掉 这个就是使用ctdb管理Samba,但是这个Samba是启动不了的。。。所以就不管理Samba了

    #CTDB_MANAGES_SAMBA=yes
    #CTDB_SAMBA_SKIP_SHARE_CHECK=yes
    

    根据日志文件 创建一个目录 存放 锁文件

    mkdir -p /gluster/lock
    

    启动ctdb服务

    systemctl start ctdb
    

    然后查看ctdb 状态 可要等一小会才会变OK,不过这个ctdb什么也不管理。

    ctdb status
    

    查看公共IP

    ctdb ip
    

    这时候,应该只有第一个启动的节点状态才会是 OK 锁文件不一致。。。这个,所以说要使用glusterfs挂载出一个卷。ctdb日志

    2020/04/07 19:51:15.301292 [set_recmode: 8826]: ERROR: recovery lock file /gluster/lock/lockfile not locked when recovering!
    

    由于暂时未安装设置glusterfs,但是由于没有共享锁,导致 几个节点的状态不OK,可以先使用 nfs 挂载出一个共享目录。做一下测试。

    新建一个虚拟机 IP 192.168.199.95
    安装完成后,新增一块硬盘,挂载上去作为共享目录

    查看新挂载硬盘。 我的是 /dev/sdb

    fidsk -l
    

    格式化新硬盘,这里不给新硬盘做分区了。

    mkfs.ext4 /dev/sdb
    

    新建一个文件夹作为,硬盘挂载点,同时也作为nfs共享目录

    mkdir  /nfs-share
    

    挂载硬盘 sdb 到 /nfs-share 目录

    echo "/dev/sdb  /nfs-share  ext4 defaults 0 0"  >> /etc/fstab
    mount -a
    

    /etc/fstab 目录是开机执行的文件挂载,mount -a 表示立即执行该文件的内容。

    可以使用df命令查看一下成功与否

    df -h
    

    挂载成功
    根据这几天学习情况,linux系统应该是自带nfs内核的,但是应该没有相应管理工具设置管理。

    安装 nfs-utils

    yum -y install nfs-utils
    

    编辑 /etc/exports 文件

    vim /etc/exports
    
    /nfs-share *(rw,async,no_root_squash,no_subtree_check)
    

    编辑nfs配置文件

    vim /etc/sysconfig/nfs
    

    可以在末尾添加, 也可以取消相应注释

    LOCKD_TCPPORT=32803
    LOCKD_UDPPORT=32769
    MOUNTD_PORT=892
    RQUOTAD_PORT=875
    STATD_PORT=662
    STATD_OUTGOING_PORT=2020
    

    这些设置的意思是固定nfs服务使用的端口号。除了两个默认的外,其它使用的端口号如果不指定,每次重启服务都是随机的。可以使用配置文件固定下来。。。这样做如果要使用防火墙添加端口也好添加,如果端口随机,防火墙开放端口也有点麻烦,,,不过我一般实验环境防火墙都是关闭状态。。。
    启动nfs服务

    systemctl enable rpcbind
    systemctl start rpcbind
    systemctl enable nfs
    systemctl start nfs
    

    至此,共享的nfs目录设置完毕,可以在其它三个节点测试一下。下面的也是三个节点都要执行

    当然也要安装nfs-utils 只用安装,不用设置

    yum -y install nfs-utils
    

    查看 nfs 节点共享的目录

    showmount -e 192.168.199.75
    

    查看共享目录
    挂载该共享目录到本地 /nfs-share

    mkdir /nfs-share
    mount -t nfs 192.168.199.75:/nfs-share /nfs-share
    

    挂载nfs共享目录

    三个节点都挂载完成后,
    在某一个节点执行 比如192.168.199.71,下面几步一个节点执行就可以了,因为在共享目录下进行。
    在共享目录挂载点创建两个文件夹,一个作为锁共享目录,一个作为数据共享目录

    mkdir /nfs-share/lock
    mkdir /nfs-share/data
    

    然后在 锁共享目录中创建 ctdb 使用到的配置文件,然后再建立软链接,这样几个节点的配置文件就是一致的了。
    创建 ctdb 文件,注(4.2.4的配置文件是/etc/sysconfig/ctdb之后版本的可能是 /etc/ctdb/ctdbd.conf)

    vim /nfs-share/lock/ctdb
    
    CTDB_RECOVERY_LOCK=/nfs-share/lock/lockfile
    CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses
    

    nodes 文件

    vim /nfs-share/lock/nodes
    
    192.168.199.71
    192.168.199.72
    192.168.199.73
    
    

    创建public_addresses 文件,官方或者其他一些文档建议,公共IP不必一致,每个节点可以是独特的设置,这里并没有什么独特设置,就都设置成一样的了。 ens33 是网卡名,看个人的可能不一样

    vim /nfs-share/lock/public_addresses
    
    192.168.199.70/24       ens33
    

    配置目录建立完毕。。。接下来三个节点要删除之前的配置文件,重新建立软链接。。其实一开始先创建nfs共享目录要好一些,不过,有个错误印象更深一点。。。
    三个节点都要执行。

    备份 ctdb 服务配置文件

    mv /etc/sysconfig/ctdb /etc/sysconfig/ctdb.bak
    

    建立软链接

    ln -s /nfs-share/lock/ctdb /etc/sysconfig/ctdb
    

    ctdb配置文件软链接
    删除原配置 nodes 文件和 public_addresses 文件

    rm -rf /etc/ctdb/nodes /etc/ctdb/public_addresses 
    

    为这两个文件建立软链接 指向 /nfs-share/lock 中内容

    ln -s /nfs-share/lock/nodes /etc/ctdb/nodes
    ln -s /nfs-share/lock/public_addresses /etc/ctdb/public_addresses
    

    建立nodes软链接

    三个节点执行完毕 可以重新启动ctdb服务,然后查看节点状态,可以设置为 开机启动

    systemctl enable ctdb
    systemctl restart ctdb
    

    过一小段时间 查看ctdb状态
    ctdb状态

    可以看到ctdb的状态。三个节点都是OK的。但是之前也说了,这个ctdb什么都未管理。。。只是测试是否可用。下一步可以测试一下ctdb管理nfs

    使用ctdb管理内核态nfs

    其实本人也不是很懂内核态nfs的意思,根据他人博客来看,glusterfs也附带了nfs服务,GlusterFS的服务称为用户态。

    这一段摘自他人博客
    https://blog.csdn.net/u013131156/article/details/78790536?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

    由于集群NAS中所使用的集群文件系统是GlusterFS,所以关于nfs存在两种形态,即内核态nfs以及用户态nfs。其中内核态nfs指Linux,内核自带的nfs,用户态nfs指是GlusterFS自带的nfs服务。注:两种形态的nfs服务是互斥的。

    还没有安装GlusterFS,刚才测试nfs共享目录时安装的nfs-utils,就当做是内核态的管理吧。

    在/nfs-share/lock/ 目录中设置nfs 配置文件

    vim /nfs-share/lock/nfs
    
    NFS_TICKLE_SHARED_DIRECTORY=/nfs-share/lock/nfs-tickles
    NFS_HOSTNAME=nfs-server
    STATD_PORT=874
    STATD_OUTGOING_PORT=876
    MOUNTD_PORT=892
    RQUOTAD_PORT=875
    LOCKD_UDPPORT=872
    LOCKD_TCPPORT=872
    STATD_SHARED_DIRECTORY=/nfs-share/lock/nfs-state
    STATD_HOSTNAME="$NFS_HOSTNAME -H /etc/ctdb/statd-callout"
    RPCNFSDARGS="-N 4"
    

    设置 exports 文件

    vim /nfs-share/lock/exports
    
    /nfs-share/data *(rw,fsid=1235)
    
    

    三个节点都要执行。下面的

    备份原文件

    mv /etc/sysconfig/nfs /etc/sysconfig/nfs.bak
    mv /etc/exports /etc/exports.bak
    

    建立软链接

    ln -s /nfs-share/lock/nfs /etc/sysconfig/nfs
    ln -s /nfs-share/lock/exports /etc/exports
    

    设置 ctdb 的配置文件 /nfs-share/lock/ctdb

     vim /nfs-share/lock/ctdb 
    

    添加两行

    CTDB_NFS_SKIP_SHARE_CHECK=yes
    CTDB_MANAGES_NFS=yes
    

    表示对ctdb将会控制 nfs服务。

    然后设置 nfs 开机不再自启,并停止nfs服务。本来三个节点也没有开启nfs服务,随便执行一下

    systemctl disable nfs
    systemctl stop nfs
    

    重新启动ctdb 服务,等待ctdb 状态变为OK

     systemctl restart ctdb
    
    ctdb status
    ctdb ip
    

    重启ctdb

    然后,可以查看nfs状态,发现被ctdb启动了

    systemctl status nfs
    

    nfs被ctdb启动

    Apr 08 10:43:42 node1.ctdb.feng exportfs[36582]: exportfs: /nfs-share/data does not support NFS export
    

    这个也可以理解,毕竟 这个nfs-share 本身就是通过nfs挂载出来的。。。但不能挂载也是可以查看一下的。

    这时候可以找一台安装过nfs-utils 且可以连通这三个节点的主机,测试一下。。。可以使用作为nfs共享的主机,但这样有种套娃的感觉。因为本来这个nfs-sahre 就是通过nfs挂载的nfs主机的nfs-sahre。。。所以有条件还是换一个主机测试。。。

    查看节点IP 的共享

    showmount -e 192.168.199.71
    

    ctdb内核态共享

    查看公共IP

    showmount -e 192.168.199.70
    

    公共IP可用
    公共IP192.168.199.70 可以查看,已经能够证明ctdb是正常提供服务了

    为了测试一下挂载使用其他目录作为共享
    三个节点都新建一个共享目录

    mkdir /mnt/nfs-share 
    

    修改一下 三个节点 nfs 配置文件

    vim /nfs-share/lock/exports
    
    /mnt/nfs-share *(rw,fsid=1235)
    

    重启ctdb 服务

    systemctl restart ctdb
    

    查看三个节点 nfs 服务运行状态

    systemctl status nfs
    

    nfs正常运行

    再次查看 nfs 共享情况
    再次查看共享
    测试挂载192.168.199.71 共享

    mkdir /mnt/test-nfs1
    mount -t nfs 192.168.199.71:/mnt/nfs-share /mnt/test-nfs1
    

    然后测试一下公共IP 是否可挂载

    mkdir /mnt/test-nfs2
    mount -t nfs 192.168.199.70:/mnt/nfs-share /mnt/test-nfs2
    

    也是没有问题查看

    df -h
    

    公共IP挂载
    尽管成功了,但是有一些问题。。。ctdb协助实现高可用。当三个节点中的一个挂掉了,公共IP会飘到另一个上面。。。现在状况是未使用gluster的卷,如果使用gluster的卷挂载到本地,三个节点的内容应当是是一致的。然后是可以通过nfs 挂载的。现在,三个节点共享点都是本地磁盘,内容有可能是不一致的。。。

    可以看一看 当前 70 IP到底指向的谁
    在 三个节点 的共享目录分别创建一个 不同的文件
    比如 192.168.199.71 节点创建 71文件

    cd /mnt/nfs-share/
    touch 71
    

    72 节点创建72 文件, 73 节点创建73文件

    然后 测试节点进入挂载192.168.199.70的目录

    cd /mnt/test-nfs2
    ls
    

    当前是72节点
    可以看到显示的 是72, 也就是说我的公共IP现在指向的是72节点。。现在把 72 节点 ctdb停掉

    systemctl stop ctdb
    

    再次使用测试节点查看
    变成71了
    这里公共IP已经飘向了71节点。。。证明 ctdb确实是在正常运行的

    ctdb的内核态nfs测试就到这里了。。。一般来说,使用ctdb是希望协助完成高可用工作。要保证数据一致的,这种情况只是一个测试。
    接下来我们可以使用 gluster来创建gluster卷挂载到然后使用ctdb管理实现高可用。。。

    安装glusterfs

    上面进行了测试后,机器上有ctdb在运行。。。现在为了接下来的测试,将ctdb 等服务和 挂载的 nfs 节点取消挂载。并把一些设置文件删掉,挂载点都没了,软链接现在失效了。。。

    停止ctdb 服务

    systemctl stop ctdb
    

    移除挂载

    umount /nfs-share/
    

    删除软链接配置文件

    rm -rf /etc/exports /etc/ctdb/nodes /etc/ctdb/public_addresses /etc/sysconfig/nfs /etc/sysconfig/ctdb
    

    为三个节点都新增一块20G硬盘,看上去更直观一点,不添加也是一样

    mkdir /data
    mkfs.xfs /dev/sdb
    
    echo "/dev/sdb  /data  xfs defaults 0 0"  >> /etc/fstab
    mount -a
    

    开始安装 gluster
    搜索gluster软件源

     yum search centos-release-gluster
    

    搜索gluster软件源
    就选择gluster4.1版本的安装吧,长久维护版本。但是和ceph的依赖包冲突,因此安装ceph就无法再安装gluster了。

    安装软件源

    yum -y install centos-release-gluster41
    

    安装需要的软件包

    yum -y install glusterfs-server
    

    安装完成后可以查看一下

    rpm -qa | grep gluster
    

    glusterfs安装完成

    安装完成 启动GlusterFS并设置开机启动

    systemctl enable glusterd
    systemctl start glusterd
    

    下面关于gluster的操作,如非注明,基本上一个节点操作就可以了。
    在某一节点执行,将其他两个节点加入集群 比如192.168.199.71

    gluster peer probe 192.168.199.72
    gluster peer probe 192.168.199.73
    

    添加完成查看集群状态

    gluster peer status
    

    集群状态
    创建卷 测试使用,创建一个简单地 3副本复制卷就好, 卷名vol-test
    如果在根目录上创建要使用 force 即命令末尾加上 force

    gluster volume create vol-test replica 3 192.168.199.71:/data/brick 192.168.199.72:/data/brick 192.168.199.73:/data/brick
    

    创建成功可以查看卷信息

    gluster volume info
    

    卷信息
    可以看到是一个 基本卷----复制卷 三个副本。
    开启卷,查看卷状态

    gluster volume start vol-test
    gluster volume status
    

    卷状态

    现在glusterfs卷已经设置成功。可以测试一下是否可用。建立一个主机,安装glusterfs glusterfs-cli glusterfs-fuse后进行测试

    yum -y install centos-release-gluster41
    yum -y install glusterfs glusterfs-cli glusterfs-fuse
    

    挂载 gluster创建的卷到本地

    mkdir /mnt/test-gluster
    mount -t glusterfs 192.168.199.71:vol-test /mnt/test-gluster/
    

    这里的ip可以是192.168.199.71,也可以是 72 或者73
    测试挂载gluster卷
    接下来,测试节点在该挂载点创建一些 文件,可以在三个节点的 /data/brick/ 中发现相同的文件,三个节点数据是一致的

    成功安装 gluster 并且创建了一个卷,使用gluster挂载到了本地。。。

    使用nfs方式挂载gluster的卷。

    有些主机 是没有安装 gluster 或者不能安装gluster,需要使用nfs挂载。这时,可以使用 gluster自带的 nfs
    首先确保本机的nfs服务时关闭的

    systemctl stop nfs
    

    设置卷开启 nfs服务

    gluster volume set vol-test nfs.disable off
    

    卷开启nfs服务

    Gluster NFS is being deprecated in favor of NFS-Ganesha Enter "yes" to continue using Gluster NFS (y/n) y
    

    说什么 GlusterFS NFS将要弃用 还是已经弃用(英语水平一般,也不知道是 is being 是将要还是已经。。。)现在使用NFS-Ganesha 代替了
    看这提示 估计是不能成功

    查看卷状态
    GlusterFS开启nfs状态
    看 NFS Server on 几行, Online 是N Pid也没有,那应该是不行了。。。
    测试节点尝试挂载也会失败

     mount -t nfs 192.168.199.71:vol-test /mnt/test-gluster-nfs/
    

    恢复卷状态

    gluster volume reset vol-test
    

    既然该方法不可用,那就使用 NFS-Ganesha尝试一下吧。。。
    安装 三个节点都要安装

    yum -y install nfs-ganesha nfs-ganesha-gluster
    

    编辑配置文件 /etc/ganesha/ganesha.conf 基本全部是注释。。

    vim  /etc/ganesha/ganesha.conf 
    

    添加到末尾即可
    三个节点不同的地方可能是 FSAL中的 Hostname?

    EXPORT
    {
    
            Export_Id = 1 ;
            Path = "/vol-test";
            Pseudo = "/vol-test";
            Disable_ACL = True;
            Protocols = "3","4";
            Access_Type = RW;
            Squash = No_root_squash;
            Sectype = "sys";
            Transports = "UDP","TCP";
    
            FSAL {
                    Name = "GLUSTER";
                    Hostname = "node3.ctdb.feng";
                    Volume = "vol-test";
            }
    
    }
    

    导出的 是 FSAL中 Volume,不是 Path 和 Pseudo。
    不要创建 /vol-test 目录
    启动nfs-ganesha 服务

    systemctl start nfs-ganesha
    

    查看 nfs-ganesha日志

    tail -f /var/log/ganesha/ganesha.log
    

    测试节点查看三个节点的导出目录

    showmount -e 192.168.199.71
    showmount -e 192.168.199.72
    showmount -e 192.168.199.73
    

    三个节点导出目录
    使用nfs方式挂载其中一个 如 192.168.199.71

    mount -t nfs 192.168.199.71:vol-test /mnt/test-gluster-nfs/
    

    nfs方式挂载
    可以看到里面有一个文件,就是上一步测试使用 gluster方式挂载时创建的。。。

    使用ctdb管理gluster的nfs挂载

    现在,可以测试使用ctdb 管理gluster达到高可用。。。

    现在有一个 gluster 创建的卷 vol-test。将这个卷使用glusterfs方式挂载在三个节点上。
    挂载点为 /mnt/gluster

    mkdir /mnt/gluster
    mount -t glusterfs 192.168.199.71:vol-test /mnt/gluster
    

    在挂载点创建两个文件夹,一个作为锁共享目录,一个作为数据共享目录

    mkdir /mnt/gluster/data
    mkdir /mnt/gluster/lock
    

    在 lock 目录创建 配置文件等。

    编辑 nodes 文件

    vim /mnt/gluster/lock/nodes
    
    192.168.199.71
    192.168.199.72
    192.168.199.73
    
    

    编辑public_addresses文件

    vim /mnt/gluster/lock/public_addresses
    
    192.168.199.70/24	ens33
    

    编辑nfs文件

    vim /mnt/gluster/lock/nfs
    
    NFS_TICKLE_SHARED_DIRECTORY=/mnt/gluster/lock/nfs-tickles
    NFS_HOSTNAME=nfs-server
    STATD_PORT=874
    STATD_OUTGOING_PORT=876
    MOUNTD_PORT=892
    RQUOTAD_PORT=875
    LOCKD_UDPPORT=872
    LOCKD_TCPPORT=872
    STATD_SHARED_DIRECTORY=/mnt/gluster/lock/nfs-state
    STATD_HOSTNAME="$NFS_HOSTNAME -H /etc/ctdb/statd-callout"
    RPCNFSDARGS="-N 4"
    

    ganesha.conf 文件应该不用放在这里。。。

    编辑 ctdb 配置文件

    vim /mnt/gluster/lock/ctdb
    
    CTDB_RECOVERY_LOCK=/mnt/gluster/lock/ctdb.lock
    CTDB_LOGFILE=/var/log/log.ctdb
    CTDB_DEBUGLEVEL=ERR
    CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses
    CTDB_NODES=/etc/ctdb/nodes
    

    将原配置文件备份后建立软链接 三个节点都要执行

    mv /etc/sysconfig/nfs /etc/sysconfig/nfs.bak 
    mv /etc/sysconfig/ctdb /etc/sysconfig/ctdb.bak 
    
    ln -s /mnt/gluster/lock/nodes /etc/ctdb/nodes
    ln -s /mnt/gluster/lock/public_addresses /etc/ctdb/public_addresses
    ln -s /mnt/gluster/lock/nfs /etc/sysconfig/nfs
    ln -s /mnt/gluster/lock/ctdb /etc/sysconfig/ctdb
    

    使用ctdb管理内核态nfs 时,都是使用本地存储。。数据不一致,现在有gluster了,可以再实验一下管理 内核态nfs

    测试节点停止挂载

    关闭nfs-ganesha服务

    systemctl stop nfs-ganesha
    

    编辑 /mnt/gluster/lock/ctdb

    vim  /mnt/gluster/lock/ctdb
    

    加上

    CTDB_NFS_SKIP_SHARE_CHECK=yes
    CTDB_MANAGES_NFS=yes
    

    编辑 /mnt/gluster/lock/exports

    vim /mnt/gluster/lock/exports
    

    备份

    mv /etc/exports /etc/exports.bak
    
    /mnt/gluster/data *(rw,async,no_root_squash,no_subtree_check,fsid=1235)
    

    在三个节点建立软链接

    ln -s /mnt/gluster/lock/exports /etc/exports
    

    三个节点启动 ctdb 等待状态OK后,使用测试节点查看并挂载公共IP。提供的共享目录

    systemctl enable ctdb
    systemctl restart ctdb
    
    showmount -e 192.168.199.70
    
    mkdir /mnt/test-ctdb-nfs
    mount -t nfs 192.168.199.70:/mnt/gluster/data /mnt/test-ctdb-nfs
    

    ctdb管理的nfs挂载
    这时,也就不知道 公共IP到底指向的是哪一个IP,即时其中一个节点挂掉了。。公共IP也会飘向另外一个。而测试节点作为用户来看,是不知晓这一过程的。。。

    测试gluster用户态nfs的高可用。。。

    编辑 /mnt/gluster/lock/ctdb 文件

    vim  /mnt/gluster/lock/ctdb
    

    将这两行删除或者注释掉。

    #CTDB_NFS_SKIP_SHARE_CHECK=yes
    #CTDB_MANAGES_NFS=yes
    

    关闭 nfs 服务

    systemctl stop nfs
    

    关闭 ctdb 服务

    systemctl stop ctdb
    

    启动nfs-ganesha 服务 并设置开机启动

    systemctl enable nfs-ganesha
    systemctl start nfs-ganesha
    

    启动 ctdb

    systemctl start ctdb
    

    测试节点。查看 几个节点的共享和 公共IP

    showmount -e 192.168.199.71
    showmount -e 192.168.199.70
    

    查看gluster共享
    测试挂载 公共IP

    mkdir /mnt/test-ctdb-gluster
    mount -t nfs 192.168.199.70:vol-test /mnt/test-ctdb-gluster/
    

    测试管理gluster

    SAMBA安装

    这里单说是因为我感觉自己被Samba+CTDB 折磨的很惨。。。

    不要直接安装

    yum -y install samba-4.2.4
    

    按照上面的安装方法 ,即先设置/etc/yum.repos.d/glusterfs-samba-epel.repo,然后执行yum -y install samba-4.2.4 安装。
    启动Samba时会报一大堆的错误。。。基本是解决不了的(至少我没解决掉,原因应该是,依赖包不对。。。某些依赖包版本过高)
    Samba启动失败
    经过检验,发现,把所有包全部下载下来,然后 本地安装 忽略依赖时,才能正常运行。。。
    找一个新的主机 。。。尝试安装 samba-4.2.4+ctdb-4.2.4
    我的系统是CentOS7 64位,需要下载这个网站的全部rpm包
    https://download.gluster.org/pub/gluster/glusterfs/samba/CentOS/epel-7/x86_64/
    将这上面的 rpm 包 全部下载下来。。。应该有48 个。然后放到本地准备在本地安装
    本来想我已经下载完成了,在这里放一个资源连接的,也方便自己后续使用。。。竟然放不成
    所有软件包

    然后执行 安装

     rpm -ivh * --nodeps --force
    

    –nodeps 表示 忽略依赖, --force 表示强制安装

    这样就将 Samba和ctdb都安装上了,版本是 4.2.4 但是,启动Samba时仍然有可能报错。。。
    缺少libcups.so.2
    这个错误好解决一点。。。

    yum -y install cups-libs
    

    可能还有其他的依赖包 ,遇到了再补充。

    yum install libarchive
    

    再次尝试启动

    systemctl start smb
    

    smb的状态
    安装完成后。。。请不要

    yum -y upgrade
    

    这个命令会把软件包升级,samba和ctdb会变成4.9。。然后,samba应该还可以用。ctdb就悲剧了。。。这强调针对自己,不过也不知道会不会看到强调就故意执行一下。。。就像灯泡包装上写着不要放进嘴里。。。有些人看到了反而想试一下

    安装完成。这时就可以使用了。。。至于ctdb管理Samba,个人理解更像是 ctdb 管理Samba的启停。。。然后Samba的作用应该是linux平台上文件资源的共享什么的。。。比如向windows共享文件。
    然后,其他的高可用之类,更多地像是ctdb自带的。如上几步进行的测试,ctdb的一些很强大的地方, ctdb的public_addresses 。这个虚拟公共IP很是厉害,ctdb服务设置后,是可以直接 ping 通的。。。然后,可以利用公共IP实现高可用,公共IP具体实现不清楚,但是测试时 表明 这个公共IP实际上是指向某一个节点的,当使用公共IP挂载 nfs 或者gluster 时,挂载的公共IP指向的实际节点的 内容。。当公共IP指向的节点出现故障,公共IP会自动飘向另一个完好的节点,因此,用户在使用公共IP挂载 nfs或gluster时,是感觉不到 自己使用哪一个节点的,且高可用。

    Samba 共享指定的目录,这个使用ctdb管理时,差不多,可以使用公共IP来访问这些共享目录,当然,实际看到的是某一个具体节点的共享。。。但是当几个节点共享的是一个类似于 gluster 创建的卷时,这样看到的内容就是一样的。。。

    Samba使用测试

    安装完 Samba后,可以先测试一下使用。。
    比如当前安装samba且服务可以正常启动。IP 192.168.199.62

    设置 smb.conf 文件 位置 /etc/samba/smb.conf 如果原本有配置文件。可以备份一份后 创建一个简单的文件

    mv /etc/samba/smb.conf /etc/samba/smb.conf.bak
    vim /etc/samba/smb.conf
    
    [global]
            workgroup = MYGROUP
    
            security = user
            map to guest = Bad User
    
            passdb backend = tdbsam
    
            log file = /var/log/samba/log.%m
    
            printcap name = cups
            load printers = yes
            cups options = raw
    [share]
            comment = share all
            path = /tmp/share
            browseable = yes
            writable = no
            public = yes                   
    

    共享的目录 是 /tmp/sahre 共享名 share,来宾可访问,只读。
    具体samba设置可以网上查找,samba教程比ctdb多得多。。。
    创建 /tmp/sahre 目录

    mkdir /tmp/share
    

    在 该目录添加一些内容。。随便就好

    touch /tmp/share/fengyun
    

    使用testparm 命令 检测配置文件 是否正确

    testparm 
    

    测试smb配置文件
    看到 Loaded services file OK 就基本正常。。。
    可以在windows上打开一个浏览器 访问

    file://192.168.199.62/share
    

    samba正常可用
    有此,基本可以证明 安装的samba是没问题的。。。

    测试Samba高可用

    把之前的三个节点重新安装一下系统。再重新安装一下samba+ctdb,测试一下使用ctdb管理samba,除了上一步安装的 samba应该都是无法启动的。。。
    三个 节点的 IP
    192.168.199.71
    192.168.199.72
    192.168.199.73

    欲使用的公共IP 192.168.199.70 就是说这个IP是没被哪个主机使用的
    测试节点 IP
    192.168.199.62

    三个节点 安装samba + ctdb
    不要设置 /etc/yum.repos.d/glusterfs-samba-epel.repo 了。。。
    安装 samba+ctdb
    安装 cups-libs

    yum -y install cups-libs
    

    简单起见,就不再挂载一块新硬盘了 创建目录 data

    mkdir /data
    

    安装 GlusterFS

    yum -y install centos-release-gluster41
    yum -y install  glusterfs glusterfs-server glusterfs-rdma glusterfs-geo-replication
    

    开启gluster服务并设置开机启动

    systemctl enable glusterd
    systemctl start glusterd
    

    在某一个节点把其它节点加入集群

    gluster peer probe 192.168.199.72
    gluster peer probe 192.168.199.73
    

    创建卷 卷名 vol-share 用来给samba设置共享目录。。。

    gluster volume create vol-share replica 3 192.168.199.71:/data/brick 192.168.199.72:/data/brick 192.168.199.73:/data/brick force
    

    查看卷信息

    gluster volume info
    

    在三个节点挂载 vol-share 卷到本地

    mkdir /mnt/data
    mount -t glusterfs 192.168.199.71:vol-share /mnt/data/
    

    创建配置文件
    先创建目录

    mkdir /mnt/data/lock
    mkdir /mnt/data/share
    

    设置权限 所有用户可读写 这个极不安全,只是试验时设置一下。

    chmod 777 /mnt/data/share
    

    编辑 samba配置文件

    vim /mnt/data/lock/smb.conf
    
    [global]
            workgroup = MYGROUP
    
            security = user
            map to guest = Bad User 
    
            passdb backend = tdbsam
    
            log file = /var/log/samba/log.%m
    
            printcap name = cups
            load printers = yes
            cups options = raw
    [share]
            comment = share all
            path = /mnt/data/share
            browseable = yes
            writable = yes
            public = yes
    

    编辑 ctdb 配置文件

    vim /mnt/data/lock/ctdb
    
    CTDB_RECOVERY_LOCK=/mnt/data/lock/ctdb.lock
    CTDB_LOGFILE=/var/log/log.ctdb
    CTDB_DEBUGLEVEL=ERR
    CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses
    CTDB_NODES=/etc/ctdb/nodes
    CTDB_MANAGES_SAMBA=yes
    CTDB_SAMBA_SKIP_SHARE_CHECK=yes
    
    CTDB_MANAGES_SAMBA=yes
    CTDB_SAMBA_SKIP_SHARE_CHECK=yes
    

    表示对samba进行管理

    编辑 nodes 文件

    vim /mnt/data/lock/nodes
    
    192.168.199.71
    192.168.199.72
    192.168.199.73
    
    

    编辑public_addresses文件

    vim /mnt/data/lock/public_addresses
    
    192.168.199.70/24	ens33
    

    三个节点备份好原文件后 建立软链接

    mv /etc/sysconfig/ctdb /etc/sysconfig/ctdb.bak
    mv /etc/samba/smb.conf /etc/samba/smb.conf.bak
    
    ln -s /mnt/data/lock/nodes /etc/ctdb/nodes
    ln -s /mnt/data/lock/public_addresses /etc/ctdb/public_addresses
    ln -s /mnt/data/lock/ctdb /etc/sysconfig/ctdb
    ln -s /mnt/data/lock/smb.conf /etc/samba/smb.conf
    

    和上文基本一致。又重写了一遍加深一下印象。。。

    三个节点都启动 ctdb。。。

    在三个节点执行

    systemctl start ctdb
    

    或者 在某一个节点执行应该是 启动集群中所有ctdb服务

    onnode -p all service ctdb start
    

    不过好像要输入密码。。。而且 也不一定能成功。。。要设置一些免ssh登录什么的。。。

    成功启动后 查看状态

    ctdb status
    

    全部变成OK 后,可以在 Windows上打开一个浏览器。。。访问

    file://192.168.199.70/share
    

    文件夹为空
    可以尝试向其中添加一些东西
    添加一个文档

    这时在 三个节点的该目录下都可以看到该文件。。。
    成功
    可以把一个节点关掉,仍然可以访问我想samba的高可用大概是这个意思吧。。。

    这篇博客还挺长。。。

    展开全文
  • samba+ctdb集群配置文档

    2013-06-07 15:40:20
    NAS集群中配置samba和CTDB操作说明
  • ctdb原理介绍

    千次阅读 2017-09-15 18:37:40
    1. CTDB概述 CTDB是一个集群TDB数据库,可以被Samba或者其他的应用使用来存储数据。如果一个应用是使用TDB来暂时存放数据,那么这个应用可以很轻松的使用CTDB扩展为集群模式。CTDB提供与TDB相同的函数接口,并且是...

    1. CTDB概述

    CTDB是一个集群TDB数据库,可以被Samba或者其他的应用使用来存储数据。如果一个应用是使用TDB来暂时存放数据,那么这个应用可以很轻松的使用CTDB扩展为集群模式。CTDB提供与TDB相同的函数接口,并且是构建在多台物理机器上的集群。

    特性:
    - CTDB提供一个横跨多个节点的并且数据一致、锁一致的TDB数据库;
    - CTDB非常快速;
    - 对于节点故障,CTDB将自动恢复和修复其所管理的所有TDB数据库;
    - CTDB是Samba3/4的一个核心组件;
    - CTDB提供高可用特性,例如节点监控、节点切换、IP切换;
    - CTDB为其多个节点上的应用提供可靠的传输通道;
    - CTDB提供可热拔插的后端传输通道,目前实现了TCP和IB;
    - CTDB可以提供为应用指定特定的管理脚本,使得应用能够实现高可用。

    2. CTDB配置

    CTDB的配置相对简单,对于搭建一个三节点的CTDB配置步骤说明如下。

    2.1 节点信息

    节点名称节点IP说明
    node110.10.10.90CTDB节点
    node210.10.10.91CTDB节点
    node310.10.10.92CTDB节点
    node410.10.10.99共享存储

    说明:此处为快速简单的搭建ctdb集群,采用单节点NFS共享,不考虑NFS共享的可靠性。
    实际应用时,共享存储应由高可靠的集群担当。

    2.2搭建CTDB集群

    2.2.1 安装软件

    在三个CTDB节点分别安装ctdb,nfsd,samba,可以通过命令 yum install ctdb依次进行安装;

    2.2.2 创建共享存储

    在node4创建一个共享目录/share,并设置权限777,在/etc/exports文件中添加如下:

    /share *(sync,rw)

    然后在节点4上执行如下命令:

    # exoprtfs -rv

    CTDB节点之间需要通过一个共享的存储来实现其基于锁机制的选举过程。

    2.2.3 挂载共享存储

    在三个CTDB节点上分别执行如下命令:

    # mount -t nfs 10.10.10.99:/share /mnt

    node1, node2,node3上都挂载了node4共享出来的目录,这样三个节点就可以访问到一个相同的锁文件了。

    2.2.4 修改CTDB服务配置

    在三个CTDB节点上修改如下文件:

    ~# vi /etc/sysconfig/ctdb
    
    CTDB_RECOVERY_LOCK=/mnt/ctdb_lock
    
    CTDB_MANAGES_SAMBA=yes
    CTDB_MANAGES_WINBIND=yes
    CTDB_MANAGES_NFS=yes

    这个步骤中主要配置CTDB管理哪些应用。还有就是指定共享锁文件的目录。

    2.2.5 修改CTDB节点配置

    在三个CTDB节点上创建或者修改如下文件:

    ~# vi /etc/ctdb/nodes
    10.10.10.91
    10.10.10.92
    10.10.10.90

    2.2.6 修改CTDB IP配置

    在三个CTDB节点上创建或者修改如下文件:

    ~# vi /etc/ctdb/public_addresses
    10.0.0.1/24    eth0

    其中eth0是节点上存在的并且在线的网卡。10.0.0.1就是配置给这个三个节点CTDB集群对外提供业务的IP。

    2.2.7 重启CTDB服务

    在三个CTDB节点上执行如下命令:

    ~# systemctl restart ctdb

    2.2.8 查看CTDB服务状态

    在节点1上执行:

    # ctdb status
    Number of nodes:3
    pnn:0 10.10.10.91      OK
    pnn:1 10.10.10.92      OK
    pnn:2 10.10.10.90      OK (THIS NODE)
    Generation:1699238992
    Size:3
    hash:0 lmaster:0
    hash:1 lmaster:1
    hash:2 lmaster:2
    Recovery mode:NORMAL (0)
    Recovery master:1
    [root@xenserver-yzulkyuc ~]# 
    

    集群搭建完成。
    说明:如果节点数量较少,可以将某一个CTDB节点作为共享存储,同时节点数量也可以为1。但是将CTDB节点作为共享存储的话,需要将/etc/sysconfig/ctdb 文件中的CTDB_MANAGES_NFS设置位NO。

    3. CTDB源码分析

    3.1 关键数据结构

    3.1.1 ctdb

    CTDB有两个进程构成,ctdbd和recoveryd。在这个两个进程进行各种事物处理时,一般都带有一个参数:ctdb。该数据结构是包含了基本上所有逻辑所需或者相关的数据。在CTDBD启动阶段就是对ctdb数据结构的填充阶段。

    struct ctdb_context {
        struct tevent_context *ev;              //封装的事件处理接口,后端使用select/poll/epoll 多路I/O复用机制
        struct timeval ctdbd_start_time;        //ctdbd启动时间
        struct timeval last_recovery_started;
        struct timeval last_recovery_finished;
        uint32_t recovery_mode;                 //根据此值可以判断是否需要进行recovery
        TALLOC_CTX *tickle_update_context;
        TALLOC_CTX *keepalive_ctx;
        TALLOC_CTX *check_public_ifaces_ctx;
        struct ctdb_tunable_list tunable;
        enum ctdb_freeze_mode freeze_mode;
        struct ctdb_freeze_handle *freeze_handle;
        bool freeze_transaction_started;
        uint32_t freeze_transaction_id;
        ctdb_sock_addr *address;               //此ctdb节点的IP地址
        const char *name;
        const char *db_directory;
        const char *db_directory_persistent;
        const char *db_directory_state;
        struct tdb_wrap *db_persistent_health;
        uint32_t db_persistent_startup_generation;
        uint64_t db_persistent_check_errors;
        uint64_t max_persistent_check_errors;
        const char *transport;
        const char *recovery_lock;
        uint32_t pnn; /* our own pnn */     
        uint32_t num_nodes;
        uint32_t num_connected;
        unsigned flags;
        uint32_t capabilities;
        struct reqid_context *idr;
        struct ctdb_node **nodes;               //集群节点列表,索引为vnn
        struct ctdb_vnn *vnn;                   //公共IP列表和网卡
        struct ctdb_interface *ifaces; /* list of local interfaces */
        char *err_msg;
        const struct ctdb_methods *methods;     //启动时注册的tcp处理函数
        const struct ctdb_upcalls *upcalls;     //启动时注册的处理函数
        void *private_data; /* private to transport */
        struct ctdb_db_context *db_list;
        struct srvid_context *srv;
        struct ctdb_daemon_data daemon;
        struct ctdb_statistics statistics;
        struct ctdb_statistics statistics_current;
    #define MAX_STAT_HISTORY 100
        struct ctdb_statistics statistics_history[MAX_STAT_HISTORY];
        struct ctdb_vnn_map *vnn_map;
        uint32_t num_clients;
        uint32_t recovery_master;
        struct ctdb_client_ip *client_ip_list;
        bool do_checkpublicip;
        bool do_setsched;
        const char *event_script_dir;
        const char *notification_script;
        const char *default_public_interface;
        pid_t ctdbd_pid;
        pid_t recoverd_pid;
        enum ctdb_runstate runstate;
        struct ctdb_monitor_state *monitor;
        int start_as_disabled;
        int start_as_stopped;
        bool valgrinding;
        uint32_t *recd_ping_count;
        TALLOC_CTX *recd_ctx; /* a context used to track recoverd monitoring events */
        TALLOC_CTX *release_ips_ctx; /* a context used to automatically drop all IPs if we fail to recover the node */
    
        struct eventd_context *ectx;
    
        TALLOC_CTX *banning_ctx;
    
        struct ctdb_vacuum_child_context *vacuumers;
    
        /* mapping from pid to ctdb_client * */
        struct ctdb_client_pid_list *client_pids;
    
        /* Used to defer db attach requests while in recovery mode */
        struct ctdb_deferred_attach_context *deferred_attach;
    
        /* if we are a child process, do we have a domain socket to send controls on */
        bool can_send_controls;
    
        struct ctdb_reloadips_handle *reload_ips;
    
        const char *nodes_file;
        const char *public_addresses_file;
        struct trbt_tree *child_processes; 
    
        /* Used for locking record/db/alldb */
        struct lock_context *lock_current;
        struct lock_context *lock_pending;
    };

    3.1.2 初始化upcall

    在上面一节中的ctdb结构中可以看到有这个upcall处理函数接口。初始化操作是在main()函数的入口处进行的。

        ctdb->recovery_mode    = CTDB_RECOVERY_NORMAL;
        ctdb->recovery_master  = (uint32_t)-1;
        ctdb->upcalls          = &ctdb_upcalls;

    而ctdb_upcalls定义如下:

    static const struct ctdb_upcalls ctdb_upcalls = {
        .recv_pkt       = ctdb_recv_pkt,        //当有消息包传入时调用此函数进行处理。
        .node_dead      = ctdb_node_dead,       //当有节点出现故障或者离线时调用此函数,进行的操作是重启。
        .node_connected = ctdb_node_connected   //当有连接请求发送时,调用此函数,更新连接统计信息。
    };
    
    

    3.1.3 创建unix socket fd

    在启动ctdbd守护进程过程中,创建了unix socket,并且将fd赋值给了3.1.1中的daemon.sd。并且开始监听是否有连接请求。

    ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);

    3.1.4 初始化tevent

    tevent是ctdb中事件处理机制,底层采用select/poll/epoll多路I/O复用机制,对外提供统一的接口。初始化就是将接口进行统一处理。接口的统一入口就是3.1.1小节中提的ctdb->ev。

    ctdb->ev = tevent_context_init(NULL);

    初始化完成后,形成一个双向链表,链表中存放的是不同的I/O多路复用接口,但是对于调用这来说,看的接口是相同的。

    image

    即ops的名称是一致的,而对于不同的I/O复用就赋值了相对应的函数接口。

    static const struct tevent_ops select_event_ops = {
        .context_init       = select_event_context_init,
        .add_fd         = select_event_add_fd,
        .set_fd_close_fn    = tevent_common_fd_set_close_fn,
        .get_fd_flags       = tevent_common_fd_get_flags,
        .set_fd_flags       = tevent_common_fd_set_flags,
        .add_timer      = tevent_common_add_timer_v2,
        .schedule_immediate = tevent_common_schedule_immediate,
        .add_signal     = tevent_common_add_signal,
        .loop_once      = select_event_loop_once,
        .loop_wait      = tevent_common_loop_wait,
    };

    3.1.5 tcp传输通道初始化

    在ctdbd守护进程启动节点,初始化tcp传输通道

    /*
      initialise tcp portion of ctdb 
    */
    int ctdb_tcp_init(struct ctdb_context *ctdb)
    {
        struct ctdb_tcp *ctcp;
        ctcp = talloc_zero(ctdb, struct ctdb_tcp);
        CTDB_NO_MEMORY(ctdb, ctcp);
    
        ctcp->listen_fd = -1;
        ctcp->ctdb      = ctdb;
        ctdb->private_data = ctcp;
        ctdb->methods = &ctdb_tcp_methods;
    
        talloc_set_destructor(ctcp, tcp_ctcp_destructor);
        return 0;
    }

    上面的代码中的ctdb->methods初始化为了&ctdb_tcp_methods,其定义如下:

    static const struct ctdb_methods ctdb_tcp_methods = {
        .initialise   = ctdb_tcp_initialise,
        .start        = ctdb_tcp_start,
        .queue_pkt    = ctdb_tcp_queue_pkt,
        .add_node     = ctdb_tcp_add_node,
        .connect_node = ctdb_tcp_connect_node,
        .allocate_pkt = ctdb_tcp_allocate_pkt,
        .shutdown     = ctdb_tcp_shutdown,
        .restart      = ctdb_tcp_restart,
    };

    进行上述接口注册后,就调用的ctdb_tcp_initialise进行初始了,在该函数中完成了两件事情
    - ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);创建了一个socket server端,监听的地址是当前ctdb节点的地址。监听后,注册了一个监听事件,一旦有其他节点来连接当前ctdb节点,将调用注册的函数:ctdb_listen_event,在该处理函数中将accept连接请求。并再次注册一个读事件到tevent中。也就是当客户端有写入数据时,当前ctdb将调用ctdb_tcp_read_cb进行数据包的处理。

        in->queue = ctdb_queue_setup(ctdb, in, in->fd, CTDB_TCP_ALIGNMENT,
                         ctdb_tcp_read_cb, in, "ctdbd-%s", ctdb_addr_to_str(&addr));
    • 给ctdb集群的所有节点都创建了一个out_queue队列,并且这个数据结构保存在ctdb->node[i]中。

    3.1.6 unix socket accept函数

    在3.1.3中已经创建了unix socket,此时注册了一个accept事件,处理函数为:ctdb_accept_client,事件类型为TEVENT_FD_READ。在此处理函数中会accept连接请求。并将已经连接上的client信息存放在 ctdb->client_pids 链表当中。最后再次注册一个读请求处理函数ctdb_daemon_read_cb。该函数注册的位置为:ctdb->client_pids->queue->callback,此外ctdb->client_pids->queue->im= tevent_create_immediate(queue);理解起来应该是,如果已连接的这个unix socket上有读事件的话,立刻处理。

    3.1.7 启动tcp传输通道

    调用的函数为ctdb_tcp_start(ctdb);该函数主要完成node节点之间的tcp连接。在前3.1.5节中说到每一个ctdb节点都在监听自己的IP地址,而ctdb_tcp_start(ctdb)相当于把当前节点作为client,去连接所有其他的ctdb节点。同样,其他节点也会进行相同的操作处理。也就是最后会出现的结果是集群的每一个节点都与剩余节点存在链接。这个已连接的fd保存在ctdb->node[i]->private_data(ctdb_tcp_node)->fd。
    同时注册了两个事件,一个是已建立连接可写时的事件处理函数。第二个是定时连接处理函数,就是每隔一秒钟去连接这个节点。
    从已有的三节点ctdb环境中可以看到相关连接的信息:

    [root]# netstat -anp | grep ctdbd
    tcp        0      0 10.10.10.90:4379        0.0.0.0:*               LISTEN      1006/ctdbd          
    tcp        0      0 10.10.10.90:50071       10.10.10.92:4379        ESTABLISHED 1006/ctdbd          
    tcp        0      0 10.10.10.90:4379        10.10.10.91:48353       ESTABLISHED 1006/ctdbd          
    tcp        0      0 10.10.10.90:4379        10.10.10.92:57112       ESTABLISHED 1006/ctdbd          
    tcp        0      0 10.10.10.90:57413       10.10.10.91:4379        ESTABLISHED 1006/ctdbd 

    从上面的连接信息判断,node1(10.10.10.90)通过57413端口作为client去connect了node2,通过50071端口去connect了node3。同样node2通过48353端口connect了node1。node3通过57112端口去连接了node1。与上述连接逻辑一致。

    3.2事件通知机制

    事件通知机制是ctdb结构中最重要的一部分,事件通知机制将各个逻辑链接起来以完成相关的功能实现。
    下面以 fde = tevent_add_fd(ctdb->ev, ctdb, ctdb->daemon.sd, TEVENT_FD_READ,ctdb_accept_client, ctdb);为例来分析是如何将该事件监控起来并调用事件处理函数的。
    在ctdb_start_daemon函数中,先后调用了tevent_add_fd以及tevent_loop_wait函数。
    - tevent_add_fd,对于这个函数是tevent对外提供的接口,其实际调用的是epoll_event_add_fd函数(此处以epoll为例,如果内核不支持epoll,那么可能就会调用select或者poll相对应的函数。)在此函数中主要进行了2个逻辑处理
    1. 将事件相关的参数和函数赋值到fde,并将fde加入到ctdb->ev->fd_events链表中;
    2. 执行epoll_update_event(epoll_ev, fde)函数更新epoll_ev,具体就是将待添加的event通过epoll_ctl加入到epoll_ev->epoll_fd;

    • tevent_loop_wait实际会调用epoll_event_loop_once,再调用epoll_event_loop,最终调用epoll_wait,查看已就绪事件,并调用相应的事件处理函数进行处理。

    tevent_loop_wait会一直循环检查是否有事件注册了,如果有,就会不断的循环去判断;

    */
    int tevent_common_loop_wait(struct tevent_context *ev,
                    const char *location)
    {
        /*
         * loop as long as we have events pending
         */
        while (tevent_common_have_events(ev)) { // 此函数会一直返回真
            int ret;
            ret = _tevent_loop_once(ev, location);
            if (ret != 0) {
                tevent_debug(ev, TEVENT_DEBUG_FATAL,
                         "_tevent_loop_once() failed: %d - %s\n",
                         ret, strerror(errno));
                return ret;
            }
        }
    
        tevent_debug(ev, TEVENT_DEBUG_WARNING,
                 "tevent_common_loop_wait() out of events\n");
        return 0;
    }

    3.3 主循环流程

    下面图中所展示的是recoveryd进程的循环处理事务的过程。函数名称为main_loop。

    A(检查ctdbd是否存活)-->B(告诉ctdbd recoveryd是活动的)
    B-->C(是否选举中)
    C-->D(是- 退出main_loop)
    C-->E(不是- 获取ctdbd debug level)
    E-->F(获取cdbd运行参数)
    F-->G(获取ctdbd运行状态)
    G-->H(获取nodemap)
    H-->I(获取recovery mode)
    I-->J(当前节点是否是stopped或者baned状态)
    J-->K(是- 设置recovery mode为 active,并freezee db就是锁住?)
    K-->L(获取所有节点所具备的角色能力,如下图所示)
    L-->M(查看recmaster,如果unknown, force elelction)
    M-->N(选举中,返回)
    M-->O(查看是否有ip需要分配)
    O-->P(查看是否所有节点都同意recmater node)
    P-->Q(获取vnnmap)
    Q-->R(查看是否需要recovery)
    R-->S(查看所有节点处于normal状态)
    S-->T(当前节点是否持有共享锁,是的话,检查一下锁状态)
    T-->U(从所有其他节点获取nodemap并比较所有nodemap是否一致,不一致的话执行do_recover)
    U-->V(更新所有节点状态标识)
    V-->W(统计活动的node数量)
    W-->X(active node情况与vnnmap记录一致)
    X-->Y(检查所有节点是否有相同的vnn和相同的版本号)

    3.4节点及节点节点间通信总结

    3.4.1单个ctdb节点内进程之间的连接

    ctdb有两个进程,ctdbd和recoveryd,这个两个进程之间通过unix socket进行消息的传递。一般recoveryd发送带opcode的消息,ctdbd通过

    3.4.2 ctdb节点之间连接

    1. 初始化函数ctdb_tcp_initialise中,为当前节点创建了一个监听ctdb address的socket,并且将fd保存在ctdb->private_data->listen_fd。其中private_data的数据结构是struct ctdb_tcp。也就是每一个ctdb节点启动时都会创建并监听本地节点的IP地址。
    2. 由于ctdb节点之间需要相互通信,因此在初始化过程中,将所有节点有关连接的信息都保存在ctdb中。ctdb->nodes[i]就可以遍历所有节点关于连接的信息。而ctdb->nodes[i]->private_data->fd就是保存相应node的fd。其中private_data的数据结构为struct ctdb_tcp_node。
    3. 基于上面步骤2中的描述,ctdb->nodes[i]->private_data->out_queue,就是初始化的一个队列。但是初始化时ctdb->nodes[i]->private_data->fd值为-1。
    4. 应该在main_loop 中getnodemap时会更新ctdb->nodes[i]->private_data->fd这个值(目前是猜测)

    3.4.3 控制消息处理流程总结

    下面以获取node map的消息为例来说明,如何从一个ctdb节点获取到另一个ctdb节点的信息。
    1. ret = ctdb_ctrl_getnodemap(ctdb, CONTROL_TIMEOUT(), pnn, rec, &rec->nodemap);执行程序的自然就是发起消息的节点,其中pnn就是目标节点;该控制消息是获取nodemap;
    2. ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,mem_ctx, &outdata, &res, &timeout, NULL);其中destnode就是要目标node;
    3. state = ctdb_control_send(ctdb, destnode, srvid, opcode, flags, data, mem_ctx,timeout, errormsg);
    4. ret = ctdb_client_queue_pkt(ctdb, &(c->hdr));其中c->hdr中包含了函数调用中需要的参数;
    5. ctdb_queue_send(struct ctdb_queue *queue, uint8_t *data, uint32_t length);
    6. n = write(queue->fd, data, length2);即将数据包写入了unix socket 的fd中;
    7. unix socket fd的read 函数是在ctdb_accept_client 中设置的:ctdb_daemon_read_cb
    8. daemon_incoming_packet(client, hdr);其中,hdr即最初发送的数据包;
    9. 依据hdr中的hdr->operation判断消息类别:CALL/MESSAGE/CONTROL
    10. 调用CONTROL消息处理函数daemon_request_control_from_client
    11. res = ctdb_daemon_send_control(client->ctdb, c->hdr.destnode,c->srvid, c->opcode, client->client_id,c->flags,data, daemon_control_callback,state);
    12. ctdb_queue_packet(ctdb, &c->hdr);并添加了一个控制消息超时处理事件ctdb_control_timeout();
    13. 语句node = ctdb->nodes[hdr->destnode]获取到目标node信息;
    14. ctdb->methods->queue_pkt(node, (uint8_t *)hdr, hdr->length);该函数为初始化时注册的;
    15. ctdb_tcp_queue_pkt(struct ctdb_node *node, uint8_t *data, uint32_t length);从node的node->private_data中提取出tnode;
    16. ctdb_queue_send(tnode->out_queue, data, length);其中tnode->out_queue->fd即是已连接到目标节点的fd。
    17. n = write(queue->fd, data, length2);数据通过fd写入到socket链接
    18. 远端node接收到请求;在远端节点中从上述的第7步开始重复。

    控制消息首先通过unix socket从recoveryd进程发送,ctdbd进程读取unix socket上的数据,并对数据进行解析,如果获取的是当前的节点信息就提供信息并返回,如果是需要获取remote node的节点信息,就使用保存在node = ctdb->nodes[hdr->destnode]中的fd将消息发送给remote node。

    static const struct ctdb_methods ctdb_tcp_methods = {
        .initialise   = ctdb_tcp_initialise,
        .start        = ctdb_tcp_start,
        .queue_pkt    = ctdb_tcp_queue_pkt,
        .add_node     = ctdb_tcp_add_node,
        .connect_node = ctdb_tcp_connect_node,
        .allocate_pkt = ctdb_tcp_allocate_pkt,
        .shutdown     = ctdb_tcp_shutdown,
        .restart      = ctdb_tcp_restart,
    };
    
    展开全文
  • CTDB介绍

    千次阅读 2018-06-06 19:19:54
    1. CTDB概述CTDB是一个集群TDB数据库,可以被Samba或者其他的应用使用来存储数据。如果一个应用是使用TDB来暂时存放数据,那么这个应用可以很轻松的使用CTDB扩展为集群模式。CTDB提供与TDB相同的函数接口,并且是...

    1. CTDB概述

    CTDB是一个集群TDB数据库,可以被Samba或者其他的应用使用来存储数据。如果一个应用是使用TDB来暂时存放数据,那么这个应用可以很轻松的使用CTDB扩展为集群模式。CTDB提供与TDB相同的函数接口,并且是构建在多台物理机器上的集群。

    特性: 
    - CTDB提供一个横跨多个节点的并且数据一致、锁一致的TDB数据库; 
    - CTDB非常快速; 
    - 对于节点故障,CTDB将自动恢复和修复其所管理的所有TDB数据库; 
    - CTDB是Samba3/4的一个核心组件; 
    - CTDB提供高可用特性,例如节点监控、节点切换、IP切换; 
    - CTDB为其多个节点上的应用提供可靠的传输通道; 
    - CTDB提供可热拔插的后端传输通道,目前实现了TCP和IB; 
    - CTDB可以提供为应用指定特定的管理脚本,使得应用能够实现高可用。

    2. CTDB配置

    CTDB的配置相对简单,对于搭建一个三节点的CTDB配置步骤说明如下。

    2.1 节点信息

    节点名称节点IP说明
    node110.10.10.90CTDB节点
    node210.10.10.91CTDB节点
    node310.10.10.92CTDB节点
    node410.10.10.99共享存储

    说明:此处为快速简单的搭建ctdb集群,采用单节点NFS共享,不考虑NFS共享的可靠性。 
    实际应用时,共享存储应由高可靠的集群担当。

    2.2搭建CTDB集群

    2.2.1 安装软件

    在三个CTDB节点分别安装ctdb,nfsd,samba,可以通过命令 yum install ctdb依次进行安装;

    2.2.2 创建共享存储

    在node4创建一个共享目录/share,并设置权限777,在/etc/exports文件中添加如下:

    /share *(sync,rw)
    • 1

    然后在节点4上执行如下命令:

    # exoprtfs -rv
    • 1

    CTDB节点之间需要通过一个共享的存储来实现其基于锁机制的选举过程。

    2.2.3 挂载共享存储

    在三个CTDB节点上分别执行如下命令:

    # mount -t nfs 10.10.10.99:/share /mnt
    • 1

    node1, node2,node3上都挂载了node4共享出来的目录,这样三个节点就可以访问到一个相同的锁文件了。

    2.2.4 修改CTDB服务配置

    在三个CTDB节点上修改如下文件:

    ~# vi /etc/sysconfig/ctdb
    
    CTDB_RECOVERY_LOCK=/mnt/ctdb_lock
    
    CTDB_MANAGES_SAMBA=yes
    CTDB_MANAGES_WINBIND=yes
    CTDB_MANAGES_NFS=yes
    
    这个步骤中主要配置CTDB管理哪些应用。还有就是指定共享锁文件的目录。

    2.2.5 修改CTDB节点配置

    在三个CTDB节点上创建或者修改如下文件:

    ~# vi /etc/ctdb/nodes
    10.10.10.91
    10.10.10.92
    10.10.10.90

    2.2.6 修改CTDB IP配置

    在三个CTDB节点上创建或者修改如下文件:

    ~# vi /etc/ctdb/public_addresses
    10.0.0.1/24    eth0

    其中eth0是节点上存在的并且在线的网卡。10.0.0.1就是配置给这个三个节点CTDB集群对外提供业务的IP。

    2.2.7 重启CTDB服务

    在三个CTDB节点上执行如下命令:

    ~# systemctl restart ctdb

    2.2.8 查看CTDB服务状态

    在节点1上执行:

    # ctdb status
    Number of nodes:3
    pnn:0 10.10.10.91      OK
    pnn:1 10.10.10.92      OK
    pnn:2 10.10.10.90      OK (THIS NODE)
    Generation:1699238992
    Size:3
    hash:0 lmaster:0
    hash:1 lmaster:1
    hash:2 lmaster:2
    Recovery mode:NORMAL (0)
    Recovery master:1
    [root@xenserver-yzulkyuc ~]# 
    

    集群搭建完成。 
    说明:如果节点数量较少,可以将某一个CTDB节点作为共享存储,同时节点数量也可以为1。但是将CTDB节点作为共享存储的话,需要将/etc/sysconfig/ctdb 文件中的CTDB_MANAGES_NFS设置位NO。

    3. CTDB源码分析

    3.1 关键数据结构

    3.1.1 ctdb

    CTDB有两个进程构成,ctdbd和recoveryd。在这个两个进程进行各种事物处理时,一般都带有一个参数:ctdb。该数据结构是包含了基本上所有逻辑所需或者相关的数据。在CTDBD启动阶段就是对ctdb数据结构的填充阶段。

    struct ctdb_context {
        struct tevent_context *ev;              //封装的事件处理接口,后端使用select/poll/epoll 多路I/O复用机制
        struct timeval ctdbd_start_time;        //ctdbd启动时间
        struct timeval last_recovery_started;
        struct timeval last_recovery_finished;
        uint32_t recovery_mode;                 //根据此值可以判断是否需要进行recovery
        TALLOC_CTX *tickle_update_context;
        TALLOC_CTX *keepalive_ctx;
        TALLOC_CTX *check_public_ifaces_ctx;
        struct ctdb_tunable_list tunable;
        enum ctdb_freeze_mode freeze_mode;
        struct ctdb_freeze_handle *freeze_handle;
        bool freeze_transaction_started;
        uint32_t freeze_transaction_id;
        ctdb_sock_addr *address;               //此ctdb节点的IP地址
        const char *name;
        const char *db_directory;
        const char *db_directory_persistent;
        const char *db_directory_state;
        struct tdb_wrap *db_persistent_health;
        uint32_t db_persistent_startup_generation;
        uint64_t db_persistent_check_errors;
        uint64_t max_persistent_check_errors;
        const char *transport;
        const char *recovery_lock;
        uint32_t pnn; /* our own pnn */     
        uint32_t num_nodes;
        uint32_t num_connected;
        unsigned flags;
        uint32_t capabilities;
        struct reqid_context *idr;
        struct ctdb_node **nodes;               //集群节点列表,索引为vnn
        struct ctdb_vnn *vnn;                   //公共IP列表和网卡
        struct ctdb_interface *ifaces; /* list of local interfaces */
        char *err_msg;
        const struct ctdb_methods *methods;     //启动时注册的tcp处理函数
        const struct ctdb_upcalls *upcalls;     //启动时注册的处理函数
        void *private_data; /* private to transport */
        struct ctdb_db_context *db_list;
        struct srvid_context *srv;
        struct ctdb_daemon_data daemon;
        struct ctdb_statistics statistics;
        struct ctdb_statistics statistics_current;
    #define MAX_STAT_HISTORY 100
        struct ctdb_statistics statistics_history[MAX_STAT_HISTORY];
        struct ctdb_vnn_map *vnn_map;
        uint32_t num_clients;
        uint32_t recovery_master;
        struct ctdb_client_ip *client_ip_list;
        bool do_checkpublicip;
        bool do_setsched;
        const char *event_script_dir;
        const char *notification_script;
        const char *default_public_interface;
        pid_t ctdbd_pid;
        pid_t recoverd_pid;
        enum ctdb_runstate runstate;
        struct ctdb_monitor_state *monitor;
        int start_as_disabled;
        int start_as_stopped;
        bool valgrinding;
        uint32_t *recd_ping_count;
        TALLOC_CTX *recd_ctx; /* a context used to track recoverd monitoring events */
        TALLOC_CTX *release_ips_ctx; /* a context used to automatically drop all IPs if we fail to recover the node */
    
        struct eventd_context *ectx;
    
        TALLOC_CTX *banning_ctx;
    
        struct ctdb_vacuum_child_context *vacuumers;
    
        /* mapping from pid to ctdb_client * */
        struct ctdb_client_pid_list *client_pids;
    
        /* Used to defer db attach requests while in recovery mode */
        struct ctdb_deferred_attach_context *deferred_attach;
    
        /* if we are a child process, do we have a domain socket to send controls on */
        bool can_send_controls;
    
        struct ctdb_reloadips_handle *reload_ips;
    
        const char *nodes_file;
        const char *public_addresses_file;
        struct trbt_tree *child_processes; 
    
        /* Used for locking record/db/alldb */
        struct lock_context *lock_current;
        struct lock_context *lock_pending;
    };

    3.1.2 初始化upcall

    在上面一节中的ctdb结构中可以看到有这个upcall处理函数接口。初始化操作是在main()函数的入口处进行的。

        ctdb->recovery_mode    = CTDB_RECOVERY_NORMAL;
        ctdb->recovery_master  = (uint32_t)-1;
        ctdb->upcalls          = &ctdb_upcalls;
    • 1
    • 2
    • 3

    而ctdb_upcalls定义如下:

    static const struct ctdb_upcalls ctdb_upcalls = {
        .recv_pkt       = ctdb_recv_pkt,        //当有消息包传入时调用此函数进行处理。
        .node_dead      = ctdb_node_dead,       //当有节点出现故障或者离线时调用此函数,进行的操作是重启。
        .node_connected = ctdb_node_connected   //当有连接请求发送时,调用此函数,更新连接统计信息。
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.1.3 创建unix socket fd

    在启动ctdbd守护进程过程中,创建了unix socket,并且将fd赋值给了3.1.1中的daemon.sd。并且开始监听是否有连接请求。

    ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0);
    • 1

    3.1.4 初始化tevent

    tevent是ctdb中事件处理机制,底层采用select/poll/epoll多路I/O复用机制,对外提供统一的接口。初始化就是将接口进行统一处理。接口的统一入口就是3.1.1小节中提的ctdb->ev。

    ctdb->ev = tevent_context_init(NULL);
    • 1

    初始化完成后,形成一个双向链表,链表中存放的是不同的I/O多路复用接口,但是对于调用这来说,看的接口是相同的。

     

    即ops的名称是一致的,而对于不同的I/O复用就赋值了相对应的函数接口。

    static const struct tevent_ops select_event_ops = {
        .context_init       = select_event_context_init,
        .add_fd         = select_event_add_fd,
        .set_fd_close_fn    = tevent_common_fd_set_close_fn,
        .get_fd_flags       = tevent_common_fd_get_flags,
        .set_fd_flags       = tevent_common_fd_set_flags,
        .add_timer      = tevent_common_add_timer_v2,
        .schedule_immediate = tevent_common_schedule_immediate,
        .add_signal     = tevent_common_add_signal,
        .loop_once      = select_event_loop_once,
        .loop_wait      = tevent_common_loop_wait,
    };

    3.1.5 tcp传输通道初始化

    在ctdbd守护进程启动节点,初始化tcp传输通道

    /*
      initialise tcp portion of ctdb 
    */
    int ctdb_tcp_init(struct ctdb_context *ctdb)
    {
        struct ctdb_tcp *ctcp;
        ctcp = talloc_zero(ctdb, struct ctdb_tcp);
        CTDB_NO_MEMORY(ctdb, ctcp);
    
        ctcp->listen_fd = -1;
        ctcp->ctdb      = ctdb;
        ctdb->private_data = ctcp;
        ctdb->methods = &ctdb_tcp_methods;
    
        talloc_set_destructor(ctcp, tcp_ctcp_destructor);
        return 0;
    }

    上面的代码中的ctdb->methods初始化为了&ctdb_tcp_methods,其定义如下:

    static const struct ctdb_methods ctdb_tcp_methods = {
        .initialise   = ctdb_tcp_initialise,
        .start        = ctdb_tcp_start,
        .queue_pkt    = ctdb_tcp_queue_pkt,
        .add_node     = ctdb_tcp_add_node,
        .connect_node = ctdb_tcp_connect_node,
        .allocate_pkt = ctdb_tcp_allocate_pkt,
        .shutdown     = ctdb_tcp_shutdown,
        .restart      = ctdb_tcp_restart,
    };

    进行上述接口注册后,就调用的ctdb_tcp_initialise进行初始了,在该函数中完成了两件事情 
    - ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);创建了一个socket server端,监听的地址是当前ctdb节点的地址。监听后,注册了一个监听事件,一旦有其他节点来连接当前ctdb节点,将调用注册的函数:ctdb_listen_event,在该处理函数中将accept连接请求。并再次注册一个读事件到tevent中。也就是当客户端有写入数据时,当前ctdb将调用ctdb_tcp_read_cb进行数据包的处理。

        in->queue = ctdb_queue_setup(ctdb, in, in->fd, CTDB_TCP_ALIGNMENT,
                         ctdb_tcp_read_cb, in, "ctdbd-%s", ctdb_addr_to_str(&addr));
    • 给ctdb集群的所有节点都创建了一个out_queue队列,并且这个数据结构保存在ctdb->node[i]中。

    3.1.6 unix socket accept函数

    在3.1.3中已经创建了unix socket,此时注册了一个accept事件,处理函数为:ctdb_accept_client,事件类型为TEVENT_FD_READ。在此处理函数中会accept连接请求。并将已经连接上的client信息存放在 ctdb->client_pids 链表当中。最后再次注册一个读请求处理函数ctdb_daemon_read_cb。该函数注册的位置为:ctdb->client_pids->queue->callback,此外ctdb->client_pids->queue->im= tevent_create_immediate(queue);理解起来应该是,如果已连接的这个unix socket上有读事件的话,立刻处理。

    3.1.7 启动tcp传输通道

    调用的函数为ctdb_tcp_start(ctdb);该函数主要完成node节点之间的tcp连接。在前3.1.5节中说到每一个ctdb节点都在监听自己的IP地址,而ctdb_tcp_start(ctdb)相当于把当前节点作为client,去连接所有其他的ctdb节点。同样,其他节点也会进行相同的操作处理。也就是最后会出现的结果是集群的每一个节点都与剩余节点存在链接。这个已连接的fd保存在ctdb->node[i]->private_data(ctdb_tcp_node)->fd。 
    同时注册了两个事件,一个是已建立连接可写时的事件处理函数。第二个是定时连接处理函数,就是每隔一秒钟去连接这个节点。 
    从已有的三节点ctdb环境中可以看到相关连接的信息:

    [root]# netstat -anp | grep ctdbd
    tcp        0      0 10.10.10.90:4379        0.0.0.0:*               LISTEN      1006/ctdbd          
    tcp        0      0 10.10.10.90:50071       10.10.10.92:4379        ESTABLISHED 1006/ctdbd          
    tcp        0      0 10.10.10.90:4379        10.10.10.91:48353       ESTABLISHED 1006/ctdbd          
    tcp        0      0 10.10.10.90:4379        10.10.10.92:57112       ESTABLISHED 1006/ctdbd          
    tcp        0      0 10.10.10.90:57413       10.10.10.91:4379        ESTABLISHED 1006/ctdbd 

    从上面的连接信息判断,node1(10.10.10.90)通过57413端口作为client去connect了node2,通过50071端口去connect了node3。同样node2通过48353端口connect了node1。node3通过57112端口去连接了node1。与上述连接逻辑一致。

    3.2事件通知机制

    事件通知机制是ctdb结构中最重要的一部分,事件通知机制将各个逻辑链接起来以完成相关的功能实现。 
    下面以 fde = tevent_add_fd(ctdb->ev, ctdb, ctdb->daemon.sd, TEVENT_FD_READ,ctdb_accept_client, ctdb);为例来分析是如何将该事件监控起来并调用事件处理函数的。 
    在ctdb_start_daemon函数中,先后调用了tevent_add_fd以及tevent_loop_wait函数。 
    - tevent_add_fd,对于这个函数是tevent对外提供的接口,其实际调用的是epoll_event_add_fd函数(此处以epoll为例,如果内核不支持epoll,那么可能就会调用select或者poll相对应的函数。)在此函数中主要进行了2个逻辑处理 
    1. 将事件相关的参数和函数赋值到fde,并将fde加入到ctdb->ev->fd_events链表中; 
    2. 执行epoll_update_event(epoll_ev, fde)函数更新epoll_ev,具体就是将待添加的event通过epoll_ctl加入到epoll_ev->epoll_fd;

    • tevent_loop_wait实际会调用epoll_event_loop_once,再调用epoll_event_loop,最终调用epoll_wait,查看已就绪事件,并调用相应的事件处理函数进行处理。

    tevent_loop_wait会一直循环检查是否有事件注册了,如果有,就会不断的循环去判断;

    */
    int tevent_common_loop_wait(struct tevent_context *ev,
                    const char *location)
    {
        /*
         * loop as long as we have events pending
         */
        while (tevent_common_have_events(ev)) { // 此函数会一直返回真
            int ret;
            ret = _tevent_loop_once(ev, location);
            if (ret != 0) {
                tevent_debug(ev, TEVENT_DEBUG_FATAL,
                         "_tevent_loop_once() failed: %d - %s\n",
                         ret, strerror(errno));
                return ret;
            }
        }
    
        tevent_debug(ev, TEVENT_DEBUG_WARNING,
                 "tevent_common_loop_wait() out of events\n");
        return 0;
    }

    3.3 主循环流程

    下面图中所展示的是recoveryd进程的循环处理事务的过程。函数名称为main_loop。

    A(检查ctdbd是否存活)-->B(告诉ctdbd recoveryd是活动的)
    B-->C(是否选举中)
    C-->D(是- 退出main_loop)
    C-->E(不是- 获取ctdbd debug level)
    E-->F(获取cdbd运行参数)
    F-->G(获取ctdbd运行状态)
    G-->H(获取nodemap)
    H-->I(获取recovery mode)
    I-->J(当前节点是否是stopped或者baned状态)
    J-->K(是- 设置recovery mode为 active,并freezee db就是锁住?)
    K-->L(获取所有节点所具备的角色能力,如下图所示)
    L-->M(查看recmaster,如果unknown, force elelction)
    M-->N(选举中,返回)
    M-->O(查看是否有ip需要分配)
    O-->P(查看是否所有节点都同意recmater node)
    P-->Q(获取vnnmap)
    Q-->R(查看是否需要recovery)
    R-->S(查看所有节点处于normal状态)
    S-->T(当前节点是否持有共享锁,是的话,检查一下锁状态)
    T-->U(从所有其他节点获取nodemap并比较所有nodemap是否一致,不一致的话执行do_recover)
    U-->V(更新所有节点状态标识)
    V-->W(统计活动的node数量)
    W-->X(active node情况与vnnmap记录一致)
    X-->Y(检查所有节点是否有相同的vnn和相同的版本号)

    3.4节点及节点节点间通信总结

    3.4.1单个ctdb节点内进程之间的连接

    ctdb有两个进程,ctdbd和recoveryd,这个两个进程之间通过unix socket进行消息的传递。一般recoveryd发送带opcode的消息,ctdbd通过

    3.4.2 ctdb节点之间连接

    1. 初始化函数ctdb_tcp_initialise中,为当前节点创建了一个监听ctdb address的socket,并且将fd保存在ctdb->private_data->listen_fd。其中private_data的数据结构是struct ctdb_tcp。也就是每一个ctdb节点启动时都会创建并监听本地节点的IP地址。
    2. 由于ctdb节点之间需要相互通信,因此在初始化过程中,将所有节点有关连接的信息都保存在ctdb中。ctdb->nodes[i]就可以遍历所有节点关于连接的信息。而ctdb->nodes[i]->private_data->fd就是保存相应node的fd。其中private_data的数据结构为struct ctdb_tcp_node。
    3. 基于上面步骤2中的描述,ctdb->nodes[i]->private_data->out_queue,就是初始化的一个队列。但是初始化时ctdb->nodes[i]->private_data->fd值为-1。
    4. 应该在main_loop 中getnodemap时会更新ctdb->nodes[i]->private_data->fd这个值(目前是猜测)

    3.4.3 控制消息处理流程总结

    下面以获取node map的消息为例来说明,如何从一个ctdb节点获取到另一个ctdb节点的信息。 
    1. ret = ctdb_ctrl_getnodemap(ctdb, CONTROL_TIMEOUT(), pnn, rec, &rec->nodemap);执行程序的自然就是发起消息的节点,其中pnn就是目标节点;该控制消息是获取nodemap; 
    2. ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_GET_NODEMAP, 0, tdb_null,mem_ctx, &outdata, &res, &timeout, NULL);其中destnode就是要目标node; 
    3. state = ctdb_control_send(ctdb, destnode, srvid, opcode, flags, data, mem_ctx,timeout, errormsg); 
    4. ret = ctdb_client_queue_pkt(ctdb, &(c->hdr));其中c->hdr中包含了函数调用中需要的参数; 
    5. ctdb_queue_send(struct ctdb_queue *queue, uint8_t *data, uint32_t length); 
    6. n = write(queue->fd, data, length2);即将数据包写入了unix socket 的fd中; 
    7. unix socket fd的read 函数是在ctdb_accept_client 中设置的:ctdb_daemon_read_cb 
    8. daemon_incoming_packet(client, hdr);其中,hdr即最初发送的数据包; 
    9. 依据hdr中的hdr->operation判断消息类别:CALL/MESSAGE/CONTROL 
    10. 调用CONTROL消息处理函数daemon_request_control_from_client 
    11. res = ctdb_daemon_send_control(client->ctdb, c->hdr.destnode,c->srvid, c->opcode, client->client_id,c->flags,data, daemon_control_callback,state); 
    12. ctdb_queue_packet(ctdb, &c->hdr);并添加了一个控制消息超时处理事件ctdb_control_timeout(); 
    13. 语句node = ctdb->nodes[hdr->destnode]获取到目标node信息; 
    14. ctdb->methods->queue_pkt(node, (uint8_t *)hdr, hdr->length);该函数为初始化时注册的; 
    15. ctdb_tcp_queue_pkt(struct ctdb_node *node, uint8_t *data, uint32_t length);从node的node->private_data中提取出tnode; 
    16. ctdb_queue_send(tnode->out_queue, data, length);其中tnode->out_queue->fd即是已连接到目标节点的fd。 
    17. n = write(queue->fd, data, length2);数据通过fd写入到socket链接 
    18. 远端node接收到请求;在远端节点中从上述的第7步开始重复。

    控制消息首先通过unix socket从recoveryd进程发送,ctdbd进程读取unix socket上的数据,并对数据进行解析,如果获取的是当前的节点信息就提供信息并返回,如果是需要获取remote node的节点信息,就使用保存在node = ctdb->nodes[hdr->destnode]中的fd将消息发送给remote node。

    static const struct ctdb_methods ctdb_tcp_methods = {
        .initialise   = ctdb_tcp_initialise,
        .start        = ctdb_tcp_start,
        .queue_pkt    = ctdb_tcp_queue_pkt,
        .add_node     = ctdb_tcp_add_node,
        .connect_node = ctdb_tcp_connect_node,
        .allocate_pkt = ctdb_tcp_allocate_pkt,
        .shutdown     = ctdb_tcp_shutdown,
        .restart      = ctdb_tcp_restart,
    };
    展开全文
  • yum直接安装 当前可安装的版本是4.9,据官方介绍,ctdb是应该是随着Samba一起安装的,尽管现在ctdb不止支持Samba,还支持nfs, cifs等。。。 遗憾的是。我安装后服务一直处于启动失败状态。。。本来关于ctdb的博客就...
  • 将linux平台构建的分布式文件系统的多个client,向window采用samba映射,并使用ctdb进行虚拟IP映射,达到一定程度的映射ip高可用
  • ctdb-1.0.114.3-4.el6.i686.rpm
  • CTDB原理介绍

    千次阅读 2018-12-27 17:26:20
    CTDB(Cluster Trivial Database)是一种轻量级的集群数据库实现,是集群Samba的集群数据库组件,主要用于处理Samba的跨节点消息以及在所有集群节点上实现分布式的TDB数据库。 CTDB的主要功能: 1) 提供TDB数据库...
  • 关于CTDB

    千次阅读 2017-07-13 10:37:28
    如果有个应用已经使用TDB存储临时数据,那么将其用集群化并使用CTDB替代会非常轻松。CTDB使用集群方式提供了与TDB相同的功能方式,提供一种TDB方式的数据库在集群中聚合多种物理主机。CTDB具有以下特性: CTDB提供...
  • 修改/etc/ctdb/functions文件,增加target环境变量 ctdb_compat_managed_service"$CTDB_MANAGES_VSFTPD""vsftpd" ctdb_compat_managed_service"$CTDB_MANAGES_SAMBA""samba" ctdb_compat_managed_...
  • CTDB

    2015-09-25 17:07:00
    CTDB Design • one daemon ctdbd on each node • smbd talks to local ctdbd for messaging and TDB access • ctdbd handles metadata of TDBs via the network • ctdbd keeps local TDB copy ...
  • python3 -m venv /Users/jimmy_lin/repos/ctdb/.venv source /Users/jimmy_lin/repos/ctdb/.venv pip install -r /Users/jimmy_lin/repos/ctdb/requirements/dev.txt 数据库迁移 python3 /Users/jimmy_lin/repos/...
  • ctdb 启动samba

    2018-11-25 08:35:33
    在用centos 7.5组合使用ctdb+samba时,samba服务在centos /redhat/oracle 7版本中,改名为smb.service,用systemctl管理,相应的,在ctdbd.conf中设定启动samba时,调用/etc/ctdb/event.d/50.samba,但面给出的服务名...
  • CTDB配置文件参数解析

    千次阅读 2019-01-02 14:40:42
    CTDB配置文件:/etc/ctdb/conf 主要参数的含义: CTDB_NODES:指定包含集群节点IP(内部IP)的文件的位置,通常是/etc/ctdb/nodes文件。集群中每个节点至少配置两个地址:一个为“Private IP”,用于节点间CTDB的...
  • 分布式高可用CTDB方案

    千次阅读 2014-11-25 10:53:07
    ctdb_check_rpc_out=$(rpcinfo -u localhost $progname $version 2>&1) ; then               ctdb_check_rpc_out="ERROR: $progname failed RPC check: $ctdb_check_rpc_out"           ...
  • db_open_ctdb // 仅仅是增加 db_ctdb_fetch_locked 回调函数 db_ctdb_fetch_locked fetch_locked_internal db_ctdb_store db_ctdb_ltdb_store ctdbd_backup : write_data_iov //发送数据 write_data_iov //发送...
  • CTDB take over代码流程梳理ctdb take over功能用于ctdb集群中某个主节点失效时,该节点上IP可以转移到其他节点,保证相应IP提供的服务不断开,其处理代码主要集中于ctdb_takeover.c中,主要代码流程梳理如下图所示...
  • [student@workstation ~]$ lab ctdb setup   1.配置环境 yum install -y samba ctdb安装软件包。firewall-cmd --add-service=samba放行服务。firewall-cmd --add-port=4379/tcp放行端口。 firewall-cmd --runtime...
  • opensuse 15.0 安装ctdb

    2019-05-20 15:40:00
    1 2019/05/20 15:27:14.574363 ctdb-eventd[26329]: 60.nfs: /etc/ctdb/nfs-linux-kernel-callout: line 143: /proc/sys/net/ipv4/tcp_tw_recycle: No such file or directory Answer: found out that this opt...
  • 坑3: selinux 服务没有关闭,导致ctdb, smb服务无法读取/gluster/lock下面的配置文件 setenforce 0   坑4 : 创建用户需要在每个ctdb(smb服务器)上执行一遍: adduser yxy smbclient -a yxy  ...
  • CTDB代码流程简要梳理

    千次阅读 2017-08-14 16:00:57
    ctdb 2.5.3主体代码流程
  • CTDB运行调试

    千次阅读 2016-07-29 18:11:23
    ctdb status 查询状态 cat /var/log/log.ctdb 日志查询 /etc/ctdb/events.d/50.samba SAMBA服务配置,根据系统配置service_name="samba" smbd /etc/ctdb/events.d/60.nfs NFS服务配置,根据系统配置service...
  • CTDB中脚本关于take ip和release ip的处理1 take ipDTDB需要接管ip时运行./config/events.d/10.interface进程,该进程可以使用三个参数:接口名、ip地址和掩码长度,如:./10.interface takeip eth1 10.1.1.2 24其...
  • <div><p>该提问来源于开源项目:ClusterLabs/resource-agents</p></div>
  • CTDB main loop

    2017-07-19 10:44:00
    args[1] = daemon.name = CTDB_SOCKET = /var/run/ctdb/ctdb.socket args[2] = random !=1 exec /usr/libexec/ctdb/ctdb_recovery_helper <log-fd> <output-fd> <ctdb-socket-path> 1 1 /var/run/ctdb/ctdbd...
  • 本文介绍使用开源软件ctdb+samba+gluster搭建NAS集群系统。 1.1 使用的开源软件介绍 1、glusterfs glusterfs是一个开源的分布式文件系统,只适用于大文件存储,存储海量小文件性能很差,不建议使用。 2、samba ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 493
精华内容 197
关键字:

CTDB