ETCD入门实战:

一、什么是ETCD

etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现,号称云原生分布式存储的基石
官网地址:https://etcd.io/

/etc 是linux 操作系统的配置存储目录, d distributed分布式缩写,简单理解为分布式配置数据库

CAP原理

也叫CAP原则,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),最多只能同时三个特性中的两个,三者不可兼得。
CAP原理的提出主要是针对分布式场景,所以P是必须具备的。


CAP原理

分布式键值存储系统对比

etcd zookeeper consul NewSQL
CAP CP CP CP CP
开发语言 go java go C/C++
线性读 Y N N 有时候
多版本并发控制 Y N N 有时候
事务 数据内容比较、读或写 版本检查,写 数据内容比较、锁、读或写 SQL式事务
用户权限 RBAC 访问控制列表 访问控制列表 每个数据库的权限和每个表的授权
数据更新通知 历史和当前健范围 当前键和目录 当前键(支持前缀) 触发器(有时候)
http/json api Y N Y 很少
最大数据库大小 几GB 几百MB到几GB 几百MB以上 几TB
最小线性读时延 网络RTT 不支持线性读 网络RTT+fsync 取决于系统和网络时钟

其实eureka专注于服务发现,严格来说不算是分布式键值存储系统

NewSQL 分布式关系型数据库,主流有google公司的Cloud Spanner,CockroachDB(与PostgreSQL兼容的开源分布式SQL数据库,由熟悉Google Cloud Spanner的前谷歌员工开发),ClustrixDB(现归MariaDB所有,这个横向扩展的集群关系HTAP(混合事务/分析处理)数据库采用无共享架构设计。ClustrixDB主要与MySQL和MariaDB兼容)

总的来说,每种系统都有其优势,etcd的优势在于配置信息共享和方便运维,etcd设计理念是设计成大规模分布式系统的通用底座,因此在云原生领域得到广泛使用;Zookeeper优势在于稳定性在大数据领域应用很广;Consul的优势在于服务发现。

二、 实现原理

1.架构图

架构图

2.架构解析

从 etcd 的架构图中我们可以看到,etcd 主要分为四个部分。

  • HTTP Server:用于处理用户发送的 API 请求以及其集群节点之间数据通信。
  • Store:涉及KV存储,WAL文件(预写式日志),Snapshot管理等,用于处理 etcd 支持的各类功能的事务,包括数据索引、节点状态变更、监控与反馈、事件处理与执行等,是 etcd 对用户提供的大多数 API 功能的具体实现。
  • Raft: etcd 的核心,是Raft 强一致性算法的具体实现。
  • 复制状态机:抽象模块的模块,状态机的数据维护在内存中,定期持久化到磁盘,每次写请求会持久化到WAL文件,并根据写请求的内容修改状态机数据

3.数据读写过程

  • 读取:由于集群所有节点数据都是强一致性的,读取可以随机读取,leader和follow 都可以读取
  • 写入:如果请求发到follow会转发给leader,由leader写入,然后分发给follower

4.如何选举

  • 集群开始的时候,所有节点的角色都是Follower
  • 当节点在指定的时间没有收到Leader 或者 Candidate的有效消息时会发起选举投票,指定时间是选举超时时间,是一个随机的值(防止多节点同时发起选举,Leader无法被选出),心跳时间比这个时间短
  • 投票过程:
    1. Follower 递增Term
    2. 自身状态变成Candidate
    3. 投票给自己
    4.向集群其它节点发起投票请求(Request Vote)
    当超过集群一半节点都同意,状态变成Leader,立即向集群所有其它节点发送心跳
    当发现其它Leader 节点并且Term不小于自己的term ,状态变成Follow,否则丢弃消息

数据通道

  • Stream类型通道: 主要用于传输数据量较小的信息,例如心跳、日志追加消息,节点之间维护长连接

  • Pipeline 类型通道: 主要用于处理数据量大的信息,比如snapshot,采用短连接,与心跳等消息区分处理,保证集群稳定

三、 应用场景

etcd的定位是通用的一致性key/value的存储,典型的应用场景包括分布式数据库、服务注册与发现、负载均衡、分布式锁、分布式队列、消息发布与订阅、分布式通知与协调、集群监控与leader竞选

四、 发展里程碑

etcd目前最新的是3.x版本,有3个重要里程碑版本,分别是etcd 0.4,etcd 2.0 和etcd 3.0; etcd 0.4是对外发布的第一个稳定版本,etcd2.0与etcd3.0版本差别比较,具体如下:

  • v3版本采用gRPC+protobuf 取代 v2版本的Http+json的通讯方式,同时保留v2版本的方式,提高整体吞吐率,降低时延
  • v3采用磁盘数据库代替v2 key-value内存数据库
  • v3引入多版本的键空间(MVCC),支持访问历史版本key
  • v3引入事务概念,etcd服务的多个请求合并成一个操作
  • v3摒弃v2的key-value的层级和目录,采用扁平的二进制键空间
  • v3更轻量级的基于租约(Lease)的key自动过期机制,取代基于TTL的key过期机制
  • v3 watch机制重新设计,采用基于http2的server push,对事件进行多路复用优化
    v2采用的是http长连接的事件驱动机制

etcd v3 版本依然保留etcd v2的协议和api,同时提供一套v3的API,也就是说,两个版本共享一套raft协议代码的,在于api不同,存储不同,数据相互隔离,采用v2版本API 只能用v2版本的API,v3版本只能用v3 版本的API

五、 常用操作

1. 安装部署

1) 单机部署

可以使用二进制或源码下载安装,但是需要自己写配置文件,推荐使用yum安装方式

hostnamectl set-hostname etcd-1
wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
# yum 仓库中的etcd版本为3.3.11,如果需要最新版本的etcd可以进行二进制安装
yum -y install etcd #安装
systemctl enable etcd 
systemctl start etcd #启动

默认配置文件vim /etc/etcd/etcd.conf

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379"  
#ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://xx.xx.xx.xx:2379"  #如果需要其它机器访问需要添加机器ip的url
ETCD_NAME="default"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379" 

2) 集群部署

集群部署分静态配置和服务发现,常用是静态配置

静态配置

1.三台机器分别安装etcd,ip分别为172.16.0.1;172.16.0.2;172.16.0.3;

  yum install etcd -y

2.修改vim /etc/etcd/etcd.conf

#[Member]
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://172.16.0.1:2379"  #对外提供服务地址
ETCD_LISTEN_PEER_URLS="http://172.16.0.1:2380" #监听的地址
ETCD_NAME="etcd1"     # 节点名称

#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.0.1:2380"  #该节点同伴监听地址,这个值会告诉集群中其他节点
ETCD_ADVERTISE_CLIENT_URLS="http://172.16.0.1:2379" #对外公告的该节点客户端监听地址,同步给集群其它节点

ETCD_INITIAL_CLUSTER="etcd1=http://172.16.0.1:2380,etcd2=http://172.16.0.2:2380,etcd3=http://172.16.0.3:2380"   # 集群中所有节点的信息

ETCD_INITIAL_CLUSTER_TOKEN="etcd-token" #每个集群唯一
ETCD_INITIAL_CLUSTER_STATE="new"  #新建集群值为 new;已经存在的集群值为 existing

另外两个机器配置记得替换IP 172.16.0.1 和etcd1 节点名称
3.分别启动etcd服务

systemctl start etcd # 第一个节点启动会阻塞等待第二个节点启动

2. 访问安全

etcd 默认是没有开启访问控制的,访问安全包括用户的认证和授权,传输安全是指使用SSL/TLS来加密信道,本身证书也可以来做认证

1) 基于身份验证的访问控制

采用基于角色访问控制(RBAC)

etcdctl user add root #首开添加root账户,才能开始认证
etcdctl auth enable #开启认证 ,默认有root角色,拥有所有权限,授予root用户
etcdctl role add test --user=root:pwd # 添加角色
etcdctl role grant-permission  --from-key test read "" --user=root:pwd #角色授予所有key读权限(read,write,readwrite)
etcdctl user grant-role test test # 用户test授予test角色

2) 基于证书的访问控制开(支持双向认证)

#[Security]
ETCD_CERT_FILE="server.pem" #服务端证书
ETCD_KEY_FILE="server-key.pem" #
ETCD_CLIENT_CERT_AUTH="true" #是否开启客户端端证书认证
ETCD_TRUSTED_CA_FILE="ca.pem" #客户端服务器TLS授信的CA证书路径,
ETCD_AUTO_TLS="true" # 客户端TLS是否使用自动生成的证书

ETCD_PEER_CERT_FILE="peer.pem" #节点通讯采用的客户端证书
ETCD_PEER_KEY_FILE="peer-key.pem" 
ETCD_PEER_CLIENT_CERT_AUTH="true" #是否启用peer客户端证书认证
ETCD_PEER_TRUSTED_CA_FILE="ca.pem" 服务端TLS授信的CA证书路径
ETCD_PEER_AUTO_TLS="true" #是否使用自动生成的证书

3、 常用命令

默认安装自带etcdctl 命令行客户端,分两个版本ETCDCTL_API=2和ETCDCTL_API=3,两个版本不一样,操作的数据也不相容

以export ETCDCTL_API=3 为例

  • help 查看所有命令集
etcdctl help
  • put 命令
etcdctl put /test1 value1 #设置test1=value1
etcdctl put /test1 value2 # 存在直接覆盖

etcdctl put /test1 value3 --lease=1234abc #绑定租赁id,租赁时间到期自动删除
etcdctl put /test1 value4 --ignore-lease # 使用当前key的租赁
etcdctl put /test1 value5 --prev-kv #设置值,并返回上一个版本的值
  • get查看
etcdctl get /test1 #获取key=/test1的值,返回key和value
etcdctl get ""  --from-key #返回比空字符串大的key的键值对,该例返回所有数据
etcdctl get "dir" --prefix --keys-only  --limit=5 # 返回"dir" 前缀的键最多5个
etcdctl get /test1 /test4 #获取[/test1,/test4) 范围的键值对,左闭右开,不包括/test4
etcdctl get /test1 --print-value-only #只返回值
etcdctl get /test1  --consistency='l'  #获取key=/test1的键值对,consistency  'l' 代表线性读(执行raft), 's' 代表串行化读

etcdctl get /test1 -w json #查看key=/test1的版本数据,返回数据如下:
#cluster_id:请求的etcd集群ID。
#member_id:请求的etcd节点ID。
#revision:etcd服务端当前全局数据版本号。对任一key的put或delete操作都会使#revision自增1。revision=1是etcd的保留版本号,因此用户的key版本号将从2开始。
#raft_term:etcd当前raft主节点任期号。
#create_revision:当前key创建时全局数据版本号revision的值。
#mod_revision:当前key最后一次修改时全局数据版本号revision的值。
#version:当前key的数据版本号。key创建时version为1,对当前key进行put操作会使version自增1,将key删除后,重新创建,version又会从1开始计数

  • del 命令
etcdctl del /test1 #删除指定key
etcdctl del /test1 --prev-kv #返回删除的键值对
etcdctl del /test --from-key # 删除比/test大的所有key,也支持--prefix 按前缀删除
  • watch命令
etcdctl watch foo -- echo watch event received #watch key=foo 输出指定文字
etchctl watch foo --rev=2 #从2版本开始watch,返回中间所有修改的版本
etcdctl watch foo -- sh -c "env | grep ETCD_WATCH_" 
# PUT
# foo
# bar
# ETCD_WATCH_REVISION=11
# ETCD_WATCH_KEY="foo"
# ETCD_WATCH_EVENT_TYPE="PUT"
# ETCD_WATCH_VALUE="bar"
  • lease 命令(租约)
etcdctl lease grant 10 #创建一个10s的租约,返回租约的id,用于绑定key
etcdctl lease revoke 1234abc #删除id=1234abc 的租约
etcdctl lease timetolive 1234abc #查看id=1234abc 的租约剩余时间
etcdctl lease timetolive --keys 1234abc #查看id=1234abc 的租约剩余时间,并显示关联的key
etcdctl lease keep-alive -- once 1234abc #一次续约id=1234abc 的租约,并退出,不加--once 命令挂起,到期自动续约
etcdctl lease list #查看所有激活的租期

  • member 命令(集群成员管理)
etcdctl member add newMember --peer-urls=https://127.0.0.1:12345

Member ced000fda4d05edf added to cluster 8c4281cc65c7b112

ETCD_NAME="newMember"
ETCD_INITIAL_CLUSTER="newMember=https://127.0.0.1:12345,default=http://10.0.0.30:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

etcdctl member update 2be1eb8f84b7f63e --peer-urls=https://127.0.0.1:11112
etcdctl member remove 2be1eb8f84b7f63e
etcdctl member list #查看集群列表
  • endpoint 查看节点状态
etcdctl endpoint status -w table #查看默认节点状态,table格式输出
etcdctl endpoint --cluster  status -w table # 查看集群状态
etcdctl endpoint --cluster hashkv -w json #查看集群hashkv

六、 集群故障处理

1. 数据备份

etcdctl snapshot save  backup.db  #数据备份到当前目录下backup.db
etcdctl -w table snapshot save  backup.db 

2. 数据恢复

etcdctl --data-dir=/var/lib/etcd/backup.etcd snapshot restore backup.db #恢复数据到新目录
#每个节点恢复数据,然后修改配置指定新的数据目录,最后重启所有节点

注意数据目录权限,权限不够,提示不是很友好

3. 数据迁移

场景1 更换高性能盘

1.停掉etcd服务
2.高性能盘上创建新的数据目录
3.copy旧数据文件到新数据目录中
4.修改配置文件的数据目录为新目录,然后重启服务

场景2 更换高性能物理机器,不停服切换

1.新的机器先安装好etcd服务
2.先启动安装好的一台etcd,单独起来,然后查看etcd的member的ID
3.到原有的三台etcd集群上,将第二部步中起来的etcd添加到集群(添加节点需要用到etcd的member ID 和peer-urls地址)
4.将原来三台的etcd的ETCD_INITIAL_CLUSTER地址添加进来,将ETCD_INITIAL_CLUSTER_STATE的new改为existing,删除数据目录,重启etcd
5.其它两台重复2-4步骤
6.确保新的三台已加入集群且数据一致,然后把原有三台剔除集群

运行时的重配置都需要经过两个阶段,1.先通知集群新的配置,采用member api 操作,2.启动新的节点,指定正确的initial-cluster,initial-cluster-state设置为existing,新节点启动会校验initial-cluster与当前集群的配置匹配

场景3 直接拿着etcd快照,进行etcd集群恢复

1.获取快照
2.先将新的三台组成集群,启动起来
3.用etcd快照恢复到新目录,在三台机器上都执行
4.分别修改目录配置到新目录,最后重启etcd

你可能感兴趣的:(ETCD入门实战:)