搭建完 etcd
集群后,接下来就是集群的管理了。集群的管理主要包括节点的重启,监控以及集群的运行时更改(Runtime Reconfiguration)。
关于节点的重启、监控相对来说比较简单,这里主要介绍下集群的运行时更改。
1. 在什么情况下需要集群的运行时更改?
让我们来看看需要集群的运行时更改的几个场景。他们中的绝大多数只需要运用到重配置中的 “添加/删除” 节点操作的组合。
1.1. 维护和升级多个机器
如果你因为进行诸如硬件升级或者断网等计划维护,而需要移动多个节点到新机器上,最好是逐个节点移动,一次操作一个。
移动 leader 节点是安全的,只不过 leader 节点下线后,需要耗费更多的时间选举新节点,所以建议最后移动。
如果你的集群有超过 50M 的数据,最好进行节点的迁移(见3.1节 迁移节点),而不要通过删除旧节点,增加新节点来实现节点的移动。
1.2. 更改集群的大小
如上一篇博客所说的,增加集群节点的个数,容错能力越强,读性能也越好。不过相应的,写性能也会下降。减少集群节点的个数,容错能力下降,不过写性能也会提高。
更改集群大小也需要集群运行时更改。
1.3. 替换一个坏掉的节点
如果一个节点的机器因为硬件出错而宕机了,那需要尽快用新机器替换。替换的操作就是简单地分为两步:(通过集群运行时更改)先删除坏掉的节点,再添加新的节点(见2节 集群节点的操作)。不过,如果你的集群有超过 50M 的数据,最好进行节点迁移(见3.1节 迁移节点)
1.4. 集群多数宕机(Majority Failure)后的重启
如果你的集群出现了多数宕机(例如超过(N-1)/2的节点当机),或者所有的节点都更改了 IP,你就需要手动操作,重启(恢复)集群了。基本步骤包括:1.基于原先的数据创建新集群;2.强制让一个节点成为 leader
节点,并最终通过运行时更改添加新节点的方式将其他节点添加到这个新的集群中。
2. 集群运行时更改的操作
知道了什么样的情况下需要运行时更改,下面让我们来了解下具体的运行时更改的操作。
一般来说,这些操作需要确保集群的多数节点是正常服务的,并且一次只操作一个节点。
升级单个节点的 peerURLs,需要执行一个更新节点操作
替换一个节点,需要先执行一个添加节点操作,再执行一个删除节点操作
将集群大小从 3 更改到 5,需要执行两个添加节点操作
将集群大小从 5 降低到 3,需要执行两个删除节点操作
下面的所有例子都是利用 etcdctl
命令实现操作,其本质是调用 etcd
的 REST API。你也可以使用其他你习惯的客户端。
2.1 更新一个节点
如果你想更新一个节点的 IP(peerURLS),首先你需要知道那个节点的 ID。你可以列出所有节点,找出对应节点的 ID。
$ etcdctl member list
6e3bd23ae5f1eae0: name=node2 peerURLs=http://localhost:23802 clientURLs=http://127.0.0.1:23792
924e2e83e93f2560: name=node3 peerURLs=http://localhost:23803 clientURLs=http://127.0.0.1:23793
a8266ecf031671f3: name=node1 peerURLs=http://localhost:23801 clientURLs=http://127.0.0.1:23791
在本例中,我们假设要更新 ID 为 a8266ecf031671f3
的节点的 peerURLs 为:http://10.0.1.10:2380
$ etcdctl member update a8266ecf031671f3 http://10.0.1.10:2380
Updated member with ID a8266ecf031671f3 in cluster
2.2 删除一个节点
假设我们要删除 ID 为 a8266ecf031671f3
的节点
$ etcdctl member remove a8266ecf031671f3
Removed member a8266ecf031671f3 from cluster
执行完后,目标节点会自动停止服务,并且打印一行日志:
etcd: this member has been permanently removed from the cluster. Exiting.
如果删除的是 leader
节点,则需要耗费额外的时间重新选举 leader
。
2.3 增加一个新的节点
增加一个新的节点分为两步:
通过
etcdctl
或对应的 API 注册新节点使用恰当的参数启动新节点
先看第一步,假设我们要新加的节点取名为 infra3, peerURLs
是 http://10.0.1.13:2380
$ etcdctl member add infra3 http://10.0.1.13:2380
added member 9bf1b35fc7761a23 to cluster
ETCD_NAME="infra3"
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
ETCD_INITIAL_CLUSTER_STATE=existing
etcdctl
在注册完新节点后,会返回一段提示,包含3个环境变量。然后在第二部启动新节点的时候,带上这3个环境变量即可。
$ export ETCD_NAME="infra3"
$ export ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
$ export ETCD_INITIAL_CLUSTER_STATE=existing
$ etcd -listen-client-urls http://10.0.1.13:2379 -advertise-client-urls http://10.0.1.13:2379 -listen-peer-urls http://10.0.1.13:2380 -initial-advertise-peer-urls http://10.0.1.13:2380 -data-dir %data_dir%
这样,新节点就会运行起来并且加入到已有的集群中了。
值得注意的是,如果原先的集群只有1个节点,在新节点成功启动之前,新集群并不能正确的形成。因为原先的单节点集群无法完成leader
的选举。
直到新节点启动完,和原先的节点建立连接以后,新集群才能正确形成。
3. 迁移节点和灾难恢复
3.1 迁移节点
移动节点有两种方式:1. 删除旧的节点,增加新的节点; 2. 迁移节点。当集群的数据超过 50M 的时候,建议通过迁移节点的方式来移动节点。
迁移节点的核心就是数据目录的迁移。因为 etcd 的各个节点会将自己的 ID 存放在自己的数据目录下面,所以迁移节点不会改变节点的 ID。
迁移节点的步骤简单来说,包括以下几步:
停止需要迁移的节点的服务
从老机器上拷贝数据目录到新机器上
通过集群运行时更改的更新操作,改变节点的 peerURLs 值为新机器的 IP:port
在新机器上指定拷贝过来的数据目录,启动 etcd 的节点服务
下面通过一个例子具体说明。
假设我们已有的集群是这样的:
name | peerURLs |
---|---|
infra0 | 10.0.1.10:2380 |
infra1 | 10.0.1.11:2380 |
infra2 | 10.0.1.12:2380 |
$ etcdctl member list
84194f7c5edd8b37: name=infra0 peerURLs=http://10.0.1.10:2380 clientURLs=http://127.0.0.1:2379,http://10.0.1.10:2379
b4db3bf5e495e255: name=infra1 peerURLs=http://10.0.1.11:2380 clientURLs=http://127.0.0.1:2379,http://10.0.1.11:2379
bc1083c870280d44: name=infra2 peerURLs=http://10.0.1.12:2380 clientURLs=http://127.0.0.1:2379,http://10.0.1.12:2379
我们要移动 infra1 从 10.0.1.11 到 10.0.1.13
1. 停止 infra1 的 etcd
进程
$ssh 10.0.1.11
$ kill `pgrep etcd`
2. 从 10.0.1.11 拷贝etcd的数据目录到 10.0.1.13 的机器上
$ tar -cvzf infra1.etcd.tar.gz %data_dir%
$ scp infra1.etcd.tar.gz 10.0.1.13:~/
3. 变更 infra1 的 peerURLs
$ curl http://10.0.1.10:2379/v2/members/b4db3bf5e495e255 -XPUT \
-H "Content-Type: application/json" -d '{"peerURLs":["http://10.0.1.13:2380"]}'
或者利用 etcdctl
etcdctl member update b4db3bf5e495e255 http://10.0.1.13:2380
4. 在新机器上使用 infra1 的数据和配置启动 etcd
$ ssh 10.0.1.13
$ tar -xzvf infra1.etcd.tar.gz -C %data_dir%
$ etcd -name infra1 \
> -listen-peer-urls http://10.0.1.13:2380 \
> -listen-client-urls http://10.0.1.13:2379,http://127.0.0.1:2379 \
> -advertise-client-urls http://10.0.1.13:2379,http://127.0.0.1:2379
3.2 灾难恢复
总的来说,etcd 的集群还是相当可靠的,但是也不能排除极端情况的出现。当出现灾难性的多数节点宕机,就不得不进行灾难恢复了。
灾难恢复需要以下几个步骤:
1 备份数据
备份操作需要在一台还'活着'的节点上进行
$ etcdctl backup \
--data-dir %data_dir% \
--backup-dir %backup_data_dir%
这个命令会备份原数据到 %backup_data_dir% 目录下,并重新相关的元数据(例如 节点的 id 和 集群的 id)。
这意味着在 %backup_data_dir% 中只包含原先的数据,而不包含原先的身份信息。
接下来我们就可以基于备份的数据创建一个单节点的集群。
2 从备份数据中重建单节点集群
$ etcd \
-data-dir=%backup_data_dir% \
-force-new-cluster \
...
...
部分省略了其他相关的参数,例如-peer-urls
-client-urls
等等
这时候,应该就成功创建了一个新的只包含一个节点的集群,并包含之前的所有数据。
当你确认新集群正常后,就可以删除原来集群的数据,暂停新集群,将新集群的数据目录拷贝回原先数据的位置,并重新启动。
$ pkill etcd
$ rm -rf %data_dir%
$ mv %backup_data_dir% %data_dir%
$ etcd \
-data-dir=%data_dir% \
...
3 恢复集群
现在已经有了一个拥有之前数据的单节点的集群了。接下来,你可以通过添加节点的操作,重建出一个同样大小的集群。
值得注意的是,如果你还是使用之前的其他机器来重建这个新的集群,一定杀掉之前的etcd 进程,并且清除掉之前的数据。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。