etcd 是 CoreOS 团队发起的一个开源项目(Go 语言,其实很多这类项目都是 Go 语言实现的,只能说很强大),实现了分布式键值存储和服务发现,etcd 和 ZooKeeper/Consul 非常相似,都提供了类似的功能,以及 REST API 的访问操作,具有以下特点:
- 简单:安装和使用简单,提供了 REST API 进行操作交互
- 安全:支持 HTTPS SSL 证书
- 快速:支持并发 10 k/s 的读写操作
- 可靠:采用 raft 算法,实现分布式系统数据的可用性和一致性
etcd 可以单个实例使用,也可以进行集群配置,因为很多项目都是以 etcd 作为服务发现,比如 CoreOS 和 Kubernetes,所以,下面我们使用 Docker 简单搭建一下 etcd 集群。
1. 主机安装
如果不使用 Docker 的话,etcd 在主机上安装,也非常简单。
Linux 安装命令:
1 | $ curl -L https://github.com/coreos/etcd/releases/download/v3.3.0-rc.0/etcd-v3.3.0-rc.0-linux-amd64.tar.gz -o etcd-v3.3.0-rc.0-linux-amd64.tar.gz && |
其实就是将编译后的二进制文件,拷贝到/usr/local/bin/
目录,各个版本的二进制文件,可以从 https://github.com/coreos/etcd/releases/ 中查找下载。
Mac OS 安装命令:
1 | $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null |
执行下面命令,查看 etcd 是否安装成功:
1 | $ etcd --version |
2. 集群搭建
搭建 etcd 集群,需要借助下 Docker Machine 创建三个 Docker 主机,命令:
1 | $ docker-machine create -d virtualbox manager1 && |
为防止 Docker 主机中垃取官方镜像,速度慢的问题,我们还需要将 etcd 镜像打包推送到私有仓库中,命令:
1 | $ docker tag quay.io/coreos/etcd 192.168.99.1:5000/quay.io/coreos/etcd:latest && |
另外,还需要将私有仓库地址配置在 Docker 主机中,并重启三个 Docker 主机,具体配置参考:Docker 三剑客之 Docker Swarm
Docker 主机配置好之后,我们需要使用docker-machine ssh
命令,分别进入三个 Docker 主机中,执行 Docker etcd 配置命令。
manager1 主机(node1 192.168.99.100
):
1 | $ docker run -d --name etcd \ |
worker1 主机(node2 192.168.99.101
):
1 | $ docker run -d --name etcd \ |
worker2 主机(node1 192.168.99.102
):
1 | $ docker run -d --name etcd \ |
先来说明下 etcd 各个配置参数的意思(参考自 etcd 使用入门):
--name
:节点名称,默认为 default。--data-dir
:服务运行数据保存的路径,默认为${name}.etcd
。--snapshot-count
:指定有多少事务(transaction)被提交时,触发截取快照保存到磁盘。--heartbeat-interval
:leader 多久发送一次心跳到 followers。默认值是 100ms。--eletion-timeout
:重新投票的超时时间,如果 follow 在该时间间隔没有收到心跳包,会触发重新投票,默认为 1000 ms。--listen-peer-urls
:和同伴通信的地址,比如http://ip:2380
,如果有多个,使用逗号分隔。需要所有节点都能够访问,所以不要使用 localhost!--listen-client-urls
:对外提供服务的地址:比如http://ip:2379,http://127.0.0.1:2379
,客户端会连接到这里和 etcd 交互。--advertise-client-urls
:对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点。--initial-advertise-peer-urls
:该节点同伴监听地址,这个值会告诉集群中其他节点。--initial-cluster
:集群中所有节点的信息,格式为node1=http://ip1:2380,node2=http://ip2:2380,…
,注意:这里的 node1 是节点的 –name 指定的名字;后面的 ip1:2380 是 –initial-advertise-peer-urls 指定的值。--initial-cluster-state
:新建集群的时候,这个值为 new;假如已经存在的集群,这个值为 existing。--initial-cluster-token
:创建集群的 token,这个值每个集群保持唯一。这样的话,如果你要重新创建集群,即使配置和之前一样,也会再次生成新的集群和节点 uuid;否则会导致多个集群之间的冲突,造成未知的错误。
上述配置也可以设置配置文件,默认为/etc/etcd/etcd.conf
。
我们可以使用docker ps
,查看 Docker etcd 是否配置成功:
1 | $ docker ps |
然后进入其中一个 Docker 主机:
1 | $ docker exec -it etcd bin/sh |
执行下面命令(查看集群成员):
1 | $ etcdctl member list |
可以看到,集群里面有三个成员,并且node2
为管理员,node1
和node3
为普通成员。
etcdctl 是 ectd 的客户端命令工具(也是 go 语言实现),里面封装了 etcd 的 REST API 执行命令,方便我们进行操作 etcd,后面再列出 etcdctl 的命令详细说明。
上面命令的 etcd API 版本为 2.0,我们可以手动设置版本为 3.0,命令:
1 | $ export ETCDCTL_API=3 && /usr/local/bin/etcdctl put foo bar |
部分命令和执行结果还是和 2.0 版本,有很多不同的,比如同是查看集群成员,3.0 版本的执行结果:
1 | $ etcdctl member list |
好了,我们现在再演示一种情况,就是从集群中移除一个节点,然后再把它添加到集群中,为演示 etcd 中使用 Raft 算法,我们将node2
管理节点,作为操作对象。
我们在随便一个主机 etcd 容器中(node2
除外),执行成员移除集群命令(必须使用 ID,使用别名会报错):
1 | $ etcdctl member remove 773d30c9fc6640b4 |
我们再执行下查看集群成员命令(v2 版本):
1 | $ etcdctl member list |
会发现node2
管理节点被移除集群了,并且通过 Raft 算法,node3
被推举为管理节点。
在将node2
节点重新加入集群之前,我们需要执行下面命令:
1 | $ etcdctl member add node2 --peer-urls="http://192.168.99.101:2380" |
可以看到,ETCD_INITIAL_CLUSTER_STATE 值为existing
,也就是我们配置的--initial-cluster-state
参数。
我们再执行下查看集群成员命令(v2 版本):
1 | $ etcdctl member list |
会发现22b0de6ffcd98f00
成员状态变为了unstarted
。
我们在node2
节点,执行 Docker etcd 集群配置命令:
1 | $ docker run -d --name etcd \ |
结果并不像我们想要的那样成功,执行查看日志:
1 | $ docker logs etcd |
这么长的日志,说明啥问题呢,就是说我们虽然重新执行的 etcd 创建命令,但因为读取之前配置文件的关系,etcd 会恢复之前的集群成员,但之前的集群节点已经被移除了,所以集群节点就一直处于停止状态。
怎么解决呢?很简单,就是将我们之前创建的etcd-data
数据卷轴删掉,命令:
1 | $ docker volume ls |
然后,再在node2
节点,重新执行 Docker etcd 集群配置命令(上面),会发现执行是成功的。
我们再执行下查看集群成员命令(v2 版本):
1 | $ etcdctl member list |
3. API 操作
etcd REST API 被用于键值操作和集群成员操作,这边就简单说几个,详细的 API 查看附录说明。
1. 键值管理
设置键值命令:
1 | $ curl http://127.0.0.1:2379/v2/keys/hello -XPUT -d value="hello world" |
查看键值命令:
1 | $ curl http://127.0.0.1:2379/v2/keys/hello |
删除键值命令:
1 | $ curl http://127.0.0.1:2379/v2/keys/hello -XDELETE |
2. 成员管理
列出集群中的所有成员:
1 | $ curl http://127.0.0.1:2379/v2/members |
查看当前节点是否为管理节点:
1 | $ curl http://127.0.0.1:2379/v2/stats/leader |
查看当前节点信息:
1 | $ curl http://127.0.0.1:2379/v2/stats/self |
查看集群状态:
1 | $ curl http://127.0.0.1:2379/v2/stats/store |
当然也可以通过 API 添加和删除集群成员。
4. API 说明和 etcdctl 命令说明
etcd REST API 说明(v2 版本):
更多 API 请查看:etcd API 和 Members API
etcdctl 命令说明:
命令 | 说明 |
---|---|
etcdctl set key value | 添加键值 |
etcdctl get key | 获取键值 |
etcdctl update key value | 更新键值 |
etcdctl rm key | 删除键值 |
etcdctl mkdir dirname | 添加目录(不存在的话创建) |
etcdctl setdir | 添加目录(都创建) |
etcdctl updatedir | 更新目录 |
etcdctl rmdir | 删除目录 |
etcdctl ls | 列出目录 |
etcdctl watch | 监控键值 |
etcdctl exec-watch | 监控键值(执行命令) |
etcdctl list | 查看集群成员 |
etcdctl member add | 添加集群成员 |
etcdctl remove | 移除集群成员 |
参考资料:
- https://www.cnblogs.com/xishuai/p/docker-etcd.html
- Install etcd on Mac with Brew
- linux 基于 docker 部署 etcd 集群
- Docker 搭建 etcd 集群及管理
- DOCKER 服务发现 - ETCD 集群
- docker-machine 使用 discovery 模式搭建 etcd 集群
- 在容器内运行 etcd 集群
- etcd rest api 基本操作
- etcd 使用入门(推荐)
- 创建高可用 etcd 集群
- 初试 ETCD(推荐)
- Run etcd clusters inside containers(官方)