一、概述
etcd是一个高可用的键值存储系统,主要用于共享配置和服务发现。etcd是由CoreOS开发并维护的,灵感来自于 ZooKeeper 和 Doozer,它使用Go语言编写,并通过Raft一致性算法处理日志复制以保证强一致性。Raft是一个新的一致性算法,适用于分布式系统的日志复制,Raft通过选举的方式来实现一致性。Google的容器集群管理系统Kubernetes、开源PaaS平台Cloud Foundry和CoreOS的Fleet都广泛使用了etcd。在分布式系统中,如何管理节点间的状态一直是一个难题,etcd像是专门为集群环境的服务发现和注册而设计,它提供了数据TTL失效、数据改变监视、多值、目录监听、分布式锁原子操作等功能,可以方便的跟踪并管理集群节点的状态。
etcd的特性如下:
- 简单: 支持curl方式的用户API(HTTP+JSON)
- 安全: 可选的SSL客户端证书认证
- 快速: 单实例每秒 1000 次写操作
- 可靠: 使用Raft保证一致性
二、安装和使用
etcd的安装非常简单,可以直接下载编译后的可执行文件。
wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
tar xzvf etcd-v3.0.12-linux-amd64.tar.gz
./etcd --version
启动方式:./etcd
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcd
2019-07-06 04:05:14.961448 I | etcdmain: etcd Version: 3.0.12
2019-07-06 04:05:14.961795 I | etcdmain: Git SHA: 2d1e2e8
2019-07-06 04:05:14.962112 I | etcdmain: Go Version: go1.6.3
2019-07-06 04:05:14.962427 I | etcdmain: Go OS/Arch: linux/amd64
2019-07-06 04:05:14.962808 I | etcdmain: setting maximum number of CPUs to 1, total number of available CPUs is 1
2019-07-06 04:05:14.963079 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd
2019-07-06 04:05:14.964292 I | etcdmain: listening for peers on http://localhost:2380
2019-07-06 04:05:14.964866 I | etcdmain: listening for client requests on localhost:2379
2019-07-06 04:05:14.972043 I | etcdserver: name = default
2019-07-06 04:05:14.972560 I | etcdserver: data dir = default.etcd
2019-07-06 04:05:14.973497 I | etcdserver: member dir = default.etcd/member
2019-07-06 04:05:14.974055 I | etcdserver: heartbeat = 100ms
2019-07-06 04:05:14.974406 I | etcdserver: election = 1000ms
2019-07-06 04:05:14.974802 I | etcdserver: snapshot count = 10000
2019-07-06 04:05:14.975163 I | etcdserver: advertise client URLs = http://localhost:2379
2019-07-06 04:05:14.975658 I | etcdserver: initial advertise peer URLs = http://localhost:2380
2019-07-06 04:05:14.975985 I | etcdserver: initial cluster = default=http://localhost:2380
2019-07-06 04:05:14.987525 I | etcdserver: starting member 8e9e05c52164694d in cluster cdf818194e3a8c32
2019-07-06 04:05:14.988349 I | raft: 8e9e05c52164694d became follower at term 0
2019-07-06 04:05:14.988796 I | raft: newRaft 8e9e05c52164694d [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0]
2019-07-06 04:05:14.989133 I | raft: 8e9e05c52164694d became follower at term 1
2019-07-06 04:05:14.993798 I | etcdserver: starting server... [version: 3.0.12, cluster version: to_be_decided]
2019-07-06 04:05:15.018325 I | membership: added member 8e9e05c52164694d [http://localhost:2380] to cluster cdf818194e3a8c32
2019-07-06 04:05:15.191979 I | raft: 8e9e05c52164694d is starting a new election at term 1
2019-07-06 04:05:15.192994 I | raft: 8e9e05c52164694d became candidate at term 2
2019-07-06 04:05:15.193820 I | raft: 8e9e05c52164694d received vote from 8e9e05c52164694d at term 2
2019-07-06 04:05:15.194712 I | raft: 8e9e05c52164694d became leader at term 2
2019-07-06 04:05:15.195595 I | raft: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at term 2
2019-07-06 04:05:15.197315 I | etcdserver: setting up the initial cluster version to 3.0
2019-07-06 04:05:15.199185 N | membership: set the initial cluster version to 3.0
2019-07-06 04:05:15.199995 I | api: enabled capabilities for version 3.0
2019-07-06 04:05:15.200486 I | etcdmain: ready to serve client requests
2019-07-06 04:05:15.205889 N | etcdmain: serving insecure client requests on localhost:2379, this is strongly discouraged!
2019-07-06 04:05:15.212655 I | etcdserver: published {Name:default ClientURLs:[http://localhost:2379]} to cluster cdf818194e3a8c32
2019-07-06 04:05:15.214893 E | etcdmain: forgot to set Type=notify in systemd service file?
从上面的输出中,我们可以看到很多信息。以下是几个比较重要的信息:
2019-07-06 04:05:14.972043 I | etcdserver: name = default
name表示节点名称,默认为default。
2019-07-06 04:05:14.972560 I | etcdserver: data dir = default.etcd
data-dir 保存日志和快照的目录,默认为当前工作目录default.etcd/目录下。
2019-07-06 04:05:14.974055 I | etcdserver: heartbeat = 100ms
heartbeat为100ms,该参数的作用是leader多久发送一次心跳到followers,默认值是100ms。
2019-07-06 04:05:14.974406 I | etcdserver: election = 1000ms
election为1000ms,该参数的作用是重新投票的超时时间,如果follow在该时间间隔没有收到心跳包,会触发重新投票,默认为1000ms。
2019-07-06 04:05:14.974802 I | etcdserver: snapshot count = 10000
snapshot count为10000,该参数的作用是指定有多少事务被提交时,触发截取快照保存到磁盘。
2019-07-06 04:05:14.975163 I | etcdserver: advertise client URLs = http://localhost:2379
在http://localhost:2379提供HTTP API服务,供客户端交互。
2019-07-06 04:05:14.975985 I | etcdserver: initial cluster = default=http://localhost:2380
在http://localhost:2380和集群中其他节点通信。
集群和每个节点都会生成一个uuid。
启动的时候会运行raft,选举出leader。
采用这种方式启动的etcd只是一个程序,如果启动etcd的窗口被关闭的话则etcd便会被关闭
,所以如果要长期使用的话最好是为etcd开启一个服务,此处便不提供开启服务的方法,如果有需要读者可以自行百度。
etcd命令行接口使用
./etcdctl -h 可以查看用法
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl -h
etcd在键的组织上采用了层次化的空间结构(类似于文件系统中目录的概念),用户指定的键可以为单独的名字,如:testkey,此时实际上放在根目录/下面,也可以为指定目录结构,如/cluster1/node2/testkey,则将创建相应的目录结构。
set get
set
指定某个键的值。
-ttl ‘0’ 该键值的超时时间(单位为秒),不配置(默认为0)则永不超时
–swap-with-value value 若该键现在的值是value,则进行设置操作
–swap-with-index ‘0’ 若该键现在的索引值是指定索引,则进行设置操作
get
获取指定键的值
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl set --ttl '5' key_1 "hello world"
hello world
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl get key_1
hello world
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl get key_1
Error: 100: Key not found (/key_1) [6]
上面第二个get方法在是在5秒之后请求的,已经请求不到key了,因为已经超时。
update
update
对指定键进行修改
–ttl ‘0’ 超时时间(单位为秒),不配置(默认为 0)则永不超时。
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl set --ttl '5' key_1 "hello world"
hello world
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl update key_1 "hello world 2"
hello world 2
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl get key_1
hello world 2
rm
rm
删除某个键值。
–dir 如果键是个空目录或者键值对则删除
–recursive 删除目录和所有子键
–with-value 检查现有的值是否匹配
–with-index ‘0’检查现有的index是否匹配
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl set --ttl '5' key_1 "hello world"
hello world
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl rm key_1
PrevNode.Value: hello world
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl get key_1
Error: 100: Key not found (/key_1) [18]
mk
mk
如果给定的键不存在,则创建一个新的键值。
–ttl ‘0’ 超时时间(单位为秒),不配置(默认为 0)。则永不超时
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl mk /testdir/testkey "hello world"
hello world
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl mk /testdir/testkey "hello world"
Error: 105: Key already exists (/testdir/testkey) [20]
mkdir
mkdir
–ttl ‘0’ 超时时间(单位为秒),不配置(默认为0)则永不超时。
如果给定的键目录不存在,则创建一个新的键目录。
如果给定的键目录存在,则报错
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl mkdir dir2
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl mkdir dir2
Error: 105: Key already exists (/dir2) [21]
setdir
setdir
创建一个键目录。如果目录不存在就创建,如果目录存在更新目录TTL。
–ttl ‘0’ 超时时间(单位为秒),不配置(默认为0)则永不超时。
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl setdir dir3
rmdir
rmdir
删除一个空目录,或者键值对。
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl rmdir dir3
ls
ls
列出目录(默认为根目录)下的键或者子目录,默认不显示子目录中内容。
–sort 将输出结果排序
–recursive 如果目录下有子目录,则递归输出其中的内容
-p 对于输出为目录,在最后添加/进行区分
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl ls
/message
/test
/testdir
/dir2
非数据库操作,非数据库操作包括:备份、监测、节点管理等
backup
backup
备份etcd的数据。
–data-dir etcd的数据目录
–backup-dir 备份到指定路径
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl backup --data-dir default.etcd/ --backup-dir ~/
watch
watch
监测一个键值的变化,一旦键值发生更新,就会输出最新的值并退出。
–forever 一直监测直到用户按CTRL+C退出
–after-index ‘0’ 在指定index之前一直监测
–recursive 返回所有的键值和子键值
先设置mykey="hello world",然后监测mykey
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl set mykey "Hello world"
Hello world
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl watch mykey
在另一个窗口中修改mykey的值:
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl update mykey "test"
test
之前的监控界面便打印出test,然后退出:
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl watch mykey
test
exec-watch
exec-watch
监测一个键值的变化,一旦键值发生更新,就执行给定命令。
–after-index ‘0’ 在指定 index 之前一直监测
–recursive 返回所有的键值和子键值
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl exec-watch mykey -- sh -c "ls"
当我在另一个窗口更新mykey时,输出:
Documentation README.md default.etcd etcd nohup.out
README-etcdctl.md READMEv2-etcdctl.md docker-node1.etcd etcdctl
member
member
list 列出etcd实例
add 添加etcd实例
remove 删除etcd实例
查看列表:
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl member list
8e9e05c52164694d: name=default peerURLs=http://localhost:2380 clientURLs=http://localhost:2379 isLeader=true
删除节点:
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl member remove 8e9e05c52164694d
Removed member 8e9e05c52164694d from cluster
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl member list
Error: client: etcd cluster is unavailable or misconfigured
error #0: dial tcp 127.0.0.1:2379: getsockopt: connection refused
error #1: dial tcp 127.0.0.1:4001: getsockopt: connection refused
向集群中新加节点,例如:
duandingyang@ubuntu:~/etcd-v3.0.12-linux-amd64$ ./etcdctl member add etcd2 http://localhost:2380