简介
ETCD 是CoreOS
团队发起的一个开源项目,实现了分布式键值存储和服务发现,etcd
和ZooKeeper/Consul
非常相似,都提供了类似的功能,以及REST API
的访问操作,具有以下特点:
简单:安装和使用简单,提供了 REST API 进行操作交互
安全:支持 HTTPS SSL 证书
快速:支持并发 10 k/s 的读写操作
可靠:采用 raft 算法,实现分布式系统数据的可用性和一致性
零. 服务部署
环境信息:
机型: 1核 1GB 1Mbps 腾讯云服务器
系统: CentOS Linux release 8.4.2105 (Core)
搭建一个不通过SSL
认证的单机ETCD
,安装部署步骤如下:
- 随便创建一个文件夹,并进入。
1
mkdir etcd & cd etcd
- 创建一个 docekr-compose.yml 文件件, 并将下面配置全部拷贝进去。
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54version: "3"
services:
etcd1:
# etcd uses gcr.io/etcd-development/etcd as a primary container registry, and quay.io/coreos/etcd as secondary.
image: quay.io/coreos/etcd:v3.5.1 # 镜像
container_name: etcd1 # 容器名 --name
restart: always # 总是重启
networks:
- etcd-net # 使用的网络 --network
ports: # 端口映射 -p
- "20000:2379"
- "20001:2380"
environment: # 环境变量 --env
- ALLOW_NONE_AUTHENTICATION=yes # 允许不用密码登录
- ETCD_NAME=etcd1 # etcd 的名字
- ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd1:2380 # 列出这个成员的伙伴 URL 以便通告给集群的其他成员
- ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 # 用于监听伙伴通讯的URL列表
- ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 # 用于监听客户端通讯的URL列表
- ETCD_ADVERTISE_CLIENT_URLS=http://etcd1:2379 # 列出这个成员的客户端URL,通告给集群中的其他成员
- ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster # 在启动期间用于 etcd 集群的初始化集群记号
- ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380 # 为启动初始化集群配置
- ETCD_INITIAL_CLUSTER_STATE=new # 初始化集群状态
- ETCDCTL_API=3 # 升级api版本,使用最新的v3 API
volumes:
- $PWD/etcd1_data:/etcd-data # 挂载的数据卷
- /etc/localtime:/etc/localtime
etcd2:
image: quay.io/coreos/etcd:v3.5.1
container_name: etcd2
restart: always
networks:
- etcd-net
ports:
- "20002:2379"
- "20003:2380"
environment:
- ALLOW_NONE_AUTHENTICATION=yes
- ETCD_NAME=etcd2
- ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd2:2380
- ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
- ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
- ETCD_ADVERTISE_CLIENT_URLS=http://etcd2:2379
- ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster
- ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380
- ETCD_INITIAL_CLUSTER_STATE=new
- ETCDCTL_API=3
volumes:
- $PWD/etcd2_data:/etcd-data
- /etc/localtime:/etc/localtime
networks:
etcd-net: # 网络
driver: bridge # 桥接模式
壹. 测试验证
docker-compose
的基础操作
在ETCD
文件夹运行以下命令,拉起服务:1
docker-compose up
或者后台启动:
1
docker-compose up -d
停止服务:
1
docker-compose down
ETCD 的基础操作
通过etcdctl version 命令查看ETCD
的版本:1
2
3docker exec -it etcd1 etcdctl version
etcdctl version: 3.5.1
API version: 3.5查看节点启动情况:
1
2
3
4
5docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------------------------------
etcd1 /usr/local/bin/etcd Up 0.0.0.0:20000->2379/tcp,:::20000->2379/tcp, 0.0.0.0:20001->2380/tcp,:::20001->2380/tcp
etcd2 /usr/local/bin/etcd Up 0.0.0.0:20002->2379/tcp,:::20002->2379/tcp, 0.0.0.0:20003->2380/tcp,:::20003->2380/tcp查看挂载的数据卷:
1
2
3
4
5docker volume ls
DRIVER VOLUME NAME
local 7982f1ed038a84127d5c08baa59b2e95cbc0474db6750494be4d001a38c7a68d
local etcd_etcd1_data
local etcd_etcd2_data查看指定数据卷的挂载详情:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 注意:没有加 internal 选项时,自动生成卷名时会加上项目名前缀
docker volume inspect etcd_etcd1_data
[
{
"CreatedAt": "2021-11-17T14:56:05+08:00",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "etcd",
"com.docker.compose.version": "1.29.2",
"com.docker.compose.volume": "etcd1_data"
},
"Mountpoint": "/var/lib/docker/volumes/etcd_etcd1_data/_data",
"Name": "etcd_etcd1_data",
"Options": null,
"Scope": "local"
}
]观察集群状态:
1
2
3
4docker exec -it etcd2 /bin/sh
etcdctl --endpoints=http://etcd1:2379,http://etcd2:2379 endpoint health
http://etcd1:2379 is healthy: successfully committed proposal: took = 8.244662ms
http://etcd2:2379 is healthy: successfully committed proposal: took = 8.300642ms获取节点 ID:
1
2
3
4docker exec -it etcd2 /bin/sh
etcdctl member list
ade526d28b1f92f7, started, etcd1, http://etcd1:2380, http://etcd1:2379, false
d282ac2ce600c1ce, started, etcd2, http://etcd2:2380, http://etcd2:2379, false移除节点:
1
2docker exec -it etcd2 /bin/sh
etcdctl --endpoints=http://etcd1:2379,http://etcd2:2379 member remove ade526d28b1f92f7
贰. 关于数据的 CRUD + Watch
CURL
- v3 restful api
我们往一个node
上上传数据,在另一个node
上就能查询到, 因为键和值字段定义为字节数组,因此必须使用JSON
进行base64
编码。1
2
3
4
5
6curl -L http://localhost:20000/v3/kv/put -X POST -d '{"key": "Zm9v", "value": "YmFy"}'
{"header":{"cluster_id":"10220489627942555976","member_id":"12530464223947363063","revision":"3","raft_term":"3"}}
# 注意:这里使用的key与value是basse64加密过的: foo=>Zm9v, bar=>YmFy
# 不然会报错: use curl , illegal base64 data at input byte 4
curl -L http://localhost:20000/v3/kv/range -X POST -d '{"key": "Zm9v"}'
{"header":{"cluster_id":"10220489627942555976","member_id":"12530464223947363063","revision":"3","raft_term":"3"},"kvs":[{"key":"Zm9v","create_revision":"2","mod_revision":"3","version":"2","value":"YmFy"}],"count":"1"} - etcdctl
使用命令行工具etcdctl
。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# 进入节点etcd1, 设置 foo => "bar"
docker exec -it etcd1 etcdctl put foo bar
OK
# 进入节点etcd2, 获取key为 foo 所对应的 value,如果能获得且为 bar,即搭建成功
docker exec -it etcd2 etcdctl get foo
# 按前缀读取:
docker exec -it etcd2 etcdctl get --limit=1 --prefix foo
foo // key
bar // value
# 上面同时返回了 key 和 value,怎么只读取 key 对应的值呢:
docker exec -it etcd2 etcdctl get foo --print-value-only
bar // value
# 所有键值:
docker exec -it etcd2 etcdctl get '' --prefix
foo
bar
# 删除 key 为 foo 的命令:
docker exec -it etcd1 etcdctl del foo
# 删除键值对的命令:
docker exec -it etcd1 etcdctl del --prev-kv foo
1
foo
bar
# 清理所有键值对
docker exec -it etcd1 etcdctl del '' --prefix
1Watch
- etcdctl
应用程序可以使用watch
观察一个键或一系列键来监视任何更新。
打开第一个终端,监听foo
的变化,我们输入如下命令:再打开另外一个终端来对 foo 进行操作:1
docker exec -it etcd1 etcdctl watch foo
第一个终端结果如下:1
2
3
4
5docker exec -it etcd2 /bin/sh
etcdctl put foo 123
OK
etcdctl put foo 456
OK1
2
3
4
5
6PUT
foo
123
PUT
foo
456 - v3 restful api
使用curl
请求:再打开另外一个终端来对1
curl -N http://localhost:20000/v3/watch -X POST -d '{"create_request": {"key":"Zm9v"} }' &
foo
进行操作:第一个终端结果如下:1
2curl -L http://localhost:20000/v3/kv/put -X POST -d '{"key": "Zm9v", "value": "MTIz"}'
curl -L http://localhost:20000/v3/kv/put -X POST -d '{"key": "Zm9v", "value": "NDU2"}'除了以上基本操作,1
2{"result":{"header":{"cluster_id":"10220489627942555976","member_id":"12530464223947363063","revision":"5","raft_term":"3"},"events":[{"kv":{"key":"Zm9v","create_revision":"2","mod_revision":"5","version":"4","value":"MTIz"}}]}}
{"result":{"header":{"cluster_id":"10220489627942555976","member_id":"12530464223947363063","revision":"6","raft_term":"3"},"events":[{"kv":{"key":"Zm9v","create_revision":"2","mod_revision":"6","version":"5","value":"NDU2"}}]}}watch
也可以像get、del
操作那样使用prefix、rev、 hex
等参数,这里就不一一列举了。
ETCD的详细API请参考相关文档。
叁. 总结
祝玩得开心!
Done.