14

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 discoveryDNS 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 方式

这个方式没有实践,而且对于一般团队实用性也不高,所以就不做分享了。

2.4 后续

到这里为止,我们已经有一个3节点的 etcd 集群了,下一篇博客我会介绍如何进行 etcd 集群的管理

--

更多文章欢迎关注自由风暴博客


Michael_Ding
1.1k 声望79 粉丝

开源爱好者,技术爱好者,爱动手,爱实践