Etcd 分布式键值存储集群部署与运维实战

一、Etcd 简介

Etcd 是一个高可用的分布式键值存储系统,由 CoreOS 团队开发,现已成为 CNCF 毕业项目。它基于 Raft 一致性算法,为分布式系统提供可靠的配置存储和服务发现能力。

核心特性

  • 强一致性:基于 Raft 协议保证数据一致性
  • 高可用:支持集群部署,容忍 (N-1)/2 个节点故障
  • 简单 API:提供 gRPC 和 HTTP RESTful API
  • Watch 机制:支持键值变化的实时监听
  • 多版本并发控制:支持 MVCC,保留历史版本

典型应用场景

  • Kubernetes 集群配置存储
  • 服务注册与发现
  • 分布式锁实现
  • 配置中心
  • leader 选举

二、生产环境集群规划

2.1 集群规模建议

集群节点数 容错能力 推荐场景
3 节点 容忍 1 节点故障 测试/开发环境
5 节点 容忍 2 节点故障 生产环境(推荐)
7 节点 容忍 3 节点故障 高可用要求极高场景

注意:节点数应为奇数,避免脑裂问题。

2.2 硬件资源配置

组件 最低配置 推荐配置
CPU 2 核 4 核+
内存 4GB 8GB+
磁盘 SSD 50GB NVMe SSD 100GB+
网络 1Gbps 10Gbps

关键提示:Etcd 对磁盘 IO 延迟敏感,必须使用 SSD,fsync 延迟应低于 10ms。

三、集群部署实战

3.1 环境准备

本次部署 5 节点集群,节点信息如下:

1
2
3
4
5
etcd-node1: 192.168.1.101
etcd-node2: 192.168.1.102
etcd-node3: 192.168.1.103
etcd-node4: 192.168.1.104
etcd-node5: 192.168.1.105

3.2 下载与安装

1
2
3
4
5
6
7
8
9
10
11
# 下载 Etcd 3.5.11(LTS 版本)
wget https://github.com/etcd-io/etcd/releases/download/v3.5.11/etcd-v3.5.11-linux-amd64.tar.gz

# 解压并安装
tar -xzf etcd-v3.5.11-linux-amd64.tar.gz
sudo mv etcd-v3.5.11-linux-amd64/etcd /usr/local/bin/
sudo mv etcd-v3.5.11-linux-amd64/etcdctl /usr/local/bin/

# 验证安装
etcd --version
etcdctl version

3.3 创建配置文件

在所有节点创建 /etc/etcd/etcd.conf.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 节点名称(每个节点不同)
name: etcd-node1

# 数据目录
data-dir: /var/lib/etcd

# 日志目录
log-dir: /var/log/etcd

# 监听地址
listen-peer-urls: http://0.0.0.0:2380
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:2380

# 初始集群配置(所有节点相同)
initial-advertise-peer-urls: http://192.168.1.101:2380
initial-cluster: etcd-node1=http://192.168.1.101:2380,etcd-node2=http://192.168.1.102:2380,etcd-node3=http://192.168.1.103:2380,etcd-node4=http://192.168.1.104:2380,etcd-node5=http://192.168.1.105:2380
initial-cluster-state: new
initial-cluster-token: etcd-cluster-prod

# 客户端访问地址
advertise-client-urls: http://192.168.1.101:2379,http://192.168.1.101:2380

# 性能调优
heartbeat-interval: 100
election-timeout: 1000
snapshot-count: 10000
max-snapshots: 5
max-wals: 5

# 配额配置
quota-backend-bytes: 8589934592 # 8GB

# 日志级别
log-level: info

注意:每个节点的 nameinitial-advertise-peer-urlsadvertise-client-urls 需要根据实际 IP 修改。

3.4 创建 Systemd 服务

创建 /etc/systemd/system/etcd.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[Unit]
Description=Etcd Server
Documentation=https://etcd.io/docs/
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
User=etcd
Group=etcd
ExecStart=/usr/local/bin/etcd --config-file=/etc/etcd/etcd.conf.yml
Restart=always
RestartSec=10s
LimitNOFILE=65536

# 安全配置
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
ReadWritePaths=/var/lib/etcd /var/log/etcd

[Install]
WantedBy=multi-user.target

3.5 创建用户与目录

1
2
3
4
5
6
7
8
9
10
11
# 创建 etcd 用户
sudo useradd -r -s /sbin/nologin etcd

# 创建数据目录
sudo mkdir -p /var/lib/etcd
sudo mkdir -p /var/log/etcd
sudo chown -R etcd:etcd /var/lib/etcd
sudo chown -R etcd:etcd /var/log/etcd

# 创建配置目录
sudo mkdir -p /etc/etcd

3.6 启动集群

1
2
3
4
5
6
7
8
9
10
11
# 重载 systemd
sudo systemctl daemon-reload

# 启动 etcd
sudo systemctl start etcd

# 设置开机自启
sudo systemctl enable etcd

# 检查状态
sudo systemctl status etcd

四、集群验证与测试

4.1 检查集群成员

1
2
3
4
5
6
7
# 查看集群成员列表
etcdctl --endpoints=192.168.1.101:2379 member list

# 输出示例:
# 422a64f21b80e0b2, started, etcd-node1, http://192.168.1.101:2380, http://192.168.1.101:2379, false
# 6f03a8b37c5e4a19, started, etcd-node2, http://192.168.1.102:2380, http://192.168.1.102:2379, false
# ...

4.2 检查集群健康状态

1
2
3
4
5
# 检查端点健康状态
etcdctl --endpoints=192.168.1.101:2379,192.168.1.102:2379,192.168.1.103:2379 endpoint health

# 检查端点状态
etcdctl --endpoints=192.168.1.101:2379 endpoint status --write-out=table

4.3 基本操作测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 写入数据
etcdctl put /test/key1 "value1"

# 读取数据
etcdctl get /test/key1

# 列出所有键
etcdctl get / --prefix --keys-only

# 删除键
etcdctl del /test/key1

# Watch 键变化(另开终端)
etcdctl watch /test/key1

五、安全配置

5.1 启用 TLS 加密

生成 CA 证书:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 安装 cfssl
wget -q --show-progress --https-only --timestamping \
https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \
https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64

chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
sudo mv cfssl_linux-amd64 /usr/local/bin/cfssl
sudo mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

# 创建 CA 配置
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"etcd": {
"expiry": "87600h",
"usages": ["signing","key encipherment","server auth","client auth"]
}
}
}
}
EOF

cat > ca-csr.json <<EOF
{
"CN": "etcd CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "etcd",
"OU": "etcd CA"
}
]
}
EOF

# 生成 CA 证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca

生成服务器证书:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
cat > server-csr.json <<EOF
{
"CN": "etcd-server",
"hosts": [
"192.168.1.101",
"192.168.1.102",
"192.168.1.103",
"192.168.1.104",
"192.168.1.105",
"localhost",
"127.0.0.1"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "etcd",
"OU": "etcd Server"
}
]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd server-csr.json | cfssljson -bare server

5.2 配置 TLS

修改 etcd.conf.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
listen-peer-urls: https://0.0.0.0:2380
listen-client-urls: https://0.0.0.0:2379
initial-advertise-peer-urls: https://192.168.1.101:2380
advertise-client-urls: https://192.168.1.101:2379

peer-trusted-ca-file: /etc/etcd/ssl/ca.pem
peer-cert-file: /etc/etcd/ssl/server.pem
peer-key-file: /etc/etcd/ssl/server-key.pem

client-cert-auth: true
trusted-ca-file: /etc/etcd/ssl/ca.pem
cert-file: /etc/etcd/ssl/server.pem
key-file: /etc/etcd/ssl/server-key.pem

六、监控与告警

6.1 关键监控指标

1
2
3
4
5
6
# Prometheus 抓取配置
scrape_configs:
- job_name: 'etcd'
static_configs:
- targets: ['192.168.1.101:2379','192.168.1.102:2379','192.168.1.103:2379']
metrics_path: /metrics

6.2 核心告警规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
groups:
- name: etcd-alerts
rules:
# Etcd 节点宕机
- alert: EtcdMemberDown
expr: up{job="etcd"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Etcd 节点 {{ $labels.instance }} 宕机"
description: "Etcd 节点已宕机超过 1 分钟"

# Leader 变更频繁
- alert: EtcdLeaderChanges
expr: rate(etcd_server_leader_changes_seen_total[5m]) > 3
for: 5m
labels:
severity: warning
annotations:
summary: "Etcd Leader 变更频繁"
description: "5 分钟内 Leader 变更超过 3 次"

# 数据库大小接近配额
- alert: EtcdDatabaseSizeHigh
expr: etcd_mvcc_db_total_size_in_bytes / etcd_server_quota_backend_bytes > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "Etcd 数据库大小超过配额 80%"
description: "当前使用率:{{ $value | humanizePercentage }}"

# 磁盘同步延迟过高
- alert: EtcdDiskBackendCommitDurationHigh
expr: histogram_quantile(0.99, rate(etcd_disk_backend_commit_duration_seconds_bucket[5m])) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "Etcd 磁盘写入延迟过高"
description: "P99 延迟:{{ $value | humanizeDuration }}"

七、备份与恢复

7.1 在线备份

1
2
3
4
5
6
7
8
9
# 创建快照
etcdctl snapshot save backup.db \
--endpoints=192.168.1.101:2379 \
--cacert=/etc/etcd/ssl/ca.pem \
--cert=/etc/etcd/ssl/server.pem \
--key=/etc/etcd/ssl/server-key.pem

# 验证快照
etcdctl snapshot status backup.db --write-out=table

7.2 数据恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 停止 etcd 服务
sudo systemctl stop etcd

# 恢复数据(在新节点或原节点)
etcdctl snapshot restore backup.db \
--data-dir=/var/lib/etcd-restored \
--name=etcd-node1 \
--initial-cluster=etcd-node1=https://192.168.1.101:2380,etcd-node2=https://192.168.1.102:2380,etcd-node3=https://192.168.1.103:2380,etcd-node4=https://192.168.1.104:2380,etcd-node5=https://192.168.1.105:2380 \
--initial-cluster-token=etcd-cluster-prod \
--initial-advertise-peer-urls=https://192.168.1.101:2380

# 修改配置指向新数据目录
# 修改 /etc/etcd/etcd.conf.yml 中 data-dir: /var/lib/etcd-restored

# 启动服务
sudo systemctl start etcd

八、常见故障排查

8.1 节点无法加入集群

现象:新节点启动后无法加入现有集群

排查步骤

1
2
3
4
5
6
7
8
9
10
11
# 1. 检查网络连通性
telnet 192.168.1.101 2380

# 2. 检查防火墙规则
sudo iptables -L -n | grep 2380

# 3. 查看 etcd 日志
sudo journalctl -u etcd -f

# 4. 检查集群成员列表
etcdctl member list

解决方案

1
2
3
4
5
# 添加新成员
etcdctl member add etcd-node6 \
--peer-urls=https://192.168.1.106:2380

# 按输出配置新节点后启动

8.2 集群脑裂

现象:出现多个 Leader

排查

1
2
# 检查各节点认为的 Leader
etcdctl endpoint status --write-out=table

解决方案

  1. 停止所有节点
  2. 保留多数派节点数据
  3. 从快照恢复少数派节点
  4. 重新启动集群

8.3 性能下降

现象:写入延迟升高,请求超时

排查

1
2
3
4
5
# 检查磁盘延迟
etcdctl check perf --auto-compact=false

# 检查数据库大小
etcdctl endpoint status --write-out=table

优化建议

  1. 更换更高性能 SSD
  2. 调整 heartbeat-intervalelection-timeout
  3. 启用数据压缩:etcdctl compact <revision>
  4. 增加 quota-backend-bytes

九、运维最佳实践

9.1 定期维护任务

1
2
3
4
5
6
7
8
9
10
11
12
# 每日:检查集群健康
etcdctl endpoint health

# 每周:创建备份
etcdctl snapshot save /backup/etcd-$(date +%Y%m%d).db

# 每月:压缩历史数据
REVISION=$(etcdctl endpoint status --write-out="json" | jq -r '.[0].revision')
etcdctl compact $REVISION

# 每季度:执行碎片整理
etcdctl defrag

9.2 升级流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 备份数据
etcdctl snapshot save backup.db

# 2. 逐节点滚动升级
# 停止节点
sudo systemctl stop etcd

# 替换二进制
sudo mv /usr/local/bin/etcd /usr/local/bin/etcd.bak
sudo mv etcd-new /usr/local/bin/etcd

# 启动节点
sudo systemctl start etcd

# 验证节点健康
etcdctl endpoint health

# 3. 重复以上步骤升级其他节点

9.3 容量规划

  • 单个键值对不超过 1MB
  • 总键值对数量不超过 100 万
  • 数据库大小不超过配额 80%
  • 定期压缩和碎片整理

十、总结

Etcd 作为分布式系统的核心组件,其稳定性和性能直接影响整个系统。生产环境部署需注意:

  1. 硬件选型:必须使用 SSD,网络延迟低于 1ms
  2. 集群规模:生产环境至少 5 节点
  3. 安全配置:启用 TLS 加密和客户端认证
  4. 监控告警:重点关注磁盘延迟和数据库大小
  5. 备份策略:定期快照并验证可恢复性
  6. 容量管理:定期压缩和碎片整理

遵循以上实践,可确保 Etcd 集群长期稳定运行。