Etcd
Etcd是CoreOS团队发起的一个分布式键值对数据库,可以应用于分布式系统中的配置信息管理和服务发现,也是在k8s集群中被使用的项目,etcd专门为集群环境设计,可以很好的实现数据一致性,提供集群节点管理和服务发现,目前在github.com/coreos/etcd进行维护。etcd重点考虑了一下四个要素:
安装使用Etcd
1 | ~]# wget https://github.com/coreos/etcd/releases/download/v3.2.9/etcd-v3.2.9-linux-amd64.tar.gz |
2 | ~]# tar xf etcd-v3.2.9-linux-amd64.tar.gz |
3 | ~]# cd etcd-v3.2.9-linux-amd64 |
4 | ~]# ls |
5 | Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md #可以先浏览下readme |
启动
1 | ~]# ./etcd |
2 | 2017-11-11 22:48:42.052212 I | etcdmain: etcd Version: 3.2.9 |
3 | 2017-11-11 22:48:42.052266 I | etcdmain: Git SHA: f1d7dd8 |
4 | 2017-11-11 22:48:42.052270 I | etcdmain: Go Version: go1.8.4 |
5 | 2017-11-11 22:48:42.052273 I | etcdmain: Go OS/Arch: linux/amd64 |
6 | 2017-11-11 22:48:42.052279 I | etcdmain: setting maximum number of CPUs to 2, total number of available CPUs is 2 |
7 | 2017-11-11 22:48:42.052286 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd |
8 | 2017-11-11 22:48:42.052814 I | embed: listening for peers on http://localhost:2380 |
9 | 2017-11-11 22:48:42.052977 I | embed: listening for client requests on localhost:2379 |
10 | 2017-11-11 22:48:42.073393 I | etcdserver: name = default |
11 | 2017-11-11 22:48:42.073424 I | etcdserver: data dir = default.etcd |
12 | 2017-11-11 22:48:42.073429 I | etcdserver: member dir = default.etcd/member |
13 | 2017-11-11 22:48:42.073433 I | etcdserver: heartbeat = 100ms |
14 | 2017-11-11 22:48:42.073436 I | etcdserver: election = 1000ms |
15 | 2017-11-11 22:48:42.073439 I | etcdserver: snapshot count = 100000 |
16 | 2017-11-11 22:48:42.073447 I | etcdserver: advertise client URLs = http://localhost:2379 |
17 | 2017-11-11 22:48:42.073452 I | etcdserver: initial advertise peer URLs = http://localhost:2380 |
18 | 2017-11-11 22:48:42.073459 I | etcdserver: initial cluster = default=http://localhost:2380 |
19 | 2017-11-11 22:48:42.075338 I | etcdserver: starting member 8e9e05c52164694d in cluster cdf818194e3a8c32 |
20 | .... |
从启动内容中我们大致可以知道,2379是rest接口端口,2380是集群通信的借口。
查看集群的健康状态:
1 | ~]# curl http://127.0.0.1:2379/health |
2 | {"health": "true"} |
3 | ~]# ./etcdctl cluster-health |
4 | member 8e9e05c52164694d is healthy: got healthy result from http://localhost:2379 |
5 | cluster is healthy |
简单的键值对数据库的使用:
1 | ~]# ./etcdctl set redis/prort 6379 |
2 | 6379 |
3 | ~]# ./etcdctl get redis/prort |
4 | 6379 |
5 | |
6 | ~]# curl -X PUT http://127.0.0.1:2379/v2/keys/testkey -d value='hello world' |
7 | {"action":"set","node":{"key":"/testkey","value":"hello world","modifiedIndex":5,"createdIndex":5}} |
8 | ~]# curl http://127.0.0.1:2379/v2/keys/testkey |
9 | {"action":"get","node":{"key":"/testkey","value":"hello world","modifiedIndex":5,"createdIndex":5}} |
数据目录结构
1 | ~]# tree default.etcd/ |
2 | default.etcd/ |
3 | └── member |
4 | ├── snap |
5 | │ └── db #快照 |
6 | └── wal |
7 | ├── 0000000000000000-0000000000000000.wal #操作日志 |
8 | └── 0.tmp |
服务参数
Etcd服务启动的时候支持一些参数,这些参数也可以通过环境变量的形式传入,命名一般为大写,并且加上ETCD_前缀,例如etcd –name ‘etcd-cluster’ 可以为变量ETCD_NAME=’etcd_cluster’,一些是节点的通用参数:
1 | --name 'default' # 设置节点的别名,数据目录默认会按照别名.etcd创建 |
2 | --data-dir '${name}.etcd' # 数据存储目录 |
3 | --wal-dir '' # 存放数据操作日志目录 |
4 | --max-wals 5 # 最多保留多少个wal文件 |
5 | --snapshot-count ‘10000’ # 发生多少次提交就存储一次snapshot |
6 | --max-snapshots 5 # 最多保留多少个snapshot |
集群参数:
1 | --heartbeat-interval '100' #心跳消息时间间隔 |
2 | --election-timeout '1000' #重新选举时间的间隔 |
3 | --listen-peer-urls 'http://localhost:2380,...' #监听peer过来的消息 |
4 | --listen-client-urls 'http://localhost:2379,..' #监听client的请求 |
5 | --initial-advertise-peer-urls 'http://localhost:2380,...' #广播集群中本节点的peer监听的通信地址 |
6 | --advertise-client-urls 'http://localhost:2379,...' #广播到集群中本节点监听客户端请求的地址 |
7 | --initial-cluster 'default=http://localhost:2380,...' #初始化集群配置 |
8 | --initial-cluster-state 'new' #初始化集群状态为新建,也可以指定为existing表示要加入的一个已有集群中 |
9 | --initial-cluster-token 'etcd-cluster' #启动集群时候指定的集群口令,只要相同token的节点才可以被加入集群 |
10 | --discovery ‘’ #通过自动探测方式发现集群成员的地址 |
11 | --debug ‘false’ #是否开启调试信息 |
安全相关的参数:
1 | --cert-file '' #客户端通信时的TLS证书文件路径 |
2 | --key-file '' #客户端通信时的TLS密钥文件路径 |
3 | --client-cert-auth 'false' #是否对客户端启用证书认证 |
4 | --trusted-ca-file '' #客户端通信时信任的ca文件 |
5 | --peer-cert-file ‘’ #对等成员节点TLS证书文件 |
6 | --peer-key-file '' #对等成员节点TLS密钥文件 |
7 | --peer-client-cert-auth ‘false’ #是否启用对等节点客户端认证 |
8 | --peer-trusted-ca-file '' #对等节点信任的ca文件 |
代理参数:
这些参数主要应用于Etcd服务自身作为代理模式时候使用,即转发来自客户端的请求到指定的etcd集群。此时etcd服务本身并不参与到集群中。
1 | --proxy ‘off’ #是否开启代理模式,可以为off(default),readonly或者on |
2 | --proxy-failure-wait 5000 #失败等待时间,单位毫秒 |
3 | --proxy-refresh-interval 30000 #节点刷新时间间隔,单位毫秒 |
4 | --proxy-dial-timeout 1000 #发起连接的超时,单位毫秒 |
5 | --proxy-read-timeout 0 #读请求的超时时间,单位毫秒 |
6 | --proxy-write-timeout 5000 #写请求的超时时间,单位毫秒 |
etcdctl的使用
etcdctl是官方对rest api的封装,可以让用户更加容易的跟etcd服务交互,这些命令与http api接口是对应的。
etcdctl:
1 | USAGE: |
2 | etcdctl [global options] command [command options] [arguments...] |
3 | |
4 | COMMANDS: |
5 | backup backup an etcd directory #备份指定目录 |
6 | cluster-health check the health of the etcd cluster #检查集群的健康状态 |
7 | mk make a new key with a given value #创建新的键值 |
8 | mkdir make a new directory #创建新的目录 |
9 | rm remove a key or a directory #删除键值或目录 |
10 | rmdir removes the key if it is an empty directory or a key-value pair #删除空目录或一对键值 |
11 | get retrieve the value of a key #获取某键对应的值 |
12 | ls retrieve a directory #列出目录下的内容 |
13 | set set the value of a key #设置某键对应的值 |
14 | setdir create a new directory or update an existing directory TTL #创建目录或更新一个已经存在目录的ttl |
15 | update update an existing key with a given value #更新某键对应的值 |
16 | updatedir update an existing directory #更新已经存在的目录 |
17 | watch watch a key for changes #健康某键的变化 |
18 | exec-watch watch a key for changes and exec an executable #某键变化时执行指定命令 |
19 | member member add, remove and list subcommands #添加、删除或者列出成员,需要子命令 |
20 | user user add, grant and revoke subcommands #用户添加,删除,授权,需要子命令 |
21 | role role add, grant and revoke subcommands #角色添加,删除,授权,需要子命令 |
22 | auth overall auth controls #全局认证管理 |
23 | help, h Shows a list of commands or help for one command |
24 | |
25 | |
26 | GLOBAL OPTIONS: |
27 | --debug output cURL commands which can be used to reproduce the request #输出调试信息,显示命令执行过程中的请求 |
28 | --no-sync don't synchronize cluster information before sending request #发起请求前不同步集群信息 |
29 | --output simple, -o simple output response in the given format (simple, `extended` or `json`) (default: "simple") #输出响应消息的格式 |
30 | --discovery-srv value, -D value domain name to query for SRV records describing cluster endpoints #通过域名查询来探测集群成员信息 |
31 | --insecure-discovery accept insecure SRV records describing cluster endpoints #接受不可信的SRV记录来描述集群对端 |
32 | --peers value, -C value DEPRECATED - "--endpoints" should be used instead #集群中成员地址列表 |
33 | --endpoint value DEPRECATED - "--endpoints" should be used instead #集群中成员地址列表 |
34 | --endpoints value a comma-delimited list of machine addresses in the cluster (default: "http://127.0.0.1:2379,http://127.0.0.1:4001") |
35 | --cert-file value identify HTTPS client using this SSL certificate file |
36 | --key-file value identify HTTPS client using this SSL key file |
37 | --ca-file value verify certificates of HTTPS-enabled servers using this CA bundle |
38 | --username value, -u value provide username[:password] and prompt if password is not supplied. #用户名密码验证信息 |
39 | --timeout value connection timeout per request (default: 2s) #请求的连接超时 |
40 | --total-timeout value timeout for the command execution (except watch) (default: 5s) #执行命令的总超时 |
41 | --help, -h show help |
42 | --version, -v print the version |
数据操作
数据类操作最基本的就是CRUD操作,etcd在键的组织上采用了层次化的空间结构(类似于文件系统中的目录的概念),用户指定的键可以为单独的名字,如testkey,此时可以理解为放在/目录下,也可以为指定目录结构,如/cluster1/node2/testkey。
- set
设置某个键的值为给定值。
1 | ~]# etcdctl set /testdir/testkey 'hello etcd' |
2 | hello etcd |
支持的选项:
1 | --ttl '0' #键值的超时时间(单位秒),不配置(默认0),永不超时 |
2 | --swap-with-value value #若该键现在的值为value,则进行设置操作 |
3 | --swap-with-index ‘0’ #若该键现在的索引值是指定索引,则进行设置操作 |
- get
获取指定键的值。
1 | ~]# etcdctl set testkey hello |
2 | hello |
3 | ~]# etcdctl get testkey |
4 | hello |
5 | ~]# ./etcdctl get testkey2 #若键不存在就报错 |
6 | Error: 100: Key not found (/testkey2) [7] |
支持的选项:
1 | --sort 对返回结果进行排序 |
- update
当键存在时,更新键的内容。
1 | ~]# ./etcdctl update testkey world |
2 | world |
支持的选项 –ttl ‘0’
- mk
如果给定的键不存在,则创建一个新的键值。
1 | ~]# ./etcdctl mk /testdir/testkey 'hello world' |
2 | hello world |
如果键已经存在会报错,支持的选项一样–ttl
- rm
删除某个键值。
1 | ~]# ./etcdctl rm testkey |
2 | PrevNode.Value: world |
3 | ~]# ./etcdctl get testkey |
4 | Error: 100: Key not found (/testkey) [10] |
支持的选项:
1 | --dir 如果键是个空目录或者是键值对则删除 |
2 | --recursive 删除目录和所有子建 |
3 | --with-value value 检查现有的值是否匹配 |
4 | --with-index 0 检查现有的index是否匹配 |
- watch
监测一个键值的变化,一旦键值发生更新,就会输出最新的值并退出。
1 | ~]# ./etcdctl watch /testdir/testkey |
2 | |
3 | ~]# ./etcdctl update /testdir/testkey 'hello etcd' |
4 | hello etcd |
5 | ~]# ./etcdctl watch /testdir/testkey |
6 | hello etcd |
支持的选项:
1 | --forever #一直监测,直到用户ctrl+c |
2 | --after-index ‘0’ #在指定index之前一直监测 |
3 | --recursive #返回所有的键值和子键值 |
- exec-watch
监测一个键值的变化,一旦键值发生变化,就执行给定命令。
1 | ~]# ./etcdctl exec-watch /testdir/testkey -- sh -c 'ls' |
2 | |
3 | ~]# ./etcdctl update /testdir/testkey 'hello etcd' |
4 | hello etcd |
5 | ~]# ./etcdctl exec-watch /testdir/testkey -- sh -c 'ls' |
6 | default.etcd Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md |
支持的选项:
1 | --after-index 0 在指定index之前一直监测 |
2 | --recursive 返回所有的键值和子键值 |
- ls
列出目录(默认根目录)下的键或者子目录,默认不显示子目录中的内容。
1 | ~]# ./etcdctl ls |
2 | /redis |
3 | /testdir |
4 | ~]# ./etcdctl ls /redis |
5 | /redis/prort |
支持的选项:
1 | --sort 将输出结果排序 |
2 | --recursive 如果目录下有子目录,则递归输出其中的内容 |
3 | -p 对输出为目录,在最后添加‘/’进行区分 |
- mkdir
如果给定的键的目录不存在,则创建一个新的键目录。
1 | ~]# ./etcdctl mkdir /test |
支持–ttl
rmdir
删除一个空目录,或者键值对。若目录不空,会报错。1
~]# ./etcdctl rmdir /test
2
~]# ./etcdctl rmdir /redis
3
Error: 108: Directory not empty (/redis) [14]
setdir
创建一个键目录,无论存在与否。
1 | ~]# ./etcdctl setdir /test/test/test |
2 | ~]# ./etcdctl ls --recursive |
3 | /testdir |
4 | /testdir/testkey |
5 | /redis |
6 | /redis/prort |
7 | /test |
8 | /test/test |
9 | /test/test/test |
支持–ttl
- updatedir
更新一个存在的目录的属性。
1 | ~}# ./etcdctl updatedir /test --ttl 100 |
目前只限于更新ttl
非数据操作
- backup
备份etcd的配置状态数据目录。
1 | ~]# ./etcdctl backup --data-dir default.etcd --backup-dir tmp |
2 | ~}# cd tmp |
3 | ~]# ls member |
4 | snap wal |
- cluster-health
查看集群健康状态
1 | ~]# ./etcdctl cluster-health |
2 | member 8e9e05c52164694d is healthy: got healthy result from http://localhost:2379 |
3 | cluster is healthy |
支持选项–forever,每隔10秒检查一次,直到ctrl+c
- member
通过list,add,remove等子命令列出、添加、删除etcd实例到etcd集群。
1 | ~]# ./etcdctl member list |
2 | 8e9e05c52164694d: name=default peerURLs=http://localhost:2380 clientURLs=http://localhost:2379 isLeader=true |
- import
导入旧的快照文件到系统
1 | ~]# ./etcdctl import --snap tmp/member/snap/0000....snap |
支持的选项:
1 | --snap 快照文件路径 |
2 | --hidden '--hidden option --hidden option' 隐藏导入的键值空间信息 |
3 | -c ‘10’ 并发导入的客户端数 |
- user
对用户进行管理,包括一系列子命令:
1 | add 添加一个用户 |
2 | get 查询用户细节 |
3 | list 列出所有用户 |
4 | remove 删除用户 |
5 | grant 添加用户到角色 |
6 | revoke 删除用户角色 |
7 | passwd 修改用户密码 |
默认情况下,先创建root用户作为etcd集群的最高权限管理
1 | ~]# ./etcdctl user add root |
2 | New password: |
3 | ~]# ./etcdctl user add testuser |
4 | New password: |
5 | ~]# ./etcdctl user grant testuser -roles testrole |
- role
对用户角色进行管理,包括一系列子命令:
1 | add 添加一个角色 |
2 | get 查询角色信息 |
3 | list 列出所有用户角色 |
4 | remove 删除用户角色 |
5 | grant 添加路径到角色控制,可以为read,write或者readwrite |
6 | revoke 删除某路径的用户角色信息 |
默认带有root、guest两种角色。
1 | ~]# ./etcdctl role add testrole |
2 | ~]# ./etcdctl role grant testrole -path '/key/*' -read |
- auth
是否启用访问验证
在root用户创建后,启用认证:
1 | ~]# ./etcdctl auth enable |