云原生学习路线导航页(持续更新中)
- kubernetes学习系列快捷链接
- Kubernetes架构原则和对象设计(一)
- Kubernetes架构原则和对象设计(二)
- Kubernetes架构原则和对象设计(三)
- Kubernetes控制平面组件:etcd(一)
- Kubernetes控制平面组件:etcd(二)
- Kubernetes控制平面组件:etcd高可用集群搭建
- kubectl 和 kubeconfig 基本原理
- kubeadm 升级 k8s集群 1.17到1.20
- Kubernetes常见问题解答
- 查看云机器的一些常用配置
本文主要介绍 Etcd 的常用配置,包括:成员参数、集群参数、安全参数、灾备参数、容量管理参数 和 碎片整理参数,并对核心参数进行讲解
1.参数分类
1.1.成员相关参数
1.2.集群相关参数
1.3.安全相关参数
1.4.灾备相关参数
1.5.容量管理相关参数
1.5.1.容量参数详情
- 一些规范
- 对应参数
# 限制单个请求的最大字节数。单个键值对的大小超过 1.5MB 可能会影响 etcd 的性能。 --max-request-bytes 1572864 # 1.5MB(1.5 * 1024 * 1024)# 设置后端存储的最大容量。可能不足以满足生产环境需求 --quota-backend-bytes 2147483648 # 2GB(2 * 1024 * 1024 * 1024) # 可以调整,但是建议不要超过8GB,etcd 的存储容量超过 8GB 可能会导致性能下降 --quota-backend-bytes 8589934592 # 8GB(8 * 1024 * 1024 * 1024)
1.5.2.Etcd容量超过8GB会发生什么
- 内存占用过大
- etcd 的存储引擎(BoltDB)是基于内存映射文件的,数据量越大,内存占用越高。
- 内存映射原理:
- 使用 Linux mmap 系统调用
- 数据库文件完全映射到内存(8GB文件 => 至少占用8GB内存)
- 实际内存占用可能更高(考虑序列化开销和KV索引)
- KV索引内存开销
- 每个键值对会产生额外索引数据
- 索引内存消耗 ≈ (总键数量 × 300字节)
- GC压力
// Go语言GC特点示例 type tempObject struct {key []bytevalue []byte // 频繁创建导致GC压力 }
- 大量临时对象影响垃圾回收效率
- GC停顿可能影响读写性能
1.5.3.Etcd磁盘空间耗尽实验
1.5.3.1.模拟写满过程
# 启动带容量限制的etcd
docker run -d \--name my-etcd \-p 2579:2379 \-p 2580:2380 \quay.io/coreos/etcd:v3.5.0 \/usr/local/bin/etcd \--name my-etcd \--data-dir /etcd-data \--listen-client-urls http://0.0.0.0:2379 \--advertise-client-urls http://0.0.0.0:2379 \--listen-peer-urls http://0.0.0.0:2380 \--initial-advertise-peer-urls http://0.0.0.0:2380 \--initial-cluster my-etcd=http://0.0.0.0:2380 \--quota-backend-bytes=16777216# 进入容器
docker exec -it 9fe6cb8a00e7 /bin/sh# 持续写入测试(使用随机值)
while true; dodd if=/dev/urandom bs=1024 count=1024 | base64 | etcdctl put key
done# 成功写了9条后就报错:
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0262849 s, 39.9 MB/s
OK
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0271854 s, 38.6 MB/s
{"level":"warn","ts":"2025-02-16T04:13:46.947Z","logger":"etcd-client","caller":"v3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc0000d2a80/#initially=[127.0.0.1:2379]","attempt":0,"error":"rpc error: code = ResourceExhausted desc = etcdserver: mvcc: database space exceeded"}
Error: etcdserver: mvcc: database space exceeded
1.5.3.2.故障现象
- 写入报错
Error: rpc error: code = ResourceExhausted desc = etcdserver: mvcc: database space exceeded
- 查看告警
# etcdctl alarm list memberID:128088275939295631 alarm:NOSPACE
- 查看集群状态
# etcdctl endpoint status -w table +----------------+-----------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------------------------------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +----------------+-----------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------------------------------+ | 127.0.0.1:2379 | 1c70f9bbb41018f | 3.5.0 | 20 MB | true | false | 2 | 123 | 123 | memberID:128088275939295631 | | | | | | | | | | | alarm:NOSPACE | +----------------+-----------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------------------------------+
- 在ERROR中 输出显示 NO SPACE 告警
- 集群自动切换为只读模式
1.5.3.3.故障恢复方案
- 碎片整理 (Defrag)
# 执行碎片整理(需逐个节点操作) etcdctl defrag --endpoints=localhost:2379# 清除告警 etcdctl alarm disarm
- 版本压缩 (Compact)
# 获取当前版本号 rev=$(etcdctl endpoint status -w json | grep -o '"revision":[0-9]*' | awk -F: '{print $2}' | head -1)# 压缩历史版本 etcdctl compact $rev# 执行碎片整理(压缩后必需) etcdctl defrag
1.5.3.4.启动自动压缩配置
# 启用自动压缩(推荐配置)
--auto-compaction-retention=1h # 每小时压缩历史版本
--auto-compaction-mode=revision # 按版本号压缩
1.5.4.生产环境容量规划参考
1.6.碎片整理
2.Etcd 常用配置详解
-
我们以etcd的真实启动命令参数为例,介绍每个参数的含义
[root@VM-226-235-tencentos ~]# ps -ef | grep etcd root 5062 5041 0 Feb10 ? 00:26:48 /usr/local/bin/etcd --name s1 --data-dir /etcd-data --listen-client-urls http://0.0.0.0:2479 --advertise-client-urls http://0.0.0.0:2479 --listen-peer-urls http://0.0.0.0:2480 --initial-advertise-peer-urls http://0.0.0.0:2480 --initial-cluster s1=http://0.0.0.0:2480 --initial-cluster-token tkn --initial-cluster-state new --log-level info --logger zap --log-outputs stderr# 格式化一下 /usr/local/bin/etcd \--name s1 \--data-dir /etcd-data \--listen-client-urls http://0.0.0.0:2479 \--advertise-client-urls http://0.0.0.0:2479 \--listen-peer-urls http://0.0.0.0:2480 \--initial-advertise-peer-urls http://0.0.0.0:2480 \--initial-cluster s1=http://0.0.0.0:2480 \--initial-cluster-token tkn \--initial-cluster-state new \--log-level info \--logger zap \--log-outputs stderr
-
核心参数解析
参数 类型 作用说明 典型值示例 注意事项 --name
基础 节点在集群中的唯一标识名称 s1
1.集群内必须唯一,默认名称为 default。
2.名称会用于日志标识和与其他节点的通信--data-dir
存储 数据存储目录(WAL文件、快照等) /etcd-data
1.需要写权限,建议使用 SSD。
2.不指定时,默认在etcd的安装目录下基于 --name 参数生成一个目录(如 default.etcd)。
3.生产环境中建议使用绝对路径(如 /var/lib/etcd)--listen-client-urls
网络 客户端 API 的监听地址列表 http://0.0.0.0:2479
1.默认监听本地的 2379 端口(客户端通过此端口读写数据)。
2.开放远程访问需配置为 0.0.0.0:2379 并启用 TLS 加密。
3.0.0.0.0
表示监听所有 IP,生产环境建议绑定具体 IP--advertise-client-urls
网络 客户端访问集群时使用的地址(需能被外部访问) http://0.0.0.0:2479
通常与 listen-client-urls
相同,云环境需配置为公网 IP--listen-peer-urls
网络 节点间通信(Raft协议)的监听地址列表 http://0.0.0.0:2480
1.必须与 initial-advertise-peer-urls
一致。
2.默认监听本地的 2380 端口(用于节点选举、数据同步)--initial-advertise-peer-urls
网络 节点向集群声明的通信地址(需能被其他节点访问) http://0.0.0.0:2480
云环境需配置为内网 IP --initial-cluster
集群 初始集群成员列表(格式: name1=url1,name2=url2
)s1=http://0.0.0.0:2480
所有节点启动时必须一致,新增节点时需动态调整 --initial-cluster-token
集群 集群唯一标识令牌,防止不同集群意外合并 tkn
同一集群所有节点必须一致 --initial-cluster-state
集群 集群初始状态: new
-新建集群existing
-加入已有集群new
首次启动设为 new
,后续扩容节点设为existing
--log-level
日志 日志级别: debug
,info
,warn
,error
info
调试时可用 debug
,生产环境建议info
--logger
日志 日志库实现: zap
(结构化日志)或capnslog
(传统日志)zap
推荐使用 zap
,兼容性更好--log-outputs
日志 日志输出目标: stderr
(标准错误)/path/to/file
(文件)stderr
生产环境建议输出到文件(如 --log-outputs /var/log/etcd.log
)
3.安全增强示例
- 安装etcd,默认是不开启安全机制的,需要指定参数来开启
--listen-client-urls https://192.168.1.100:2379 \ --advertise-client-urls https://node1.example.com:2379 \ --cert-file=/path/to/server.crt \ --key-file=/path/to/server.key \ --client-cert-auth
- 启用 TLS 加密通信
- 绑定具体 IP 而非 0.0.0.0