etcd构建自身高可用集群主要有三种形式:
- 静态发现: 预先已知etcd集群中有哪些节点,在启动时通过
--initial-cluster
参数直接指定好etcd的各个节点地址。 - etcd动态发现: 通过已有的etcd集群作为数据交互点,然后在扩展新的集群时实现通过已有集群进行服务发现的机制。比如官方提供的:discovery.etcd.io
- DNS动态发现: 通过DNS查询方式获取其他节点地址信息。
静态发现:
这里将部署一个3节点的集群, 以下为3台主机信息,
节点名称 | 地址 |
---|---|
etcd1 | 192.168.2.210 |
etcd2 | 192.168.2.211 |
etcd3 | 192.168.2.212 |
配置etcd集群
修改etcd配置文件,我这里的环境是在/opt/etcd/config/etcd.conf
,请根据实际情况修改。
- etcd1配置示例
# 编辑配置文件
$ vim /opt/etcd/config/etcd.conf
ETCD_NAME=etcd1
ETCD_DATA_DIR="/var/lib/etcd/etcd1"
ETCD_LISTEN_PEER_URLS="http://192.168.2.210:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.2.210:2379,http://192.168.2.210:4001"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.2.210:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.2.210:2380,etcd2=http://192.168.2.211:2380,etcd3=http://192.168.2.212:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="hilinux-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.2.210:2379,http://192.168.2.210:4001"
- etcd2配置示例
# 编辑配置文件
$ vim /opt/etcd/config/etcd.conf
ETCD_NAME=etcd2
ETCD_DATA_DIR="/var/lib/etcd/etcd2"
ETCD_LISTEN_PEER_URLS="http://192.168.2.211:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.2.211:2379,http://192.168.2.211:4001"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.2.211:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.2.210:2380,etcd2=http://192.168.2.211:2380,etcd3=http://192.168.2.212:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="hilinux-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.2.211:2379,http://192.168.2.211:4001"
- etcd3配置示例
# 编辑配置文件
$ vim /opt/etcd/config/etcd.conf
ETCD_NAME=etcd3
ETCD_DATA_DIR="/var/lib/etcd/etcd3"
ETCD_LISTEN_PEER_URLS="http://192.168.2.212:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.2.212:2379,http://192.168.2.212:4001"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.2.212:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.2.210:2380,etcd2=http://192.168.2.211:2380,etcd3=http://192.168.2.212:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="hilinux-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.2.212:2379,http://192.168.2.212:4001"
针对上面几个配置参数做下简单的解释:
- ETCD_NAME :ETCD的节点名
- ETCD_DATA_DIR:ETCD的数据存储目录
- ETCD_SNAPSHOT_COUNTER:多少次的事务提交将触发一次快照
- ETCD_HEARTBEAT_INTERVAL:ETCD节点之间心跳传输的间隔,单位毫秒
- ETCD_ELECTION_TIMEOUT:该节点参与选举的最大超时时间,单位毫秒
- ETCD_LISTEN_PEER_URLS:该节点与其他节点通信时所监听的地址列表,多个地址使用逗号隔开,其格式可以划分为scheme://IP:PORT,这里的scheme可以是http、https
- ETCD_LISTEN_CLIENT_URLS:该节点与客户端通信时监听的地址列表
- ETCD_INITIAL_ADVERTISE_PEER_URLS:该成员节点在整个集群中的通信地址列表,这个地址用来传输集群数据的地址。因此这个地址必须是可以连接集群中所有的成员的。
- ETCD_INITIAL_CLUSTER:配置集群内部所有成员地址,其格式为:ETCD_NAME=ETCD_INITIAL_ADVERTISE_PEER_URLS,如果有多个使用逗号隔开
- ETCD_ADVERTISE_CLIENT_URLS:广播给集群中其他成员自己的客户端地址列表
- ETCD_INITIAL_CLUSTER_STATE:初始化集群状态,new表示新建
- ETCD_INITIAL_CLUSTER_TOKEN:初始化集群token
注意:所有ETCD_MY_FLAG的配置参数也可以通过命令行参数进行设置,但是命令行指定的参数优先级更高,同时存在时会覆盖环境变量对应的值。
下面给出常用配置的参数和它们的解释:
--name:方便理解的节点名称,默认为default,在集群中应该保持唯一,可以使用 hostname
--data-dir:服务运行数据保存的路径,默认为 ${name}.etcd
--snapshot-count:指定有多少事务(transaction)被提交时,触发截取快照保存到磁盘
--heartbeat-interval:leader 多久发送一次心跳到 followers。默认值是 100ms
--eletion-timeout:重新投票的超时时间,如果 follow 在该时间间隔没有收到心跳包,会触发重新投票,默认为 1000 ms
--listen-peer-urls:和同伴通信的地址,比如 http://ip:2380,如果有多个,使用逗号分隔。需要所有节点都能够访问,所以不要使用 localhost!
--listen-client-urls:对外提供服务的地址:比如 http://ip:2379,http://127.0.0.1:2379,客户端会连接到这里和 etcd 交互
--advertise-client-urls:对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点
--initial-advertise-peer-urls:该节点同伴监听地址,这个值会告诉集群中其他节点
--initial-cluster:集群中所有节点的信息,格式为 node1=http://ip1:2380,node2=http://ip2:2380,…。注意:这里的 node1 是节点的 --name 指定的名字;后面的 ip1:2380 是 --initial-advertise-peer-urls 指定的值
--initial-cluster-state:新建集群的时候,这个值为new;假如已经存在的集群,这个值为 existing
--initial-cluster-token:创建集群的token,这个值每个集群保持唯一。这样的话,如果你要重新创建集群,即使配置和之前一样,也会再次生成新的集群和节点 uuid;否则会导致多个集群之间的冲突,造成未知的错误
所有以--init开头的配置都是在bootstrap集群的时候才会用到,后续节点的重启会被忽略。
etcd提供了多种部署集群的方式,在「通过静态发现方式部署etcd集群」 一文中我们介绍了如何通过静态发现方式部署集群。
不过很多时候,你只知道你要搭建一个多大(包含多少节点)的集群,但是并不能事先知道这几个节点的ip,从而无法使用--initial-cluster
参数。
这个时候,你就需要使用discovery的方式来搭建etcd集群。discovery方式有两种:etcd discovery
和DNS discovery
。
这里我们先介绍下etcd discovery
方式。这种启动方式依赖另外一个ETCD集群,在该集群中创建一个目录,并在该目录中创建一个_config的子目录,并且在该子目录中增加一个size节点,指定集群的节点数目。在这种情况下,将该目录在ETCD中的URL作为节点的启动参数,即可完成集群启动。
etcd discovery
集群方式分为两种:自定义的etcd discovery和公共 etcd discovery。
- 公共etcd discovery服务
公共的discovery就是通过CoreOS提供的公共discovery服务申请token。
获取集群标识
集群标识可以从已有的etcd集群中创建,这里通过CoreOS提供的公共discovery服务申请token
$ curl -w "\n" 'https://discovery.etcd.io/new?size=3'
https://discovery.etcd.io/c5b52d9d8fd7af9017bd7b54cf13e420
以上命令会生成一个链接样式的token,参数size代表要创建的集群大小。
修改etcd配置
依次编辑三个节点的etcd配置文件,删除ETCD_INITIAL_CLUSTER
、ETCD_INITIAL_CLUSTER_STATE
、ETCD_INITIAL_CLUSTER_TOKEN
配置参数并加上ETCD_DISCOVERY
参数为获取的集群标识即可。
这里以etcd1节点为例(etcd2、etcd3同理):
# 编辑etcd配置文件
$ vim /opt/etcd/config/etcd.conf
ETCD_NAME=etcd1
ETCD_DATA_DIR="/var/lib/etcd/etcd1"
ETCD_LISTEN_PEER_URLS="http://192.168.2.210:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.2.210:2379,http://192.168.2.210:4001"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.2.210:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.2.210:2379,http://192.168.2.210:4001"
ETCD_DISCOVERY="https://discovery.etcd.io/c5b52d9d8fd7af9017bd7b54cf13e420"
测试etcd集群
按上面配置好各集群节点后,分别在各节点启动etcd。
$ systemctl start etcd
启动完成后,执行以下命令:
$ curl -w '\n' https://discovery.etcd.io/c5b52d9d8fd7af9017bd7b54cf13e420
{"action":"get","node":{"key":"/_etcd/registry/c5b52d9d8fd7af9017bd7b54cf13e420","dir":true,"nodes":[{"key":"/_etcd/registry/c5b52d9d8fd7af9017bd7b54cf13e420/a44795c1770e34ec","value":"etcd1=http://192.168.2.210:2380","modifiedIndex":1301600912,"createdIndex":1301600912},{"key":"/_etcd/registry/c5b52d9d8fd7af9017bd7b54cf13e420/a085e7281cb15be2","value":"etcd2=http://192.168.2.211:2380","modifiedIndex":1301601030,"createdIndex":1301601030},{"key":"/_etcd/registry/c5b52d9d8fd7af9017bd7b54cf13e420/173070ace158b9d1","value":"etcd3=http://192.168.2.212:2380","modifiedIndex":1301601101,"createdIndex":1301601101}],"modifiedIndex":1301571633,"createdIndex":1301571633}}
从输出结果看,说明集群已在discovery.etcd.io
注册成功。
查看集群成员
$ etcdctl --endpoints "http://192.168.2.210:2379" member list
173070ace158b9d1: name=etcd3 peerURLs=http://192.168.2.212:2380 clientURLs=http://192.168.2.212:2379,http://192.168.2.212:4001 isLeader=false
a085e7281cb15be2: name=etcd2 peerURLs=http://192.168.2.211:2380 clientURLs=http://192.168.2.211:2379,http://192.168.2.211:4001 isLeader=false
a44795c1770e34ec: name=etcd1 peerURLs=http://192.168.2.210:2380 clientURLs=http://192.168.2.210:2379,http://192.168.2.210:4001 isLeader=true
更多集群使用方法可参考「通过静态发现方式部署etcd集群」一文。
自定义的etcd discovery服务
这种方式就是利用一个已有的etcd
集群来提供discovery服务,从而搭建一个新的etcd
集群。
假设已有的etcd
集群的一个访问地址是:192.168.2.210,那么我们首先需要在已有etcd
中创建一个特殊的key,方法如下:
$ curl http://192.168.2.210:2379/v2/keys/discovery/8ebee6723eaf3f5c7724e879f8797e85/_config/size -d value=3
{"action":"create","node":{"key":"/discovery/8ebee6723eaf3f5c7724e879f8797e85/_config/size/00000000000000000011","value":"3","modifiedIndex":11,"createdIndex":11}}
其中value=3
表示本集群的大小,即: 有多少集群节点。而 8ebee6723eaf3f5c7724e879f8797e85就是用来做discovery的token。
值得注意的是:如果实际启动的etcd节点个数大于discovery token创建时指定的size,多余的节点会自动变为proxy节点。
etcd proxy模式简介:
作为反向代理把客户的请求转发给可用的etcd集群,新节点加入集群如果核心节点数已满足要求,则自动转化为proxy模式,此项不会在节点不足时逆向转化为实际节点。
接下来的配置就和公共etcd discovery
服务中的方法类似,就不再重复阐述了。
基于 DNS 动态发现方式部署 Etcd 集群
使用discovery的方式来搭建etcd集群方式有两种:etcd discovery
和DNS discovery
。在 「基于已有集群动态发现方式部署etcd集群」一文中讲解了etcd discovery
这种方式,今天我们就来讲讲DNS discovery
这种方式的实现。
etcd在基于DNS做服务发现时,实际上是利用DNS的SRV记录不断轮训查询实现的。DNS SRV
是DNS数据库中支持的一种资源记录的类型,它记录了哪台计算机提供了哪个服务这么一个简单信息。
本文采用dnsmasq
作为dns
服务器,关于dnsmasq
搭建可参考 「利用Dnsmasq部署DNS服务」。
创建DNS记录
- 增加DNS SRV记录
$ vim /etc/dnsmasq.conf
#增加内容如下
srv-host=_etcd-server._tcp.hi-linux.com,etcd1.hi-linux.com,2380,0,100
srv-host=_etcd-server._tcp.hi-linux.com,etcd2.hi-linux.com,2380,0,100
srv-host=_etcd-server._tcp.hi-linux.com,etcd3.hi-linux.com,2380,0,100
- 增加对应的域名解析
$ vim /etc/dnsmasq.hosts
#增加内容如下
192.168.2.210 etcd1.hi-linux.com
192.168.2.211 etcd2.hi-linux.com
192.168.2.212 etcd3.hi-linux.comxxxxxxxxxx7 1$ vim /etc/dnsmasq.hosts23#增加内容如下45192.168.2.210 etcd1.hi-linux.com6192.168.2.211 etcd2.hi-linux.com7192.168.2.212 etcd3.hi-linux.com$ vim /etc/dnsmasq.hosts#增加内容如下192.168.2.210 etcd1.hi-linux.com192.168.2.211 etcd2.hi-linux.com192.168.2.212 etcd3.hi-linux.com
- 重启dnsmasq
$ systemctl restart dnsmasq
- 测试是否成功
# 查询SRV记录
$ dig @192.168.2.210 +noall +answer SRV _etcd-server._tcp.hi-linux.com
_etcd-server._tcp.hi-linux.com. 0 IN SRV 0 100 2380 etcd2.hi-linux.com.
_etcd-server._tcp.hi-linux.com. 0 IN SRV 0 100 2380 etcd1.hi-linux.com.
_etcd-server._tcp.hi-linux.com. 0 IN SRV 0 100 2380 etcd3.hi-linux.com.
# 查询域名解析结果
$ dig @192.168.2.210 +noall +answer etcd1.hi-linux.com etcd2.hi-linux.com etcd3.hi-linux.com
etcd1.hi-linux.com. 0 IN A 192.168.2.210
etcd2.hi-linux.com. 0 IN A 192.168.2.211
etcd3.hi-linux.com. 0 IN A 192.168.2.212
- 修改DNS服务器
Linux系统默认从/etc/resolv.conf
配置文件读取DNS服务器,为了让etcd能够从dnsmasq
服务器获取自定义域名解析,要修改三台etcd服务器的/etc/resolv.conf
文件。
# 编辑resolv.conf文件
# 文件内容如下,保证我们自定义的dnsmasq服务器在第一位
$ vim /etc/resolv.conf
nameserver 192.168.2.210
配置etcd
- 修改etcd配置文件
开启DNS服务发现,主要是删除掉ETCD_INITIAL_CLUSTER
字段(用于静态服务发现),并指定DNS SRV
域名(ETCD_DISCOVERY_SRV)
这里以etcd1节点为例(etcd2、etcd3同理):
$ vim /opt/etcd/config/etcd.conf
ETCD_NAME=etcd1
ETCD_DATA_DIR="/var/lib/etcd/etcd1"
ETCD_LISTEN_PEER_URLS="http://etcd1.hi-linux.com:2380"
ETCD_LISTEN_CLIENT_URLS="http://etcd1.hi-linux.com:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://etcd1.hi-linux.com:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="hilinux-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://etcd1.hi-linux.com:2379,http://etcd1.hi-linux.com:4001"
ETCD_DISCOVERY_SRV="hi-linux.com"
- 测试etcd集群
按上面配置好各集群节点后,分别在各节点启动etcd。
$ systemctl start etcd
启动完成后,执行以下命令查看集群成员:
$ etcdctl --endpoints "http://etcd1.hi-linux.com:2379" member list
1da4b0d74a9ecfff: name=etcd2 peerURLs=http://etcd2.hi-linux.com:2380 clientURLs=http://etcd2.hi-linux.com:2379,http://etcd2.hi-linux.com:4001 isLeader=false
7dd139e539054326: name=etcd1 peerURLs=http://etcd1.hi-linux.com:2380 clientURLs=http://etcd1.hi-linux.com:2379,http://etcd1.hi-linux.com:4001 isLeader=true
a12d567c7c7f2e2b: name=etcd3 peerURLs=http://etcd3.hi-linux.com:2380 clientURLs=http://etcd3.hi-linux.com:2379,http://etcd3.hi-linux.com:4001 isLeader=false