在多主机Docker网络中运行XtraDB Cluster

译者前言

Percona 所维护的XtraDB 是mysql的一个分支,使用了性能比innodb更加出色的xtrodb驱动,XtraDB-Cluster产品,是其集群化的方案,方案内容,请自行google。最近XtraDB-Cluster的5.7版本的推出,跟上了mysql主分支的脚步,更加吸引mysql爱好者转移到Percona上来。)
Percona-XtraDB-Cluster-certification-1

译文如下

以下,我将阐述一下,怎么样在多主机Docker网络中运行Percona XtraDB Cluster。
随着我们的Pecrona XtraDB Cluster 5.7 beta版本的发布,我们亦决定提供Pecrona XtraDB Cluster 5.6 和 Pecrona XtraDB Cluster 5.7 的镜像文件。
启动一个单点的Percona XtraDB Cluster 是很方便的,基本和Percona Server的镜像相同。唯一的不同就是需要指定CLUSTER_NAME环境变量. 启动容器的命令如下

docker run -d -p 3306:3306
    -e MYSQL_ROOT_PASSWORD= Theistareyk
    -e CLUSTER_NAME= Theistareykjarbunga
    -e XTRABACKUP_PASSWORD=Theistare
    percona/percona-xtradb-cluster

你应该会注意到我们提供了可选的参数 XTRABACKUP_PASSWORD,这个参数是用户xtradbbackup@localhost 执行xtrabackup-SST 同步的用户密码。
运行单点的Percona XtraDB Cluster 需要迎合Cluster启动所需要的 CLUSTER_NAME 参数,单点其实也无所谓这个。在我们提供的镜像中,需要解决以下任务:

  1. 运行在多主机的环境(多主机环境上一般跑Docker Swarm 和Kubernetes)
  2. 如我们所需的,在某个Cluster中启动多个节点

  3. 在服务发现的服务端口上,注册所有的节点,这样,所有的客户端就能知道有多少个节点以及他们运行的状态

  4. 集成 ProxySQL

让我们一个一个看。

随着Docker网络协议的完善,可以使用多主机环境部署Percona XtraDB了。 最近的Docker 版本带来了网络overlay驱动,我们将使用这个特性建立一个虚拟网络。安装和启动Docker 的overlay 网络超出了本问的范围,这里给出个链接,感兴趣的人可以看下这个非常好的介绍资料了解下这个虚拟网络是如何运行的。

好了,等你overlay网络驱动装好,我们要在这上创建一个虚拟网络:

docker network create -d overlay cluster1_net

然后我们可以这样启动容器:

docker run -d -p 3306 --net=cluster1_net
 -e MYSQL_ROOT_PASSWORD=Theistareyk
 -e CLUSTER_NAME=cluster1
 ...
 -e XTRABACKUP_PASSWORD=Theistare
 percona/percona-xtradb-cluster

这玩意儿很cool,cool点在于,你随便在哪台服务器启动这个节点,只要是基于同一个网络的相同的 CLUSTER_NAME,他们都会自动的进行通信。
如果你处在单一Docker主机的环境中,譬如做个测试什么的,你还可以创建一个网桥网络,在一个单主机的环境中使用他。
好吧,以上这个脚本,怎么说呢,基本可以执行。问题在于每个新加入的节点需要知道运行的cluster的地址。
为了让实例知道这个地址,我们可以使用 CLUSTER_JOIN 这个变量,这个变量的值为某一个运行中的节点的ip地址,(如果是一个新的群,那么就是空)

在本例中,这个脚本应该像这样:

docker run -d -p 3306 --net=cluster1_net
 -e MYSQL_ROOT_PASSWORD=Theistareyk
 -e CLUSTER_NAME=cluster1
 -e CLUSTER_JOIN=10.0.5.5
 -e XTRABACKUP_PASSWORD=Theistare
 percona/percona-xtradb-cluster

手动追踪一个ip地址在我看来完全是一个额外的工作,尤其是要在一个动态的环境中起停一个节点的时候,真是有够麻烦的。所以我们决定使用一个发现服务。现在我们使用的是Etcd发现服务,当然,使用其他的发现服务也没啥问题,譬如Consul。

举个例子,当你在主机 10.20.2.4:2379上运行发现服务的时候,你可以这样启动节点:

docker run -d -p 3306 --net=cluster1_net
 -e MYSQL_ROOT_PASSWORD=Theistareyk
 -e CLUSTER_NAME=cluster1
 -e DISCOVERY_SERVICE=10.20.2.4:2379
 -e XTRABACKUP_PASSWORD=Theistare
 percona/percona-xtradb-cluster

这个节点就会自己把自己注册到发现服务中去,并且加入名为$CLUSTER_NAME的集群中。

下面是显示 CLUSTER_NAME 为 $CLUSTER_NAME 集群的一个简单的方法:

curl http://$ETCD_HOST/v2/keys/pxc-cluster/$CLUSTER_NAME/?recursive=true | jq
{
  "action": "get",
  "node": {
    "key": "/pxc-cluster/cluster4",
    "dir": true,
    "nodes": [
      {
        "key": "/pxc-cluster/cluster4/10.0.5.2",
        "dir": true,
        "nodes": [
          {
            "key": "/pxc-cluster/cluster4/10.0.5.2/ipaddr",
            "value": "10.0.5.2",
            "modifiedIndex": 19600,
            "createdIndex": 19600
          },
          {
            "key": "/pxc-cluster/cluster4/10.0.5.2/hostname",
            "value": "2af0a75ce0cb",
            "modifiedIndex": 19601,
            "createdIndex": 19601
          }
        ],
        "modifiedIndex": 19600,
        "createdIndex": 19600
      },
      {
        "key": "/pxc-cluster/cluster4/10.0.5.3",
        "dir": true,
        "nodes": [
          {
            "key": "/pxc-cluster/cluster4/10.0.5.3/ipaddr",
            "value": "10.0.5.3",
            "modifiedIndex": 26420,
            "createdIndex": 26420
          },
          {
            "key": "/pxc-cluster/cluster4/10.0.5.3/hostname",
            "value": "cfb29833f1d6",
            "modifiedIndex": 26421,
            "createdIndex": 26421
          }
        ],
        "modifiedIndex": 26420,
        "createdIndex": 26420
      }
    ],
    "modifiedIndex": 19600,
    "createdIndex": 19600
  }
}

用这个方法,你就可以在任意个Docker主机上启动任意多个数据库节点了。现在我们可以在数据库集群前端放置SQL Proxy了,这个下回再讨论了。

译者附

我在实施该XtraDB Cluster的时候,发现脚本有问题,同时发现该文的后方,亦有人发现相同的问题,现贴出该bug并给出解决办法:

发言人为Roma Cherepanov

他在启动节点的时候发现了一些error,我也发现了这些问题,导致容器一直启动不起来,之后经过调试,解决该问题,并在下方给出了答复

kevin:

在跑这个镜像的时候,我有相同的问题。

pxc-entry.sh脚本有些问题

line 125: (应该是125,之前数错了,帖子上面写的也错了☹)

i=$(curl http://$DISCOVERY_SERVICE/v2/keys/pxc-cluster/queue/$CLUSTER_NAME | jq -r '.node.nodes[].value')

应该是

i=(curl http://$DISCOVERY_SERVICE/v2/keys/pxc-cluster/queue/$CLUSTER_NAME | jq -r '.node.nodes[].value')

line 139:

i=$(curl http://$DISCOVERY_SERVICE/v2/keys/pxc-cluster/$CLUSTER_NAME/?quorum=true | jq -r '.node.nodes[]?.key' | awk -F'/' '{print $(NF)}')

应该是

i=(curl http://$DISCOVERY_SERVICE/v2/keys/pxc-cluster/$CLUSTER_NAME/?quorum=true | jq -r '.node.nodes[]?.key' | awk -F'/' '{print $(NF)}')

脚本要给i 赋值一个数组,那么shell的数组赋值形式应该是i=(a b c d) ,而不是i=$(a b c d) 不知道作者的脚本解释语言是啥,反正在我这里应该是这样的,改了之后就OK啦!

标签:Docker 发布于:2019-11-09 10:05:08