etcd 诞生于 CoreOS 公司,最初用于解决集群管理系统中 OS 升级的分布式并发控制,配置文件的存储与分发等问题。基于此,etcd 被设计为提供高可用,强一致的小型 key-value 数据存储服务,该项目当前隶属于 cncf 基金会。目前根据不完全统计有超过 30 个公司在自己的项目中使用了 etcd,其中最出名的就是 Google 公司开源的 kubernetes,kubernetes 使用 etcd 来存储关键的元数据。
etcd 可以通过多种方式安装,可以直接下载官方提供的 tar 包或者通过使用官方镜像容器启动。
我们这里采用下载 tar 包的方式安装 etcd (以 Linux 为例)
curl -L https://github.com/etcd-io/etcd/releases/download/v3.4.14/etcd-v3.4.14-linux-amd64.tar.gz -o /tmp/etcd-v3.4.14-linux-amd64.tar.gz
mkdir -p /tmp/etcd-download-test
tar -xzvf /tmp/etcd-v3.4.14-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1
通过 ./etcd --version
查看 etcd 版本
./etcd &>etcd.log &
etcd 是分布式的,可靠的,key-value 存储系统,用于存储分布式系统中的关键数据的。
在一个 etcd 集群中通常会由 3 个或者 5 个节点组成,多个节点之间会由一个叫 Raft 的一致性算法方式来完成分布式一致性协同,多个节点之间算法会选举出一个 leader,由 leader 来负责数据的同步与分发,当 leader 发生故障的时候,系统自动选取另一个节点成为 leader 并重新完成数据的同步与分发
etcd 对外暴露非常简单的 http 接口,etcd 还提供 watch 的机制实时的拿到数据的增量更新从而保持与 etcd 中的数据保持一致
etcd 支持对一个 key 发起多次修改,而且通过上面可以知道每一次修改都对应了一个版本号,这样我们查询数据的时候可以指定版本号获取指定版本的数据,如果不指定数据就会返回最新的版本数据。
我们还可以在 watch 的时候指定数据的版本,通过这种方式创建一个 watcher,并且通过这个 watcher 提供的数据管道能够获取制定版本之后所有的数据变更,如果我们指定的是一个旧版本,那我们可以马上拿到从旧版本到新版本的数据更新。
在 etcd 中所有的数据都存储在一棵 B+ 树中,这颗 B+ 树是保存在磁盘中的如下图灰色的部分,这棵树维护着 revision 到 value 的映射关系,当我们指定 revsion 的时候可以通过这颗 b+ 树直接返回数据,当使用 watch 的来订阅数据的时候也可以通过这颗 b+ 树中维护的 revision 到 value 的映射关系从而通过指定的 revision 之后遍历 b+ 树从而获取数据的增量更新
同时在 etcd 内部还维护了另一颗 b+ 树,它维护着 key-revision 的映射关系,这样我们如果想通过 key 查找数据的时候,我们通过这两颗 b+ 树就可以实现
在这种多版本历史数据的机制下,可能会造成内存和磁盘的大量消耗,这样对资源有限的场景是不能接受的,所以 etcd 中有 Compaction 的机制来定期清理历史数据
etcd 的 transaction 的机制比较简单,可以理解为一段 if-else 的程序
在 etcd 内部会保证整个事务操作的原子性
通过 etcd 的事务机制来保证 kubernetes 中多个 APIServer 的对同样一份数据修改的一致性
lease 是分布式系统中常见的一个概念,用于代表一个租约
如上图创建了一个 10 的租约,如果在 10 内不做任何操作,这个租约就会过期
然后创建了 key1 和 key2 两个数据并绑定到这个租约上,如果租约过期,etcd 就会自定清理掉 key1 和 key2 的数据
我们也可以通过调用 KeepAlive 方法来续约
etcd 可以允许将多个 key 绑定到同一个 lease 对象上,这样可以大幅减少 lease 对象个数和刷新时间
创建 key0 到 key9
./etcdctl get key1 key6
./etcdctl get key --prefix