etcd
是一个高可用的分布式 key-value(键值) 存储系统。在暴漫我们用他用来做配置管理和服务发现。
这一次我们主要介绍关于 etcd 集群的搭建与管理。
1. etcd 集群概述
首先我们需要理解,etcd
是一个分布式的 key-value 存储系统,所以其基本原理和前面我们介绍过的
分布式数据库相关理论 是一致的。
两种不同的 node(节点)
值得注意的是,为了方便使用,etcd
引入了 proxy
的概念,所以 etcd
的节点分为两种:集群节点
和代理节点
。
集群节点
和 代理节点
在使用上几乎没有任何区别。这使得我们可以在每台机器上都安装 etcd
,进而把 etcd
当作本地服务来使用(通过 0.0.0.0)。
他们的区别在于:内部原理不同。
集群节点是真正的 etcd
集群的构成者,这些节点负责数据存取,集群管理等等。
代理节点可以理解为一个反向代理,它只是简单的接受请求,转发请求给 etcd
集群。
集群大小与容错
集群的大小指集群节点的个数。根据 etcd
的分布式数据冗余策略,集群节点越多,容错能力(Failure Tolerance)越强,同时写性能也会越差。
所以关于集群大小的优化,其实就是容错和写性能的一个平衡。
另外, etcd 推荐使用 奇数
作为集群节点个数。因为奇数个节点与和其配对的偶数个节点相比(比如 3节点和4节点对比),
容错能力相同,却可以少一个节点。
所以综合考虑性能和容错能力,etcd 官方文档推荐的 etcd 集群大小是 3, 5, 7。至于到底选择 3,5 还是 7,根据需要的容错能力而定。
关于节点数和容错能力对应关系,如下表所示:
集群大小 | 最大容错 |
---|---|
1 | 0 |
3 | 1 |
4 | 1 |
5 | 2 |
6 | 2 |
7 | 3 |
8 | 3 |
9 | 4 |
2. etcd 集群的搭建(初始化一个 etcd 集群)
这里说的搭建指“从无到有”搭建。关于在已有集群中添加减少集群节点,属于下面"第3节:etcd 集群的管理"的内容。
etcd 集群的搭建有三种方式,包括:static 方式,etcd discovery 方式 和 DNS discovery。
这里,我们以一个例子来讲解 etcd 集群各种方式的搭建。假设我们需要搭建一个3节点的 etcd 集群。这三个节点的 name(我们需要给每个节点取个名字)和 ip 分别是:
name | ip |
---|---|
etcd0 | 10.0.0.10 |
etcd1 | 10.0.0.11 |
etcd2 | 10.0.0.12 |
2.1 static 方式
static 方式是最简单的一种搭建 etcd 的方式。不像其他两种方式, static 方式不需要任何额外的服务,只需要你知道你准备用来运行 etcd 的所有节点(的name和ip)。
本例中,我们来看看如何在3个节点上构建 etcd
集群。
首先我们需要构造一个描述集群所有节点的参数,这个参数可以以命令行参数的方式传给 etcd
程序,也可以以环境变量的方式。
如果用命令行参数,应该将下列参数附在 etcd
的启动命令后面:
-initial-cluster etcd0=http://10.0.1.10:2380,etcd1=http://10.0.1.11:2380,etcd2=http://10.0.1.12:2380 \
-initial-cluster-state new
其中 -initial-cluster-state new
表示这是在从无到有搭建 etcd 集群。
-initial-cluster
参数描述了这个新集群中总共有哪些节点,其中每个节点用 name=ip
的形式描述,节点之间用,
分隔。
如果用环境变量,应该在启动 etcd
时,加入如下环境变量:
ETCD_INITIAL_CLUSTER="etcd0=http://10.0.1.10:2380,etcd1=http://10.0.1.11:2380,etcd2=http://10.0.1.12:2380"
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_INITIAL_CLUSTER
变量和 -initial-cluster
作用相同,
ETCD_INITIAL_CLUSTER_STATE
变量和 -initial-cluster-state
作用相同。
接着,分别在3个节点上启动 etcd
,以命令行参数方式启动为例:
$ etcd -name etcd0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
-listen-peer-urls http://10.0.1.10:2380 \
-listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.10:2379 \
-initial-cluster-token my-etcd-cluster \
-initial-cluster etcd0=http://10.0.1.10:2380,etcd1=http://10.0.1.11:2380,etcd2=http://10.0.1.12:2380 \
-initial-cluster-state new
$ etcd -name etcd1 -initial-advertise-peer-urls http://10.0.1.11:2380 \
-listen-peer-urls http://10.0.1.11:2380 \
-listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.11:2379 \
-initial-cluster-token my-etcd-cluster \
-initial-cluster etcd0=http://10.0.1.10:2380,etcd1=http://10.0.1.11:2380,etcd2=http://10.0.1.12:2380 \
-initial-cluster-state new
$ etcd -name etcd2 -initial-advertise-peer-urls http://10.0.1.12:2380 \
-listen-peer-urls http://10.0.1.12:2380 \
-listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.12:2379 \
-initial-cluster-token my-etcd-cluster \
-initial-cluster etcd0=http://10.0.1.10:2380,etcd1=http://10.0.1.11:2380,etcd2=http://10.0.1.12:2380 \
-initial-cluster-state new
注意
值得注意的是,无论是 -initial-cluster
参数,还是对应的环境变量,只有在第一次启动 etcd
的时候才起作用。
之后如果重启 etcd
,这个参数或环境变量会被自动忽略。所以当成功初始化了一个 etcd
集群以后,你就不在需要这个参数或环境变量了。
2.2 etcd discovery 方式
很多时候,你只知道你要搭建一个多大(包含多少节点)的集群,但是并不能事先知道这几个节点的 ip,从而无法使用 -initial-cluster
参数。
这个时候,你就需要使用 discovery
的方式来搭建 etcd
集群。discovery 方式有两种:etcd discovery
和 DNS discovery
。
这里我们先介绍下 etcd discovery
方式,etcd discovery
有两种:自定义的 etcd discovery
和 公共 etcd discovery
2.2.1 自定义的 etcd discovery 服务
这种方式就是利用一个已有的 etcd
集群来提供 discovery
服务,从而搭建一个新的 etcd
集群。
假设已有的 etcd
集群的一个访问地址是:myetcd.local
,那么我们首先需要在已有 etcd
中创建一个特殊的 key,方法如下:
$ curl -X PUT https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/_config/size -d value=3
其中 value=3
表示本集群的大小,即: 有多少集群节点。而6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
就是用来做 discovery 的 token。
接下来你在 3 个节点上分别启动 etcd
程序,并加上刚刚的 token。
加 token 的方式同样也有 命令行参数 和 环境变量 两种。
命令行参数:
-discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
环境变量
ETCD_DISCOVERY=https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
以命令行参数启动方式为例:
$ etcd -name etcd0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
-listen-peer-urls http://10.0.1.10:2380 \
-listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.10:2379 \
-discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
$ etcd -name etcd1 -initial-advertise-peer-urls http://10.0.1.11:2380 \
-listen-peer-urls http://10.0.1.11:2380 \
-listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.11:2379 \
-discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
$ etcd -name etcd2 -initial-advertise-peer-urls http://10.0.1.12:2380 \
-listen-peer-urls http://10.0.1.12:2380 \
-listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.12:2379 \
-discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
2.2.2 公共 etcd discovery 服务
如果没有已有的 etcd
集群,也可以用 etcd 提供的公共服务: discovery.etcd.io
。
步骤和 2.2.1 节基本一致。
你得先创建一个用于 discovery 的 token,创建方式如下:
$ curl https://discovery.etcd.io/new?size=3
返回:
https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
返回值作为启动节点时的 -discovery
参数或者 ETCD_DISCOVERY
环境变量的值。
以环境变量启动方式为例:
$ ETCD_DISCOVERY=https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de \
etcd -name etcd0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
-listen-peer-urls http://10.0.1.10:2380 \
-listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.10:2379 \
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
$ ETCD_DISCOVERY=https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de \
etcd -name etcd1 -initial-advertise-peer-urls http://10.0.1.11:2380 \
-listen-peer-urls http://10.0.1.11:2380 \
-listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.11:2379 \
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
$ ETCD_DISCOVERY=https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de \
etcd -name etcd2 -initial-advertise-peer-urls http://10.0.1.12:2380 \
-listen-peer-urls http://10.0.1.12:2380 \
-listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
-advertise-client-urls http://10.0.1.12:2379 \
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
2.2.3 注意点
值得注意的是:如果实际启动的 etcd 节点个数大于
discovery token创建时指定的size
,
多余的节点会自动变为 proxy
节点。
2.3 DNS discovery 方式
这个方式没有实践,而且对于一般团队实用性也不高,所以就不做分享了。