etcd

etcd 是一个分布式键值对存储,设计用来可靠而快速的保存关键数据并提供访问。通过分布式锁,leader选举和写屏障(write barriers)来实现可靠的分布式协作。etcd集群是为高可用,持久性数据存储和检索而准备。

下面的文章基于Ubuntu20.04安装

安装

# 修改主机名
# hostnamectl set-hostname test-180
# vim /etc/hosts

# 修改ip
# vim /etc/netplan/00-installer-config.yaml
# netplan apply

# snap为Ubuntu新的包管理软件
# 默认安装就自启动了,但是有个问题启动的时候会生成 ETCD_NAME="default" 的 默认数据,修改配置后任然无法生效
# 修改配置后需要清理数据:rm -fr /var/lib/etcd/default/
apt install etcd

集群配置

# 等价于 etcd --data-dir=data.etcd --name ${THIS_NAME} \
#	--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
#	--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
#	--initial-cluster ${CLUSTER} \
#	--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}

# 主机:test-180
vim /etc/default/etcd
ETCD_NAME="test-180"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.26.180:2380"
ETCD_LISTEN_PEER_URLS="http://10.0.26.180:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.26.180:2379"
ETCD_LISTEN_CLIENT_URLS="http://10.0.26.180:2379"
ETCD_INITIAL_CLUSTER="test-180=http://10.0.26.180:2380,test-181=http://10.0.26.181:2380,test-182=http://10.0.26.182:2380"
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_INITIAL_CLUSTER_TOKEN="zYpFCSeVWWwmvoryOyhW"

# 主机:test-181
vim /etc/default/etcd
ETCD_NAME="test-181"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.26.181:2380"
ETCD_LISTEN_PEER_URLS="http://10.0.26.181:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.26.181:2379"
ETCD_LISTEN_CLIENT_URLS="http://10.0.26.181:2379"
ETCD_INITIAL_CLUSTER="test-180=http://10.0.26.180:2380,test-181=http://10.0.26.181:2380,test-182=http://10.0.26.182:2380"
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_INITIAL_CLUSTER_TOKEN="zYpFCSeVWWwmvoryOyhW"

# 主机:test-182
vim /etc/default/etcd
ETCD_NAME="test-182"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.26.182:2380"
ETCD_LISTEN_PEER_URLS="http://10.0.26.182:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.26.182:2379"
ETCD_LISTEN_CLIENT_URLS="http://10.0.26.182:2379"
ETCD_INITIAL_CLUSTER="test-180=http://10.0.26.180:2380,test-181=http://10.0.26.181:2380,test-182=http://10.0.26.182:2380"
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_INITIAL_CLUSTER_TOKEN="zYpFCSeVWWwmvoryOyhW"

# 重新加载
# 第一次需要删除默认数据
# member 为 8e9e05c52164694d 是默认名称 ETCD_NAME="default"
# rm -fr /var/lib/etcd/default/
systemctl restart etcd.service
systemctl status etcd.service

管理

配置alias

grep -q etcdctl ~/.bashrc || cat >> ~/.bashrc << 'EOF'
export ETCDCTL_API=3
ENDPOINTS=10.0.26.180:2379,10.0.26.181:2379,10.0.26.182:2379
# alias etcdctl='etcdctl --endpoints=${ENDPOINTS} --user=root:123456'
alias etcdctl='etcdctl --endpoints=${ENDPOINTS}'
EOF
source ~/.bashrc

查看集群状态

# 查看集群leader
# 所有member 为 8e9e05c52164694d 是默认名称default,需要清理数据并重启
# rm -fr /var/lib/etcd/default/
etcdctl --write-out=table endpoint status
# leader宕机后,RAFT TERM会自增1
# 查看集群状态
etcdctl endpoint health

操作

写和读

# 写入数据
etcdctl put foo "Hello World!"
# 读取数据
etcdctl get foo
etcdctl --write-out="json" get foo

prefix读取

etcdctl put web1 value1
etcdctl put web2 value2
etcdctl put web3 value3

etcdctl get web --prefix

删除

etcdctl put key myvalue
etcdctl del key

etcdctl put k1 value1
etcdctl put k2 value2
# 以k为前缀的全部删除
etcdctl del k --prefix

交互操作(事务(txn)?)

etcdctl put user1 bad
# 交互操作
etcdctl txn --interactive

compares:
value("user1") = "bad"

success requests (get, put, delete):
del user1

failure requests (get, put, delete):
put user1 good
Watch

监听数据

etcdctl watch stock1
etcdctl put stock1 1000

etcdctl watch stock --prefix
etcdctl put stock1 10
etcdctl put stock2 20

生命周期(lease)

# 生命周期为30s
etcdctl lease grant 30
# lease 7ffb79835a629611 granted with TTL(30s)
# 主要指定lease值,30s中内没有操作的话会被释放(put、get)
# put报错,get为空
etcdctl put sample value --lease=7ffb79835a629615

# 关闭TTL?
etcdctl lease keep-alive 2be7547fbc6a5afa
etcdctl lease revoke 2be7547fbc6a5afa

锁操作

etcdctl lock mutex1

# another client with the same name blocks
etcdctl lock mutex1

选举新的leader

# etcdctl --write-out=table --endpoints=$ENDPOINTS endpoint status
etcdctl elect one p1

快照(snapshot)

用于备份数据库

# /snap/bin/etcdctl --endpoints=10.0.26.180:2379 --user=root:123456 snapshot save my.db
/snap/bin/etcdctl --endpoints=10.0.26.180:2379 snapshot save my.db
# 查看快照数据信息
etcdctl --write-out=table snapshot status my.db

认证

# 注意使用新版本
export ETCDCTL_API=3
# ENDPOINTS=localhost:2379


############### 常见操作
# 创建角色
etcdctl role add 角色名
# 角色授权
# 给以/foo/开头的所有key赋予读写权限. The prefix is equal to the range [/foo/, /foo0)
# 不能用:/foo/*
etcdctl role grant-permission myrolename --prefix=true read /foo/
# 创建账号
# etcdctl --user root --password (root密码) role add xinweiblog
etcdctl user add 用户名
# 用户角色关联
etcdctl user grant-role 用户名 角色名
# 用户角色取消关联
etcdctl user revoke-role 用户名 角色名
# 激活认证(所有请求都需要认证了)
etcdctl auth enable


############### 完整实例
# 一、创建角色并授权
# 创建平台角色:plats,对"/plat/"具有读写
etcdctl role add plats
# 2.0的接口标准 etcdctl role grant plats --path /plat/ --readwrite
etcdctl role grant-permission plats --prefix=true readwrite /plat/
# 创建平台客户端角色:platc,对"/plat/"具有读权限
etcdctl role add platc
etcdctl role grant-permission platc --prefix=true read /plat/
# 查看角色列表
etcdctl role list
# 查看权限
etcdctl role get plats
etcdctl role get platc


# 二、创建用户并关联角色
etcdctl user add plats
etcdctl user add platc
# 关联角色
etcdctl user grant-role plats plats
etcdctl user grant-role platc platc
# 查看用户关联的角色信息
etcdctl user get plats
etcdctl user get platc

# 激活认证(所有请求都需要认证了)
etcdctl user add root
etcdctl user grant-role root root
etcdctl auth enable

# 三、权限测试
etcdctl --user=root:123456 put /foo bar
# 这里报错,账号为空
etcdctl get foo
etcdctl --user=root:123456 get /foo
etcdctl --user=root:123456 get /foo1

etcdctl --user=plats:123456 get /foo
etcdctl --user=platc:123456 get /foo
etcdctl --user=plats:123456 put /plat1 bar
etcdctl --user=platc:123456 put /plat/test foo
etcdctl --user=plats:123456 put /plat/test bar
etcdctl --user=plats:123456 get /plat/test
etcdctl --user=platc:123456 get /plat/test

查看所有key

# etcdctl get / --prefix --keys-only
etcdctl get "" --prefix --keys-only | sed '/^\s*$/d'

问题

集群ID一致,并且都是leader

因为安装的时候会自启动,生成默认值的数据 ETCD_NAME=“default”

对应的ID为8e9e05c52164694d,所有集群需要删除再重启

rm -fr /var/lib/etcd/default/

root@test-180:~# etcdctl --write-out=table --endpoints=$ENDPOINTS endpoint status
+-----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|    ENDPOINT     |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+-----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| 10.0.26.180:2379 | 8e9e05c52164694d |  3.2.26 |   25 kB |      true |      false |         6 |         12 |                  0 |        |
| 10.0.26.181:2379 | 8e9e05c52164694d |  3.2.26 |   25 kB |      true |      false |         6 |         12 |                  0 |        |
| 10.0.26.182:2379 | 8e9e05c52164694d |  3.2.26 |   25 kB |      true |      false |         5 |         10 |                  0 |        |

参考