Etcd 高可用分布式键值数据库
1, Etcd简介
etcd是CoreOS
团队于2016年6月发起的开源项目,他的目标是构建一个高可用的分布式键值(key_value)数据库。Etcd内部采用raft
协议作为一致性算法,Etcd是基于Go
语言实现的。目前很火的kubernetes
等项目都用到etcd组件作为一个高可用分布式键值存储。
etcd作为服务发现系统,有以下特点:
- 简单: 安装配置简单,而且提供了HTTP API进行交互,使用也很简单
- 安全: 支持SSL证书验证
- 快速: 根据官方提供的benchmark数据,单实例支持每秒2k 读操作
- 可靠: 采用Raft算法,实现分布式系统数据的可用性和一致性
Etcd应用场景
etcd比较多的应用场景适用于服务发现,服务发现(Service Disvocery)要解决的是分布式系统中最常见的问题之一,在同一个分布式集群中的进程或服务如何才能找到对方并建立连接。 服务发现: 就是要了解集群中是否有进程在监听UDP或TCP端口,并通过名字可以进行查找和链接。
解决服务发现的先决条件:
- 一个强一致性、高可用的服务存储目录 基于Ralf算法的etcd天生的就是这样一个强一致性、高可用的服务存储目录
- 一种注册服务和健康服务健康状况的机制。 用户可以在etcd中注册服务,并且对注册的服务配置key TTL,定时保持服务的心跳以达到监控健康状态的效果。
- 一种查找和连接服务的机制。 通过在etcd指定的主题下注册的服务业能在对应的主题下查找到。为了确保连接,我们可以在每个服务机器上都部署一个proxy模式的etcd,这样就可以确保访问etcd集群的服务都能够互相连接。
2,单节点安装etcd
etcd在生产环境中一般推荐集群方式部署。 etcd目前默认使用2379端口提供HTTP API服务,2380端口和peer通信(这两个端口已经被IANA官方预留给etcd);在之前的版本中可能会分别使用4001和7001,在使用的过程中需要注意这个区别。 我们直接yum安装etcd即可
代码语言:javascript复制yum -y install etcd
启动服务
代码语言:javascript复制systemctl start etcd.service && systemctl enable etcd.service
查看服务状态
代码语言:javascript复制[root@etcd-197 /]# systemctl status etcd
● etcd.service - Etcd Server
Loaded: loaded (/usr/lib/systemd/system/etcd.service; disabled; vendor preset: disabled)
Active: active (running) since 四 2019-08-29 15:27:16 CST; 9s ago
Main PID: 24426 (etcd)
Tasks: 13
Memory: 12.7M
CGroup: /system.slice/etcd.service
└─24426 /usr/bin/etcd --name=default --data-dir=/var/lib/etcd/default.etcd --listen-client-urls=http://localhost:2379
8月 29 15:27:16 etcd-197 etcd[24426]: 8e9e05c52164694d received MsgVoteResp from 8e9e05c52164694d at term 2
8月 29 15:27:16 etcd-197 etcd[24426]: 8e9e05c52164694d became leader at term 2
8月 29 15:27:16 etcd-197 etcd[24426]: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at term 2
8月 29 15:27:16 etcd-197 etcd[24426]: published {Name:default ClientURLs:[http://localhost:2379]} to cluster cdf818194e3a8c32
8月 29 15:27:16 etcd-197 etcd[24426]: ready to serve client requests
8月 29 15:27:16 etcd-197 etcd[24426]: setting up the initial cluster version to 3.3
8月 29 15:27:16 etcd-197 systemd[1]: Started Etcd Server.
8月 29 15:27:16 etcd-197 etcd[24426]: set the initial cluster version to 3.3
8月 29 15:27:16 etcd-197 etcd[24426]: enabled capabilities for version 3.3
8月 29 15:27:16 etcd-197 etcd[24426]: serving insecure client requests on 127.0.0.1:2379, this is strongly discouraged!
3, 安装Etcd集群
Etcd 是 CoreOS 推出的高可用的键值存储系统,主要用于k8s集群的服务发现等,而本身 Etcd 也支持集群模式部署,从而实现自身高可用; Etcd 构建自身高可用集群主要有三种形式:
静态发现: 预先已知 Etcd 集群中有哪些节点,在启动时直接指定好 Etcd 的各个 node 节点地址 Etcd 动态发现: 通过已有的 Etcd 集群作为数据交互点,然后在扩展新的集群时实现通过已有集群进行服务发现的机制 DNS 动态发现: 通过 DNS 查询方式获取其他节点地址信息
3.1, 静态发现搭建Etcd集群
3.1.1, 环境准备
在下面3台机器安装Etcd集群,(注意,Etcd集群节点必须为奇数)
节点/主机名 | IP地址 |
---|---|
Etcd1 | 172.16.1.193 |
Etcd2 | 172.16.1.195 |
Etcd3 | 172.16.1.198 |
3.1.2 安装Etcd
CentOS 官方提供了 Etcd 的rpm,可通过 yum 直接安装,目前 yum 上最新版本为 3.3.11,比较合适;官方最新版本更新到了 3.3.12,鉴于稳定因素,这里使用 3.3.11 搭建
代码语言:javascript复制# yum -y install etcd
# etcd --version
etcd Version: 3.3.11
Git SHA: 2cf9e51
Go Version: go1.10.3
Go OS/Arch: linux/amd64
3.1.3 修改配置文件
默认的配置文件
代码语言:javascript复制[root@Etcd2 /]# cat /etc/etcd/etcd.conf
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
#ETCD_WAL_DIR=""
#ETCD_LISTEN_PEER_URLS="http://localhost:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="default"
#ETCD_SNAPSHOT_COUNT="100000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_QUOTA_BACKEND_BYTES="0"
#ETCD_MAX_REQUEST_BYTES="1572864"
#ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
#ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
#ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
#
#[Clustering]
#ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
#ETCD_INITIAL_CLUSTER="default=http://localhost:2380"
#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
#ETCD_INITIAL_CLUSTER_STATE="new"
#ETCD_STRICT_RECONFIG_CHECK="true"
#
#[Proxy]
#ETCD_PROXY="off"
#ETCD_PROXY_FAILURE_WAIT="5000"
#ETCD_PROXY_REFRESH_INTERVAL="30000"
#ETCD_PROXY_DIAL_TIMEOUT="1000"
#ETCD_PROXY_WRITE_TIMEOUT="5000"
#ETCD_PROXY_READ_TIMEOUT="0"
#
#[Security]
#ETCD_CERT_FILE=""
#ETCD_KEY_FILE=""
#ETCD_CLIENT_CERT_AUTH="false"
#ETCD_TRUSTED_CA_FILE=""
#ETCD_AUTO_TLS="false"
#ETCD_PEER_CERT_FILE=""
#ETCD_PEER_KEY_FILE=""
#ETCD_PEER_CLIENT_CERT_AUTH="false"
#ETCD_PEER_TRUSTED_CA_FILE=""
#ETCD_PEER_AUTO_TLS="false"
#
#[Logging]
#ETCD_DEBUG="false"
#ETCD_LOG_PACKAGE_LEVELS=""
#ETCD_LOG_OUTPUT="default"
#
#[Unsafe]
#ETCD_FORCE_NEW_CLUSTER="false"
#
#[Version]
#ETCD_VERSION="false"
#ETCD_AUTO_COMPACTION_RETENTION="0"
#
#[Profiling]
#ETCD_ENABLE_PPROF="false"
#ETCD_METRICS="basic"
#
#[Auth]
#ETCD_AUTH_TOKEN="simple"
修改后的配置文件,另外两台对照更改
代码语言:javascript复制[root@Etcd1 /]# grep -v "^#" /etc/etcd/etcd.conf
#数据存放的目录
ETCD_DATA_DIR="/var/lib/etcd/etcd1"
#监听的URL,用于与其他节点通讯
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
#对外提供服务的地址,客户端会连接到这里和Etcd进行交互
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#节点的名称
ETCD_NAME="etcd1"
#改节点的member(同伴)监听的地址,这个值会告诉集群中其他节点
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.1.193:2380"
#对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点
ETCD_ADVERTISE_CLIENT_URLS="http://172.16.1.193:2379"
#集群中所有节点的信息,这里的 etcd1 是节点的 --name 指定的名字;后面的172.16.1.93:2380 是 --initial-advertise-peer-urls 指定的值
ETCD_INITIAL_CLUSTER="etcd1=http://172.16.1.193:2380,etcd2=http://172.16.1.195:2380,etcd3=http://172.16.1.198:2380"
# 创建集群的 token,这个值每个集群保持唯一。这样的话,如果你要重新创建集群,即使配置和之前一样,也会再次生成新的集群和节点 uuid;否则会导致多个集群之间的冲突,造成未知的错误
ETCD_INITIAL_CLUSTER_TOKEN="zsf-etcd-cluster"
#新建集群的时候,这个值为 new ;假如已经存在的集群,这个值为 existing
ETCD_INITIAL_CLUSTER_STATE="new"
3.1.4 启动etcd集群,并查看其状态
启动etcd集群
代码语言:javascript复制systemctl start etcd.service
集群启动完成之后我们在任意节点执行etcdctl member list
可列出所有集群节点信息,
[root@Etcd1 /]# etcdctl member list
729a9a39e059871b: name=etcd2 peerURLs=http://172.16.1.195:2380 clientURLs=http://172.16.1.195:2379 isLeader=false
ce1ac55777b620f9: name=etcd1 peerURLs=http://172.16.1.193:2380 clientURLs=http://172.16.1.193:2379 isLeader=true
e62232af7400cdbe: name=etcd3 peerURLs=http://172.16.1.198:2380 clientURLs=http://172.16.1.198:2379 isLeader=false
使用etcdctl cluster-health
检查集群健康状态
[root@Etcd1 /]# etcdctl cluster-health
member 729a9a39e059871b is healthy: got healthy result from http://172.16.1.195:2379
member ce1ac55777b620f9 is healthy: got healthy result from http://172.16.1.193:2379
member e62232af7400cdbe is healthy: got healthy result from http://172.16.1.198:2379
4,etcdctl V3版本使用
etcdctl是一个命令行客户端,它能提供一些简洁的命令,供用户直接跟etcd服务打交道,而无需基于 HTTP API方式。可以方便我们在对服务进行测试或者手动修改数据库内容。建议刚刚接触etcd时通过etdctl来熟悉相关操作。这些操作跟HTTP API基本上是对应的。
4.1 设置环境变量
etcd项目二进制发行包中已经包含了etcdctl工具,etcdctl支持的命令大体上分为数据库操作和非数据库操作两类。 因为我们这边使用的是etcd 3.3.11版本,etcdctl默认操作的事etcd 2.X 版本,2和3版本有些命令不一样,所以我们要添加个环境变量,来使其默认操作etcd 3.X版本
代码语言:javascript复制export ETCDCTL_API=3
或者在`/etc/profile`文件中添加环境变量
vi /etc/profile
...
ETCDCTL_API=3
...
source /etc/profile
4.2 查看当前etcdctl的版本信息
代码语言:javascript复制[root@etcd-197 ~]# etcdctl version
etcdctl version: 3.3.11
API version: 3.3
4.3 ectd常用命令
4.3.1 增
代码语言:javascript复制//增
[root@etcd-197 ~]# etcdctl put zsf 'hello world!'
OK
4.3.2 查
代码语言:javascript复制[root@etcd-197 ~]# etcdctl get zsf
zsf
hello world!
指定为json格式查找
代码语言:javascript复制[root@etcd-197 ~]# etcdctl get --write-out="json" zsf
{"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":6,"raft_term":3},"kvs":[{"key":"enNm","create_revision":6,"mod_revision":6,"version":1,"value":"aGVsbG8gd29ybGQh"}],"count":1}
基于相同前缀查找
代码语言:javascript复制[root@etcd-197 ~]# etcdctl put zsf1 'one'
OK
[root@etcd-197 ~]# etcdctl put zsf2 'two'
OK
[root@etcd-197 ~]# etcdctl get zsf --prefix
zsf
hello world!
zsf1
one
zsf2
two
4.3.3 改
代码语言:javascript复制[root@etcd-197 ~]# etcdctl put zsf "test"
OK
[root@etcd-197 ~]# etcdctl get zsf
zsf
test
4.3.4 删
代码语言:javascript复制[root@etcd-197 ~]# etcdctl del zsf1
1
[root@etcd-197 ~]# etcdctl get zsf1
[root@etcd-197 ~]#
4.3.5 查看集群状态
代码语言:javascript复制[root@etcd-197 ~]# etcdctl --write-out=table endpoint status
---------------- ------------------ --------- --------- ----------- ----------- ------------
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
---------------- ------------------ --------- --------- ----------- ----------- ------------
| 127.0.0.1:2379 | 8e9e05c52164694d | 3.3.11 | 20 kB | true | 3 | 17 |
---------------- ------------------ --------- --------- ----------- ----------- ------------
4.4 集群操作
代码语言:javascript复制member add Adds a member into the cluster
member remove Removes a member from the cluster
member update Updates a member in the cluster
member list Lists all members in the cluster
列出集群成员:
代码语言:javascript复制[root@Etcd1 ~]# etcdctl member list -w table
------------------ --------- ------- -------------------------- --------------------------
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
------------------ --------- ------- -------------------------- --------------------------
| 729a9a39e059871b | started | etcd2 | http://172.16.1.195:2380 | http://172.16.1.195:2379 |
| ce1ac55777b620f9 | started | etcd1 | http://172.16.1.193:2380 | http://172.16.1.193:2379 |
| e62232af7400cdbe | started | etcd3 | http://172.16.1.198:2380 | http://172.16.1.198:2379 |
------------------ --------- ------- -------------------------- --------------------------