13.生产环境部署策略
生产环境部署 etcd 不是简单地把二进制文件扔到服务器上跑起来就算完事。真实的线上系统需要考虑容灾、扩缩容、监控、安全、性能隔离等一系列问题。这一章我们聚焦如何把 etcd 集群稳妥地部署到生产环境,涵盖从容器化到高可用架构的完整实践。
Kubernetes 部署模式
在 Kubernetes 生态中部署 etcd 有两种典型场景:作为 Kubernetes 自身的数据存储,或是作为业务应用依赖的独立服务。这两种场景对部署策略的要求截然不同。
作为 Kubernetes 控制平面组件
当 etcd 为 Kubernetes 本身提供存储时,它通常以静态 Pod 的形式运行在 master 节点上。kubelet 直接管理这些 Pod,不经过 API Server。这种部署方式在 kubeadm 等工具中已经是标准实践。静态 Pod 的配置文件放在 /etc/kubernetes/manifests 目录,kubelet 会定时扫描并确保这些 Pod 始终运行。
这种模式下,etcd 实例与 master 节点绑定,网络使用宿主机网络栈,存储使用本地 SSD 卷。配置参数通过 Pod 定义中的 command 字段直接注入。由于 Kubernetes 自身依赖 etcd,任何对 etcd 的运维操作都必须极其谨慎,升级前必须备份数据,并准备好回滚方案。
作为独立服务部署
业务应用使用的 etcd 集群应该以普通 Deployment 或 StatefulSet 形式部署在 Kubernetes 中。推荐使用 StatefulSet,因为它能为每个 Pod 提供稳定的网络标识和持久化存储卷,这对 etcd 这类有状态服务至关重要。
StatefulSet 部署时需要注意几个关键点。首先,headless service 必须正确配置,确保 Pod 有稳定的 DNS 记录。其次,存储卷要使用 volumeClaimTemplates 动态申请,存储类应选择支持高性能随机读写的 SSD 类型。最后,初始化集群时要用 initial-cluster-token 防止意外加入其他集群。
Pod 的 resource requests 和 limits 要设置合理,特别是 memory limit。etcd 对内存敏感,OOM killed 会导致成员频繁重启,影响集群稳定性。建议 requests 和 limits 保持一致,避免资源竞争。
配置管理
Kubernetes 中的 etcd 配置建议通过 ConfigMap 管理,但敏感信息如初始集群 token、客户端证书等应使用 Secret。启动脚本可以写在 ConfigMap 中,通过 volume 挂载到 Pod 内。
对于需要动态调整的配置项,比如心跳间隔、选举超时时间,可以通过修改 ConfigMap 后滚动更新 Pod 实现。但要注意,某些参数修改需要重启才能生效,滚动更新策略要设置 maxUnavailable: 1,确保集群始终有足够多的节点维持仲裁。
Docker 容器运行
不使用 Kubernetes 时,直接用 Docker 运行 etcd 也是常见选择。这种方式更轻量,适合小规模部署或开发测试环境模拟生产场景。
基础运行命令
最简单的启动方式使用官方镜像:
docker run -d \
--name etcd-server \
--network host \
-v /var/lib/etcd:/etcd-data \
-e ETCD_NAME=node1 \
-e ETCD_DATA_DIR=/etcd-data \
-e ETCD_INITIAL_ADVERTISE_PEER_URLS=http://10.0.1.10:2380 \
-e ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 \
-e ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 \
-e ETCD_ADVERTISE_CLIENT_URLS=http://10.0.1.10:2379 \
-e ETCD_INITIAL_CLUSTER=node1=http://10.0.1.10:2380,node2=http://10.0.1.11:2380,node3=http://10.0.1.12:2380 \
-e ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-1 \
-e ETCD_INITIAL_CLUSTER_STATE=new \
quay.io/coreos/etcd:v3.5.0
这段命令启动了单节点 etcd,使用宿主机网络避免容器网络性能损耗,数据目录挂载到宿主机保证数据持久化。环境变量方式配置清晰直观,适合脚本化管理。
生产级 Docker 配置
生产环境需要更完善的配置。首先,资源限制必须设置:
docker run -d \
--name etcd-prod \
--network host \
--restart unless-stopped \
--memory 4g \
--cpus 2 \
--ulimit nofile=65536:65536 \
--ulimit nproc=4096:4096 \
-v /var/lib/etcd:/etcd-data \
-v /etc/etcd/ssl:/etcd-ssl:ro \
-e ETCD_NAME=node1 \
-e ETCD_DATA_DIR=/etcd-data \
-e ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380 \
-e ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379 \
-e ETCD_INITIAL_ADVERTISE_PEER_URLS=https://10.0.1.10:2380 \
-e ETCD_ADVERTISE_CLIENT_URLS=https://10.0.1.10:2379 \
-e ETCD_INITIAL_CLUSTER=... \
-e ETCD_CLIENT_CERT_AUTH=true \
-e ETCD_TRUSTED_CA_FILE=/etcd-ssl/ca.crt \
-e ETCD_CERT_FILE=/etcd-ssl/server.crt \
-e ETCD_KEY_FILE=/etcd-ssl/server.key \
-e ETCD_PEER_CLIENT_CERT_AUTH=true \
-e ETCD_PEER_TRUSTED_CA_FILE=/etcd-ssl/ca.crt \
-e ETCD_PEER_CERT_FILE=/etcd-ssl/peer.crt \
-e ETCD_PEER_KEY_FILE=/etcd-ssl/peer.key \
quay.io/coreos/etcd:v3.5.0
这个配置增加了内存和 CPU 限制,防止资源耗尽。文件描述符和进程数限制也调整到生产级水平。TLS 证书通过只读卷挂载,确保传输安全。重启策略设为 unless-stopped,保证容器意外退出后自动恢复。
多节点集群编排
手动管理多节点 Docker 部署容易出错,建议用 Docker Compose 编排。docker-compose.yml 示例如下:
version: '3.7'
services:
etcd-node1:
image: quay.io/coreos/etcd:v3.5.0
container_name: etcd-node1
network_mode: host
restart: unless-stopped
volumes:
- /data/etcd/node1:/etcd-data
- /etc/etcd/ssl:/etcd-ssl:ro
environment:
- ETCD_NAME=node1
- ETCD_DATA_DIR=/etcd-data
- ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380
- ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379
- ETCD_INITIAL_ADVERTISE_PEER_URLS=https://10.0.1.10:2380
- ETCD_ADVERTISE_CLIENT_URLS=https://10.0.1.10:2379
- ETCD_INITIAL_CLUSTER=node1=https://10.0.1.10:2380,node2=https://10.0.1.11:2380,node3=https://10.0.1.12:2380
- ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-prod
- ETCD_INITIAL_CLUSTER_STATE=new
- ETCD_CLIENT_CERT_AUTH=true
- ETCD_TRUSTED_CA_FILE=/etcd-ssl/ca.crt
- ETCD_CERT_FILE=/etcd-ssl/server.crt
- ETCD_KEY_FILE=/etcd-ssl/server.key
deploy:
resources:
limits:
memory: 4g
cpus: '2'
etcd-node2:
image: quay.io/coreos/etcd:v3.5.0
container_name: etcd-node2
network_mode: host
restart: unless-stopped
volumes:
- /data/etcd/node2:/etcd-data
- /etc/etcd/ssl:/etcd-ssl:ro
environment:
- ETCD_NAME=node2
- ETCD_DATA_DIR=/etcd-data
- ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380
- ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379
- ETCD_INITIAL_ADVERTISE_PEER_URLS=https://10.0.1.11:2380
- ETCD_ADVERTISE_CLIENT_URLS=https://10.0.1.11:2379
- ETCD_INITIAL_CLUSTER=node1=https://10.0.1.10:2380,node2=https://10.0.1.11:2380,node3=https://10.0.1.12:2380
- ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-prod
- ETCD_INITIAL_CLUSTER_STATE=new
- ETCD_CLIENT_CERT_AUTH=true
- ETCD_TRUSTED_CA_FILE=/etcd-ssl/ca.crt
- ETCD_CERT_FILE=/etcd-ssl/server.crt
- ETCD_KEY_FILE=/etcd-ssl/server.key
deploy:
resources:
limits:
memory: 4g
cpus: '2'
etcd-node3:
image: quay.io/coreos/etcd:v3.5.0
container_name: etcd-node3
network_mode: host
restart: unless-stopped
volumes:
- /data/etcd/node3:/etcd-data
- /etc/etcd/ssl:/etcd-ssl:ro
environment:
- ETCD_NAME=node3
- ETCD_DATA_DIR=/etcd-data
- ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380
- ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379
- ETCD_INITIAL_ADVERTISE_PEER_URLS=https://10.0.1.12:2380
- ETCD_ADVERTISE_CLIENT_URLS=https://10.0.1.12:2379
- ETCD_INITIAL_CLUSTER=node1=https://10.0.1.10:2380,node2=https://10.0.1.11:2380,node3=https://10.0.1.12:2380
- ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-prod
- ETCD_INITIAL_CLUSTER_STATE=new
- ETCD_CLIENT_CERT_AUTH=true
- ETCD_TRUSTED_CA_FILE=/etcd-ssl/ca.crt
- ETCD_CERT_FILE=/etcd-ssl/server.crt
- ETCD_KEY_FILE=/etcd-ssl/server.key
deploy:
resources:
limits:
memory: 4g
cpus: '2'
这个 Compose 文件定义了三节点集群,每个节点使用独立的数据目录和相同的 TLS 配置。通过 docker-compose up -d 可以一键启动整个集群。升级时修改镜像版本后执行 docker-compose up -d 即可实现滚动更新。
etcd 网关配置
etcd gateway 是一个轻量级的 TCP 代理,设计初衷是解决客户端端点管理的问题。它不是缓存代理,也不终止 TLS,纯粹是网络层面的流量转发器。
网关工作原理
网关启动时会从配置中读取后端 etcd 集群的端点列表,然后在本机监听一个固定端口。客户端连接网关时,网关按简单轮询策略将请求转发到健康的后端节点。如果某个后端节点故障,网关会自动将其剔除,客户端无感知。
这种设计让网关本身无状态,可以任意扩缩容。网关不解析应用层协议,只是单纯转发 TCP 包,因此开销极低,延迟增加在微秒级别。但这也意味着它无法提供高级功能如请求缓存、批量合并或 watch 优化。
使用场景分析
网关最适合的场景是:同一台服务器上运行多个访问相同 etcd 集群的应用。传统方式下,每个应用都需要配置 etcd 集群所有端点,集群拓扑变化时所有应用都要重启更新配置。引入网关后,应用只需连接本地网关,拓扑变化只需更新网关配置。
举个例子,假设有 10 个微服务运行在同一台宿主机,都依赖同一个三节点 etcd 集群。没有网关时,10 个服务的配置文件中都要写三个 etcd 节点的 IP 和端口。当集群扩容增加一个节点时,10 个服务的配置都要修改并重启。有了网关,10 个服务统一连接 127.0.0.1:23790,集群变化只需重启网关,业务服务完全无感知。
不推荐使用网关的场景
网关不是性能优化工具。它不做缓存,所有请求都要转发到后端 etcd 节点,无法减轻集群负载。如果目标是提升集群吞吐量,应该考虑客户端连接池优化或 etcd 自身的水平扩容。
在 Kubernetes 这类具备服务发现的平台中,网关的价值也有限。Kubernetes 的 Service 和 Endpoint 机制已经提供了类似功能,kube-proxy 本身就实现了 TCP 转发和负载均衡。再部署一层网关反而增加复杂度。
网关部署实践
假设后端 etcd 集群有三个节点,IP 分别为 10.0.1.10、10.0.1.11、10.0.1.12,客户端端口都是 2379。在应用服务器上启动网关:
etcd gateway start \
--endpoints=10.0.1.10:2379,10.0.1.11:2379,10.0.1.12:2379 \
--listen-addr=0.0.0.0:23790 \
--retry-delay=30s \
--insecure-skip-tls-verify=true
命令参数说明:
--endpoints指定后端 etcd 节点列表,用逗号分隔--listen-addr是网关监听的本地地址,应用连接这个端口--retry-delay设置后端节点故障后的重试间隔,避免频繁探测--insecure-skip-tls-verify跳过 TLS 验证,仅用于测试环境
启动后日志会显示 ready to proxy client requests to [...],表示网关已就绪。此时应用只需将 etcd 客户端地址改为 127.0.0.1:23790 即可。
基于 DNS 的服务发现
如果 etcd 集群使用 DNS SRV 记录做服务发现,网关可以自动从 DNS 获取端点列表。假设 DNS 配置如下:
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra0.example.com.
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra1.example.com.
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra2.example.com.
对应的 A 记录:
infra0.example.com. 300 IN A 10.0.1.10
infra1.example.com. 300 IN A 10.0.1.11
infra2.example.com. 300 IN A 10.0.1.12
启动网关时指定域名:
etcd gateway start \
--discovery-srv=example.com \
--listen-addr=0.0.0.0:23790
网关会定期查询 DNS SRV 记录,自动更新后端节点列表。这种方式与 etcd 集群自身的 DNS 发现机制保持一致,运维更方便。
网关高可用
网关本身无状态,可以在每台应用服务器上部署一个实例,由 systemd 或 supervisord 管理。如果网关进程崩溃,监控工具会自动重启。应用连接本地网关,不存在单点故障。
对于更严格的可用性要求,可以在每台服务器上部署两个网关实例监听不同端口,应用配置中写入两个地址实现 failover。但实践中,网关足够稳定,单实例通常已能满足需求。
gRPC 代理设置
gRPC 代理是 etcd 3.x 引入的另一种代理模式,与网关不同,它工作在应用层,理解 etcd 的 gRPC 协议,能提供更多高级功能。
代理与网关的区别
gRPC 代理会终止客户端的 gRPC 连接,自己作为客户端向后端 etcd 集群发起新连接。它可以缓存响应、合并 watch 请求、实现负载均衡策略。相比网关的透明转发,gRPC 代理更智能,但延迟也略高。
关键区别:
- 网关是 TCP 层代理,gRPC 代理是应用层代理
- 网关不终止 TLS,gRPC 代理可以终止 TLS
- 网关无状态,gRPC 代理需要维护连接状态
- 网关配置简单,gRPC 代理功能更强大
启动 gRPC 代理
基础启动命令:
etcd grpc-proxy start \
--endpoints=10.0.1.10:2379,10.0.1.11:2379,10.0.1.12:2379 \
--listen-addr=0.0.0.0:23790 \
--namespace=myapp/
关键参数:
--endpoints指定后端 etcd 集群--listen-addr代理监听地址--namespace为所有请求添加前缀,实现多租户隔离
命名空间隔离
gRPC 代理的命名空间功能非常实用。假设多个业务团队共享同一个 etcd 集群,团队 A 使用前缀 /team-a/,团队 B 使用 /team-b/。代理可以为每个团队启动一个实例:
# 团队 A 的代理
etcd grpc-proxy start \
--endpoints=10.0.1.10:2379,10.0.1.11:2379,10.0.1.12:2379 \
--listen-addr=0.0.0.0:23791 \
--namespace=team-a/
# 团队 B 的代理
etcd grpc-proxy start \
--endpoints=10.0.1.10:2379,10.0.1.11:2379,10.0.1.12:2379 \
--listen-addr=0.0.0.0:23792 \
--namespace=team-b/
团队 A 的应用连接 127.0.0.1:23791,所有键值操作自动加上 /team-a/ 前缀。团队 B 同理。这样既实现了资源隔离,又简化了客户端代码,客户端无需关心前缀。
缓存与可扩展性
gRPC 代理可以缓存部分读请求,减轻后端压力。启用缓存:
etcd grpc-proxy start \
--endpoints=10.0.1.10:2379,10.0.1.11:2379,10.0.1.12:2379 \
--listen-addr=0.0.0.0:23790 \
--cache-size=10000 \
--cache-ttl=30s
--cache-size 设置缓存条目数,--cache-ttl 设置缓存过期时间。对于读多写少的场景,这能显著降低后端集群的 QPS。
代理还支持水平扩展,多个代理实例可以共享同一个后端集群,前端通过负载均衡器分发请求。这为大流量场景提供了弹性伸缩能力。
TLS 配置
gRPC 代理可以终止客户端 TLS,然后用新的 TLS 连接后端集群:
etcd grpc-proxy start \
--endpoints=https://10.0.1.10:2379,https://10.0.1.11:2379,https://10.0.1.12:2379 \
--listen-addr=0.0.0.0:23790 \
--cert-file=/path/to/proxy-server.crt \
--key-file=/path/to/proxy-server.key \
--trusted-ca-file=/path/to/ca.crt \
--endpoints-cert-file=/path/to/client.crt \
--endpoints-key-file=/path/to/client.key \
--endpoints-trusted-ca-file=/path/to/ca.crt
这里配置了两种证书:
--cert-file和--key-file是代理对外服务的证书,客户端连接代理时使用--endpoints-cert-file和--endpoints-key-file是代理连接后端 etcd 的客户端证书
这种分层 TLS 架构让安全控制更精细,代理可以作为统一的 TLS 终止点,简化客户端配置。
生产环境清单
部署到生产前,必须逐项检查以下配置,任何遗漏都可能成为线上故障的隐患。
硬件与系统调优
存储:必须使用 SSD,NVMe 更佳。etcd 对磁盘 I/O 延迟极度敏感,HDD 会导致请求超时和 leader 频繁切换。磁盘要单独分区,避免与其他应用共享。文件系统推荐 ext4 或 xfs,挂载时添加 noatime 选项减少写操作。
网络:千兆网卡是底线,万兆更好。etcd 节点间延迟应小于 10ms,跨机房部署需慎重评估。防火墙规则要开放 2379(客户端)和 2380(peer)端口,同时限制来源 IP,只允许可信网络访问。
内核参数:必须调整以下参数:
# 增加文件描述符限制
echo "fs.file-max = 1000000" >> /etc/sysctl.conf
# 优化内存分配
echo "vm.swappiness = 1" >> /etc/sysctl.conf
echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
# 提高网络吞吐量
echo "net.core.somaxconn = 32768" >> /etc/sysctl.conf
echo "net.ipv4.tcp_max_syn_backlog = 16384" >> /etc/sysctl.conf
sysctl -p
这些参数确保系统能处理高并发连接,避免内存交换导致的性能抖动。
安全配置
TLS:生产环境必须启用 TLS 加密传输和客户端证书认证。自签证书可以使用 cfssl 工具生成,但要注意证书有效期和轮换策略。商业环境建议用内部 CA 签发。
证书文件权限要严格限制:
chmod 600 /etc/etcd/ssl/server.key
chmod 644 /etc/etcd/ssl/server.crt
chmod 644 /etc/etcd/ssl/ca.crt
chown -R etcd:etcd /etc/etcd/ssl
RBAC:启用用户认证和角色权限控制。至少创建三个角色:
root:拥有所有权限,仅用于紧急运维admin:拥有读写权限,用于日常管理readonly:只读权限,用于监控和备份
为每个应用创建独立用户,分配最小权限。定期审计权限配置,删除无用账号。
网络隔离:etcd 集群应部署在独立 VPC 或子网,仅对应用层开放 2379 端口。Peer 端口 2380 只应在 etcd 节点间互通,不对外暴露。
监控与告警
必须监控的核心指标:
etcd_server_has_leader:是否有 leader,0 表示集群异常etcd_disk_backend_commit_duration_seconds:磁盘提交延迟,超过 100ms 需告警etcd_network_peer_round_trip_time_seconds:节点间网络延迟etcd_mvcc_db_total_size_in_bytes:数据库大小,超过配额前预警etcd_grpc_requests_failed_total:失败请求数,突增说明有问题
告警阈值设置要合理,避免告警风暴。例如磁盘延迟可以设 50ms 警告、100ms 严重,给运维人员预留处理时间。
备份策略
快照备份要自动化,每天至少一次全量备份。备份脚本示例:
#!/bin/bash
ETCDCTL_API=3 etcdctl \
--endpoints=https://10.0.1.10:2379 \
--cacert=/etc/etcd/ssl/ca.crt \
--cert=/etc/etcd/ssl/client.crt \
--key=/etc/etcd/ssl/client.key \
snapshot save /backup/etcd-$(date +%Y%m%d-%H%M%S).db
# 保留最近 7 天的备份
find /backup -name "etcd-*.db" -mtime +7 -delete
备份文件要异地存储,定期做恢复演练。备份期间集群性能会受影响,建议在业务低峰期执行。
日志管理
日志级别建议设为 info,记录关键操作和异常。日志要集中收集到 ELK 或 Loki 系统,方便检索和分析。保留 30 天日志以满足审计需求。
关键日志字段包括:时间戳、节点名称、日志级别、消息内容、请求 ID。通过日志可以追踪请求全链路,定位性能瓶颈。
高可用架构
高可用是生产部署的核心目标,需要从架构层面保证 etcd 集群在各种故障场景下仍能提供服务。
仲裁机制与节点数选择
etcd 使用 Raft 共识算法,要求多数派节点存活才能工作。节点数与容错能力关系如下:
- 3 节点:容忍 1 个节点故障,是生产环境最小配置
- 5 节点:容忍 2 个节点故障,适合对可用性要求极高的场景
- 7 节点:容忍 3 个节点故障,但写入性能下降明显,一般不建议
节点数必须是奇数,偶数节点不提供额外容错能力,反而增加通信开销。大多数场景下,3 节点或 5 节点是最佳选择。
跨可用区部署
在云环境中,etcd 节点应分布在不同可用区(AZ),避免单 AZ 故障导致集群不可用。但跨 AZ 会增加网络延迟,需要权衡。
推荐部署策略:
- 3 节点集群:每个 AZ 部署 1 节点,共 3 个 AZ
- 5 节点集群:选择 3 个 AZ,其中 2 个 AZ 各部署 2 节点,另 1 个 AZ 部署 1 节点
这种分布确保任意一个 AZ 整体故障时,集群仍能保持仲裁。但要注意,跨 AZ 的延迟可能触发 Raft 心跳超时,需要适当调大 heartbeat-interval 和 election-timeout。
故障切换与恢复
当 leader 节点故障时,剩余节点会在选举超时后发起新选举,通常在 1-3 秒内完成。客户端请求会短暂失败,需要重试机制。
follower 节点故障对集群无影响,但会减少容错能力。监控到节点故障后,应尽快修复或替换。替换流程:
- 从集群中移除故障节点:
etcdctl member remove <member-id> - 清理故障节点数据目录
- 在新机器上启动 etcd,加入集群:
etcdctl member add <name> --peer-urls=<url> - 新节点从现有节点同步数据,完成后集群恢复正常
读写分离架构
对于读多写少的场景,可以部署只读节点分担压力。etcd 3.4 开始支持 learner 节点,learner 不参与投票,只同步数据,可以作为只读副本。
部署 learner 节点:
# 在现有集群添加 learner 成员
etcdctl member add learner-node --peer-urls=http://10.0.1.13:2380 --learner
# 启动 learner 节点
etcd --name=learner-node \
--initial-cluster-state=existing \
--initial-cluster=node1=http://10.0.1.10:2380,node2=http://10.0.1.11:2380,node3=http://10.0.1.12:2380,learner-node=http://10.0.1.13:2380 \
--listen-peer-urls=http://10.0.1.13:2380 \
--listen-client-urls=http://10.0.1.13:2379 \
--advertise-client-urls=http://10.0.1.13:2379 \
--initial-advertise-peer-urls=http://10.0.1.13:2380
learner 节点可以水平扩展,部署多个用于读请求负载均衡。但要注意,learner 的数据可能略有延迟,不适合强一致性读场景。
异地容灾方案
跨地域部署 etcd 面临高延迟挑战,通常不推荐。如果必须跨地域,建议采用集群联邦方案:每个地域部署独立的 etcd 集群,应用层做数据同步。
另一种方案是使用异步复制工具如 etcd- Mirror-Maker,将主集群数据实时同步到备集群。主集群故障时,手动切换应用到备集群。这种方案有数据丢失风险,适合对 RPO 要求不高的场景。
容量规划与扩展
etcd 数据量增长要持续监控。单个集群建议不超过 8GB,超过后性能会急剧下降。如果数据量持续增长,应考虑:
- 压缩历史版本:
etcdctl compact - 增加空间配额:
--quota-backend-bytes - 拆分集群:按业务维度拆分为多个小集群
水平扩展 etcd 集群只能增加 learner 节点,不能增加 voting 成员。voting 成员数在集群创建时就已确定,后期只能替换不能增加。这是 Raft 算法的限制,设计架构时要充分考虑未来容量需求。
生产环境部署 etcd 是一项系统工程,涉及基础设施、网络、安全、监控等多个层面。没有一劳永逸的方案,必须根据业务特点、流量模型、故障容忍度等因素综合设计。部署前充分测试,模拟各种故障场景,验证监控和恢复流程,这样才能在真实故障来临时从容应对。下一章我们将探讨客户端开发的最佳实践,看看如何在应用层更好地使用 etcd。