etcd之etcd集群实践(六)
1、etcd集群实践
etcd 作为一个高可用键值存储系统,天生就是为集群化而设计的。由于 Raft 算法在做决策时需要多数节点的投
票,所以 etcd 一般部署集群推荐奇数个节点,推荐的数量为 3、5 或者 7 个节点构成一个集群。
本文使用3个节点的etcd构成一个集群。
1.1 集群启动
etcd 有三种集群化启动的配置方案,分别为静态配置启动
、etcd自身服务发现
、通过DNS
进行服务发现。
1.2 静态配置
这种方式比较适用于离线环境,在启动整个集群之前,你就已经预先清楚所要配置的集群大小,以及集群上各节点
的地址和端口信息。那么启动时,你就可以通过配置initial-cluster
参数进行 etcd 集群的启动。
在每个 etcd 机器启动时,配置环境变量或者添加启动参数。
配置环境变量如下:
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380"
ETCD_INITIAL_CLUSTER_STATE=new
添加启动参数如下:
-initial-cluster
infra0=http://10.0.1.10:2380,http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
-initial-cluster-state new
值得注意的是,-initial-cluster
参数中配置的 url 地址必须与各个节点启动时设置的initial-advertise-
peer-urls
参数相同。(initial-advertise-peer-urls
参数表示节点监听其他节点同步信号的地址)。
如果你所在的网络环境配置了多个etcd集群,为了避免意外发生,最好使用-initial-cluster-token
参数为每
个集群单独配置一个token认证。这样就可以确保每个集群和集群的成员都拥有独特的ID。
综上所述,如果你要配置包含3个etcd节点
的集群,那么你在三个机器上的启动命令分别如下所示。
$ etcd -name infra0 -initial-advertise-peer-urls http://192.168.165.165:2380 \
-listen-peer-urls http://192.168.165.165:2380 \
-initial-cluster-token etcd-cluster-1 \
-advertise-client-urls http://192.168.165.165:2379 \
-listen-client-urls http://localhost:2379,http://192.168.165.165:2379 \
-initial-cluster infra0=http://192.168.165.165:2380,infra1=http://192.168.165.185:2380,infra2=http://192.168.165.195:2380 \
-initial-cluster-state new \
--enable-v2
$ etcd -name infra1 -initial-advertise-peer-urls http://192.168.165.185:2380 \
-listen-peer-urls http://192.168.165.185:2380 \
-initial-cluster-token etcd-cluster-1 \
-advertise-client-urls http://192.168.165.185:2379 \
-listen-client-urls http://localhost:2379,http://192.168.165.185:2379 \
-initial-cluster infra0=http://192.168.165.165:2380,infra1=http://192.168.165.185:2380,infra2=http://192.168.165.195:2380 \
-initial-cluster-state new \
--enable-v2
$ etcd -name infra2 -initial-advertise-peer-urls http://192.168.165.195:2380 \
-listen-peer-urls http://192.168.165.195:2380 \
-initial-cluster-token etcd-cluster-1 \
-advertise-client-urls http://192.168.165.195:2379 \
-listen-client-urls http://localhost:2379,http://192.168.165.195:2379 \
-initial-cluster infra0=http://192.168.165.165:2380,infra1=http://192.168.165.185:2380,infra2=http://192.168.165.195:2380 \
-initial-cluster-state new \
--enable-v2
配置参数解析(结果参数上面可能没有使用到):
-
name
:当前etcd节点名称。 -
data-dir
:数据存储目录。 -
initial-advertise-peer-urls
:集群的其他节点通过该地址与当前节点通信。 -
listen-peer-urls
:当前节点通过该地址监听集群其他节点发送的信息。 -
listen-client-urls
:当前节点通过该地址监听客户端发送的信息。 -
advertise-client-urls
:客户端通过该地址与当前节点通信 -
initial-cluster-token
:用于区分不同的集群,同一集群的所有节点配置相同的值。 -
initial-cluster
:当前集群的所有节点信息,当前节点根据此信息与其他节点取得联系。 -
initial-cluster-state
: 本次是否为新建集群,有两个取值:new和existing。
查看集群健康状况:
$ etcdctl --endpoints=http://192.168.165.165:2380,http://192.168.165.185:2380,http://192.168.165.195:2380 endpoint health
http://192.168.165.165:2380 is healthy: successfully committed proposal: took = 3.174461ms
http://192.168.165.195:2380 is healthy: successfully committed proposal: took = 3.900067ms
http://192.168.165.185:2380 is healthy: successfully committed proposal: took = 3.07624ms
查看集群列表:
$ etcdctl member list
43b786eba90b1b8, started, infra1, http://192.168.165.185:2380, http://192.168.165.185:2379, false
ce5d5e6f583c9638, started, infra2, http://192.168.165.195:2380, http://192.168.165.195:2379, false
e79eb5319f6d1299, started, infra0, http://192.168.165.165:2380, http://192.168.165.165:2379, false
在初始化完成后,etcd 还提供动态增、删、改 etcd 集群节点的功能,这个需要用到etcdctl
命令进行操作。
1.3 etcd自发现模式
在实际环境中,集群成员的ip可能不会提前知道。如使用dhcp自动获取的情况,在这些情况下,使用自动发现来
引导etcd集群,而不是指定静态配置,这个过程被称为“发现”。
下面将演示自发现模式的使用方法。
1、通过自发现的方式启动etcd集群需要事先准备一个etcd集群,本文使用上面搭建的静态集群。
$ etcdctl member list
43b786eba90b1b8, started, infra1, http://192.168.165.185:2380, http://192.168.165.185:2379, false
ce5d5e6f583c9638, started, infra2, http://192.168.165.195:2380, http://192.168.165.195:2379, false
e79eb5319f6d1299, started, infra0, http://192.168.165.165:2380, http://192.168.165.165:2379, false
2、找一个node节点(192.168.165.175),在上面仅安装好etcd即可,不要进行过多配置。
3、获取 discovery 的 token
随机生成一个可以标识新集群的唯一令牌,在后续步骤中,它将用作发现键空间中的唯一前缀。
[root@localhost ~]# UUID=$(uuidgen)
[root@localhost ~]# echo $UUID
852b9794-c74d-4f59-bc42-46ac0dc721a3
4、指定集群的大小
获取令牌时,必须指定集群大小, 发现服务使用该大小来了解何时发现了最初将组成集群的所有成员。
可以执行如下命令设定集群的大小,假设为1。
在新的节点(192.168.165.175)上往已有的集群发送:
[root@localhost ~]# curl -X PUT http://192.168.165.165:2379/v2/keys/discovery/852b9794-c74d-4f59-bc42-46ac0dc721a3/_config/size -d value=1
{"action":"set","node":{"key":"/discovery/852b9794-c74d-4f59-bc42-46ac0dc721a3/_config/size","value":"1","modifiedIndex":23,"createdIndex":23}}
我们需要把该 url 地址:
http://192.168.165.165:2379/v2/keys/discovery/852b9794-c74d-4f59-bc42-46ac0dc721a3
作为--discovery
参数来启动etcd。
新节点会自动使用已有集群:
http://192.168.165.165:2379/v2/keys/discovery/852b9794-c74d-4f59-bc42-46ac0dc721a3
目录进行etcd
的注册和发现服务。
5、执行启动 etcd 的命令
$ etcd --name infra3 --initial-advertise-peer-urls http://192.168.165.175:2380 \
--listen-peer-urls http://192.168.165.175:2380 \
--data-dir /opt/soft/etcd/etcd_data \
--listen-client-urls http://192.168.165.175:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.165.175:2379 \
--discovery http://192.168.165.165:2379/v2/keys/discovery/852b9794-c74d-4f59-bc42-46ac0dc721a3 \
--enable-v2
出现下面的信息代表成功:
......
{"level":"info","ts":"2023-02-15T10:45:04.030+0800","caller":"api/capability.go:75","msg":"enabled capabilities for version","cluster-version":"3.5"}
{"level":"info","ts":"2023-02-15T10:45:04.030+0800","caller":"etcdserver/server.go:2587","msg":"cluster version is updated","cluster-version":"3.5"}
{"level":"info","ts":"2023-02-15T10:45:04.031+0800","caller":"embed/serve.go:146","msg":"serving client traffic insecurely; this is strongly discouraged!","address":"127.0.0.1:2379"}
{"level":"info","ts":"2023-02-15T10:45:04.032+0800","caller":"embed/serve.go:146","msg":"serving client traffic insecurely; this is strongly discouraged!","address":"192.168.165.175:2379"}
{"level":"info","ts":"2023-02-15T10:45:04.033+0800","caller":"etcdmain/main.go:44","msg":"notifying init daemon"}
{"level":"info","ts":"2023-02-15T10:45:04.033+0800","caller":"etcdmain/main.go:50","msg":"successfully notified init daemon"}
需要注意的是,在我们完成了集群的初始化后,这些信息就失去了作用(每次都需要信息的discovery token)。当需
要增加节点时,需要使用 etcdctl 进行操作。为了安全,每次启动新 etcd 集群时,都使用新的 discovery token 进
行注册。另外,如果初始化时启动的节点超过了指定的数量,多余的节点会自动转化为 Proxy 模式的 etcd。
6、结果验证
集群启动好之后,进行验证,我们看一下集群的成员:
[root@localhost ~]# etcdctl member list
e94ddd1e41a68ff3, started, infra3, http://192.168.165.175:2380, http://192.168.165.175:2379, false
结果符合预期,再看下节点的健康状态:
[root@localhost ~]# etcdctl --endpoints="http://localhost:2379" endpoint health
http://localhost:2379 is healthy: successfully committed proposal: took = 4.800588ms
如果后续有其它节点加入的话,节点的操作和上面的一样,继续操作192.168.165.165
的etcd,前提是value的数
量进行调整。
如果你本地没有可用的 etcd 集群,etcd 官网提供了一个可以公网访问的 etcd 存储地址。你可以通过如下命令得
到 etcd 服务的目录,并把它作为-discovery
参数使用。
$ curl http://discovery.etcd.io/new?size=3
http://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
如果访问报错的话:
[root@localhost ~]# curl http://discovery.etcd.io/new?size=3
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx</center>
</body>
</html>
可以访问浏览器:
1.4 DNS 自发现模式
etcd 还支持使用 DNS SRV 记录进行启动。实际上是利用 DNS 的 SRV 记录不断轮训查询实现。DNS SRV 是 DNS
数据库中支持的一种资源记录的类型,它记录了计算机与所提供服务信息的对应关系。
这里使用 Dnsmasq 创建 DNS 服务。Dnsmasq 提供 DNS 缓存和 DHCP 服务、Tftp 服务功能。作为域名解析服
务器,Dnsmasq 可以通过缓存 DNS 请求来提高对访问过的网址的连接速度。
下面的操作需要在所有节点上执行。
1、首先安装 Dnsmasq
$ yum install dnsmasq
安装好之后,进行配置,所有的配置都在一个文件中完成 /etc/dnsmasq.conf。我们也可以在 /etc/dnsmasq.d 中
自己写任意名字的配置文件。
2、配置上游服务器地址
$ vim /etc/dnsmasq.conf
# 增加如下的内容
resolv-file=/etc/resolv.dnsmasq.conf
srv-host=_etcd-server._tcp.example.com,infra0.example.com,2380,0,100
srv-host=_etcd-server._tcp.example.com,infra1.example.com,2380,0,100
srv-host=_etcd-server._tcp.example.com,infra2.example.com,2380,0,100
在 dnsmasq.conf 中相应的域名记录,配置了我们所涉及的三台服务器,分别对应 infra0,infra1,infra2。
resolv-file 配置 Dnsmasq 额外的上游的 DNS 服务器,如果不开启就使用 Linux 主机默认的 /etc/resolv.conf 里的
nameserver。
3、在指定文件中增加转发 DNS 的地址
$ vim /etc/resolv.dnsmasq.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
这两个免费的 DNS服务,大家应该不陌生,读者可以根据本地实际网络进行配置。
4、本地启用 Dnsmasq 解析
$ vim /etc/resolv.conf
nameserver 127.0.0.1
将 Dnsmasq 解析配置到本地。
5、添加解析记录
分别为各个域名配置相关的记录 A 指向 etcd 核心节点对应的机器 IP。
添加解析记录有三种方式:使用系统默认 hosts、使用自定义 hosts 文件、使用自定义 conf。
这里我们使用比较简单的第一种方式。
$ vim /etc/hosts
# 每个节点都需要执行
# 增加如下的内容解析
192.168.165.165 infra0.example.com
192.168.165.175 infra1.example.com
192.168.165.195 infra2.example.com
6、启动服务
$ service dnsmasq start
Redirecting to /bin/systemctl start dnsmasq.service
7、启动好之后,我们进行验证
DNS 服务器上进行 SRV 记录查询,查询到的结果如下:
[root@zsx ~]# dig @192.168.165.165 +noall +answer SRV _etcd-server._tcp.example.com
_etcd-server._tcp.example.com. 0 IN SRV 0 100 2380 infra1.example.com.
_etcd-server._tcp.example.com. 0 IN SRV 0 100 2380 infra0.example.com.
_etcd-server._tcp.example.com. 0 IN SRV 0 100 2380 infra2.example.com.
查询域名解析结果如下:
[root@zsx ~]# dig @192.168.165.165 +noall +answer infra0.example.com infra1.example.com infra2.example.com
infra0.example.com. 0 IN A 192.168.165.165
infra1.example.com. 0 IN A 192.168.165.175
infra2.example.com. 0 IN A 192.168.165.195
至此,我们已成功安装好 Dnsmasq,下面我们基于 DNS 发现启动 etcd 集群。
8、启动集群
做好了上述两步 DNS 的配置,就可以使用 DNS 启动 etcd 集群了。需要删除-initial-cluster
配置(用于静态服
务发现),并指定 DNS SRV 域名(-discovery-srv
)。配置 DNS 解析的 url 参数为 -discovery-srv
。
各个节点的启动命令如下:
$ etcd -name infra0 \
-discovery-srv example.com \
-initial-advertise-peer-urls http://infra0.example.com:2380 \
-initial-cluster-token etcd-cluster-0 \
-initial-cluster-state new \
-data-dir /opt/etcd/data \
-advertise-client-urls http://infra0.example.com:2379 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380
$ etcd -name infra1 \
-discovery-srv example.com \
-initial-advertise-peer-urls http://infra1.example.com:2380 \
-initial-cluster-token etcd-cluster-1 \
-initial-cluster-state new \
-data-dir /opt/etcd/data \
-advertise-client-urls http://infra1.example.com:2379 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380
$ etcd -name infra2 \
-discovery-srv example.com \
-initial-advertise-peer-urls http://infra2.example.com:2380 \
-initial-cluster-token etcd-cluster-2 \
-initial-cluster-state new \
-data-dir /opt/etcd/data \
-advertise-client-urls http://infra2.example.com:2379 \
-listen-client-urls http://0.0.0.0:2379 \
-listen-peer-urls http://0.0.0.0:2380
当然,你也可以直接把节点的域名改成 IP 来启动。
etcd 群集成员可以使用域名或 IP 地址进行广播,启动的过程将解析 DNS 记录。–initial-advertise-peer-urls 中的
解析地址必须与 SRV 目标中的解析地址匹配。etcd 成员读取解析的地址,以查找其是否属于 SRV 记录中定义的群
集。
我们验证基于 DNS 发现启动集群的正确性,查看集群的成员列表:
$ etcdctl member list
43b786eba90b1b8, started, infra1, http://192.168.165.175:2380, http://192.168.165.175:2379, false
ce5d5e6f583c9638, started, infra2, http://192.168.165.195:2380, http://192.168.165.195:2379, false
e79eb5319f6d1299, started, infra0, http://192.168.165.165:2380, http://192.168.165.165:2379, false
可以看到,结果输出 etcd 集群有三个成员,符合预期。下面我们使用 IP 地址的方式,继续验证集群节点的状态。
$ etcdctl --endpoints=http://192.168.165.165:2380,http://192.168.165.175:2380,http://192.168.165.195:2380 endpoint health
http://192.168.165.165:2380 is healthy: successfully committed proposal: took = 3.174461ms
http://192.168.165.195:2380 is healthy: successfully committed proposal: took = 3.900067ms
http://192.168.165.175:2380 is healthy: successfully committed proposal: took = 3.07624ms