Linux.中国 - 开源社区

 找回密码
 骑士注册

QQ登录

微博登录


etcd:从应用场景到实现原理的全方位解读

2015-2-3 09:57    收藏: 5 分享: 5    

4 集群化应用实践

etcd作为一个高可用键值存储系统,天生就是为集群化而设计的。由于Raft算法在做决策时需要多数节点的投票,所以etcd一般部署集群推荐奇数个节点,推荐的数量为3、5或者7个节点构成一个集群。

4.1 集群启动

etcd有三种集群化启动的配置方案,分别为静态配置启动、etcd自身服务发现、通过DNS进行服务发现。

通过配置内容的不同,你可以对不同的方式进行选择。值得一提的是,这也是新版etcd区别于旧版的一大特性,它摒弃了使用配置文件进行参数配置的做法,转而使用命令行参数或者环境变量的做法来配置参数。

4.1.1. 静态配置

这种方式比较适用于离线环境,在启动整个集群之前,你就已经预先清楚所要配置的集群大小,以及集群上各节点的地址和端口信息。那么启动时,你就可以通过配置initial-cluster参数进行etcd集群的启动。

在每个etcd机器启动时,配置环境变量或者添加启动参数的方式如下。

ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380"
ETCD_INITIAL_CLUSTER_STATE=new

参数方法:

-initial-cluster 
infra0=http://10.0.1.10:2380,http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
 -initial-cluster-state new

值得注意的是,-initial-cluster参数中配置的url地址必须与各个节点启动时设置的initial-advertise-peer-urls参数相同。(initial-advertise-peer-urls参数表示节点监听其他节点同步信号的地址)

如果你所在的网络环境配置了多个etcd集群,为了避免意外发生,最好使用-initial-cluster-token参数为每个集群单独配置一个token认证。这样就可以确保每个集群和集群的成员都拥有独特的ID。

综上所述,如果你要配置包含3个etcd节点的集群,那么你在三个机器上的启动命令分别如下所示。

$ etcd -name infra0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
  -listen-peer-urls http://10.0.1.10:2380 \
  -initial-cluster-token etcd-cluster-1 \
  -initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
  -initial-cluster-state new

$ etcd -name infra1 -initial-advertise-peer-urls http://10.0.1.11:2380 \
  -listen-peer-urls http://10.0.1.11:2380 \
  -initial-cluster-token etcd-cluster-1 \
  -initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
  -initial-cluster-state new

$ etcd -name infra2 -initial-advertise-peer-urls http://10.0.1.12:2380 \
  -listen-peer-urls http://10.0.1.12:2380 \
  -initial-cluster-token etcd-cluster-1 \
  -initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
  -initial-cluster-state new

在初始化完成后,etcd还提供动态增、删、改etcd集群节点的功能,这个需要用到etcdctl命令进行操作。

4.1.2. etcd自发现模式

通过自发现的方式启动etcd集群需要事先准备一个etcd集群。如果你已经有一个etcd集群,首先你可以执行如下命令设定集群的大小,假设为3.

$ curl -X PUT http://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/_config/size -d value=3

然后你要把这个url地址http://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83作为-discovery参数来启动etcd。节点会自动使用http://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83目录进行etcd的注册和发现服务。

所以最终你在某个机器上启动etcd的命令如下。

$ etcd -name infra0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
  -listen-peer-urls http://10.0.1.10:2380 \
  -discovery http://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83

如果你本地没有可用的etcd集群,etcd官网提供了一个可以公网访问的etcd存储地址。你可以通过如下命令得到etcd服务的目录,并把它作为-discovery参数使用。

$ curl http://discovery.etcd.io/new?size=3
http://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de

同样的,当你完成了集群的初始化后,这些信息就失去了作用。当你需要增加节点时,需要使用etcdctl来进行操作。

为了安全,请务必每次启动新etcd集群时,都使用新的discovery token进行注册。另外,如果你初始化时启动的节点超过了指定的数量,多余的节点会自动转化为Proxy模式的etcd。

4.1.3. DNS自发现模式

etcd还支持使用DNS SRV记录进行启动。关于DNS SRV记录如何进行服务发现,可以参阅RFC2782,所以,你要在DNS服务器上进行相应的配置。

(1) 开启DNS服务器上SRV记录查询,并添加相应的域名记录,使得查询到的结果类似如下。

$ dig +noall +answer SRV _etcd-server._tcp.example.com
_etcd-server._tcp.example.com. 300 IN   SRV 0 0 2380 infra0.example.com.
_etcd-server._tcp.example.com. 300 IN   SRV 0 0 2380 infra1.example.com.
_etcd-server._tcp.example.com. 300 IN   SRV 0 0 2380 infra2.example.com.

(2) 分别为各个域名配置相关的A记录指向etcd核心节点对应的机器IP。使得查询结果类似如下。

$ dig +noall +answer infra0.example.com infra1.example.com infra2.example.com
infra0.example.com. 300 IN  A   10.0.1.10
infra1.example.com. 300 IN  A   10.0.1.11
infra2.example.com. 300 IN  A   10.0.1.12

做好了上述两步DNS的配置,就可以使用DNS启动etcd集群了。配置DNS解析的url参数为-discovery-srv,其中某一个节点地启动命令如下。

$ etcd -name infra0 \
-discovery-srv example.com \
-initial-advertise-peer-urls http://infra0.example.com:2380 \
-initial-cluster-token etcd-cluster-1 \
-initial-cluster-state new \
-advertise-client-urls http://infra0.example.com:2379 \
-listen-client-urls http://infra0.example.com:2379 \
-listen-peer-urls http://infra0.example.com:2380

当然,你也可以直接把节点的域名改成IP来启动。

4.2 关键部分源码解析

etcd的启动是从主目录下的main.go开始的,然后进入etcdmain/etcd.go,载入配置参数。如果被配置为Proxy模式,则进入startProxy函数,否则进入startEtcd,开启etcd服务模块和http请求处理模块。

在启动http监听时,为了保持与集群其他etcd机器(peers)保持连接,都采用的transport.NewTimeoutListener启动方式,这样在超过指定时间没有获得响应时就会出现超时错误。而在监听client请求时,采用的是transport.NewKeepAliveListener,有助于连接的稳定。

在etcdmain/etcd.go中的setupCluster函数可以看到,根据不同etcd的参数,启动集群的方法略有不同,但是最终需要的就是一个IP与端口构成的字符串。

在静态配置的启动方式中,集群的所有信息都已经在给出,所以直接解析用逗号隔开的集群url信息就好了。

DNS发现的方式类似,会预先发送一个tcp的SRV请求,先查看etcd-server-ssl._tcp.example.com下是否有集群的域名信息,如果没有找到,则去查看etcd-server._tcp.example.com。根据找到的域名,解析出对应的IP和端口,即集群的url信息。

较为复杂是etcd式的自发现启动。首先就用自身单个的url构成一个集群,然后在启动的过程中根据参数进入discovery/discovery.go源码的JoinCluster函 数。因为我们事先是知道启动时使用的etcd的token地址的,里面包含了集群大小(size)信息。在这个过程其实是个不断监测与等待的过程。启动的 第一步就是在这个etcd的token目录下注册自身的信息,然后再监测token目录下所有节点的数量,如果数量没有达标,则循环等待。当数量达到要求 时,才结束,进入正常的启动过程。

配置etcd过程中通常要用到两种url地址容易混淆,一种用于etcd集群同步信息并保持连接,通常称为peer-urls;另外一种用于接收用户端发来的HTTP请求,通常称为client-urls。

  • peer-urls:通常监听的端口为2380(老版本使用的端口为7001),包括所有已经在集群中正常工作的所有节点的地址。
  • client-urls:通常监听的端口为2379(老版本使用的端口为4001),为适应复杂的网络环境,新版etcd监听客户端请求的url从原来的1个变为现在可配置的多个。这样etcd可以配合多块网卡同时监听不同网络下的请求。

4.3 运行时节点变更

etcd集群启动完毕后,可以在运行的过程中对集群进行重构,包括核心节点的增加、删除、迁移、替换等。运行时重构使得etcd集群无须重启即可改变集群的配置,这也是新版etcd区别于旧版包含的新特性。

只有当集群中多数节点正常的情况下,你才可以进行运行时的配置管理。因为配置更改的信息也会被etcd当成一个信息存储和同步,如果集群多数节点损坏,集群就失去了写入数据的能力。所以在配置etcd集群数量时,强烈推荐至少配置3个核心节点。

4.3.1. 节点迁移、替换

当你节点所在的机器出现硬件故障,或者节点出现如数据目录损坏等问题,导致节点永久性的不可恢复时,就需要对节点进行迁移或者替换。当一个节点失效以后,必须尽快修复,因为etcd集群正常运行的必要条件是集群中多数节点都正常工作。

迁移一个节点需要进行四步操作:

  • 暂停正在运行着的节点程序进程
  • 把数据目录从现有机器拷贝到新机器
  • 使用api更新etcd中对应节点指向机器的url记录更新为新机器的ip
  • 使用同样的配置项和数据目录,在新的机器上启动etcd。

4.3.2. 节点增加

增加节点可以让etcd的高可用性更强。举例来说,如果你有3个节点,那么最多允许1个节点失效;当你有5个节点时,就可以允许有2个节点失效。同 时,增加节点还可以让etcd集群具有更好的读性能。因为etcd的节点都是实时同步的,每个节点上都存储了所有的信息,所以增加节点可以从整体上提升读 的吞吐量。

增加一个节点需要进行两步操作:

  • 在集群中添加这个节点的url记录,同时获得集群的信息。
  • 使用获得的集群信息启动新etcd节点。

4.3.3. 节点移除

有时你不得不在提高etcd的写性能和增加集群高可用性上进行权衡。Leader节点在提交一个写记录时,会把这个消息同步到每个节点上,当得到多数节点的同意反馈后,才会真正写入数据。所以节点越多,写入性能越差。在节点过多时,你可能需要移除一个或多个。

移除节点非常简单,只需要一步操作,就是把集群中这个节点的记录删除。然后对应机器上的该节点就会自动停止。

4.3.4. 强制性重启集群

当集群超过半数的节点都失效时,就需要通过手动的方式,强制性让某个节点以自己为Leader,利用原有数据启动一个新集群。

此时你需要进行两步操作。

  • 备份原有数据到新机器。
  • 使用-force-new-cluster加备份的数据重新启动节点

注意:强制性重启是一个迫不得已的选择,它会破坏一致性协议保证的安全性(如果操作时集群中尚有其它节点在正常工作,就会出错),所以在操作前请务必要保存好数据。

查看其它分页:

发表评论


最新评论

我也要发表评论

返回顶部

分享到微信朋友圈

打开微信,点击底部的“发现”,
使用“扫一扫”将网页分享至朋友圈。