文章目录
- [ETCD 存储系统](#ETCD 存储系统)
-
- [ETCD 存储系统介绍](#ETCD 存储系统介绍)
-
- [ETCD 概述](#ETCD 概述)
- [ETCD 特点](#ETCD 特点)
- [ETCD 应用场景](#ETCD 应用场景)
- [ETCD 单节点部署](#ETCD 单节点部署)
- [ETCD 多节点集群部署](#ETCD 多节点集群部署)
- [etcdctl 命令](#etcdctl 命令)
-
- 配置补全
- 帮助信息
- key-value管理
-
- [创建 key-value](#创建 key-value)
- [查询 key-value](#查询 key-value)
- 脚本查询
- [更新 value](#更新 value)
- [删除 key](#删除 key)
- [动态监控 key 值](#动态监控 key 值)
- [user 管理](#user 管理)
- [role 管理](#role 管理)
- [member 管理](#member 管理)
- [查询 Kubernetes 数据](#查询 Kubernetes 数据)
- 数据的备份和恢复
ETCD 存储系统
ETCD 存储系统介绍
ETCD 概述
- etcd,是一款开源、高度一致的分布式键值(key-value)存储系统。
- etcd,使用 Go 语言编写的,节点之间通信通过Raft共识算法处理。
- etcd,是 CoreOS 公司于 2013 年 6 月发起的开源项目,于 2018 年 12 月正式加入云原生计算基金会(CNCF-Cloud Native Computing Foundation),并由 CNCF 支持。
CNCF 是一个中立的基金会、云原生技术推广和普及的领导者。

ETCD 特点
- 读写性能强:官网给出的Benchmark,在2CPU、1.8G内存、SSD磁盘这样的配置下,单节点的写性能可以达到16K QPS,而先写后读也能达到12K QPS。
- 简单:安装配置简单,而且提供了 HTTP API 进行交互,使用也很简单。
- 支持 HTTPS:更安全可靠。
- 跨平台支持:支持不同系统。
- 二进制文件小和社区活跃。
ETCD 应用场景
归根结底,etcd 是一个键值存储的组件,其功能都是基于其键值存储功能展开的。
从简单的 Web 应用程序到 Kubernetes 集群,任何复杂的应用程序都可以从 etcd 中读取数据或将数据写入 etcd。
- 服务注册与发现:服务提供方向 ETCD 注册,服务请求方向 ETCD 查询服务方,随后与服务提供方建立连接。

- 消息发布与订阅:在分布式系统中,最适用的一种组件间通信方式就是消息发布与订阅。即构建一个配置共享中心,数据提供者在这个配置中心发布消息,而消息使用者则订阅他们关心的主题,一旦主题有消息发布,就会实时通知订阅者。通过这种方式可以做到分布式系统配置的集中式管理与动态更新。

- 分布式通知与协调:与消息发布和订阅有些相似。

- 选主,在同一个分布式集群中,多个节点选举出主节点对外提供服务。
- 分布式锁 :当在分布式系统中,数据只有一份(或有限制),此时需要利用锁的技术控制某一时刻修改数据的进程数。分布式环境下下的锁不仅保证进程可见,还需要考虑进程与锁之间的网络问题。锁服务有两种使用方式:独占锁 ,即获取锁的用户最终只有一个可以得到;控制时序锁,即获得锁的用户都会按数序顺序执行。
ETCD 单节点部署
提前设置:
- 主机名:etcd.cyw.cloud
- IP地址:10.1.8.10
bash
# 所有节点配置
root@etcd:~# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.1.8.10 etcd.cyw.cloud etcd
# 安装
root@etcd:~# apt install -y etcd-server etcd-client
# 安装完成后,etcd 会默认启用并启动
# 配置
root@etcd:~# cp /etc/default/etcd /etc/default/etcd.ori
root@etcd:~# vim /etc/default/etcd
bash
# 定义节点名称,默认为default
ETCD_NAME="default"
# 定义节点数据存储目录,默认/var/lib/etcd/default
ETCD_DATA_DIR="/var/lib/etcd/default"
# 定义对外提供服务的监听地址,本机机器执行etcdctl命令连接的监听
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.10:2379"
# 定义对外提供服务的监听地址,其他机器执行etcdctl命令连接的监听
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.10:2379"
配置说明:
- 如果只需要服务器自己可以访问http://localhost:2379,则配置:
- ETCD_LISTEN_CLIENT_URLS="http://localhost:2379"
- ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
- 如果只需要服务器自己可以访问http://10.1.8.10:2379,则配置:
- ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.10:2379"
- ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
- 如果需要客户端和服务器都可以访问http://10.1.8.10:2379,则配置:
- ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.10:2379"
- ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.10:2379"
bash
# 重启服务
root@etcd:~# systemctl restart etcd
# 验证状态
root@etcd:~# etcdctl member list
8e9e05c52164694d, started, default, http://localhost:2380, http://10.1.8.10:2379,http://localhost:2379, false
键值对操作
bash
# 键值对操作示例1:单行文本
# 写入单行键值对数据;put为etcd写入命令,参数依次为键路径、存储值,单引号包裹避免内容被shell解析
root@etcd:~# etcdctl put /etc/hosts '10.1.8.10 etcd.cyw.cloud etcd'
OK # 写入操作成功的返回标识
# 读取指定键的存储值;get为etcd读取命令,--print-value-only表示仅输出值内容,省略键名与元信息
root@etcd:~# etcdctl get /etc/hosts --print-value-only
10.1.8.10 etcd.cyw.cloud etcd # 对应键存储的单行文本内容
# 键值对操作示例2:多行文本
# 写入多行键值对数据;通过shell跨行输入传入内容,单引号包裹保留原始换行格式
root@etcd:~# etcdctl put /etc/hosts '10.1.8.11 etcd1.cyw.cloud etcd1
> 10.1.8.12 etcd2.cyw.cloud etcd2'
OK # 多行数据写入成功
# 读取键值验证多行写入结果
root@etcd:~# etcdctl get /etc/hosts --print-value-only
10.1.8.11 etcd1.cyw.cloud etcd1 # 第一行存储内容
10.1.8.12 etcd2.cyw.cloud etcd2 # 第二行存储内容,完整保留换行格式
# 键值对操作示例3:上传文件
# 将本地文件内容写入对应键;put无显式值参数时从标准输入读取内容,配合cat管道实现文件全量存入
root@etcd:~# cat /etc/hosts | etcdctl put /etc/hosts
OK # 文件内容写入成功
# 读取键值验证文件上传结果
root@etcd:~# etcdctl get /etc/hosts --print-value-only
......
10.1.8.10 etcd.cyw.cloud etcd # 本地hosts文件中的解析条目,与源文件内容一致
清除节点所有数据
bash
root@etcd:~# systemctl stop etcd.service
root@etcd:~# apt remove -y etcd-server etcd-client
root@etcd:~# rm -fr /var/lib/etcd/default
ETCD 多节点集群部署
部署集群
**实践:**先部署两节点环境,再添加增删节点。
所有节点配置
bash
# 配置所有节点hosts域名解析;添加etcd集群节点的主机名IP映射,保障集群内通过主机名互通
root@etcdN:~# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 # IPv4本地回环地址解析
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 # IPv6本地回环地址解析
######### etcd cluster #########
10.1.8.11 etcd1.cyw.cloud etcd1 # etcd集群1号节点IP与主机名映射
10.1.8.12 etcd2.cyw.cloud etcd2 # etcd集群2号节点IP与主机名映射
10.1.8.13 etcd3.cyw.cloud etcd3 # etcd集群3号节点IP与主机名映射
# 安装sshpass非交互SSH工具;用于批量远程执行命令时自动填充密码,无需手动交互输入
root@etcd1:~# apt install -y sshpass
# 批量验证三台节点主机名与网卡IP;for循环遍历etcd1-3,-p指定SSH密码,StrictHostKeyChecking=no跳过主机密钥确认
root@etcd1:~# for host in etcd{1..3}; do sshpass -p123 ssh -o StrictHostKeyChecking=no $host 'hostname;echo;ip -br a';done
Warning: Permanently added 'etcd1' (ED25519) to the list of known hosts. # 首次SSH连接自动将主机密钥加入已知主机列表
etcd1.cyw.cloud # 1号节点完整主机名
lo UNKNOWN 127.0.0.1/8 ::1/128 # 回环网卡状态与地址
ens33 UP 10.1.8.11/24 fe80::20c:29ff:fe75:b31a/64 # 业务网卡运行状态与IP地址
Warning: Permanently added 'etcd2' (ED25519) to the list of known hosts.
etcd2.cyw.cloud
lo UNKNOWN 127.0.0.1/8 ::1/128
ens33 UP 10.1.8.12/24 fe80::20c:29ff:fecf:31d6/64
Warning: Permanently added 'etcd3' (ED25519) to the list of known hosts.
etcd3.cyw.cloud
lo UNKNOWN 127.0.0.1/8 ::1/128
ens33 UP 10.1.8.13/24 fe80::20c:29ff:fe5d:56ea/64
# 更新软件源并安装etcd组件;etcd-server为集群服务端程序,etcd-client为etcdctl命令行客户端
root@etcdN:~# apt update && apt install -y etcd-server etcd-client
# 停止默认etcd服务;apt安装后会自动启动单节点默认实例,需停止后重新配置为集群模式
root@etcdN:~# systemctl stop etcd.service
# 清理默认etcd数据目录;删除默认单节点实例的残留数据与日志,避免影响后续集群部署
root@etcdN:~# rm -fr /var/lib/etcd/default
etcd1 配置
bash
root@etcd1:~# cp /etc/default/etcd /etc/default/etcd.ori
root@etcd1:~# vim /etc/default/etcd
bash
ETCD_NAME="etcd1"
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://10.1.8.11:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.11:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.8.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.11:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.1.8.11:2380,etcd2=http://10.1.8.12:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcdcluster"
ETCD_INITIAL_CLUSTER_STATE="new"
参数说明
bash
# ETCD_DATA_DIR 定义节点的数据存储目录,默认/var/lib/etcd/default
# ETCD_NAME 定义ETCD节点名称,默认为default
# ETCD_LISTEN_CLIENT_URLS 对外提供服务的监听地址,用于服务端自己
# ETCD_ADVERTISE_CLIENT_URLS 该节点对外提供服务的监听地址,用于客户端
# ETCD_LISTEN_PEER_URLS 定义ETCD监听URL,用于与其他节点心跳通讯
# ETCD_INITIAL_ADVERTISE_PEER_URLS 该节点同伴监听地址,这个值会告诉集群中其他节点
# ETCD_INITIAL_CLUSTER 集群中所有节点的信息
# ETCD_INITIAL_CLUSTER_TOKEN 集群的token,用于集群节点心跳通信认证,集群中所有节点统一。
# ETCD_INITIAL_CLUSTER_STATE 新建集群的时候,这个值为 new ;假如已经存在的集群,这个值为 existing
etcd2 配置
bash
root@etcd2:~# cp /etc/default/etcd /etc/default/etcd.ori
root@etcd2:~# vim /etc/default/etcd
bash
ETCD_NAME="etcd2"
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://10.1.8.12:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.12:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.8.12:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.12:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.1.8.11:2380,etcd2=http://10.1.8.12:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcdcluster"
ETCD_INITIAL_CLUSTER_STATE="new"
启动集群
bash
# etcd1 和 etcd2 节点启动服务
root@etcdN:~# systemctl start etcd
# 如果etcd节点之前是一个独立的集群,则需要删除/var/lib/etcd/default目录下所有文件再启动。
# 验证状态
root@etcd1:~# etcdctl member list
1b344327dd751339, started, etcd2, http://10.1.8.12:2380, http://10.1.8.12:2379,http://localhost:2379, false
5b1db881c63d5ce4, started, etcd1, http://10.1.8.11:2380, http://10.1.8.11:2379,http://localhost:2379, false
验证部署
bash
root@etcd1:~# etcdctl put /users/user1/name cyw
OK
root@etcd2:~# etcdctl get /users/user1/name
/users/user1/name
cyw
集群添加节点
更新现有集群中现有节点配置文件:
- 更新ETCD_INITIAL_CLUSTER参数,添加etcd3=http://10.1.8.13:2380
- 更新ETCD_INITIAL_CLUSTER_STATE为existing
更新 etcd1 配置文件
bash
root@etcd1:~# vim /etc/default/etcd
bash
ETCD_NAME="etcd1"
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://10.1.8.11:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.11:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.8.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.11:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.1.8.11:2380,etcd2=http://10.1.8.12:2380,etcd3=http://10.1.8.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcdcluster"
ETCD_INITIAL_CLUSTER_STATE="existing"
bash
# 重启etcd服务
root@etcd1:~# systemctl restart etcd
更新 etcd2 配置文件
bash
root@etcd2:~# vim /etc/default/etcd
bash
ETCD_NAME="etcd2"
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://10.1.8.12:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.12:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.8.12:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.12:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.1.8.11:2380,etcd2=http://10.1.8.12:2380,etcd3=http://10.1.8.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcdcluster"
ETCD_INITIAL_CLUSTER_STATE="existing"
bash
# 重启 etcd 服务
root@etcd2:~# systemctl restart etcd
集群添加节点
集群中任意节点执行以下指令添加节点
bash
root@etcd1:~# etcdctl member add etcd3 --peer-urls=http://10.1.8.13:2380
输入内容如下:
bash
Member 2038744cfb6bf628 added to cluster f917ad0d43233ca7
ETCD_NAME="etcd3"
ETCD_INITIAL_CLUSTER="etcd2=http://10.1.8.12:2380,etcd3=http://10.1.8.13:2380,etcd1=http://10.1.8.11:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.8.13:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"
etcd3 部署 etcd
bash
root@etcd3:~# apt install -y etcd-server etcd-client
root@etcd3:~# systemctl stop etcd.service
root@etcd3:~# rm -fr /var/lib/etcd/default
root@etcd1:~# scp /etc/default/etcd root@etcd3:/etc/default/etcd
root@etcd3:~# vim /etc/default/etcd
bash
ETCD_NAME="etcd3"
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://10.1.8.13:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.13:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.8.13:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.13:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.1.8.11:2380,etcd2=http://10.1.8.12:2380,etcd3=http://10.1.8.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcdcluster"
ETCD_INITIAL_CLUSTER_STATE="existing"
bash
# 启动etcd 服务
root@etcd3:~# systemctl start etcd
# 查看成员列表
root@etcd1:~# etcdctl member list
1b344327dd751339, started, etcd2, http://10.1.8.12:2380, http://10.1.8.12:2379,http://localhost:2379, false
2038744cfb6bf628, started, etcd3, http://10.1.8.13:2380, http://10.1.8.13:2379,http://localhost:2379, false
5b1db881c63d5ce4, started, etcd1, http://10.1.8.11:2380, http://10.1.8.11:2379,http://localhost:2379, false
集群删除节点
bash
# 删除etcd3
root@etcd1:~# etcdctl member remove 2038744cfb6bf628
Member 2038744cfb6bf628 removed from cluster f917ad0d43233ca7
root@etcd1:~# etcdctl member list
1b344327dd751339, started, etcd2, http://10.1.8.12:2380, http://10.1.8.12:2379,http://localhost:2379, false
ae40c1152eed3b3a, started, etcd1, http://10.1.8.11:2380, http://10.1.8.11:2379,http://localhost:2379, false
# 更新etcd1和etcd2节点配置文件为初始2节点集群配置,状态设置为existing
root@etcd1:~# vim /etc/default/etcd
ETCD_NAME="etcd1"
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://10.1.8.11:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.11:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.8.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.11:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.1.8.11:2380,etcd2=http://10.1.8.12:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcdcluster"
ETCD_INITIAL_CLUSTER_STATE="existing"
root@etcd2:~# vim /etc/default/etcd
ETCD_NAME="etcd2"
ETCD_DATA_DIR="/var/lib/etcd/default"
ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://10.1.8.12:2380"
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://10.1.8.12:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.8.12:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://10.1.8.12:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.1.8.11:2380,etcd2=http://10.1.8.12:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcdcluster"
ETCD_INITIAL_CLUSTER_STATE="existing"
# 更新完成后建议etcd1和etcd2节点重启etcd服务
root@etcd1:~# systemctl restart etcd
root@etcd2:~# systemctl restart etcd
**重要说明:**节点加入集群前,确保etcd数据目录不能有数据。
清理节点etcd3
bash
root@etcd3:~# systemctl stop etcd.service
root@etcd3:~# apt remove -y etcd-server etcd-client
root@etcd3:~# rm -fr /var/lib/etcd/default
etcdctl 命令
etcd api 有两个版本 V2 和 V3,可通过环境变量 ETCDCTL_API 设置,默认使用v3。
注意:所有节点 ETCDCTL_API 必须保持一致,support backup of v2 and v3 stores 。
配置补全
bash
# 创建bash补全配置目录;系统默认补全脚本存放目录,bash启动时会自动加载该目录下的所有补全规则
root@etcd1:~# mkdir /etc/bash_completion.d
# 生成etcdctl的bash补全脚本;completion子命令输出bash格式的补全规则,重定向保存到补全目录,实现命令、子命令、参数的Tab自动补全
root@etcd1:~# etcdctl completion bash > /etc/bash_completion.d/etcdctl
# 加载etcdctl补全脚本;source命令立即生效补全配置,无需重新登录shell即可使用Tab键补全etcdctl相关命令
root@etcd1:~# source /etc/bash_completion.d/etcdctl
帮助信息
bash
# 查看etcdctl客户端完整帮助手册;-h输出所有子命令与全局参数说明,用于快速查阅命令用法
root@etcd1:~# etcdctl -h
NAME:
etcdctl - A simple command line client for etcd3. # 工具定位;etcd v3版本的官方命令行客户端,用于管理和操作etcd集群
USAGE:
etcdctl [flags] # 使用语法;命令格式为 etcdctl + 全局参数 + 子命令
VERSION:
3.4.30 # etcdctl二进制程序的版本号
API VERSION:
3.4 # 适配的etcd API版本;基于v3 API接口,与v2数据模型不兼容
COMMANDS: # 子命令列表,按功能分类展示
alarm disarm Disarms all alarms # 告警管理;解除集群所有告警状态
alarm list Lists all alarms # 列出集群当前所有告警条目
auth disable Disables authentication # 认证管理;关闭集群用户认证鉴权
auth enable Enables authentication # 开启集群用户认证鉴权
check datascale Check the memory usage of holding data for different workloads on a given server endpoint. # 性能检查;评估指定节点在不同负载下的数据内存占用
check perf Check the performance of the etcd cluster # 测试集群整体的读写性能
compaction Compacts the event history in etcd # 数据维护;压缩历史版本数据,释放存储空间
completion bash Generate the autocompletion script for bash # 命令补全;生成对应shell环境的自动补全脚本
completion fish Generate the autocompletion script for fish
completion powershell Generate the autocompletion script for powershell
completion zsh Generate the autocompletion script for zsh
defrag Defragments the storage of the etcd members with given endpoints # 数据维护;对指定节点执行存储碎片整理
del Removes the specified key or range of keys [key, range_end) # 键值操作;删除指定键或键范围的数据
elect Observes and participates in leader election # 分布式选举;参与或观察集群leader选举过程
endpoint hashkv Prints the KV history hash for each endpoint in --endpoints # 端点检查;输出各节点KV数据哈希值,校验数据一致性
endpoint health Checks the healthiness of endpoints specified in `--endpoints` flag # 检查指定端点的健康状态
endpoint status Prints out the status of endpoints specified in `--endpoints` flag # 输出指定端点的运行状态详情
get Gets the key or a range of keys # 键值操作;读取指定键或键范围的数据
help Help about any command # 查看任意子命令的详细帮助说明
lease grant Creates leases # 租约管理;创建带有效期的租约
lease keep-alive Keeps leases alive (renew) # 持续续租,保持租约长期有效
lease list List all active leases # 列出集群所有活跃租约
lease revoke Revokes leases # 主动撤销租约,关联的键会自动删除
lease timetolive Get lease information # 查询租约剩余存活时长
lock Acquires a named lock # 分布式锁;获取指定名称的分布式互斥锁
make-mirror Makes a mirror at the destination etcd cluster # 数据同步;将数据镜像同步到目标etcd集群
member add Adds a member into the cluster # 集群管理;向集群添加新节点成员
member list Lists all members in the cluster # 列出集群所有成员节点信息
member promote Promotes a non-voting member in the cluster # 将非投票节点提升为正式投票节点
member remove Removes a member from the cluster # 从集群移除指定节点成员
member update Updates a member in the cluster # 更新集群成员的配置信息
migrate Migrates keys in a v2 store to a mvcc store # 数据迁移;将v2存储数据迁移到v3 MVCC存储引擎
move-leader Transfers leadership to another etcd cluster member. # 集群管理;手动将leader角色迁移到指定节点
put Puts the given key into the store # 键值操作;写入或更新指定键的值
role add Adds a new role # 权限管理;创建新的权限角色
role delete Deletes a role # 删除指定权限角色
role get Gets detailed information of a role # 查询角色的详细权限配置
role grant-permission Grants a key to a role # 为角色授予指定键的访问权限
role list Lists all roles # 列出所有已创建的权限角色
role revoke-permission Revokes a key from a role # 收回角色的指定键访问权限
snapshot restore Restores an etcd member snapshot to an etcd directory # 快照管理;从快照文件恢复etcd节点数据
snapshot save Stores an etcd node backend snapshot to a given file # 生成当前节点的数据快照备份文件
snapshot status Gets backend snapshot status of a given file # 查看快照文件的元数据与状态信息
txn Txn processes all the requests in one transaction # 事务操作;原子执行多个请求,保证事务一致性
user add Adds a new user # 用户管理;创建新的认证用户
user delete Deletes a user # 删除指定认证用户
user get Gets detailed information of a user # 查询用户的详细信息与角色绑定
user grant-role Grants a role to a user # 为用户授予指定角色权限
user list Lists all users # 列出所有已创建的认证用户
user passwd Changes password of user # 修改用户的认证密码
user revoke-role Revokes a role from a user # 收回用户的指定角色权限
version Prints the version of etcdctl # 输出etcdctl的版本信息
watch Watches events stream on keys or prefixes # 事件监听;持续监听指定键或前缀的变更事件
OPTIONS: # 全局可选参数列表
--cacert="" verify certificates of TLS-enabled secure servers using this CA bundle # TLS配置;指定CA证书文件,校验服务端TLS证书合法性
--cert="" identify secure client using this TLS certificate file # 指定客户端TLS证书,用于双向认证
--command-timeout=5s timeout for short running command (excluding dial timeout) # 短命令执行超时时间,不含连接建立耗时
--debug[=false] enable client-side debug logging # 开启客户端调试日志,输出详细交互细节
--dial-timeout=2s dial timeout for client connections # 客户端建立连接的超时时间
-d, --discovery-srv="" domain name to query for SRV records describing cluster endpoints # DNS服务发现;通过SRV记录自动发现集群端点
--discovery-srv-name="" service name to query when using DNS discovery # DNS发现时指定的服务名称
--endpoints=[127.0.0.1:2379] gRPC endpoints # 目标集群端点;默认连接本地2379端口,多节点用逗号分隔
-h, --help[=false] help for etcdctl # 显示帮助信息
--hex[=false] print byte strings as hex encoded strings # 输出格式;将字节数据以十六进制格式展示
--insecure-discovery[=true] accept insecure SRV records describing cluster endpoints # 允许使用非加密SRV记录做服务发现
--insecure-skip-tls-verify[=false] skip server certificate verification (CAUTION: this option should be enabled only for testing purposes) # 跳过服务端证书校验,仅测试环境使用
--insecure-transport[=true] disable transport security for client connections # 禁用传输层加密,使用明文连接
--keepalive-time=2s keepalive time for client connections # 客户端连接保活探测间隔
--keepalive-timeout=6s keepalive timeout for client connections # 客户端连接保活超时时间
--key="" identify secure client using this TLS key file # 指定客户端TLS私钥文件,配合cert实现双向认证
--password="" password for authentication (if this option is used, --user option shouldn't include password) # 认证密码;指定用户认证的密码
--user="" username[:password] for authentication (prompt if password is not supplied) # 认证用户名,可附带密码,未提供则交互输入
-w, --write-out="simple" set the output format (fields, json, protobuf, simple, table) # 输出格式;支持simple、json、table等多种展示格式
key-value管理
创建 key-value
bash
root@etcd:~# etcdctl put /users/user1/name cyw
OK
查询 key-value
bash
# 查看key-value
root@etcd:~# etcdctl get /users/user1/name
/users/user1/name
cyw
# 只查看value
root@etcd:~# etcdctl get /users/user1/name --print-value-only
cyw
# 只查看key
root@etcd:~# etcdctl get /users/user1/name --keys-only
/users/user1/name
# 再创建一些 key-value
root@etcd:~# etcdctl put /users/user1/age 18
root@etcd:~# etcdctl put /users/user2/name laowang
root@etcd:~# etcdctl put /usage/ls ls--help
root@etcd:~# etcdctl put /usage/cd cd--help
root@etcd:~# etcdctl put /registry/services/endpoints/cyw/web 10.224.225.98:80
# k8s将svc数据按如下格式命名存在etcd系统中:
# /registry/services/endpoints/namespace/svcname
# 查看以/开头的所有key,--prefix启用前缀匹配实现全量查询,--keys-only仅输出键名省略值内容,grep -v过滤输出中的空行
root@etcd:~# etcdctl get / --keys-only --prefix |grep -v '^$'
/registry/services/endpoints/cyw/web
/usage/cd
/usage/ls
/users/user1/age
/users/user1/name
/users/user2/name
# 查看以/users开头的所有key
root@etcd:~# etcdctl get /users --keys-only --prefix |grep '^/users'
/users/user1/age
/users/user1/name
/users/user2/name
# 如何查看"特定目录"下有哪些文件或者子目录,例如/users;--prefix启用前缀匹配查询所有子键,--keys-only仅输出键名,awk按斜杠分割提取前两级路径,排序后去重得到二级目录唯一列表
root@etcd:~# etcdctl get /users --keys-only --prefix |grep -v '^$'| awk -F '/' '{print "/"$2"/"$3}'| sort |uniq
/users/user1
/users/user2
脚本查询
以上命令太繁琐,编写脚本 /usr/local/bin/etcdls 实现:
bash
#!/bin/bash
# 如果脚本未提供参数,查询的前缀设置为"/"
PREFIX=${1:-/}
# 统计以该前缀开头的"目录"数量
count=$(etcdctl get $PREFIX --keys-only --prefix |grep -v '^$'|egrep -o "$PREFIX[^/]*/" |sort |uniq|wc -l)
# 正则表达式说明 $PREFIX[^/]*/
## $PREFIX 变量
## [^/]* 变量后跟着任意数量的非/字符串
## 最后补1个/
# 如果数量等于1,则显示该目录下子条目
if [ $count -eq 1 ];then
etcdctl get $PREFIX --keys-only --prefix |grep -v '^$'|egrep -o "^$PREFIX[^/]*/[^/]*" | sort | uniq
else
# 如果数量不等于1,则显示该前缀匹配的目录条目
etcdctl get $PREFIX --keys-only --prefix |grep -v '^$'|egrep -o "^$PREFIX[^/]*" | sort | uniq
fi
bash
root@etcd:~# chmod +x /usr/local/bin/etcdls
查询效果如下:
bash
root@etcd:~# etcdls
/registry
/usage
/users
root@etcd:~# etcdls /us
/usage
/users
root@etcd:~# etcdls /user
/users/user1
/users/user2
更新 value
bash
root@etcd:~# etcdctl put /users/user1/name laohu
OK
root@etcd:~# etcdctl get /users/user1/name --print-value-only
laohu
删除 key
bash
root@etcd:~# etcdctl del /users/user2/name
1
root@etcd:~# etcdctl get /users/user2/name --print-value-only
root@etcd:~# etcdls /users/user
/users/user1/age
/users/user1/name
仔细观察:当删除/users/user2/name时 /users/user2条目也没有了。
动态监控 key 值
bash
[root@etcd bin]# etcdctl put /users/user1/name cyw1
OK
[root@etcd bin]# etcdctl put /users/user1/name cyw2
OK
# 当执行以上命令时,watch结果如下:
root@etcd:~# etcdctl watch /users/user1/name
PUT
/users/user1/name
cyw1
PUT
/users/user1/name
cyw2
user 管理
bash
root@etcd:~# etcdctl user -h
NAME:
user - User related commands
USAGE:
etcdctl user <subcommand> [flags]
API VERSION:
3.3
COMMANDS:
add Adds a new user
delete Deletes a user
get Gets detailed information of a user
grant-role Grants a role to a user
list Lists all users
passwd Changes password of user
revoke-role Revokes a role from a user
......
role 管理
bash
root@etcd:~# etcdctl role -h
NAME:
role - Role related commands
USAGE:
etcdctl role <subcommand> [flags]
API VERSION:
3.3
COMMANDS:
add Adds a new role
delete Deletes a role
get Gets detailed information of a role
grant-permission Grants a key to a role
list Lists all roles
revoke-permission Revokes a key from a role
......
member 管理
bash
root@etcd:~# etcdctl member -h
NAME:
member - Membership related commands
USAGE:
etcdctl member <subcommand> [flags]
API VERSION:
3.3
COMMANDS:
add Adds a member into the cluster
list Lists all members in the cluster
remove Removes a member from the cluster
update Updates a member in the cluster
查询 Kubernetes 数据
Kubernetes从 1.13 版本开始,默认使用etcd v3 API。数据存放在以 /registry 中。
确保master节点安装了etcdctl工具。
bashroot@master30:~# apt install etcd-client -y
我们以集成 etcd 静态 pod 的Kubernetes为例,讲解如何查询。
在master节点创建脚本/usr/local/bin/etcdls,内容如下:
bash
#!/bin/bash
export ETCDCTL_API=3
key_file=/etc/kubernetes/pki/etcd/server.key
cert_file=/etc/kubernetes/pki/etcd/server.crt
cacert_file=/etc/kubernetes/pki/etcd/ca.crt
endpoints=https://127.0.0.1:2379
# 如果脚本未提供参数,查询的前缀设置为"/"
PREFIX=${1:-/}
tmpfile=$(mktemp)
etcdctl --key=${key_file} --cert=${cert_file} --cacert=${cacert_file} --endpoints=${endpoints} get $PREFIX --keys-only --prefix |grep -v '^$'|egrep "$PREFIX[^/]*/" > $tmpfile
# 统计以该前缀开头的"目录"数量
count=$(cat $tmpfile | egrep -o "$PREFIX[^/]*/" | sort | uniq | wc -l )
# 如果数量等于1,则显示该目录下子条目
if [ $count -eq 1 ];then
cat $tmpfile | egrep -o "^$PREFIX[^/]*/[^/]*" | sort | uniq
else
# 如果数量不等于1,则显示该前缀匹配的目录条目
cat $tmpfile | egrep -o "^$PREFIX[^/]*" | sort | uniq
fi
# 清理临时文件
rm -f $tmpfile
在 master 节点创建脚本/usr/local/bin/etcdget,内容如下:
bash
#!/bin/bash
# etcdctl TLS认证查询封装脚本;统一配置证书与API版本,简化本地etcd的HTTPS认证查询,调用时传入键名即可执行查询
export ETCDCTL_API=3 # 设置etcd API版本环境变量;强制etcdctl使用v3版本API,适配etcd 3.x集群
key_file=/etc/kubernetes/pki/etcd/server.key # 客户端私钥路径变量;etcd双向TLS认证的客户端私钥文件
cert_file=/etc/kubernetes/pki/etcd/server.crt # 客户端证书路径变量;etcd双向TLS认证的客户端身份证书
cacert_file=/etc/kubernetes/pki/etcd/ca.crt # 根CA证书路径变量;用于校验服务端TLS证书的合法性
endpoints=https://127.0.0.1:2379 # etcd端点地址变量;指定本地etcd服务的HTTPS访问地址与默认2379端口
etcdctl --key=${key_file} --cert=${cert_file} --cacert=${cacert_file} --endpoints=${endpoints} get $* # 执行etcd查询命令;传入全套TLS认证参数,$*透传脚本所有入参作为get命令的键名参数
以查询 service 数据为例
bash
# 枚举registry目录下ser前缀的键路径;etcdls为自定义列键工具,传入路径前缀匹配所有对应开头的键
root@master30:~# etcdls /registry/ser
/registry/serviceaccounts # 服务账号资源的存储根路径
/registry/services # 服务与端点资源的存储根路径
# 列出services目录下的子键分类;查看服务资源在etcd中的存储结构分类
root@master30:~# etcdls /registry/services
/registry/services/endpoints # 端点资源存储目录,按命名空间分层存放
/registry/services/specs # Service规格存储目录,保存服务定义配置
# 列出endpoints下的命名空间目录;端点资源按命名空间分层存储,隔离不同命名空间的资源数据
root@master30:~# etcdls /registry/services/endpoints
/registry/services/endpoints/default # default命名空间的端点存储路径
/registry/services/endpoints/kube-system # kube-system命名空间的端点存储路径
# 列出kube-system命名空间下的端点键;查看该命名空间下所有端点资源的存储条目
root@master30:~# etcdls /registry/services/endpoints/kube-system
/registry/services/endpoints/kube-system/kube-dns # kube-dns服务的端点数据存储键
# 查看kube-dns端点键的下级路径;确认该键为最终存储节点,无下级子键
root@master30:~# etcdls /registry/services/endpoints/kube-system/kube-dns
# 读取kube-dns端点的原始存储值;--print-value-only仅输出值内容,默认返回protobuf编码的二进制数据
root@master30:~# etcdget /registry/services/endpoints/kube-system/kube-dns --print-value-only
# 存储格式说明;除apiregistration.k8s.io等少数资源用JSON存储外,绝大多数资源使用protobuf格式存储,目的是提升序列化性能、降低存储体积
# 快速提取可读文本;使用strings命令可从二进制数据中筛选可打印字符串,该工具由binutils软件包提供,无需完整解码即可快速查看关键字段
root@master30:~# etcdget /registry/services/endpoints/kube-system/kube-dns --print-value-only | strings
# 专业解码工具说明;OpenShift项目开源的etcdhelper工具可完整解码etcd中的protobuf格式数据,还原为可读的Kubernetes资源对象结构
数据的备份和恢复
- etcd v3 可以同时备份和恢复 v2和v3创建的数据。
- etcd v2 无法备份 v3 创建的数据,也无法恢复v3 创建的数据。
物理备份和恢复
单节点集群
备份
bash
# 准备测试数据
root@etcd:~# etcdctl put /users/user1/name cyw
root@etcd:~# etcdctl put /users/user1/age 18
root@etcd:~# etcdctl put /users/user2/name laowang
root@etcd:~# etcdctl put /usage/ls ls--help
root@etcd:~# etcdctl put /usage/cd cd--help
# 停止 etcd 集群,备份数据目录
root@etcd:~# systemctl stop etcd.service
root@etcd:~# cp -a /var/lib/etcd/default /var/lib/etcd/default.bak
删除数据
bash
# 启动etcd集群
root@etcd:~# systemctl start etcd.service
# 删除测试数据
root@etcd:~# etcdctl del /users/user2/name
恢复
bash
# 停止 etcd 集群,恢复数据目录
root@etcd:~# systemctl stop etcd.service
root@etcd:~# mv /var/lib/etcd/default /var/lib/etcd/default.bad
root@etcd:~# cp -a /var/lib/etcd/default.bak /var/lib/etcd/default
root@etcd:~# chown -R etcd:etcd /var/lib/etcd/default/
root@etcd:~# systemctl start etcd.service
# 验证恢复
root@etcd:~# etcdctl get /users/user2/name
/users/user2/name
laowang
多节点集群
备份
bash
# 准备测试数据
root@etcd1:~# etcdctl put /users/user1/name cyw
root@etcd1:~# etcdctl put /users/user1/age 18
root@etcd1:~# etcdctl put /users/user2/name laowang
root@etcd1:~# etcdctl put /usage/ls ls--help
root@etcd1:~# etcdctl put /usage/cd cd--help
# 所有节点停止 etcd 服务,备份数据目录
root@etcdN:~# systemctl stop etcd.service
root@etcdN:~# cp -a /var/lib/etcd/default /var/lib/etcd/default.bak
删除数据
单节点删除数据即可。
bash
# 启动etcd集群
root@etcd1:~# systemctl start etcd.service
# 删除测试数据
root@etcd1:~# etcdctl del /users/user2/name
恢复
bash
# 所有节点停止 etcd 服务,恢复数据目录
root@etcdN:~# systemctl stop etcd.service
root@etcdN:~# mv /var/lib/etcd/default /var/lib/etcd/default.bad
root@etcdN:~# cp -r /var/lib/etcd/default.bak /var/lib/etcd/default
root@etcdN:~# chown -R etcd:etcd /var/lib/etcd/default/
root@etcdN:~# systemctl start etcd.service
# 验证恢复
root@etcdN:~# etcdctl get /users/user2/name
/users/user2/name
laowang
逻辑备份与恢复
单节点集群
备份
bash
# 确保使用 API 3
root@etcd:~# export ETCDCTL_API=3
# 备份数据到文件 snapshot.db
root@etcd:~# etcdctl snapshot save snapshot.db
Snapshot saved at snapshot.db
恢复
bash
# 停止etcd服务并删除数据目录 /var/lib/etcd/default/
root@etcd:~# systemctl stop etcd
root@etcd:~# mv /var/lib/etcd/default /var/lib/etcd/default.old
# 恢复快照文件snapshot.db到目录/var/lib/etcd/default/
root@etcd:~# etcdctl snapshot restore snapshot.db --data-dir=/var/lib/etcd/default/
# 更改文件所有权,并启动etcd服务
root@etcd1:~# chown -R etcd:etcd /var/lib/etcd/default
root@etcd1:~# systemctl start etcd.service
多节点集群
备份
因为多节点集群之间数据是一致的,所以多节点集群备份,只需要在单个节点备份即可。
bash
# 确保使用 API 3
root@etcd:~# export ETCDCTL_API=3
# 切换etcdctl API版本为v3;设置环境变量强制使用v3接口,保障快照备份兼容3.x集群数据格式
# 备份数据到文件snapshot1.db
root@etcd1:~# etcdctl snapshot save /root/snapshot1.db
Snapshot saved at snapshot.db
# 将备份文件同步到所有节点
恢复
bash
# 停止所有节点etcd服务并删除数据目录 /var/lib/etcd/default/
root@etcdN:~# systemctl stop etcd
root@etcdN:~# rm -fr /var/lib/etcd/default/
# 所有节点恢复快照文件snapshot1.db到目录/var/lib/etcd/default/
root@etcd1:~# etcdctl snapshot restore /root/snapshot1.db \
--data-dir=/var/lib/etcd/default
root@etcd1:~# chown -R etcd:etcd /var/lib/etcd/default
root@etcd1:~# systemctl start etcd
root@etcd2:~# etcdctl snapshot restore /root/snapshot1.db \
--data-dir=/var/lib/etcd/default
root@etcd2:~# chown -R etcd:etcd /var/lib/etcd/default
root@etcd2:~# systemctl start etcd
root@etcd3:~# etcdctl snapshot restore /root/snapshot1.db \
--data-dir=/var/lib/etcd/default
root@etcd3:~# chown -R etcd:etcd /var/lib/etcd/default
root@etcd3:~# systemctl start etcd
Kubernetes 备份和恢复
bash
# 准备工作
# 切换etcdctl为v3 API版本;强制使用v3接口,保障快照备份与恢复命令兼容3.x集群数据格式
root@master30:~# export ETCDCTL_API=3
# 定义TLS客户端私钥路径变量;存储etcd双向认证的客户端私钥文件路径,后续命令统一引用避免重复输入
root@master30:~# key_file=/etc/kubernetes/pki/etcd/server.key
# 定义TLS客户端证书路径变量;存储etcd双向认证的客户端身份证书路径,用于服务端校验客户端身份
root@master30:~# cert_file=/etc/kubernetes/pki/etcd/server.crt
# 定义根CA证书路径变量;用于校验etcd服务端TLS证书合法性,建立可信加密连接
root@master30:~# cacert_file=/etc/kubernetes/pki/etcd/ca.crt
# 定义etcd客户端端点变量;指定本地etcd服务的HTTPS访问地址与默认2379客户端端口
root@master30:~# endpoints=https://127.0.0.1:2379
# 创建测试Deployment应用;指定业务镜像与2副本数,生成持久化到etcd的测试数据,用于验证备份恢复效果
root@master30:~# kubectl create deployment web --image=hub.cyw.cloud/library/httpd --replicas=2
# 备份
# 生成etcd全量数据快照;传入全套TLS认证参数,将当前集群所有数据备份为本地snapshot.db文件
root@master30:~# etcdctl --key=${key_file} --cert=${cert_file} --cacert=${cacert_file} --endpoints=${endpoints} snapshot save snapshot.db
# 删除应用
# 删除测试Deployment;模拟业务数据丢失场景,验证后续快照恢复的有效性
root@master30:~# kubectl delete deployments.apps web
# 恢复验证
# 清空etcd数据目录;删除原有数据文件模拟集群数据损坏
root@master30:~# rm -fr /var/lib/etcd/
#删除后需立刻执行以下命令,否则会自动恢复
# 从快照恢复单节点etcd集群;指定快照源文件与数据写入目录,配置节点名称、初始集群列表与节点间通信通告地址,重建etcd数据
root@master30:~# etcdctl --key=${key_file} --cert=${cert_file} --cacert=${cacert_file} --endpoints=${endpoints} snapshot restore snapshot.db --data-dir=/var/lib/etcd --name=master30.cyw.cloud --initial-cluster=master30.cyw.cloud=https://10.1.8.30:2380 --initial-advertise-peer-urls=https://10.1.8.30:2380
# 说明:
# master30.cyw.cloud是master节点主机名
# 10.1.8.30 是 master30 节点主机 ip
# 验证备份恢复结果;查询Deployment资源列表,确认之前删除的web应用是否随etcd数据恢复
root@master30:~# kubectl get deployments.apps