一、docker下部署etcd时的docker配置
docker网络配置方式的选择:bridge和host方式都可以。具体配置见下:
bridge方式(缺省):
docker run -it -p 2380:2380 -p 2379:2379 --name myetcd22 4e5b8fabb3af /bin/sh
host方式:
docker run -it --network host --name myetcd22 4e5b8fabb3af /bin/sh
说明:
4e5b8fabb3af 为etcd的docker imageID
2379和2380为etcd在IANA 的注册端口。以前为私有端口4001和7001。
后续举例,都以bridge方式为例。
二、etcd启动参数说明及注意事项
参数
|
使用说明
|
|
---|---|---|
--name etcd0 | 本member的名字 | |
--initial-advertise-peer-urls http://192.168.2.55:2380 | 其他member使用,其他member通过该地址与本member交互信息。一定要保证从其他member能可访问该地址。静态配置方式下,该参数的value一定要同时在--initial-cluster参数中存在。 memberID的生成受--initial-cluster-token和--initial-advertise-peer-urls影响。 | |
--listen-peer-urls http://0.0.0.0:2380 | 本member侧使用,用于监听其他member发送信息的地址。ip为全0代表监听本member侧所有接口 | |
--listen-client-urls http://0.0.0.0:2379 | 本member侧使用,用于监听etcd客户发送信息的地址。ip为全0代表监听本member侧所有接口 | |
--advertise-client-urls http://192.168.2.55:2379 | etcd客户使用,客户通过该地址与本member交互信息。一定要保证从客户侧能可访问该地址 | |
--initial-cluster-token etcd-cluster-2 | 用于区分不同集群。本地如有多个集群要设为不同。 | |
--initial-cluster etcd0=http://192.168.2.55:2380, | 本member侧使用。描述集群中所有节点的信息,本member根据此信息去联系其他member。 memberID的生成受--initial-cluster-token和--initial-advertise-peer-urls影响。 | |
--initial-cluster-state new | 用于指示本次是否为新建集群。有两个取值new和existing。如果填为existing,则该member启动时会尝试与其他member交互。 集群初次建立时,要填为new,经尝试最后一个节点填existing也正常,其他节点不能填为existing。 集群运行过程中,一个member故障后恢复时填为existing,经尝试填为new也正常。 | |
-data-dir | 指定节点的数据存储目录,这些数据包括节点ID,集群ID,集群初始化配置,Snapshot文件,若未指定-wal-dir,还会存储WAL文件;如果不指定会用缺省目录。 |
|
-discovery http://192.168.1.163:20003/v2/keys/discovery/78b12ad7-2c1d-40db-9416-3727baf686cb | 用于自发现模式下,指定第三方etcd上key地址,要建立的集群各member都会向其注册自己的地址。 |
三、etcd几种集群部署方式
etcd部署分两个阶段:集群建立阶段,集群运行阶段。
两个阶段中操作etcd的方法不同。
下面各种部署方式也分两个阶段说明。
etcd有三种集群部署方式:
1、static配置方式(要配置本方地址和其他人地址)
适用于在配置前已经明确各种信息的情况,比如集群的大小,各member的ip,端口等信息。
各member依靠配置得知其他member的联系地址。当然ip等信息可以通过环境变量传进去,不一定要写死。
假设需要建一个有三个节点的集群,三个节点地址分别为:192.168.2.55,192.168.2.54,192.168.2.56。
1.1、集群建立阶段
在第一个节点上执行:
etcd --name etcd0 --initial-advertise-peer-urls http://192.168.2.55:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.55:2379 \
--initial-cluster-token etcd-cluster-2 \
--initial-cluster etcd0=http://192.168.2.55:2380,etcd1=http://192.168.2.54:2380,etcd2=http://192.168.2.56:2380 \
--initial-cluster-state new
在第二个节点上执行:
etcd --name etcd1 --initial-advertise-peer-urls http://192.168.2.54:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.54:2379 \
--initial-cluster-token etcd-cluster-2 \
--initial-cluster etcd0=http://192.168.2.55:2380,etcd1=http://192.168.2.54:2380,etcd2=http://192.168.2.56:2380 \
--initial-cluster-state new
在第三个节点上执行:
etcd --name etcd2 --initial-advertise-peer-urls http://192.168.2.56:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.56:2379 \
--initial-cluster-token etcd-cluster-2 \
--initial-cluster etcd0=http://192.168.2.55:2380,etcd1=http://192.168.2.54:2380,etcd2=http://192.168.2.56:2380 \
--initial-cluster-state new
1.2、运行阶段member异常恢复
假设一个节点etcd2异常重启,可以再执行如下命令拉起来
etcd --name etcd2 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.56:2379
static配置方式下,且处于运行阶段时,所有--initial-cluster参数没作用,带与不带都没有影响。
2、discovery自发现方式(只配置本方地址,其他人地址从中介处获取)
依赖于第三方etcd服务。在“集群建立阶段”各member都向第三方etcd服务注册,也从其获取其他member的信息。就像有个中介一样。
在“集群运行阶段”,对第三方etcd不再有依赖。
以私有etcd方式地址做中介为例说明:
2.1、集群建立阶段
a、首先在中介处申请一块地方
有两种方式,私有和官网方式任选其一
- 私有etcd方式:
uuidgen 先生成一个标识78b12ad7-2c1d-40db-9416-3727baf686cb
curl -X PUT http://192.168.1.163:20003/v2/keys/discovery/78b12ad7-2c1d-40db-9416-3727baf686cb/_config/size -d value=3
- 官网方式:
curl https://discovery.etcd.io/new?size=3
返回 https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
b、在各个节点上分别执行
etcd --name etcd0 --initial-advertise-peer-urls http://192.168.2.55:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.55:2379 \
-discovery http://192.168.1.163:20003/v2/keys/discovery/78b12ad7-2c1d-40db-9416-3727baf686cb \
--initial-cluster-state new
etcd --name etcd1 --initial-advertise-peer-urls http://192.168.2.54:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.54:2379 \
-discovery http://192.168.1.163:20003/v2/keys/discovery/78b12ad7-2c1d-40db-9416-3727baf686cb \
--initial-cluster-state new
etcd --name etcd2 --initial-advertise-peer-urls http://192.168.2.56:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.56:2379 \
-discovery http://192.168.1.163:20003/v2/keys/discovery/78b12ad7-2c1d-40db-9416-3727baf686cb \
--initial-cluster-state new
2.1、运行阶段member异常恢复
下面两条命令任选其一都可以起来。优选第一条
etcd --name etcd2 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.56:2379
etcd --name etcd2 --initial-advertise-peer-urls http://192.168.2.56:2380 \
--listen-peer-urls http://0.0.0.0:2380 \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://192.168.2.56:2379 \
-discovery http://192.168.1.163:20003/v2/keys/discovery/78b12ad7-2c1d-40db-9416-3727baf686cb \
--initial-cluster-state existing
3、DNS方式 – 暂未研究,不作说明
四、etcd集群运行过程中的改配
主要用于故障节点替换,集群扩容需求。
集群运行过程中的改配不区分static和discovery方式。
1、替换的步骤:
比如集群中某一member重启后仍不能恢复时,就需要替换一个新member进来。
a、从集群中删除老member
etcdctl member remove 1609b5a3a078c227
b、向集群中新增新member
etcdctl member add <name> <peerURL>
例子:敲命令 etcdctl member add etcd2 http://192.168.2.56:2380 后返回如下信息
Added member named etcd2 with ID b7d510356ee2e68b to cluster
ETCD_NAME="etcd2"
ETCD_INITIAL_CLUSTER="etcd0=http://192.168.2.55:2380,etcd2=http://192.168.2.56:2380,etcd1=http://192.168.2.54:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"
c、删除老节点data目录
如果不删除,启动后节点仍旧沿用之前的老id, 其他正常节点不认,不能建立联系
d、在新member上启动etcd进程
2、扩容的步骤:
执行上面第b,d两步即可。
五、常见使用场景
1、单节点故障
在该节点重启后数据会自动同步。包括在该节点故障后与恢复前之间新变化的数据。
2、客户对etcd的读写访问
对读写操作,客户可以从任一节点发起,数据都会同步到整个集群。
读操作由各个接收member直接处理,写操作由各个接收member转发给leader处理。
3、集群可服务性对故障的容忍度
以3节点集群为例。
结论:
- 在1个member故障时,即小部分节点故障: 集群处于健康态,读写都正常。
- 在2个member故障时,即大部分节点故障情况:集群整体状态为”不健康“,剩下的member也为”不健康“。只能read,但不能write,可能是因为剩下的member竞选leader失败,拿不到多数票。
- 在大部分节点恢复后,集群整体状态为”健康“,每个member也为”健康“
如下例子,终止掉了54和60,就剩下55
root@paas-controller-1:/home/yan# docker exec -it myetcd22 /bin/sh
/ # etcdctl cluster-health
failed to check the health of member 1018ddcc3ad118c8 on http://192.168.2.60:2379: Gethttp://192.168.2.60:2379/health: dial tcp 192.168.2.60:2379: getsockopt: connection refused
member 1018ddcc3ad118c8 is unreachable: [http://192.168.2.60:2379] are all unreachable
member 35d37c0c6139bb9a is unhealthy: got unhealthy result from http://192.168.2.55:2379
failed to check the health of member bd47c147acde4ad7 on http://192.168.2.54:2379: Gethttp://192.168.2.54:2379/health: dial tcp 192.168.2.54:2379: getsockopt: connection refused
member bd47c147acde4ad7 is unreachable: [http://192.168.2.54:2379] are all unreachable
cluster is unhealthy
/ # exit
root@paas-controller-1:/home/yan# curl http://192.168.2.55:2379/v2/keys/message
{"action":"get","node":{"key":"/message","value":"Hello everyone","modifiedIndex":8,"createdIndex":8}}
root@paas-controller-1:/home/yan#
root@paas-controller-1:/home/yan#
root@paas-controller-1:/home/yan# curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="Hello world"
{"errorCode":300,"message":"Raft Internal Error","cause":"etcdserver: request timed out","index":0}
root@paas-controller-1:/home/yan# curl http://192.168.2.55:2379/v2/keys/message -XPUT -d value="Hello world"
{"errorCode":300,"message":"Raft Internal Error","cause":"etcdserver: request timed out","index":0}
root@paas-controller-1:/home/yan#
root@paas-controller-1:/home/yan# curl http://192.168.2.55:2379/health
{"health": "false"}
root@paas-controller-1:/home/yan# curl http://192.168.2.54:2379/health
curl: (7) Failed to connect to 192.168.2.54 port 2379: Connection refused
root@paas-controller-1:/home/yan# curl http://192.168.2.60:2379/health
curl: (7) Failed to connect to 192.168.2.60 port 2379: Connection refused
在恢复54节点后:
root@paas-controller-1:/home/yan# curl http://192.168.2.55:2379/health
{"health": "true"}root@paas-controller-1:/home/yan# curl http://192.168.2.54:2379/health
{"health": "true"}root@paas-controller-1:/home/yan# curl http://192.168.2.60:2379/health
curl: (7) Failed to connect to 192.168.2.60 port 2379: Connection refused
root@paas-controller-1:/home/yan# curl http://192.168.2.55:2379/v2/keys/message
{"action":"get","node":{"key":"/message","value":"Hello everyone","modifiedIndex":8,"createdIndex":8}}
root@paas-controller-1:/home/yan# curl http://192.168.2.55:2379/v2/keys/message -XPUT -d value="Hello world"
{"action":"set","node":{"key":"/message","value":"Hello world","modifiedIndex":20,"createdIndex":20},"prevNode":{"key":"/message","value":"Hello everyone","modifiedIndex":8,"createdIndex":8}}
root@paas-controller-1:/home/yan# docker exec -it myetcd22 /bin/sh
/ # etcdctl cluster-health
failed to check the health of member 1018ddcc3ad118c8 on http://192.168.2.60:2379: Gethttp://192.168.2.60:2379/health: dial tcp 192.168.2.60:2379: getsockopt: connection refused
member 1018ddcc3ad118c8 is unreachable: [http://192.168.2.60:2379] are all unreachable
member 35d37c0c6139bb9a is healthy: got healthy result from http://192.168.2.55:2379
member bd47c147acde4ad7 is healthy: got healthy result from http://192.168.2.54:2379
cluster is healthy
4、static方式下增加新member
cluster的member数之前已经根据initial-cluster描述的成员确定下来了,如果不先add member,直接启动etcd的话生成的clusterID和老clusterID不一致,根本加不进去。
后续要增加member走"运行中改配扩容"流程,即先add member,然后启动新etcd。加入后都是正式member,不存在降为proxy的机制。
5、discovery方式下size对新加入节点的限制。
size这个key如果不存在或者不设置有效值,集群所有节点都建不起来。
在集群中已经存在size个member的情况下,以--initial-cluster-state new参数新加入的节点自动降为proxy。通过该proxy可进行读写操作。该proxy不在member列表中。原member之一退出后(member异常和remove member情况下相同),proxy无变化,不会自动加入集群。
要加入群,必须走"运行中改配替换"流程。
不执行add member直接启动etcd的情况下自动降为proxy,新加入节点打印如下信息:
2017-01-24 23:35:47.956624 I | etcdmain: stopping listening for peers on http://0.0.0.0:2380
2017-01-24 23:35:47.956637 N | etcdmain: discovery cluster full, falling back to proxy
2017-01-24 23:35:47.956643 N | etcdmain: proxy: this proxy supports v2 API only!
2017-01-24 23:35:47.965691 I | etcdmain: proxy: using peer urls [http://192.168.2.54:2380http://192.168.2.55:2380 http://192.168.2.60:2380]
2017-01-24 23:35:47.988806 I | etcdmain: proxy: listening for client requests on http://0.0.0.0:2379
2017-01-24 23:35:47.989190 I | httpproxy: endpoints found ["http://192.168.2.54:2379" "http://192.168.2.60:2379" "http://192.168.2.55:2379"]
六、一些可能遇到的问题
1、各节点时钟相差过大导致集群建立不起来
etcd启动信息中有提示错误信息
2、listen-url配为localhost或127.0.0.1导致集群建立不起来
localhost为127.0.0.1,对应lo接口,只有同一空间内的进程之间才能通过此接口交互。
分布在三个不同机器上的各member之间通过--initial-advertise-peer-urls地址交互,该地址与lo对应不同的接口。
3、--listen-client-urls配为--initial-advertise-peer-urls地址导致etcdctl工具执行不正常
两全其美的方法:
--listen-client-urls http://192.168.2.55:2379,http://localhost:2379 《–用逗号分隔,且不能有空格
4、-data-dir目录的问题
该目录下保存了memberID,clusterID和数据等信息,如果集群归属有变化,一定要先删除该目录。
5、--initial- 前缀类参数的使用
所有带此前缀的选项在集群启动后就没用了,member故障后再重起不用带,带了也没影响。
七、常用命令:
1、集群member管理类:
命令行:(在任一健康member上执行)
etcdctl member list
etcdctl cluster-health
etcdctl member add <membername> <advertise-peer-url>
etcdctl member remove <memberID>
RESTful:
curl http://127.0.0.1:2379/v2/members
curl http://10.0.0.10:2379/health
curl http://127.0.0.1:2379/v2/members -XPOST -H "Content-Type: application/json" -d '{"peerURLs":["http://192.168.2.61:2380"]}'
此处不能填name,在启动etcd时填写会更新member的name属性
curl http://127.0.0.1:2379/v2/members/272e204152 -XDELETE