48小时系统班试听入口

【Linux运维实战技术】K8S的核心组件Etcd介绍

发布作者:新盟教育 发布日期:2023-02-22 浏览人数:902人

Linux运维实战技术

资源放送 

Etcd技术教程讲解

↓ 扫一扫 视频在线观看↓

Linux运维资料.png


Etcd简介

Etcd是采用Go语言编写的一个分布式key-value存储,它通过Raft协议进行leader选举和数据备份,对外提供高可用的数据存储,能有效应对网络问题和机器故障带来的数据丢失问题。同时它还可以提供服务发现、分布式锁、分布式数据队列、分布式通知和协调、集群选举等功能。

在kubernetes集群中,Etcd用于保存集群所有的网络配置和对象的状态信息。

Etcd主要解决的是分布式系统中数据一致性的问题,而分布式系统中的数据分为控制数据和应用数据,Etcd处理的数据类型为控制数据,对于很少量的应用数据也可以进行处理。

Etcd主要功能

  • 基本的key-value存储;

  • 监听机制;

  • key的过期及续约机制,用于监控和服务发现;

  • 原子CAS和CAD,用于分布式锁和leader选举.


Etcd特点

  • 完全复制:集群中的每个节点都可以使用完整的存档;

  • 高可用性:Etcd可用于避免硬件的单点故障或网络问题;

  • 一致性:每次读取都会返回跨多主机的最新写入;

  • 简单:包括一个定义良好、面向用户的API(gRPC);

  • 安全:实现了带有可选的客户端证书身份验证的自动化TLS;

  • 可靠:使用Raft算法实现了强一致、高可用的服务存储目录;

  • 监测变更:监测特定的键或目录以进行更改,并对值的变更做出反应;

  • 快速:根据官方提供的benchmark数据,单实例支持每秒2K+读操作.


Etcd集群中的术语

2.22-运维-1.png


Etcd架构及组件

2.22-运维-2.png


Etcd主要分为四个部分:http server、store、raft、WAL 。

HTTP Server:用于处理用户发送的API请求以及其他etcd节点的同步与心跳信息请求。

Store:用于处理etcd支持的各类功能的事务,包括数据索引、节点状态变更、监控与反馈、事件处理与执行等等,是etcd对用户提供的大多数API功能的具体实现。

Raft:Raft强一致性算法的具体实现,是etcd的核心。

WAL:Write Ahead Log(预写式日志/日志先行),是etcd的数据存储方式,也是一种实现事务日志的标准方法。etcd通过WAL进行持久化存储,所有的数据提交前都会事先记录日志。Snapshot是为了防止数据过多而进行的状态快照;Entry表示存储的具体日志内容。

Etcd工作原理

Raft协议

要理解Etcd分布式协同的工作原理,必须提到Raft算法。Raft算法是斯坦福的Diego Ongaro、John Ousterhout两人以易懂(Understandability)为目标设计的一致性共识算法。在此之前,提到共识算法(Consensus Algorithm)必然会提到Paxos,但是Paxos的实现和理解起来都非常复杂,以至于Raft算法提出者的博士论文中,作者提到,他们用了将近一年时间研究这个算法的各种解释,但还是没有完全理解这个算法。

Paxos的算法原理和真正实现也有很大的距离,实现Paxos的系统,如Chubby,对Paxos进行了很多的改进有优化,但是细节却是不为人所知的。

Raft协议采用分治的思想,把分布式协同的问题分为3个问题:

选举:一个新的集群启动时,或者老的leader故障时,会选举出一个新的leader。

日志同步:leader必须接受客户端的日志条目并且将他们同步到集群的所有机器。

安全:保证任何节点只要在它的状态机中生效了一条日志条目,就不会在相同的key上生效另一条日志条目。

一个Raft集群一般包含数个节点,典型的是5个,这样可以承受其中2个节点故障。每个节点实际上就是维护一个状态机,节点在任何时候都处于以下三个状态中的一个:

leader:负责日志的同步管理,处理来自客户端的请求,与Follower保持这heartBeat的联系。

follower:刚启动时所有节点为Follower状态,响应Leader的日志同步请求,响应Candidate的请求,把请求到Follower的事务转发给Leader。

candidate:负责选举投票,Raft刚启动时由一个节点从Follower转为Candidate发起选举,选举出Leader后从Candidate转为Leader状态。

状态机的转移图如下所示:

2.22-运维-3.png


节点启动以后,首先都是follower状态,在follower状态下,会有一个选举超时时间的计时器(这个时间是在配置的超时时间基础上加一个随机的时间得来的)。如果在这个时间内没有收到leader发送的心跳包,则节点状态会变成candidate状态,也就是变成了候选人,候选人会循环广播选举请求,如果超过半数的节点同意选举请求,则节点转化为leader状态。

如果在选举过程中,发现已经有了leader或者有更高的任期值的选举信息,则自动变成follower状态。处于leader状态的节点如果发现有更高任期值的leader存在,则也是自动变成follower状态。

Raft把时间划分为任期(Term)(如下图所示),任期是一个递增的整数,一个任期是从开始选举leader到leader失效的这段时间。有点类似于一届总统任期,只是它的时间是不一定的,也就是说只要leader工作状态良好,它可能成为一个独裁者,一直不下台。

2.22-运维-4.png


日志复制【数据复制】是指主节点将每次操作形成日志条目,并持久化到本地磁盘,然后通过网络IO发送给其他节点。一旦一个领导人被选举出来,他就开始为客户端提供服务。客户端的每一个请求都包含一条被复制状态机执行的指令。

领导人把这条指令作为一条新的日志条目附加到日志中去,然后并行的发起附加条目RPCs给其他的服务器,让他们复制这条日志条目。Raft算法保证所有已提交的日志条目都是持久化的并且最终会被所有可用的状态机执行。当主节点收到包括自己在内超过半数节点成功返回,那么认为该日志是可提交的(committed),并将日志输入到状态机,将结果返回给客户端。

在正常的操作中,领导人和跟随者的日志保持一致性,所以附加日志RPC的一致性检查从来不会失败。然而,领导人崩溃的情况会使得日志处于不一致的状态(老的领导人可能还没有完全复制所有的日志条目)。这种不一致问题会在一系列的领导人和跟随者崩溃的情况下加剧。跟随者的日志可能和新的领导人不同的方式。

跟随者可能会丢失一些在新的领导人中有的日志条目,他也可能拥有一些领导人没有的日志条目,或者两者都发生。丢失或者多出日志条目可能会持续多个任期。这就引出了另一个部分,就是安全性。

安全性【数据安全】选主以及日志复制并不能保证节点间数据一致。试想当一个某个节点挂掉了,一段时间后再次重启,并当选为主节点。而在其挂掉这段时间内,集群若有超过半数节点存活,集群会正常工作,那么会有日志提交。这些提交的日志无法传递给挂掉的节点。

当挂掉的节点再次当选主节点,它将缺失部分已提交的日志。在这样场景下,按Raft协议,它将自己日志复制给其他节点,会将集群已经提交的日志给覆盖掉,显然是错误的。其他协议解决这个问题的办法是,新当选的主节点会询问其他节点,和自己数据对比,确定出集群已提交数据,然后将缺失的数据同步过来。

这个方案有明显缺陷,增加了集群恢复服务的时间(集群在选举阶段不可服务),并且增加了协议的复杂度。Raft解决的办法是,在选主逻辑中,对能够成为主的节点加以限制,确保选出的节点已定包含了集群已经提交的所有日志。如果新选出的主节点已经包含了集群所有提交的日志,那就不需要从和其他节点比对数据了。简化了流程,缩短了集群恢复服务的时间。

Etcd应用场景

Etcd应用场景很多,主要的有以下六种:

  • 服务发现;

  • 消息发布与订阅(配置中心);

  • 负载均衡(集群管理);

  • 分布式锁、分布式队列;

  • 集群监控;

  • LEADER竞选。


服务发现

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

要解决服务发现的问题,需要具备以下三点:

1.一个强一致性、高可用的服务存储目录。基于Raft算法的Etcd天生就是这样一个强一致性高可用的服务存储目录;

2.一种注册服务和监控服务健康状态的机制。用户可以在Etcd中注册服务,并且对注册的服务设置key TTL,定时保持服务的心跳以达到监控健康状态的效果;

3.一种查找和连接服务的机制。通过在Etcd指定的主题下注册的服务也能在对应的主题下查找到。为了确保连接,我们可以在每个服务机器上都部署一个 Proxy模式的Etcd,这样就可以确保能访问Etcd集群的服务都能互相连接。

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

消息发布与订阅(配置中心)

在分布式系统中,最为适用的组件间通信方式是消息发布与订阅机制。

具体而言,即构建一个配置共享中心,数据提供者在这个配置中心发布消息,而消息使用者则订阅他们关心的主题,一旦相关主题有消息发布,就会实时通知订阅者。

通过这种方式可以实现分布式系统配置的集中式管理与实时动态更新。

负载均衡(集群管理)

利用Etcd维护一个负载均衡节点表。Etcd可以监控一个集群中多个节点的状态,当有一个请求发过来后,可以轮询式地把请求转发给存活着的多个节点。

类似KafkaMQ,通过Zookeeper来维护生产者和消费者的负载均衡。同样也可以用Etcd来做Zookeeper的工作。

分布式锁

因为Etcd使用Raft算法保持了数据的强一致性,某次操作存储到集群中的值必然是全局一致的,所以很容易实现分布式锁。

锁服务有以下两种使用方式:

保持独占,即所有试图获取锁的用户最终只有一个可以得到。Etcd为此提供了一套实现分布式锁原子操作CAS(CompareAndSwap)的API。通过设置prevExist值,可以保证在多个节点同时创建某个目录时,只有一个成功,而该用户即可认为是获得了锁;

控制时序,即所有试图获取锁的用户都会进入等待队列,获得锁的顺序是全局唯一的,同时决定了队列执行顺序。Etcd为此也提供了一套API(自动创建有序键),对一个目录建值时指定为POST动作,这样Etcd会自动在目录下生成一个当前最大的值为键,存储这个新的值(客户端编号)。同时还可以使用API按顺序列出所有当前目录下的键值。此时这些键的值就是客户端的时序,而这些键中存储的值可以是代表客户端的编号。

分布式队列

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

condition可以表示队列大小。比如一个大的任务需要很多小任务就绪的情况下才能执行,每次有一个小任务就绪,就给这个condition数字加1,直到达到大任务规定的数字,再开始执行队列里的一系列小任务,最终执行大任务。

condition可以表示某个任务在不在队列。这个任务可以是所有排序任务的首个执行程序,也可以是拓扑结构中没有依赖的点。通常,必须执行这些任务后才能执行队列中的其他任务。

condition还可以表示其它的一类开始执行任务的通知。可以由控制程序指定,当condition出现变化时,开始执行队列任务。

集群监控与LEADER竞选

通过Etcd来进行监控实现起来非常简单并且实时性强,用到了以下两点特性:Watcher机制,当某个节点消失或有变动时,Watcher会第一时间发现并告知用户;

节点可以设置TTL key,比如每隔30s向Etcd发送一次心跳使代表该节点仍然存活,否则说明节点消失。这样就可以第一时间检测到各节点的健康状态,以完成集群的监控要求。

Etcd、Zookeeper、Consul比较

1、并发原语:Etcd和ZooKeeper并未提供原生的分布式锁、Leader选举支持,只提供了核心的基本数据读写、并发控制API,由应用上层去封装,consul 就简单多了,提供了原生的支持,通过简单点命令就能使用;

2、服务发现:Etcd 和 ZooKeeper并未提供原生的服务发现支持,Consul在服务发现方面做了很多解放用户双手的工作,提供了服务发现的框架,帮助你的业务快速接入,并提供了HTTP和DNS两种获取服务方式;

3、健康检查:consul的健康检查机制,是一种基于client、Gossip协议、分布式的健康检查机制,具备低延时、可扩展的特点。业务可通过Consul的健康检查机制,实现HTTP接口返回码、内存乃至磁盘空间的检测,相比Etcd、ZooKeeper它们提供的健康检查机制和能力就非常有限了;

Etcd提供了Lease机制来实现活性检测。它是一种中心化的健康检查,依赖用户不断地发送心跳续租、更新TTL。

ZooKeeper使用的是一种名为临时节点的状态来实现健康检查。当client与 ZooKeeper节点连接断掉时,ZooKeeper就会删除此临时节点的key-value 数据。它比基于心跳机制更复杂,也给client带去了更多的复杂性,所有client必须维持与ZooKeeper server的活跃连接并保持存活;

4、watch特性:相于Etcd , Consul存储引擎是基于Radix Tree实现的,因此它不支持范围查询和监听,只支持前缀查询和监听,而Etcd都支持,ZooKeeper的Watch特性有更多的局限性,它是个一次性触发器;

5、线性读:Etcd和Consul都支持线性读,而ZooKeeper并不具备;

6、权限机制比较:Etcd实现了RBAC的权限校验,而ZooKeeper和Consul 实现的ACL;

7、事务比较:Etcd和Consul都提供了简易的事务能力,支持对字段进行比较,而ZooKeeper只提供了版本号检查能力,功能较弱;

8、多数据中心:在多数据中心支持上,只有Consul是天然支持的,虽然它本身不支持数据自动跨数据中心同步,但是它提供的服务发现机制、Prepared Query功能,赋予了业务在一个可用区后端实例故障时,可将请求转发到最近的数据中心实例。而Etcd和ZooKeeper并不支持。


1671585dc74035d34ac554d5f2ae42fc.jpg

推荐阅读

>>>新手必备-Linux入门之云计算是什么

>>>红帽认证入门-Linux系统介绍及企业版本选型

>>>新手必备-Linux系统安装配置+Xshell远程连接

>>>Linux常用命令行合集之绝对路径和相对路径

>>>软连接与硬连接