抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

基本概念

etcd是一个分布式、强一致性,高可靠性的开源键值对存储系统,通常被用来配置管理或者服务发现,K8s就是用它来存储所有集群的状态信息的。

etcd is a strongly consistent, distributed key-value store that provides a reliable way to store data that needs to be accessed by a distributed system or cluster of machines. It gracefully handles leader elections during network partitions and can tolerate machine failure, even in the leader node.

image-20240119230604099

特点

etcd根据官方介绍具有以下特点

  1. 强一致性:使用raft一致性算法来保证各个节点数据的一致性
  2. HTTP协议简单API:提供了一个简单的HTTP/JSON API和GRPC接口,可以通过接口请求来存储和查找键值对数据
  3. 安全性:支持通过TLS加密和客户端证书验证来提高系统安全性
  4. 观察者模式:支持键值对的变更通知机制,使得应用程序可以订阅这些通知并自定义逻辑来处理
  5. TTL:支持设置键的超时时间,来实现自动删除过期数据
  6. 高性能:每个实例支持每秒1K次的写操作

安装

大致了解etcd的特点后,根据官方的安装脚本来尝试一下,macOS系统上的安装步骤如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 定义下载版本为3.5.11
ETCD_VER=v3.5.11

// 选择下载路径,正常默认选官方路径即可
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

// 强制删除可能存在的安装包
rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
// 删除安装目录然后创建安装目录
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

// 根据版本号和下载路径下载压缩包,随后解压,移动到安装目录
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-darwin-amd64.zip -o /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
unzip /tmp/etcd-${ETCD_VER}-darwin-amd64.zip -d /tmp && rm -f /tmp/etcd-${ETCD_VER}-darwin-amd64.zip
mv /tmp/etcd-${ETCD_VER}-darwin-amd64/* /tmp/etcd-download-test && rm -rf mv /tmp/etcd-${ETCD_VER}-darwin-amd64

// 测试etcd安装是否成功
/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
/tmp/etcd-download-test/etcdutl version

基本操作

安装好后,我们来试下etcd的基本使用方法和命令,这里了解和学习的是etcd3,不同大版本之间存在一些不同特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 在A终端启动一下etcd的服务
cd /tmp/etcd-download-test/
./etcd
{"level":"warn","ts":"2024-01-17T15:21:37.467655+0800","caller":"embed/config.go:679","msg":"Running http and grpc server on single port. This is not recommended for production."}
{"level":"info","ts":"2024-01-17T15:21:37.468396+0800","caller":"etcdmain/etcd.go:73","msg":"Running: ","args":["./etcd"]}

// 随后在B终端开始用客户端命令行
cd /tmp/etcd-download-test/

// 使用 put 命令可以将一个值与一个键相关联
./etcdctl put mykey "this is the value"

// 使用 get 命令可以检索与指定键相关联的值,如果键存在就会输出值
./etcdctl get mykey

// 使用 del 命令可以删除一个键及其关联的值,如果删除成功则返回1否则0
./etcdctl del mykey

// 使用get和--prefix可以实现范围取值
./etcdctl put mykey1 "value1"
./etcdctl put mykey2 "value2"
./etcdctl get mykey --prefix
mykey1
value1
mykey2
value2

// 还可以通过将键值设置为空来搜索全部键值对
etcdctl get "" --prefix

租约lease

etcd中有种稍微特殊一点的机制:租约Lease,用于为键值对设置过期时间(TTL,Time To Live)。Lease允许键值对在一段时间后自动过期,除非租约被续约。

PS:一个租约lease可以同时绑定多个键值对,但一个键值在任何时刻对只能对应一个租约lease

1
2
3
4
5
6
7
8
// TTL单位是秒,同时被创建时立即生效,执行成功时会返回一个leaseId
./etcdctl lease grant <TTL>

// 在存放键值对时,使用--lease来设置租约值,一个leaseid可以绑定多个键值对,当该lease过期时,所有绑定的键值对都会自动过期
./etcdctl put <key> <value> --lease=<LEASE_ID>

// 可以使用keep-alive来防止某个租约lease过期,执行后会定期去续约该租约
./etcdctl lease keep-alive <LEASE_ID>

etcd还支持对某个键或者特定前缀甚至全部键进行监听,当发生新增、修改、删除等操作时,etcd就会向客户端发送一个时间通知

1
2
3
4
5
6
7
8
// 监听某个特定的键
etcdctl watch <key>

// 监听特定前缀的键
etcdctl watch <prefix> --prefix

// 监听全部键
etcdctl watch "" --prefix

修订号revision

etcd还有个很厉害的revision修订号特性,它用于标识键值存储中数据变动的版本。每当存储在etcd中的数据发生变化(新增、删除、更新),全局的revision就会递增,revision在整个etcd集群中是唯一标识。

我们在读取键值对时可以通过指定特定的revision号来读取历史读取,也可以监听某个键时从指定版本号开始。

PS:etcd中每次操作其实都是通过事务来完成的,一个事务可能包含多个操作,所有操作要么全部成功,要么全部失败。每个成功的事务revision都会递增。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 存放键值对,通过--write-out="json"可以看到此时revision版本号为22
./etcdctl put test-revision "1"
./etcdctl get test-revision --write-out="json"
{"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":22,"raft_term":2},"kvs":[{"key":"dGVzdC1yZXZpc2lvbg==","create_revision":22,"mod_revision":22,"version":1,"value":"MQ=="}],"count":1}

// 更改test-revision键的值为2,此时revision版本号递增为23
./etcdctl put test-revision "2"
./etcdctl get test-revision --write-out="json"
{"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":23,"raft_term":2},"kvs":[{"key":"dGVzdC1yZXZpc2lvbg==","create_revision":22,"mod_revision":23,"version":2,"value":"Mg=="}],"count":1}

// 若不带--rev参数则默认读取最新版本号
./etcdctl get test-revision
test-revision
2

// 指定--rev为22即可看到修改前的值
./etcdctl get test-revision --rev=22
test-revision
1

和zookeeper基本比较

可以看到etcd的基本用法和API和zookeeper类似,他们都被用来做元数据的存储,依靠于云服务和k8s流行,etcd在新项目中用的越来越多了。

etcd相对于zookeeper,具有以下优点,

  • 更简单的一致性算法(Raft)。
  • 提供更现代的API接口(HTTP/gRPC)。
  • 容易部署和操作(单个静态的Go二进制文件)。
  • 与Kubernetes和其他现代分布式系统紧密集成。
  • 支持租约和TTL,适用于服务发现和配置管理。

在k8s中etcd是一个很重要的组件,他负责存储和管理所有集群数据,来确保集群的一致性和可用性。

  1. 持久化集群状态: Kubernetes的所有组件状态都存储在etcd中。这包括资源对象如Pods、Services、Deployments、ConfigMaps、Secrets等。
  2. API Server的后端存储: Kubernetes的API Server是与用户和内部组件交互的主要接口。当API Server收到资源的创建、更新或删除请求时,它会将这些更改反映到etcd中,以此来持久化这些更改。
  3. 服务发现和配置etcd用于服务发现,存储内部服务的地址和端口,以便其他组件可以找到并与它们通信。同时,它也用于存储集群配置,如调度信息、节点信息等。
  4. 分布式锁和领导者选举: Kubernetes中的某些组件(如scheduler和controller manager)需要在多实例部署时进行领导者选举,以确保在任何给定时刻只有一个实例在执行操作。etcd提供了分布式锁和领导者选举功能。

Golang接入etcd库通常使用官方库:go.etcd.io/etcd/client/v3

具体使用文档可看:https://github.com/etcd-io/etcd/tree/main/client/v3

参考资料