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

来源:互联网 发布:淘宝主号怎么关联小号 编辑:程序博客网 时间:2024/06/03 17:07

随着CoreOS和Kubernetes等项目在开源社区日益火热,它们项目中都用到的etcd组件作为一个高可用强一致性的服务发现存储仓库,渐渐为开发人员所关注。在云计算时代,如何让服务快速透明地接入到计算集群中,如何让共享配置信息快速被集群中的所有机器发现,更为重要的是,如何构建这样一套高可用、安全、易于部署以及响应快速的服务集群,已经成为了迫切需要解决的问题。etcd为解决这类问题带来了福音,本文将从etcd的应用场景开始,深入解读etcd的实现方式,以供开发者们更为充分地享用etcd所带来的便利。

经典应用场景

要问etcd是什么?很多人第一反应可能是一个键值存储仓库,却没有重视官方定义的后半句,用于配置共享和服务发现。

A highly-available key value store for shared configuration and service discovery.

实际上,etcd作为一个受到ZooKeeper与doozer启发而催生的项目,除了拥有与之类似的功能外,更专注于以下四点。

  • 简单:基于HTTP+JSON的API让你用curl就可以轻松使用。
  • 安全:可选SSL客户认证机制。
  • 快速:每个实例每秒支持一千次写操作。
  • 可信:使用Raft算法充分实现了分布式。

随着云计算的不断发展,分布式系统中涉及到的问题越来越受到人们重视。受阿里中间件团队对ZooKeeper典型应用场景一览一文的启发,笔者根据自己的理解也总结了一些etcd的经典使用场景。让我们来看看etcd这个基于Raft强一致性算法的分布式存储仓库能给我们带来哪些帮助。

值得注意的是,分布式系统中的数据分为控制数据和应用数据。使用etcd的场景默认处理的数据都是控制数据,对于应用数据,只推荐数据量很小,但是更新访问频繁的情况

场景一:服务发现(Service Discovery)

服务发现要解决的也是分布式系统中最常见的问题之一,即在同一个分布式集群中的进程或服务,要如何才能找到对方并建立连接。本质上来说,服务发现就 是想要了解集群中是否有进程在监听udp或tcp端口,并且通过名字就可以查找和连接。要解决服务发现的问题,需要有下面三大支柱,缺一不可。

  1. 一个强一致性、高可用的服务存储目录。基于Raft算法的etcd天生就是这样一个强一致性高可用的服务存储目录。
  2. 一种注册服务和监控服务健康状态的机制。用户可以在etcd中注册服务,并且对注册的服务设置key TTL,定时保持服务的心跳以达到监控健康状态的效果。
  3. 一种查找和连接服务的机制。通过在etcd指定的主题下注册的服务也能在对应的主题下查找到。为了确保连接,我们可以在每个服务机器上都部署一个Proxy模式的etcd,这样就可以确保能访问etcd集群的服务都能互相连接。

  4. 图1 服务发现示意图

    下面我们来看服务发现对应的具体场景。

    • 微服务协同工作架构中,服务动态添加。随着Docker容器的流行,多种微服务共同协作,构成一个相对功能 强大的架构的案例越来越多。透明化的动态添加这些服务的需求也日益强烈。通过服务发现机制,在etcd中注册某个服务名字的目录,在该目录下存储可用的服 务节点的IP。在使用服务的过程中,只要从服务目录下查找可用的服务节点去使用即可。

    图2 微服务协同工作

    • PaaS平台中应用多实例与实例故障重启透明化。PaaS平台中的应用一般都有多个实例,通过域名,不仅可以透明的对这多个实例进行访问,而且还可以做到负载均衡。但是应用的某个实例随时都有可能故障重启,这时就需要动态的配置域名解析(路由)中的信息。通过etcd的服务发现功能就可以轻松解决这个动态配置的问题。

    图3 云平台多实例透明化

    场景二:消息发布与订阅

    在分布式系统中,最适用的一种组件间通信方式就是消息发布与订阅。即构建一个配置共享中心,数据提供者在这个配置中心发布消息,而消息使用者则订阅他们关心的主题,一旦主题有消息发布,就会实时通知订阅者。通过这种方式可以做到分布式系统配置的集中式管理与动态更新。

    • 应用中用到的一些配置信息放到etcd上进行集中管理。这类场景的使用方式通常是这样:应用在启动的时候主动从etcd获取一次配置信息,同时,在etcd节点上注册一个Watcher并等待,以后每次配置有更新的时候,etcd都会实时通知订阅者,以此达到获取最新配置信息的目的。
    • 分布式搜索服务中,索引的元信息和服务器集群机器的节点状态存放在etcd中,供各个客户端订阅使用。使用etcd的key TTL功能可以确保机器状态是实时更新的。
    • 分布式日志收集系统。这个系统的核心工作是收集分布在不同机器的日志。收集器通常是按照应用(或主题)来分 配收集任务单元,因此可以在etcd上创建一个以应用(主题)命名的目录P,并将这个应用(主题相关)的所有机器ip,以子目录的形式存储到目录P上,然 后设置一个etcd递归的Watcher,递归式的监控应用(主题)目录下所有信息的变动。这样就实现了机器IP(消息)变动的时候,能够实时通知到收集 器调整任务分配。
    • 系统中信息需要动态自动获取与人工干预修改信息请求内容的情况。通常是暴露出接口,例如JMX接口,来获取一些运行时的信息。引入etcd之后,就不用自己实现一套方案了,只要将这些信息存放到指定的etcd目录中即可,etcd的这些目录就可以通过HTTP的接口在外部访问。

    图4 消息发布与订阅

    场景三:负载均衡

    在场景一中也提到了负载均衡,本文所指的负载均衡均为软负载均衡。分布式系统中,为了保证服务的高可用以及数据的一致 性,通常都会把数据和服务部署多份,以此达到对等服务,即使其中的某一个服务失效了,也不影响使用。由此带来的坏处是数据写入性能下降,而好处则是数据访 问时的负载均衡。因为每个对等服务节点上都存有完整的数据,所以用户的访问流量就可以分流到不同的机器上。

    • etcd本身分布式架构存储的信息访问支持负载均衡。etcd集群化以后,每个etcd的核心节点都可以处 理用户的请求。所以,把数据量小但是访问频繁的消息数据直接存储到etcd中也是个不错的选择,如业务系统中常用的二级代码表(在表中存储代码,在 etcd中存储代码所代表的具体含义,业务系统调用查表的过程,就需要查找表中代码的含义)。
    • 利用etcd维护一个负载均衡节点表。etcd可以监控一个集群中多个节点的状态,当有一个请求发过来后,可以轮询式的把请求转发给存活着的多个状态。类似KafkaMQ,通过ZooKeeper来维护生产者和消费者的负载均衡。同样也可以用etcd来做ZooKeeper的工作。

    图5 负载均衡

    场景四:分布式通知与协调

    这里说到的分布式通知与协调,与消息发布和订阅有些相似。都用到了etcd中的Watcher机制,通过注册与异步通知机制,实现分布式环境下不同 系统之间的通知与协调,从而对数据变更做到实时处理。实现方式通常是这样:不同系统都在etcd上对同一个目录进行注册,同时设置Watcher观测该目 录的变化(如果对子目录的变化也有需要,可以设置递归模式),当某个系统更新了etcd的目录,那么设置了Watcher的系统就会收到通知,并作出相应 处理。

    • 通过etcd进行低耦合的心跳检测。检测系统和被检测系统通过etcd上某个目录关联而非直接关联起来,这样可以大大减少系统的耦合性。
    • 通过etcd完成系统调度。某系统有控制台和推送系统两部分组成,控制台的职责是控制推送系统进行相应的推送工作。管理人员在控制台作的一些操作,实际上是修改了etcd上某些目录节点的状态,而etcd就把这些变化通知给注册了Watcher的推送系统客户端,推送系统再作出相应的推送任务。
    • 通过etcd完成工作汇报。大部分类似的任务分发系统,子任务启动后,到etcd来注册一个临时工作目录,并且定时将自己的进度进行汇报(将进度写入到这个临时目录),这样任务管理者就能够实时知道任务进度。

    图6 分布式协同工作

    场景五:分布式锁

    因为etcd使用Raft算法保持了数据的强一致性,某次操作存储到集群中的值必然是全局一致的,所以很容易实现分布式锁。锁服务有两种使用方式,一是保持独占,二是控制时序。

    • 保持独占即所有获取锁的用户最终只有一个可以得到。etcd为此提供了一套实现分布式锁原子操作CAS(CompareAndSwap)的API。通过设置prevExist值,可以保证在多个节点同时去创建某个目录时,只有一个成功。而创建成功的用户就可以认为是获得了锁。
    • 控制时序,即所有想要获得锁的用户都会被安排执行,但是获得锁的顺序也是全局唯一的,同时决定了执行顺序。etcd为此也提���了一套API(自动创建有序键),对一个目录建值时指定为POST动作,这样etcd会自动在目录下生成一个当前最大的值为键,存储这个新的值(客户端编号)。同时还可以使用API按顺序列出所有当前目录下的键值。此时这些键的值就是客户端的时序,而这些键中存储的值可以是代表客户端的编号。

    图7 分布式锁

    场景六:分布式队列

    分布式队列的常规用法与场景五中所描述的分布式锁的控制时序用法类似,即创建一个先进先出的队列,保证顺序。

    另一种比较有意思的实现是在保证队列达到某个条件时再统一按顺序执行。这种方法的实现可以在/queue这个目录中另外建立一个/queue/condition节点。

    • condition可以表示队列大小。比如一个大的任务需要很多小任务就绪的情况下才能执行,每次有一个小任务就绪,就给这个condition数字加1,直到达到大任务规定的数字,再开始执行队列里的一系列小任务,最终执行大任务。
    • condition可以表示某个任务在不在队列。这个任务可以是所有排序任务的首个执行程序,也可以是拓扑结构中没有依赖的点。通常,必须执行这些任务后才能执行队列中的其他任务。
    • condition还可以表示其它的一类开始执行任务的通知。可以由控制程序指定,当condition出现变化时,开始执行队列任务。

    图8 分布式队列

    场景七:集群监控与Leader竞选

    通过etcd来进行监控实现起来非常简单并且实时性强。

    1. 前面几个场景已经提到Watcher机制,当某个节点消失或有变动时,Watcher会第一时间发现并告知用户。
    2. 节点可以设置TTL key,比如每隔30s发送一次心跳使代表该机器存活的节点继续存在,否则节点消失。

    这样就可以第一时间检测到各节点的健康状态,以完成集群的监控要求。

    另外,使用分布式锁,可以完成Leader竞选。这种场景通常是一些长时间CPU计算或者使用IO操作的机器,只需要竞选出的Leader计算或处理一次,就可以把结果复制给其他的Follower。从而避免重复劳动,节省计算资源。

    这个的经典场景是搜索系统中建立全量索引。如果每个机器都进行一遍索引的建立,不但耗时而且建立索引的一致性不能保证。通过在etcd的CAS机制同时创建一个节点,创建成功的机器作为Leader,进行索引计算,然后把计算结果分发到其它节点。

    图9 Leader竞选

    场景八:为什么用etcd而不用ZooKeeper

    阅读了“ZooKeeper典型应用场景一览”一文的读者可能会发现,etcd实现的这些功能,ZooKeeper都能实现。那么为什么要用etcd而非直接使用ZooKeeper呢?

    相较之下,ZooKeeper有如下缺点:

    1. 复杂。ZooKeeper部署维护复杂,管理员需要掌握一系列的知识和技能;而Paxos强一致性算法也是素来以复杂难懂而闻名于世;另外,ZooKeeper的使用也比较复杂,需要安装客户端,官方只提供了Java和C两种语言的接口。
    2. Java编写。这里不是对Java有偏见,而是Java本身就偏向于重型应用,它会引入大量的依赖。而运维人员则普遍希望保持强一致、高可用的机器集群尽可能简单,维护起来也不易出错。
    3. 发展缓慢。Apache基金会项目特有的“Apache Way”在开源界饱受争议,其中一大原因就是由于基金会庞大的结构以及松散的管理导致项目发展缓慢。

    而etcd作为一个后起之秀,其优点也很明显。

    1. 简单。使用Go语言编写部署简单;使用HTTP作为接口使用简单;使用Raft算法保证强一致性让用户易于理解
    2. 数据持久化。etcd默认数据一更新就进行持久化。
    3. 安全。etcd支持SSL客户端安全认证。

    最后,etcd作为一个年轻的项目,真正告诉迭代和开发中,这既是一个优点,也是一个缺点。优点是它的未来具有无限的可能性,缺点是无法得到大项目 长时间使用的检验。然而,目前CoreOS、Kubernetes和CloudFoundry等知名项目均在生产环境中使用了etcd,所以总的来 说,etcd值得你去尝试。

    etcd实现原理解读

    上一节中,我们概括了许多etcd的经典场景,这一节,我们将从etcd的架构开始,深入到源码中解析etcd。

    1 架构

    图10 etcd架构图

    从etcd的架构图中我们可以看到,etcd主要分为四个部分。

    • HTTP Server: 用于处理用户发送的API请求以及其它etcd节点的同步与心跳信息请求。
    • Store:用于处理etcd支持的各类功能的事务,包括数据索引、节点状态变更、监控与反馈、事件处理与执行等等,是etcd对用户提供的大多数API功能的具体实现。
    • Raft:Raft强一致性算法的具体实现,是etcd的核心。
    • WAL:Write Ahead Log(预写式日志),是etcd的数据存储方式。除了在内存中存有所有数据的状态以及节点的索引以外,etcd就通过WAL进行持久化存储。WAL中, 所有的数据提交前都会事先记录日志。Snapshot是为了防止数据过多而进行的状态快照;Entry表示存储的具体日志内容。

    通常,一个用户的请求发送过来,会经由HTTP Server转发给Store进行具体的事务处理,如果涉及到节点的修改,则交给Raft模块进行状态的变更、日志的记录,然后再同步给别的etcd节点以确认数据提交,最后进行数据的提交,再次同步。

    2 新版etcd重要变更列表

    • 获得了IANA认证的端口,2379用于客户端通信,2380用于节点通信,与原先的(4001 peers / 7001 clients)共用。
    • 每个节点可监听多个广播地址。监听的地址由原来的一个扩展到多个,用户可以根据需求实现更加复杂的集群环境,如一个是公网IP,一个是虚拟机(容器)之类的私有IP。
    • etcd可以代理访问leader节点的请求,所以如果你可以访问任何一个etcd节点,那么你就可以无视网络的拓扑结构对整个集群进行读写操作。
    • etcd集群和集群中的节点都有了自己独特的ID。这样就防止出现配置混淆,不是本集群的其他etcd节点发来的请求将被屏蔽。
    • etcd集群启动时的配置信息目前变为完全固定,这样有助于用户正确配置和启动。
    • 运行时节点变化(Runtime Reconfiguration)。用户不需要重启 etcd 服务即可实现对 etcd 集群结构进行变更。启动后可以动态变更集群配置。
    • 重新设计和实现了Raft算法,使得运行速度更快,更容易理解,包含更多测试代码。
    • Raft日志现在是严格的只能向后追加、预写式日志系统,并且在每条记录中都加入了CRC校验码。
    • 启动时使用的_etcd/* 关键字不再暴露给用户
    • 废弃集群自动调整功能的standby模式,这个功能使得用户维护集群更困难。
    • 新增Proxy模式,不加入到etcd一致性集群中,纯粹进行代理转发。
    • ETCD_NAME(-name)参数目前是可选的,不再用于唯一标识一个节点。
    • 摒弃通过配置文件配置 etcd 属性的方式,你可以用环境变量的方式代替。
    • 通过自发现方式启动集群必须要提供集群大小,这样有助于用户确定集群实际启动的节点数量。

    3 etcd概念词汇表

    • Raft:etcd所采用的保证分布式系统强一致性的算法。
    • Node:一个Raft状态机实例。
    • Member: 一个etcd实例。它管理着一个Node,并且可以为客户端请求提供服务。
    • Cluster:由多个Member构成可以协同工作的etcd集群。
    • Peer:对同一个etcd集群中另外一个Member的称呼。
    • Client: 向etcd集群发送HTTP请求的客户端。
    • WAL:预写式日志,etcd用于持久化存储的日志格式。
    • snapshot:etcd防止WAL文件过多而设置的快照,存储etcd数据状态。
    • Proxy:etcd的一种模式,为etcd集群提供反向代理服务。
    • Leader:Raft算法中通过竞选而产生的处理所有数据提交的节点。
    • Follower:竞选失败的节点作为Raft中的从属节点,为算法提供强一致性保证。
    • Candidate:当Follower超过一定时间接收不到Leader的心跳时转变为Candidate开始竞选。
    • Term:某个节点成为Leader到下一次竞选时间,称为一个Term。
    • Index:数据项编号。Raft中通过Term和Index来定位数据。

    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=3http://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.cominfra0.example.com. 300 IN  A   10.0.1.10infra1.example.com. 300 IN  A   10.0.1.11infra2.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加备份的数据重新启动节点

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


0 0
原创粉丝点击