介绍

etcd是一个高可用的 Key/Value 存储系统,主要用于分享配置和服务发现。它是一款云原生时代的首选元数据存储产品,已经成为云原生和分布式系统的存储基石。类似项目有zookeeper和consul。

etcd具有以下特点

  • 完全复制:集群中的每个节点都可以使用完整的存档
  • 高可用性:Etcd可用于避免硬件的单点故障或网络问题
  • 一致性:每次读取都会返回跨多主机的最新写入
  • 简单:包括一个定义良好、面向用户的API(gRPC)
  • 安全:实现了带有可选的客户端证书身份验证的自动化TLS
  • 快速:每秒10000次写入的基准速度
  • 可靠:使用Raft算法实现了强一致、高可用的服务存储目录

etcd架构介绍

Client层

  • 组成
    • client v2 API 客户端库
    • client v3 API 客户端库
  • 作用
    • 提供了简洁易用的 API
    • 支持负载均衡、节点间故障自动转移
    • 极大降低业务使用 etcd 复杂度,提升开发效率、服务可用性

API 网络层

  • client 访问 server的通信协议
    • v2API
      • HTTP/1.x 协议
    • v3API
      • gRPC 协议
      • HTTP/1.x 协议(通过 etcd grpc-gateway 组件支持)
  • server 节点之间的通信协议
    • 节点间通过 Raft 算法实现数据复制和 Leader 选举等功能时使用的 HTTP 协议

Raft 算法层(基石和亮点)

  • 核心算法组成
    • Leader 选举
    • 日志复制
    • ReadIndex
  • 作用
    • 用于保障 etcd 多个节点间的数据一致性、提升服务可用性等

功能逻辑层(核心特性实现层)

  • KVServer 模块

    • 限速判断(保证集群稳定性,避免雪崩)

    • 生成一个唯一的 ID,将此请求关联到一个对应的消息通知 channel,然后向 Raft 模块发起(Propose)一个提案(Proposal)
    • 等待此 put 请求,等待写入结果通过消息通知 channel 返回或者超时。etcd 默认超时时间是 7 秒(5 秒磁盘 IO 延时 +2*1 秒竞选超时时间),如果一个请求超时未返回结果,则可能会出现 etcdserver: request timed out 错误
  • MVCC 模块

    • 读场景

      img

    • 写场景

    • treeIndex 模块(内存树形索引模块)

      • 保存用户 key 和版本号的映射关系
    • boltdb 模块

      • 基于 B+ tree 实现的 key-value 键值库,支持事务,提供 Get/Put 等简易 API 给 etcd 操作
      • 每次修改操作,生成一个新的版本号 (revision),以版本号为 key, value 为用户 key-value 等信息组成的结构体
      • 数据隔离
        • boltdb 里每个 bucket 类似对应 MySQL 一个表
          • 用户的 key 数据存放的 bucket 名字的是 key
          • etcd MVCC 元数据存放的 bucket 是 meta
  • Auth 鉴权模块

  • Lease 租约模块

  • Compactor 压缩模块

  • Quota 模块(配额)

  • Apply模块

存储层

  • 预写日志 (WAL) 模块
    • 可保障 etcd crash 后数据不丢失
  • 快照 (Snapshot) 模块
  • boltdb 模块
    • 保存了集群元数据和用户写入的数据

参考文献

安装与配置

本文基于 centos7etcd v3.5.1 进行讲解,请注意版本软件区分。

安装

下载etcd

curl -O  https://github.com/etcd-io/etcd/releases/download/v3.5.1/etcd-v3.5.1-linux-amd64.tar.gz

PS:curl默认不支持Https,命令curl -V(V大写)查看Protocols项有没有https ,如果没有就要用命令:yum install openssl-devel 装SSL

解压文件

tar -zxvf etcd-v3.5.1-linux-amd64.tar.gz

cd etcd-v3.5.1-linux-amd6

添加环境变量

etcd是服务端,etcdctl是运维人员操作的控制端,一般只需要装etcd,现在是学习就都装在同一台机器。

cp etcd /usr/local/bin
cp etcdctl /usr/local/bin

PS:用echo $PATH查看自己的环境变量路径

修改环境变量PATH

vi /etc/profile

在文件最后加入变量,因为etcd默认使用V2版本,我们需要V3版本的API

export ETCDCTL_API=3

刷新环境变量

source /etc/profile

查看版本信息

etcd -version
或
etcdctl version

启动etcd

单机部署

启动

etcd

直接运行命令 ./etcd 就可以启动了,非常简单。默认使用2379端口为客户端提供通讯, 并使用端口2380来进行服务器间通讯。

测试

[root@VM-0-15-centos ~]# etcdctl put foo bar
OK
[root@VM-0-15-centos ~]# etcdctl get foo
foo
bar

集群部署

内容略去。。。。。。

其他配置

创建etcd配置文件

[root@VM-0-15-centos ~]# mkdir -p /var/lib/etcd/
[root@VM-0-15-centos ~]# cat <<EOF | sudo tee /etc/etcd.conf
> # 节点名称
> ETCD_NAME=etcd1
> # 数据存放位置
> ETCD_DATA_DIR=/var/lib/etcd/
> EOF

创建开机启动文件

vim  /etc/systemd/system/etcd.service

写入以下配置信息

[Unit]
Description=Etcd Server
Documentation=https://github.com/coreos/etcd
After=network.target
 
[Service]
User=root
Type=notify
#这个文件特别关键,etcd使用的环境变量都需要通过环境变量文件读取
EnvironmentFile=-/etc/etcd.conf
ExecStart=/usr/local/bin/etcd
Restart=on-failure
RestartSec=10s
LimitNOFILE=40000
 
[Install]
WantedBy=multi-user.target

PS:EnvironmentFile=-/etc/etcd.conf 这个配置项里/etc前的-K8S生成配置文件时就有的,不是我误写的。

重新加载配置 && 开机启动 && 启动etcd

systemctl daemon-reload && systemctl enable etcd && systemctl start etcd

开机启动设置状态,状态enabled

[root@VM-0-15-centos ~]# systemctl list-unit-files etcd.service
UNIT FILE    STATE  
etcd.service enabled

1 unit files listed.

查看etcd状态

systemctl show etcd.service

查看2379端口是否启动成功

[root@VM-0-15-centos ~]# netstat -an |grep 2379
tcp        0      0 127.0.0.1:2379          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:50822         127.0.0.1:2379          ESTABLISHED
tcp        0      0 127.0.0.1:2379          127.0.0.1:50822         ESTABLISHED

PS: CentOS默认没有装netstat,需要 yum install -y net-tools 自己装