Jusene's Blog

Etcd 高可用的键值对数据库

字数统计: 3.5k阅读时长: 16 min
2017/11/11 Share

Etcd

Etcd是CoreOS团队发起的一个分布式键值对数据库,可以应用于分布式系统中的配置信息管理和服务发现,也是在k8s集群中被使用的项目,etcd专门为集群环境设计,可以很好的实现数据一致性,提供集群节点管理和服务发现,目前在github.com/coreos/etcd进行维护。etcd重点考虑了一下四个要素:

  • 简单:支持REST风格的HTTP+JSON API
  • 安全:支持HTTPS方法的访问
  • 快速:支持并发每秒一千次的写操作
  • 可靠:支持分布式结构,基于Raft算法实现一致性

安装使用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
CATALOG
  1. 1. Etcd
  2. 2. 安装使用Etcd
  3. 3. 服务参数
  4. 4. etcdctl的使用
  5. 5. 数据操作
  6. 6. 非数据操作