Etcd集群的介绍和选主应用

部署运行你感兴趣的模型镜像

ETCD作为开源、分布式、高可用、强一致性的key-value存储系统,提供了配置共享和服务发现等众多功能。目前已广泛应用在kubernetes、ROOK、CoreDNS、M3以及openstack等领域。本文作者基于公司内部的场景需求,对etcd进行了介绍,并对选主机制进行了实践,下来就跟随作者一起学习下吧。

1

背景介绍

在实际生产环境中,有很多应用在同一时刻只能启动一个实例,例如更新数据库的操作,多个实例同时更新不仅会降低系统性能,还可能导致数据的不一致。但是单点部署也使得系统的容灾性减弱,比如进程异常退出。目前进程保活,也有很多方案,如supervisor和systemd。但是,如果宿主机down掉呢?所有的进程保活方法都会无济于事。本文基于etcd自带的leader选举机制,轻松的使服务具备了高可用性。

2

Etcd简介

Etcd是一个开源的、高度一致的分布式key-value存储系统。由Go语言实现,具有很好的跨平台性。主要用于配置共享和服务发现。通过raft算法维护集群中各个节点的通信和数据一致性,节点之间是对等的关系,即使leader节点故障,会很快选举出新的leader,保证系统的正常运行。目前已广泛应用在kubernetes、ROOK、CoreDNS、M3、openstack等领域。

特性:

  1. 接口操作简单,提供了http+json和grpc接口。

  2. 可选的ssl客户端认证,支持https访问。

  3. 每个实例支持1000的QPS,适用于存储数据量小但更新和访问频繁的数据。

  4. 数据按照文件系统的方式,分层存储,数据持久化。

  5. 监视特定的键或目录的变化,并对值的更改做出响应,适用于消息的发布和订阅。

3

Etcd架构及工作原理

架构

Etcd的架构如下图所示,主要分为四部分。HTTP server、Store、Raft和WAL。

  • HTTP server:为用户提供的Api请求。

  • Store:用于处理 etcd 支持的各类功能的事务,包括数据索引、节点状态变更、监控与反馈、事件处理与执行等等。

  • Raft:利用raft算法,保证节点之间数据的强一致性。

  • WAL:数据存储方式。通过 WAL 进行数据持久化存储。Snapshot 存储数据的状态快照;Entry 表示存储的具体日志内容。

工作原理

ETCD集群是一个分布式系统,每个ETCD节点都维护了一个状态机,并且存储了完整的数据,任意时刻至多存在一个有效的主节点。主节点处理所有来自客户端的读写操作。其中状态机的状态转换规则如下:

ETCD中每个节点的状态集合为(Follower、Candidate、Leader),集群初始化时候,每个节点都是Follower角色,当Follower在一定时间内没有收到来自主节点的心跳,会将自己角色改变为Candidate,并发起一次选主投票;当收到包括自己在内超过半数节点赞成后,选举成功;当收到票数不足半数选举失败,或者选举超时。若本轮未选出主节点,将进行下一轮选举。当某个Candidate节点成为Leader后,Leader节点会通过心跳与其他节点同步数据,同时参与竞选的Candidate节点进入Follower角色。

4

Etcd集群搭建及基本应用

部署环境

三台系统为centos7的虚机,IP地址如下:

10.143.74.108

10.202.252.147

10.202.254.213

下来以10.143.74.108为例,介绍安装与配置步骤。

一键安装etcd

1、创建安装脚本build.sh。

ETCD_VER=v3.4.7
# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GITHUB_URL}
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
cp /tmp/etcd-download-test/etcd /usr/bin
etcd --version
cp /tmp/etcd-download-test/etcdctl /usr/bin
etcdctl version

2、或者执行以下命令,脚本已上传到公网S3存储。

wget -qO- http://pub-shbt.s3.360.cn/v2s3/build-20200419214912.sh | bash

etcd配置和systemd保活

1、 创建etcd配置文件/etc/etcd/etcd.conf。

ETCD_NAME=instance01
ETCD_DATA_DIR="/usr/local/etcd/data"
ETCD_LISTEN_CLIENT_URLS="http://10.143.74.108:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://10.143.74.108:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.143.74.108:2380"
ETCD_LISTEN_PEER_URLS="http://10.143.74.108:2380"
ETCD_INITIAL_CLUSTER="instance01=http://10.143.74.108:2380,instance02=http://10.202.253.147:2380,instance03=http://10.202.254.213:2380"
ETCD_INITIAL_CLUSTER_STATE=new

注释:

  • ETCD_NAME:本member的名称;

  • ETCD_DATA_DIR:存储数据的目录;

  • ETCD_LISTEN_CLIENT_URLS:用于监听客户端etcdctl或者curl连接;

  • ETCD_ADVERTISE_CLIENT_URLS: 本机地址, 用于通知客户端,客户端通过此IPs与集群通信;

  • ETCD_INITIAL_ADVERTISE_PEER_URLS:本机地址,用于通知集群member,与member通信;

  • ETCD_LISTEN_PEER_URLS:用于监听集群中其它member的连接;

  • ETCD_INITIAL_CLUSTER:描述集群中所有节点的信息,本member根据此信息去联系其他member;

  • ETCD_INITIAL_CLUSTER_STATE:集群状态,新建集群时候设置为new,若是想加入某个已经存在的集群设置为existing。

2、 创建etcd的systemd配置文件 /usr/lib/systemd/system/etcd.service。

[Unit]
Description=Etcd Server
After=network.target
[Service]
Type=simple
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/bin/etcd
KillMode=process
Restart=always
RestartSec=3
LimitNOFILE=655350
LimitNPROC=655350
PrivateTmp=false
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target

3、 启动etcd。

systemctl daemon-reload
systemctl enable etcd.service
systemctl start etcd.service

4、 查看etcd集群状态。

HOST_1=10.143.74.108
HOST_2=10.202.253.147
HOST_3=10.202.254.213
ENDPOINTS=$HOST_1:2379,$HOST_2:2379,$HOST_3:2379
etcdctl -w table --endpoints=$ENDPOINTS endpoint status


5、 读写以及删除操作。

6、 watch监听操作。

至此,在10.143.74.108主机上,我们已经成功安装、启动etcd服务,并测试了基本的功能。其他两台机器的配置类似,在此不再做介绍。

5

Etcd选主在Go中的实践

什么是选主机制呢?举个例子,在军事演习中,我们总会发现某架预警机周围分布着多架战斗机和歼击机,他们统一听从预警机的调度,有序的完成消灭敌军的任务。那么在这个集群中,预警机就类似于我们选主中的master,某个集群有且只有一个master,完成任务的分发等工作,其他节点配合行动,当这个master节点挂掉之后,要能够立刻选出新的节点作为master。

下来我们一起看下项目中如何利用etcd的选主机制来实现应用的高可用吧。

1、安装clientv3。

go get "github.com/coreos/etcd/clientv3"

2、添加常量。

const prefix = "/nanoPing"
const prop = "local"
var leaderFlag bool

3、编写client节点竞选函数campaign。

func campaign(c *clientv3.Client, election string, prop string) {
   for {
      //gets the leased session for a client
      s, err := concurrency.NewSession(c, concurrency.WithTTL(15))
      if err != nil {
         log.Println(err)
         continue
      }
      //returns a new election on a given key prefix
      e := concurrency.NewElection(s, election)
      ctx := context.TODO()
      //Campaign puts a value as eligible for the election on the prefix key.
      //Multiple sessions can participate in the election for the same prefix,
      //but only one can be the leader at a time
      if err = e.Campaign(ctx, prop); err != nil {
         log.Println(err)
         continue
      }
      log.Println("elect: success")
      leaderFlag = true
      select {
      case <-s.Done():
         leaderFlag = false
         log.Println("elect: expired")
      }
   }
}

4、添加竞选成功后执行的动作run。

func run() {
      log.Println("[info] Service master")
      log.Println("[info] Task start.")
}

5、编写入口函数,创建client节点,参与竞选master,竞选成功,执行任务。

func Start() {
   donec := make(chan struct{})
   //create a client
   cli, err := clientv3.New(clientv3.Config{Endpoints: g.Config().Etcd.Addr,Username:g.Config().Etcd.User,Password:g.Config().Etcd.Password})
   if err != nil {
      log.Fatal(err)
   }
   defer cli.Close()
   go campaign(cli, prefix, prop)
   go func() {
      ticker := time.NewTicker(time.Duration(10) * time.Second)
      for {
         select {
         case <-ticker.C:
            {
               if leaderFlag == true{
                  run()
                  return
               }else{
                  log.Println("[info] Service is not master")
               }
            }
         }
      }
   }()
   <-donec
}

6、 测试运行结果。

选主成功的节点输出:

选主失败的节点输出:

Master节点进程退出后,之前的非master节点,自动竞选为master节点。

6

总结

通过etcd中的选主机制,我们实现了服务的高可用。同时利用systemd对etcd本身进行了保活,只要etcd服务所在的机器没有宕机,进程就具备了容灾性。当然,一个etcd集群,不仅仅可以对一个服务提供高可用,我们可以将多个服务注册在一个etcd集群中,同时利用etcd所提供的共享配置和服务发现,此外,etcd还有很多值得深入研究的技术,比如raft一致性算法等等,希望和大家能够一起深入交流。

相关文章

https://etcd.io/docs/v3.4.0/demo/

https://www.ipcpu.com/2017/09/etcd-start/

https://www.cnblogs.com/itzgr/p/9920910.html


往期精彩回顾

围观“33行代码的React

360技术中台招聘啦!!

实习招聘|360云平台火热招聘中

360技术公众号

技术干货|一手资讯|精彩活动

扫码关注我们

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<think>好的,用户想了解etcd集群的工作原理,特别是与分布式存储架构相关的部分。我需要结合之前的引用内容来组织回答。首先,根据引用[1]到[4],etcd基于Raft协议,用于集群管理、配置共享节点状态监控。应该先解释Raft一致性算法在etcd中的作用,比如主、日志复制等。 然后,需要描述集群的组成,比如三个节点的角色:Leader、Follower、Candidate,以及它们之间的交互。引用[4]提到etcd使用Raft协议,而ZooKeeper用的是ZAB,Consul也用Raft,这可能对比较有帮助,但用户主要关注etcd,所以重点放在Raft的实现上。 接下来,数据存储机制是关键。etcd的数据模型是键值对,支持范围查询,这点引用[2][4]都有提到。需要解释数据如何通过Raft日志同步到各个节点,保证一致性。另外,引用[4]中的性能优化参数,如--max-request-bytes快照配置,可以说明数据持久化恢复机制。 读写流程部分,Leader处理写请求,Follower响应读请求,但为了强一致性可能需要线性化读,这里可能需要引用[2]中的分布式锁写屏障概念。读写性能方面,引用[4]指出etcd在高性能场景下优化较好,比如使用SSD。 高可用性灾难恢复也是重点。etcd集群通过多数派机制维持可用性,引用[1]提到超大规模集群管理,说明其扩展性。灾难恢复部分引用[4]的技术对比,可以提到快照日志回放。 最后,应用场景如Kubernetes的服务发现配置存储,引用[3][4]都提到了,需要联系实际用例。同时,相关问题可以围绕主机制、数据一致性保证、性能优化等展开,帮助用户深入理解。</think>### etcd集群工作原理分步解析 ### 一、Raft一致性协议核心机制 etcd集群采用Raft算法实现分布式一致性,包含三个关键过程: 1. **Leader举**:当Follower节点超过$election-timeout$(默认5秒)未收到心跳,会发起举成为Candidate,需要获得$N/2+1$节点的投票才能成为Leader[^4] $$ \text{举成功条件}:\text{得票数} > \lfloor \frac{N}{2} \rfloor $$ 2. **日志复制**:Leader将客户端请求封装为日志条目,通过$AppendEntries$ RPC同步给Followers,收到多数节点确认后提交 3. **成员变更**:使用Joint Consensus机制实现节点动态增删,确保配置变更期间集群持续可用 ### 二、集群节点角色与交互 | 角色 | 职责 | 状态转换条件 | |------------|--------------------------------------|----------------------------------| | Leader | 处理所有写请求,发送心跳包 | 失去多数节点连接时退位 | | Follower | 响应Leader心跳,转发写请求到Leader | 举超时后成为Candidate | | Candidate | 发起举投票请求 | 获得多数票成为Leader | ![etcd集群架构图](https://example.com/etcd-arch.png)(示意图:三节点组成的Raft集群) ### 三、数据存储与同步机制 1. **键值存储引擎**:采用B+树结构的MVCC多版本存储 - 每个修改操作生成新的修订版本(revision) - 支持事务操作:`IF`条件判断 + `THEN/ELSE`执行体 2. **数据同步流程**: ```go // 伪代码示例写请求处理 func handlePutRequest(key, value) { if currentRole != Leader { return redirectToLeader() } logEntry := createLogEntry(key, value) replicateToFollowers(logEntry) if majorityAckReceived() { applyToStateMachine() return successResponse() } } ``` 3. **持久化保障**: - 预写日志(WAL):每次更新先写入磁盘日志 - 定期快照:当日志条目超过$snapshot-count$(默认10万)时创建快照[^4] ### 四、读写操作处理 1. **写请求**: - 必须通过Leader节点处理 - 需要满足$W > N/2$的写入确认(W为写确认节点数) 2. **读请求**: - 默认提供线性一致性读 - 通过ReadIndex机制避免脏读: ```mermaid sequenceDiagram Client->>Leader: 读请求 Leader->>Leader: 记录当前commit index Leader->>Followers: 心跳确认多数派存活 Leader->>Client: 返回最新已提交数据 ``` ### 五、高可用保障措施 1. **故障恢复**: - Leader故障:在$election-timeout$内完成新Leader举 - 网络分区:采用PreVote机制防止脑裂 2. **动态配置**: - 安全变更成员:`etcdctl member add/remove` - 滚动升级支持:通过`--enable-v2=false`逐步淘汰旧协议 3. **监控指标**: - 核心指标监控项: ```bash etcd_server_leader_changes_seen_total # Leader变更次数 etcd_disk_wal_fsync_duration_seconds # 持久化延迟 etcd_network_client_grpc_sent_bytes # 网络吞吐量 ``` ### 六、与Kubernetes的集成实践 1. **服务发现**: - 存储所有Pod的Endpoint信息 - Watch机制实时通知服务变更 2. **配置管理**: - 存储集群的ConfigMapSecret - 支持加密存储敏感数据 3. **调度协调**: - 存储节点状态信息 - 协助完成分布式锁控制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值