etcd 快速入门

news2024/11/28 22:53:22

简介

随着go与kubernetes的大热,etcd作为一个基于go编写的分布式键值存储,逐渐为开发者所熟知,尤其是其还作为kubernetes的数据存储仓库,更是引起广泛专注。

本文我们就来聊一聊etcd到底是什么及其工作机制。

首先,coreos官方是这么定义etcd的:

A highly-available key value store for shared configuration and service discovery(etcd是一个高可用的用于共享配置和服务发现的KV存储)

事实上,etcd是一个受到zookeeper和doozer启发而催生的项目。除了与之拥有类似的功能之外,现专注于如下几点:

  • 简单: 基于http+json的api
  • 安全: 可选的ssl认证机制
  • 快速: 每个实例每秒支持1000次写操作
  • 可信: 使用raft算法实现分布式

使用场景

下面是一些etcd较常用的使用场景:

  • 服务发现:在微服务的应用场景中,各服务主动向etcd注册自己,并通过etcd获取其依赖的服务的注册信息。
  • 配置管理:事实上配置管理使用的就是消息发布与订阅。即构建一个配置共享中心,数据提供者在这个配置中心发布消息,而消息使用者则订阅他们关心的主题,一旦主题有消息发布,就会实时通知订阅者。通过这种方式可以做到分布式系统配置的集中式管理与动态更新。
  • 应用调度: 事实上应用调度的功能也是依托于服务的注册与发现。一个服务多个副本都注册至etcd,利用etcd维护一个负载均衡节点表。etcd可以监控一个集群中多个节点的状态,当有一个请求发过来后,可以轮询式的把请求转发给存活着的多个状态。
  • 分布式通知与协调:与消息发布和订阅有些相似。都用到了etcd中的Watcher机制,通过注册与异步通知机制,实现分布式环境下不同系统之间的通知与协调,从而对数据变更做到实时处理。与消息发布和订阅不同的是,发布和订阅通常用于获取配置以更新服务。而分布式通知与协调,通常是多个不同的服务监听同一个目录,但其中一个服务修改了该目录,则触发其他服务的相应操作,一个典型的应用场景即通过etcd实现应用的健康检查
  • 分布式锁:因为etcd使用raft算法保证了数据的强一致性,某次操作存储至etcd的值必须全局唯一,所以比较容易实现分布式锁
  • 分布式队列:与分布式锁的场景类似,可创建一个先进先出队列,保证顺序
  • 选主:通过etcd为一些分布式应用选举leader节点

组件说明

架构说明

在这里插入图片描述

etcd主要分为四个部分。

HTTP Server: 用于处理用户发送的API请求以及其它etcd节点的同步与心跳信息请求。在最新的版本中也已经支持了grpc

Store:Store 是 Etcd 数据存储的核心部分,它保存了所有的键值对。Store 可以看作是一个内存中的键值数据库,所有的读写操作都会在这个内存结构中进行。Store 是为了提供快速的数据访问而设计的,因为大多数读写操作可以直接从内存中完成。

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

WAL:Write Ahead Log(预写式日志),是一种用于持久化数据的技术,它是在内存中的 Store 发生更改之前先将更改记录到磁盘的日志。WAL 的主要目的是为了提高数据的持久性和容错能力。即使在节点突然宕机的情况下,WAL 文件也可以用来恢复内存中的 Store。

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

工作原理

选主

Raft协议是用于维护一组服务节点数据一致性的协议。这一组服务节点构成一个集群,并且有一个主节点来对外提供服务。当集群初始化,或者主节点挂掉后,就需要重新选主。集群中每个节点,任意时刻处于Leader, Follower, Candidate这三个角色之一。选举特点如下:

  • 当集群初始化时候,每个节点都是Follower角色;
  • 集群中存在至多1个有效的主节点,通过心跳与其他节点同步数据;
  • 当Follower在一定时间内没有收到来自主节点的心跳,会将自己角色改变为Candidate,并发起一次选主投票;当收到包括自己在内超过半数节点赞成后,选举成功,自己成为主;当收到票数不足半数选举失败,或者选举超时。若本轮未选出主节点,将进行下一轮选举(出现这种情况,是由于多个节点同时选举,所有节点均未获得过半选票)。
  • Candidate节点收到来自主节点的信息后,会立即终止选举过程,进入Follower角色。
  • 为了避免陷入选主失败循环,每个节点未收到心跳发起选举的时间是一定范围内的随机值,这样能够避免2个节点同时发起选主。
日志复制

在这里插入图片描述

所谓日志复制,是指主节点将每次操作形成日志条目,并持久化到本地磁盘,然后通过网络IO发送给其他节点。其他节点根据日志的逻辑时钟(TERM)和日志编号(INDEX)来判断是否将该日志记录持久化到本地。当主节点收到包括自己在内超过半数节点成功返回,那么认为该日志是可提交的(committed),并将日志输入到状态机,将结果返回给客户端。

这里需要注意的是,每次选主都会形成一个唯一的TERM编号,相当于逻辑时钟。每一条日志都有全局唯一的编号。

主节点通过网络IO向其他节点追加日志。若某节点收到日志追加的消息,首先判断该日志的TERM是否过期,以及该日志条目的INDEX是否比当前以及提交的日志的INDEX跟早。若已过期,或者比提交的日志更早,那么就拒绝追加,并返回该节点当前的已提交的日志的编号。否则,将日志追加,并返回成功。

当主节点收到其他节点关于日志追加的回复后,若发现有拒绝,则根据该节点返回的已提交日志编号,发生其编号下一条日志。

主节点像其他节点同步日志,还作了拥塞控制。具体地说,主节点发现日志复制的目标节点拒绝了某次日志追加消息,将进入日志探测阶段,一条一条发送日志,直到目标节点接受日志,然后进入快速复制阶段,可进行批量日志追加。

按照日志复制的逻辑,我们可以看到,集群中慢节点不影响整个集群的性能。另外一个特点是,数据只从主节点复制到Follower节点,这样大大简化了逻辑流程。

安全性

选主以及日志复制都是为了保证节点间的数据一致性。但是仅仅依靠选主和日志复制并不能完全保证节点间数据一致。比如,当某个节点挂掉了,一段时间后再次重启,并当选为主节点。而在其挂掉这段时间内,集群若有超过半数节点存活,集群会正常工作,那么会有日志提交。这些提交的日志无法传递给挂掉的节点。当挂掉的节点再次当选主节点,它将缺失部分已提交的日志。在这样场景下,按Raft协议,它将自己日志复制给其他节点,会将集群已经提交的日志给覆盖掉。

这显然是不可接受的。

其他协议解决这个问题的办法是,新当选的主节点会询问其他节点,和自己数据对比,确定出集群已提交数据,然后将缺失的数据同步过来。这种方案有明显缺陷,增加了集群恢复服务的时间(集群在选举阶段不可服务),并且增加了协议的复杂度。

Raft的解决办法是,在选主逻辑中,对能够成为主的节点加以限制,确保选出的节点一定包含了集群已经提交的所有日志。如果新选出的主节点已经包含了集群所有提交的日志,那就不需要从和其他节点比对数据了。简化了流程,缩短了集群恢复服务的时间。

这里存在一个问题,加以这样限制之后,还能否选出主呢?答案是:只要仍然有超过半数节点存活,这样的主一定能够选出。因为已经提交的日志必然被集群中超过半数节点持久化,显然前一个主节点提交的最后一条日志也被集群中大部分节点持久化。当主节点挂掉后,集群中仍有大部分节点存活,那这存活的节点中一定存在一个节点包含了已经提交的日志了。

相关术语

  • 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来定位数据。

部署

docker compose 单机部署

首先创建两个文件夹,一个是数据目录,一个是密钥目录

mkdir -p /docker/etcd/data
mkdir /docker/etcd/ca-certificates

进入密钥目录

cd  /docker/etcd/ca-certificates

生成 CA 的私钥和证书

openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=etcd-ca" -days 10000 -out ca.crt

生成 etcd 服务器的私钥和证书签名请求

openssl genrsa -out etcd.key 2048
openssl req -new -key etcd.key -subj "/CN=etcd-server" -out etcd.csr

使用 CA 证书和私钥签署 etcd 服务器的证书

openssl x509 -req -in etcd.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out etcd.crt -days 10000

生成 etcd 客户端的私钥和证书签名请求

openssl genrsa -out etcdclient.key 2048
openssl req -new -key etcdclient.key -subj "/CN=etcd-client" -out etcdclient.csr

使用 CA 证书和私钥签署 etcd 客户端的证书

openssl x509 -req -in etcdclient.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out etcdclient.crt -days 10000

创建 docker-compose.yml 在 /docker/etcd/ 目录下即可

vim docker-compose.yml
services:
  etcd:
    image: bitnami/etcd
    container_name: etcd
    restart: always
    ports:
      - 4001:4001
      - 2380:2380
      - 2379:2379
    volumes:
      - /docker/etcd/ca-certificates/:/etc/ssl/certs
      - /docker/etcd/data:/bitnami/etcd/data
    environment:
      - TZ=Asia/Shanghai
      - ETCD_NAME=etcd0
      - ETCD_DATA_DIR=/bitnami/etcd/data
      - ETCD_ROOT_PASSWORD=123456
      - ETCD_CLIENT_CERT_AUTH=true
      - ETCD_PEER_CLIENT_CERT_AUTH=true
      - ETCD_ADVERTISE_CLIENT_URLS=http://192.168.142.157:2379,http://192.168.142.157:4001
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379,http://0.0.0.0:4001
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://192.168.142.157:2380
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-1
      - ETCD_INITIAL_CLUSTER=etcd0=http://192.168.142.157:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
      - ETCD_CERT_FILE=/etc/ssl/certs/etcd.crt
      - ETCD_KEY_FILE=/etc/ssl/certs/etcd.key
      - ETCD_TRUSTED_CA_FILE=/etc/ssl/certs/ca.crt
      - ETCD_PEER_CERT_FILE=/etc/ssl/certs/etcd.crt
      - ETCD_PEER_KEY_FILE=/etc/ssl/certs/etcd.key
      - ETCD_PEER_TRUSTED_CA_FILE=/etc/ssl/certs/ca.crt
      - ETCD_CLIENT_CERT_AUTH=true

元神启动

docker compose up -d

查看是否启动

root@master:/docker/etcd# docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                                                                                      NAMES
55ff0118d4be   bitnami/etcd   "/opt/bitnami/script…"   22 minutes ago   Up 22 minutes   0.0.0.0:2379-2380->2379-2380/tcp, :::2379-2380->2379-2380/tcp, 0.0.0.0:4001->4001/tcp, :::4001->4001/tcp   etcd

运行

docker exec -it etcd etcdctl --endpoints=http://192.168.142.157:2379   --user=root:123456 get /

在这个过程中我遇到了这个问题

chmod: changing permissions of '/bitnami/etcd/data': Operation not permitted

我是这么解决的:设置权限(实在不行干脆把 /docker/etcd 设置成 777)

chmod 777 /docker/etcd/data -R

现在权限问题解决了之后我又遇到了一个新的问题

root@master:/docker/etcd# docker exec -it etcd  etcdctl --endpoints=http://192.168.142.157:2379   --user=root:123456 get /
{"level":"warn","ts":"2024-10-04T23:15:09.800270+0800","logger":"etcd-client","caller":"v3@v3.5.16/retry_interceptor.go:63","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc0003501e0/192.168.142.157:2379","attempt":0,"error":"rpc error: code = FailedPrecondition desc = etcdserver: authentication is not enabled"}

这个错误是etcd的认证没有开启
接下来让我们来开启认证

先查看是否开启了认证

docker exec -it etcd etcdctl auth status

结果

Authentication Status: false
AuthRevision: 1

查看用户列表和角色列表

docker exec -it etcd etcdctl role list
docker exec -it etcd etcdctl user list

结果:什么都没有
添加root角色

docker exec -it etcd etcdctl role add root

添加root用户

 docker exec -it etcd etcdctl user add root:123456

再次查看用户列表和角色列表
给root用户赋予root角色

docker exec -it etcd etcdctl user grant-role root root

结果:两个都是 root
好了,开启认证看看

docker exec -it etcd etcdctl auth enable

参考:https://blog.csdn.net/HYZX_9987/article/details/135237119
感谢大佬的博客 ^–^

这个时候我就再也没有遇到报错了,让我们来插入数据试试

docker exec -it etcd etcdctl --endpoints=http://192.168.142.157:2379   --user=root:123456 put /mykey "myvalue"

查看插入的数据

etcdctl --endpoints=http://192.168.142.157:2379 --user=root:123456 get /mykey

结果

/mykey
myvalue

至此,单机部署完成

etcd 的简单使用

etcdctl put /key "value"

设置带有过期时间的键

etcdctl put /key --ttl 60 "value"

etcdctl del /key

etcdctl get /key

列出

etcdctl ls /

监控

监控键 key 的变化,如果有更新,会输出变化后的值。

etcdctl watch /key

执行事务

执行一个包含多个操作的事务

etcdctl txn \
  put /txn_key "value1" \
  get /txn_key

检查领导选举

使用 etcd 进行领导者选举。

etcdctl elect --ttl 60 --period 5 /myelection mycandidate

获取成员列表

etcdctl member list

获取集群状态

etcdctl endpoint health

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2189340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

查找回收站里隐藏的文件

在Windows里,每个磁盘分区都有一个隐藏的回收站Recycle, 回收站里保存着用户删除的文件、图片、视频等数据,比如,C盘的回收站为C:\RECYCLE.BIN\,D盘的的回收站为D:\RECYCLE.BIN\,E盘的的回收站为E:\RECYCLE…

【解决方案】JVM调优:给定资源条件下减少Full GC频率

1 缘起 在一次其他团队技术分享时,有幸进行了旁听, 谈到一个应用场景,服务端在给定的资源下,频繁Full GC, 降低了服务请求处理能力以及任务处理能力,频繁Full GC,导致服务处理能力下降, 服务在Full GC期间无法处理用户请求以及其他任务,服务不稳定,可以理解为服务在…

【C++算法】9.双指针_四数之和

文章目录 题目链接:题目描述:解法C 算法代码:图解 题目链接: 18.四数之和 题目描述: 解法 解法一:排序暴力枚举利用set去重 解法二:排序双指针 从左往右依次固定一个数a在a后面的区间里&#x…

坐标系变换总结

二维情况下的转换 1 缩放变换 形象理解就是图像在x方向和y方向上放大或者缩小。 代数形式: { x ′ k x x y ′ k y y \begin{cases} x k_x x \\ y k_y y \end{cases} {x′kx​xy′ky​y​ 矩阵形式: ( x ′ y ′ ) ( k x 0 0 k y ) ( x y ) \be…

【C语言】数据在内存中的存储(万字解析)

文章目录 一、大小端字节序和字节序判断1.案例引入2.什么是大小端字节序3.大小端字节序判断 二、整数在内存中的存储以及相关练习1.整型在内存中的存储2.练习练习1:练习2练习3练习4练习5:练习6 三、浮点数在内存中的存储1.案例引入2.浮点数在内存中的存储…

uniapp+Android面向网络学习的时间管理工具软件 微信小程序

目录 项目介绍支持以下技术栈:具体实现截图HBuilderXuniappmysql数据库与主流编程语言java类核心代码部分展示登录的业务流程的顺序是:数据库设计性能分析操作可行性技术可行性系统安全性数据完整性软件测试详细视频演示源码获取方式 项目介绍 用户功能…

KVM虚拟化技术介绍

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 虚拟化技术是云计算的基础,什么是虚拟化?虚拟化技术的本质是什么?主流的虚拟化技术有哪些?本章将为您揭晓 一.虚拟化概述 虚拟化是一种将计…

【有啥问啥】领域自适应(Domain Adaptation, DA)详解

领域自适应(Domain Adaptation, DA)详解 引言 在机器学习和深度学习的广泛应用中,一个核心挑战在于模型往往在一个特定数据集(源领域)上训练后,难以直接应用于另一个不同但相关的数据集(目标领…

通信工程学习:什么是ICMP因特网控制报文协议

ICMP:因特网控制报文协议 ICMP(Internet Control Message Protocol,因特网控制报文协议)是TCP/IP协议簇中的一个重要子协议,主要用于在IP主机和路由器之间传递控制消息。以下是关于ICMP协议的详细解释: 一…

Pikachu-Unsafe FileUpload-客户端check

上传图片,点击查看页面的源码, 可以看到页面的文件名校验是放在前端的;而且也没有发起网络请求; 所以,可以通过直接修改前端代码,删除 checkFileExt(this.value) 这部分; 又或者先把文件名改成…

九、2 USART串口外设

1、STM32内部的USART外设的介绍 (1) STM32的USART的同步模式只是多了个时钟输出,只支持时钟输出,不支持时钟输入。该同步模式更多是为了兼容别的协议或者特殊用途而设计的,并不支持两个USART之间进行同步通信&#xf…

剖解最小栈

最小栈 思路: 1. 首先实例化两个栈,分别是stack用于存放数据,minstack用于存放最小值 2. 将第一个元素压入两个栈中,判断此时若minStack栈中为空,则表示压入的为第一个数据 if ( minStack.empty () ) { minStack.pus…

MySQL 查询优化器

文章目录 控制查询计划optimizer_prune_leveloptimizer_search_depth 优化器参数优化器提示索引提示成本模型server_costcost_name engine_cost 控制查询计划 https://dev.mysql.com/doc/refman/8.4/en/controlling-query-plan-evaluation.html 在执行SQL前会根据优化器选择执…

Leetcode 第 140 场双周赛题解

Leetcode 第 140 场双周赛题解 Leetcode 第 140 场双周赛题解题目1:3300. 替换为数位和以后的最小元素思路代码复杂度分析 题目2:3301. 高度互不相同的最大塔高和思路代码复杂度分析 题目3:3302. 字典序最小的合法序列思路代码复杂度分析 题目…

入手一个小扒菜fqrr#com

fqrr#com 既带q又带r是很多人不喜的类型, 父亲 夫妻 番茄 分期 人人 日日 好无聊的米呀,竟然组合不出来意思 这个不是购买的,别人说他1150元购买的,算是半抵给我的吧 其实我也不喜欢,我4声母.com 已经够多了&am…

【教程】文字转语音的3个方法,文字转语音使用攻略

文字转语音的需求还是蛮多的,很多用户在视频剪辑中会遇到。不想用本人的声音,那么视频中的旁白就只能通过文字转语音软件实现了。 想要将文字转为语音那还是蛮好解决的,如果你还在找方法,那么以下内容可以了解下。本文整理了三种简…

2c 操作符详解

1. 操作符分类: 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 2. 算术操作符 - * / % 1除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。对于 / 操作…

NVIDIA NVLink-C2C

NVIDIA NVLink-C2C 文章目录 前言一、介绍1. 用于定制芯片集成的超快芯片互连技术2. 构建半定制芯片设计3. 使用 NVLink-C2C 技术的产品 二、NVLink-C2C 技术优势1. 高带宽2. 低延迟3. 低功率和高密度4. 行业标准协议 前言 将 NVLink 扩展至芯片级集成 一、介绍 1. 用于定制芯…

Candance仿真二阶米勒补偿OTA

1.OTA电路搭建目标——25Mhz GBW,65dB的增益 2.电路参照 3.candance电路搭建 实现步骤:应该是从下面这个公式开始推导 然后那个CL就是两边的那个CCa或CCb的大小 算出来就是gm75us

MongoDB-aggregate流式计算:带条件的关联查询使用案例分析

在数据库的查询中,是一定会遇到表关联查询的。当两张大表关联时,时常会遇到性能和资源问题。这篇文章就是用一个例子来分享MongoDB带条件的关联查询发挥的作用。 假设工作环境中有两张MongoDB集合:SC_DATA(学生基本信息集合&…