Kubernetes 运维管理ETCD工作机制和客户端访问 备份和还原
Kubernetes 备份和还原及迁移
Kubernetes 集群的容灾架构与方案
https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-forkubernetes/use-cases/disaster-recovery-architecture-and-scheme-based-onkubernetes-container-cluster?spm=a2c4g.11186623.help-menu85222.d_3_2_0.d67169eejnjqVX
在进行系统架构设计时,必须考虑到信息系统和基础设施可能遇到的各种潜在威胁,例如:硬件故障、
软件系统崩溃、人为操作失误、安全攻击、自然灾害等。
为了确保Kubernetes集群系统能够在各种异常故障场景下快速恢复并保持业务连续性,必须为系统设计
一套完善的容灾方案。
容灾目标
- Recovery time objective(RTO):服务中断与服务恢复之间可接受的最大延迟时间。决定服务停机的可接受时长。
- Recovery point objective(RPO):自上一个数据恢复点以来可接受的最大时间量。决定可接受的数据最大丢失量或重建。
对于RTO和RPO来说,数值越低表示服务停机的时间和数据丢失量越少,但是越低的RTO和RPO意味着
资源成本和运维复性越高。因此,您需要考虑实际业务成本及运维成本制定适当的RTO和RPO。
容灾策略
策略概述

如上图所示,提供了三种常见的容灾策略:备份与恢复、主备、双活。
不同容灾策略的成本和收益均有所差异,您需要根据业务的重要性、数据丢失风险、可投入成本等进行
综合评估,选择合适的容灾策略。
备份与恢复(Backup-Restore)
在备份与恢复模式下,系统运行时会备份应用和数据,故障或灾难发生时,系统会将备份的应用和数据在另一地点进行恢复,并切换业务流量。
由于数据无法实时备份,在恢复数据时会有一定的数据丢失,并且如果数据量较大时,恢复时间可能较长。
主备(Active-Standby)

如上图所示,在主备容灾模式下,主Location处理所有的业务流量,备用Location可以启动较少的应用
实例以节省成本,并周期性发送测试流量以验证系统有效性。
在故障或灾难发生时,系统进行数据库主备切换,扩容备用Location中的应用实例数量,并将业务流量切换到备用Location上。
双活(Active-Active)

如上图所示,在双活容灾模式下,两个Location启动相同的应用实例数,同时处理业务流量。
在故障或灾难发生时,系统进行数据库主备切换,并将业务流量全部切换到正常的Location上。
常见的两地三中心容灾模型, 比如: 阿里巴巴部分核心业务系统
方案说明:
以杭州的两个同城数据中心构建双活体系,通过自研的分布式存储和数据库同步技术,实现数据的
实时同步以及应用的灵活调度,让业务可以在两个中心均衡运行。
异地灾备中心选择在其他地区,依靠先进的异步复制和数据一致性校验等手段,确保关键业务数据
能在异地有可靠备份和可恢复性,像淘宝、天猫的交易数据、商家信息等都是重点保障对象。
应用场景:
在面对电商大促等超高并发业务场景以及偶发的机房制冷故障等意外情况时,同城双活中心能够高
效协同,分担流量压力,保障购物流程顺畅进行,消费者下单、支付、查询订单等操作不受影响。
而异地灾备中心也为数据安全上了一道坚固的保险,万一出现极端的区域性灾难,能迅速恢复业务
数据,重启关键业务运营,维持庞大的电商生态正常运转。
Kubernetes 备份还原说明
在 Kubernetes 中,备份和还原是一个重要的操作,尤其是在生产环境中,确保集群状态的持久性和可恢复性至关重要。
Kubernetes 的备份和还原可以通过多种方式实现,具体取决于你想要备份的内容。以下是常见的备份和还原方法:
备份和还原的内容
在 Kubernetes 中,需要备份的内容主要包括以下几部分:
- 集群资源:如 Deployment、Service、ConfigMap、Secret、PersistentVolumeClaim 等。
- ETCD 数据库:Kubernetes 集群的状态存储在 ETCD 中,备份 ETCD 可以恢复整个集群的状态。
- 持久化存储数据:如 PersistentVolume 中的数据。
根据你的需求,可以选择备份部分或全部内容。
备份和还原方法
方法 1:备份 Kubernetes 指定资源
如果你只需要备份 Kubernetes 的资源(如 Deployment、Service、ConfigMap 等),可以使用kubectl 导出资源。
备份 Kubernetes 资源
1. 导出所有命名空间资源:
使用以下命令导出所有命名空间中的常见的资源,不包括: configmap,secret,pvc,pv 等
kubectl get all --all-namespaces -o yaml > all-resources.yaml
2. 导出特定命名空间资源:
如果只需要备份特定命名空间的常见的资源,可以指定命名空间。
kubectl get all -n <namespace> -o yaml > namespace-resources.yaml
3. 备份 Secrets 和 ConfigMaps:
备份 Secrets 和 ConfigMaps 时需要特别注意,因为它们可能包含敏感信息。
kubectl get secrets,configmaps -n <namespace> -o yaml > secretsconfigmaps.yaml
还原 Kubernetes 资源
1. 创建命名空间(如果需要):
在还原资源之前,确保目标命名空间存在。
kubectl create namespace <namespace>
2. 应用资源:
使用 kubectl apply 命令还原资源。
kubectl apply -f all-resources.yaml
方法 2:备份 ETCD
ETCD 是 Kubernetes 的核心存储组件,存储了集群的所有状态信息。备份 ETCD 是最彻底的备份方式,
可以恢复整个集群的状态。
备份 ETCD
1. 检查 ETCD 配置:
确保你能够访问 ETCD 集群,并获取 ETCD 的配置信息(如证书、端口等)。
kubectl get pods -n kube-system -l component=etcd
2. 使用 etcdctl 备份 ETCD:
使用 etcdctl 工具备份 ETCD 数据。
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
snapshot save /backup/etcd-snapshot.db
这会生成一个快照文件 /backup/etcd-snapshot.db
3. 验证备份:
使用以下命令验证备份文件的完整性。
ETCDCTL_API=3 etcdctl --write-out=table snapshot status /backup/etcdsnapshot.db
还原 ETCD
1. 停止 Kubernetes API Server:
在还原 ETCD 之前,需要停止 Kubernetes API Server,以确保集群状态不会被修改。
systemctl stop kubelet
docker stop $(docker ps -q --filter name=k8s_kube-apiserver)
2. 还原 ETCD 数据:
使用 etcdctl 还原 ETCD 数据。
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/var/lib/etcd-restore
3. 更新 ETCD 配置:
将还原后的数据目录配置到 ETCD 的启动参数中。
--data-dir=/var/lib/etcd-restore
4. 启动 Kubernetes API Server:
启动 Kubernetes API Server 和 kubelet。
systemctl start kubelet
docker start $(docker ps -a -q --filter name=k8s_kube-apiserver)
方法 3:备份持久化存储数据
如果你的应用依赖 PersistentVolume(PV)和 PersistentVolumeClaim(PVC),还需要备份持久化存储中的数据。
备份持久化存储数据
1. 找到 PVC 对应的 PV:
使用以下命令找到 PVC 对应的 PV。
kubectl get pvc -n <namespace>
kubectl get pv <pv-name>
2. 备份数据:
使用工具(如 rsync 或 tar )备份 PV 中的数据。
rsync -av /mnt/data /backup/data
还原持久化存储数据
1. 创建新的 PV 和 PVC:
在目标集群中创建新的 PV 和 PVC。
kubectl apply -f new-pv.yaml
kubectl apply -f new-pvc.yaml
2. 恢复数据:
将备份的数据恢复到新的 PV 中。
rsync -av /backup/data /mnt/data
方法 4:使用工具自动化备份
为了简化备份和还原过程,可以使用一些开源工具,如:
Velero:一个 Kubernetes 备份和还原工具,支持备份资源和持久化存储数据。
Stash:一个 Kubernetes 的备份工具,专注于备份应用数据。
使用 Velero 备份和还原
1. 安装 Velero:
下载并安装 Velero CLI。
wget https://github.com/vmwaretanzu/velero/releases/download/v1.10.0/velero-v1.10.0-linux-amd64.tar.gz
tar -xvf velero-v1.10.0-linux-amd64.tar.gz
sudo mv velero-v1.10.0-linux-amd64/velero /usr/local/bin/
2. 配置 Velero
配置 Velero 与云存储(如 AWS S3、GCP Storage)集成。
velero install --provider aws --bucket my-bucket --secret-file
./credentials-velero
3. 备份资源:
使用 Velero 备份 Kubernetes 资源。
velero backup create my-backup --include-namespaces my-namespace
4. 还原资源:
使用 Velero 还原 Kubernetes 资源。
velero restore create --from-backup my-backup
ETCD 备份和还原
ETCD 特性和原理
ETCD 介绍

Etcd由 CoreOS 团队在2013年6月创建的一个开源的、高可用的分布式 key-value 数据存储系统
Etcd 在 2018年底作为孵化项目加入CNCF,并于2020年11月成功毕业
Etcd 的名字来源于 Unix 系统中的 /etc 目录,etcd 可以理解为 "etc distributed",即“分布式的
/etc”。
它扩展了传统 /etc 目录的功能,使其能够在分布式环境中存储和管理配置信息。体现了它作为分布式配
置存储的核心功能。
Etcd 的设计理念是将传统的单机配置管理扩展到分布式环境中,为现代分布式系统提供高可用、一致性
的配置管理解决方案。
Etcd 可以用于配置共享和服务的注册发现以及一致性保障(如数据库选主、分布式锁等)。类似项目有
zookeeper和consul。
Etcd 基于Raft协议开发,使用Go语言实现
官方网站
https://etcd.io/
官方文档
https://etcd.io/docs/v3.5/
ETCD 特性和应用场景
ETCD 特性
1. 简单接口:
curl 可访问的基于gRPC的用户的API(HTTP + JSON)
2. 简单的键值对数据模型:
以键值对(key-value)的形式来存储数据,
将数据存储在分层组织的目录中,就像在标准文件系统中一样
这种模型非常简洁直观,方便用户使用。无论是配置信息、服务发现中的相关记录,还是分布式锁
等各种应用场景下的数据,都可以方便地以键值对的形式存入和取出。例如,在 Kubernetes 中,
存储着众多关于集群资源(如 Pod、Service 等)的配置信息,以键值对的形式被 etcd 管理着。
3. 支持监听机制:
客户端可以通过 Watch 机制来监听某个键或者键范围的变化情况。一旦相关键对应的数据发生改
变(比如值被更新、键被删除等),客户端能及时收到通知,进而可以根据这些变化来触发相应的
业务逻辑调整,这在实现配置自动更新、服务状态实时感知等场景中非常有用。
4. 安全可靠:
支持 TLS(Transport Layer Security)加密通信,确保在网络传输过程中数据的保密性和完整性,
防止数据被窃取或篡改。同时,还可以设置访问认证机制,通过用户名、密码或者基于证书等方式
来限制对数据的访问权限,保障数据存储的安全性。
用于密钥过期的可选 TTL
5. 快速:
单实例每秒1000次写操作
6. 采用 Raft 实现数据分布:
采用 Raft 一致性算法来保证在分布式环境下多个节点之间数据的强一致性。即使面对部分节点出
现故障、网络分区等复杂情况,各个正常节点上存储的数据始终能保持一致,这使得基于 etcd 存
储的数据在分布式集群的各个节点中都是可靠且同步的。
应用场景
1. 键值对存储
ETCD是一个用于键值对存储的数据库
2. 服务发现:
在分布式系统中,众多服务实例会动态地启动、停止或者迁移,使用 etcd 可以帮助服务客户端快
速准确地找到服务提供者的地址等相关信息。服务实例在启动时可以将自己的相关信息(如 IP 地
址、端口、服务状态等)以键值对的形式注册到 etcd 中,而客户端通过查询 etcd 中对应的键值信
息就能获取到服务的位置,实现服务的发现与调用,像微服务架构中的服务注册与发现场景经常会
用到 etcd 来做这件事。
3. 配置管理:
分布式系统往往有着复杂的配置,并且这些配置可能需要动态地调整和同步到各个相关节点。将配
置文件内容以键值对拆分后存储在 etcd 中,各个节点上的应用程序可以从 etcd 获取配置信息并按
照其来运行。而且当配置发生变化时,借助 Watch 机制,节点能及时得知变化并更新自身配置,
实现配置的集中管理和动态更新,许多大规模分布式应用都会采用这种方式来管理配置。
4. 集群状态存储:
对于像 Kubernetes 这样的大规模集群,需要一个地方来存储整个集群的各种状态信息,例如节点
状态、Pod 状态、资源分配情况等。etcd 就充当了这个角色,它将这些关键的集群状态数据以键
值对的形式安全可靠地存储起来,供集群内各个组件查询、更新以及依赖这些数据来协同工作,是
保障集群正常运转的重要基础设施之一。
5. 消息发布订阅
ETCD可以保存生产者注册主题并发布该主题的消息,支持订阅者订阅主题,如何消息变化,则主动通知
给该主题的订阅者
6. 分布式锁:
多个进程或者线程在分布式环境下可能需要争抢某些共享资源,这时可以利用 etcd 实现分布式锁
机制。通过在 etcd 中创建特定的键值对来表示锁资源,不同的进程尝试去创建这个键值对,只有
成功创建的那个进程相当于获取到了锁,可以操作对应的共享资源,操作完成后再删除该键值对来
释放锁,从而保证在分布式场景下对共享资源访问的互斥性。
与其他类似工具的比较
与传统的关系数据库相比,etcd 更专注于分布式环境下简单、高效的数据存储和一致性保障,它不像关
系数据库那样有着复杂的表结构、SQL 查询等功能,而是以轻量级的键值对形式服务于分布式系统的关
键需求,更适合用于存储配置、状态等相对简洁的数据,并且在分布式一致性方面有专门的优化和优势。
与同样用于分布式存储的 Zookeeper 相比,虽然两者都能用于服务发现、分布式锁等场景,但 etcd 在
使用的简易性、与容器生态(特别是 Kubernetes)的融合度以及性能等方面表现出色。例如,etcd 的
API 相对更简洁易懂,而且由于其在 Kubernetes 中的广泛应用,已经成为容器编排领域存储关键数据
的主流选择之一,而 Zookeeper 更多地在传统分布式系统场景中有着深厚的应用基础。
ETCD 版本
etcd 目前有 V2.X 和 V3.X两个大版本
接口不一样、存储不一样,两个版本的数据互相隔离
ETCD 架构
ETCD 相关术语
术语 描述 备注
Raft
Raft 算
法,etcd
实现一致
性的核心
etcd 有 etcd-raft 模块
Node
Raft 算法
会涉及多
个 Node
节点实例
Raft 中涉及多个节点,这些节点共同参与 Raft 算法的运行,确保数
据的一致性和可靠性。
Cluster etcd 集群 拥有多个 etcd Member
Member
etcd 实
例,管理
着对应的
Node 节
点
可处理客户端请求
Peer
同一个集
群中的另
一个
Member
其他成员
Leader
Raft 中的
领导协调
节点,用
于处理数
据提交
Leader 节点协调整个集群
Follower Raft 中的
从属节点 竞争 Leader 失败
Candidate 候选节点 当 Follower 接收 Leader 节点的消息超时会转变为 Candidate
Client 客户端 向 etcd 发起请求的客户端,比如:api-server
Term 任期 某个节点成为 Leader,到下一次竞选的时间
Lease 租期 设置关键数据key的租期,过期删除
Watch 监测机制
在 etcd 中, watch 机制允许客户端订阅一个或多个键(key)或键
范围(key range)的变化。 当这些被监控的键发生了任何修改操
作(例如创建、更新、删除)时,etcd 会将这些事件推送给订阅了
相应 watch 的客户端。
ETCD 的核心组件
ETCD 分为下面部分

层级 相关内容
客户
端层
包括 client v2 和 v3 两个大版本 API 客户端库,提供了简洁易用的 API,同时支持负载均
衡、节点间故障自动转移,可极大降低业务使用 etcd 复杂度,提升开发效率、服务可用
性。如 clientv3 库和 etcdctl 等工具
API
接口
层
提供客户端访问服务端的通信协议和接口定义,以及服务端节点之间相互通信的协议
客户端访问协议:client 访问 etcd server 的 API 分为 v2 和 v3 两个大版本。
v2 API 使用 HTTP/1.x 协议,v3 API 使用 gRPC 协议,同时 v3 通过 etcd grpc-gateway
组件也支持 HTTP/1.x 协议,便于各种语言的服务调用。
节点间通信协议:server 之间通信协议,是指节点间通过 Raft 算法实现数据复制和
Leader 选举等功能时使用的 HTTP 协议。
业务
逻辑
层
etcd 核心特性实现层,如典型的 KVServer 模块、MVCC 模块、Auth 鉴权模块、Lease
租约模块、Compactor 压缩模块等
etcd
Raft
层
Raft 算法层实现了 Leader 选举、日志复制、ReadIndex 等核心算法特性,用于保障
etcd 多个节点间的数据一致性、提升服务可用性等,是 etcd 的基石和亮点。
etcd
存储
用于处理 etcd 支持的各类功能的事务,包括数据索引、节点状态变更、监控与反馈、事
件处理与执行等等,是 etcd 对用户提供的大多数 API 功能的具体实现
实现了快照、预写式日志 WAL(Write Ahead Log)
Client: etcdctl 或者其它客户端
gRPC Server:etcd与其他etcd节点之间的通信和信息的同步。
ETCD Server:对外接受和处理客户端的请求
Snapshot:快照,以防WAL日志过多用于存储某一时刻etcd的所有数据。
WAL:Write Ahead Log(预写式日志),是 etcd 的数据存储方式。除了在内存中存有所有数据的状态
以及节点的索引以外,etcd 就通过 WAL 进行持久化存储。WAL 中,所有的数据提交前都会事先记录日
志。Snapshot 是为了防止数据过多而进行的状态快照;Entry 表示存储的具体日志内容。
Raft:负责Leader的选举和数据一致性算法
MVCC:多版本控制,etcd的键值对的每一次操作行为都会被记录存储。这些数据底层存储在BoltDB数
据库中。
在 etcd 中, applier v3 是 etcd v3 版本中用于处理和应用事务操作的一个关键组件,在整个 etcd 系
统的状态机实现里扮演重要角色。
核心功能
事务应用:负责接收并执行来自 etcd 集群中各个节点的事务请求。这些事务请求可以包含一系列的操作,如创建、更新或删除键值对等。 applier v3 会按照请求的顺序依次应用这些操作,确保
etcd 的键值存储状态能够准确反映这些事务的结果。
状态更新:在应用事务的过程中, applier v3 会相应地更新 etcd 的状态。这包括更新内存中的键值存储数据结构,以及可能涉及到的持久化存储(如 WAL 日志)的更新,以保证即使在节点故
障后,数据也能恢复到正确的状态。
工作原理
请求接收: applier v3 从 etcd 的网络层接收客户端或其他节点发来的事务请求。这些请求首先会经过一定的验证和预处理,确保请求格式正确且符合 etcd 的协议规范。
操作执行:对于每个事务请求, applier v3 会解析其中包含的具体操作。例如,如果是一个写操作,它会在 etcd 的键值存储中更新相应的键值对;如果是读操作,它会从键值存储中检索并返回
所需的数据。在执行操作的过程中, applier v3 会遵循 etcd 的一致性协议(如 Raft)来保证数据的一致性和正确性。
事件发布:在操作执行完成后, applier v3 可能会发布一些事件,通知其他组件(如 Watcher机制)有相关的状态变化。这使得客户端能够及时了解到 etcd 中键值对的变更情况。
与其他组件的协作
Raft 模块: applier v3 与 etcd 的 Raft 模块紧密协作。Raft 模块负责在集群节点间达成一致
性,确定事务请求的执行顺序。 applier v3 则在 Raft 确定了顺序后,实际应用这些事务。例
如,当一个新的 Raft 日志条目被提交时, applier v3 会根据日志条目中记录的事务操作来更新
etcd 的状态。
存储模块: applier v3 依赖 etcd 的存储模块来持久化数据。在应用事务操作后,它会与存储模
块交互,将状态变化写入 WAL 日志和快照文件。同时,在 etcd 启动或恢复过程中, applier v3
会从存储模块加载数据,重建键值存储的状态。
ETCD工作原理
如何选举 Leader节点
ETCD节点状态有三种
Leader 领导人:
领导者状态,选举出来的节点,所有数据提交都必须先提交到 Leader上
Leader 处理所有的客户端请求,在通常情况下,系统中只有一个Leader 并且其他节点都是
Follower。
基于Heartbeat Interval (默认100ms)定期发送心跳信息
Follower 跟随者:
跟随者状态,该状态意味着选举结束
Follower 不会发送任何请求,只是简单地响应来自 Leader和Candidate 的请求
如果一个客户端与 Follower 联系,那么 Follower 会把请求重定向至 Leader。
Candidate 候选人:
候选人状态,该状态意味着将进行一次新的选举,
如果 Follower 在一段时间Election Timeout (默认1s)内接收不到来自 Leader 的消息,那么它就会
变成 Candidate 并发起一次选举
获得集群中大多数选票(超过 n/2+1)的候选人将成为新的Leader。
选举流程
针对 Etcd ,Raft 通过领导选举机制选举出一个 Leader,由它全权管理日志复制来实现一致性。
一个 Raft 集群包含若干个服务器节点,每一个节点都有一个唯一标识 ID
只有在 Candidate 或者 Follower 状态下的节点才有可能发起一个选举流程
假设集群中有三个节点,集群节点启动之初节点中并没有被选举出的Leader。
- 所有节点都以 Follower 角色启动,并随机生成自已的选举超时时间计时器 Timer,使用随机时间是为了防止同时参与选举导致无法过半数
- Raft算法使用随机Timer来初始化Leader选举流程。比如说在上面三个节点上都运行了计时器Timer(每个Timer的持续时间是随机的)
- 率先完成了Timer的第一个节点,它就会向其他两个节点发送成为Leader的请求,其他节点接收到请求后会以投票回应
- 如果在一个选举超时期间内,发起新的选举流程的节点得到了超过半数的节点投票,那么状态就切换到Leader状态,即第一个节点被选举为Leader。

- 成为Leader后,该节点会以固定时间间隔向其他节点发送通知,确保自己仍是Leader。
- 有些情况下当Follower们收不到Leader的通知后,比如说Leader节点宕机或者失去了连接,其他节点会重复之前选举过程选举出新的Leader。
Etcd 如何保证数据一致性

所有的分布式系统,都面临的一个问题是多个节点之间的数据共享问题,每个成员可以分别工作,但总
是需要共享一些必须的信息,比如谁是 leader, 都有哪些成员,依赖任务之间的顺序协调等。所以分布
式系统依赖一个可靠的共享存储服务,而 Etcd 就是这样一个服务。
根据 CAP 理论,etcd 在满足网络分区容忍性的基础上,优先满足了一致性C,即使用CP模式
Etcd Cluster 是一个分布式系统,由多个 Nodes 相互通信构成整体对外服务,每个 Node 都存储了完整
的数据,并且通过 Raft 协议保证每个 Node 维护的数据是一致的。
Etcd Cluster 中的每个 Node 都维护了一个状态机,并且任意时刻,Cluster 中只存在唯一的有效的主节
点Leader Node。
由 Leader 处理所有来自客户端写操作,通过 Raft 协议保证写操作对状态机的改动会可靠的同步到其他
Follower Nodes。
ETCD 基于事务写入数据
事务隔离级别
未提交读(Read Uncommitted)
能够读取到其他事务中还未提交的数据,这可能会导致脏读的问题
ETCD 默认不支持此级别
读已提交(Read Committed)
只能读取到已经提交的数据
即别的事务一提交,当前事务就能读取到被修改的数据
这可能导致不可重复读的问题
可重复读(Repeated Read)
一个事务中,同一个读操作在事务的任意时刻都能得到同样的结果
其他事务的提交操作对本事务不会产生影响
会产生幻读,即读取过程中,即使有其它提交的事务后续修改数据,仍只能读取到未修改前的旧数
据。
串行化(SerializableSnapshot)
串行化执行事务,即一个事务的执行会阻塞其他事务
该隔离级别通过牺牲并发能力换取数据的安全,属于最高的隔离级别
也是ETCD默认的隔离级别
用户从集群中哪个节点读写数据

为了保证数据的强一致性,etcd集群中所有的数据流向都是一个方向,从 Leader (主节点)流向
Follower,也就是所有 Follower 的数据必须与 Leader 保持一致,如果不一致会被覆盖。
用户可以对etcd集群中的所有节点进行读写,读取非常简单因为每个节点保存的数据是强一致的。
对于写入来说,etcd集群中的节点会选举出Leader节点,如果写入请求来自Leader节点即可直接写入然
后Leader节点会把写入分发给所有Follower
如果客户端提交写入请求到其他Follower节点,那么会将写入请求会给转发给Leader节点,最终由
Leader节点写入之后再分发给集群上的所有其他节点。
下面的图示中1、3节点都有写入请求,节点1为Leader所以3的写入请求会转发给1,写入完成后再同步
给所有节点。

客户端发起写请求及集群节点处理流程

- 1. 客户端发起请求,请求内容为 put foo=bar 。
- 2. 通过API接收请求,发现是写请求,转发请求给Leader,节点 A(作为 Leader)将请求内容 put foo=bar 追加到本地日志(append local log)。
- 3. 节点 A 向其他节点(节点 B 和节点 C)广播 AppendEntries 消息,消息内容为 put foo=bar 。
- 4. 节点 B 和节点 C(均为 Follower)收到 AppendEntries 消息后,将 put foo=bar 追加到本地日志(Append local log)。
- 5. 节点 A 收到节点 B 和节点 C 的 AppendEntries Response (即节点 B 和节点 C 告知节点 A 已成功追加日志)。
- 6. 节点 A 提交日志(commit log)
通过以上流程,确保了客户端的请求在 etcd 集群的多个节点间进行了同步和处理,实现了数据的一致性
和可靠性。其中,Leader 节点负责协调和广播操作,Follower 节点接收并记录操作,最终共同完成数
据的存储和处理。
判断写入是否成功
etcd认为写入请求被Leader节点处理并分发给了多数节点后,就是一个成功的写入。
如何界定多数节点呢?很简单,假设总结点数是N,那么界定多数节点的公式是 Quorum=N/2+1
关于节点数的最佳实践
关于如何确定etcd集群应该有多少个节点的问题,上图的左侧的图表给出了集群中节点总数(Instances)
对应的Quorum数量,用Instances减去Quorom就是集群中容错节点(允许出故障的节点)的数量。
所以在集群中推荐的最少节点数量是3个,因为1和2个节点的容错节点数都是0,一旦有一个节点宕掉整
个集群就不能正常工作了。当决定集群中节点的数量时,强烈推荐奇数数量的节点
比如,6个节点的集群它的容错能力并没有比5个节点的好,他们的容错节点数一样,一旦容错节点超过
2后,由于Quorum节点数小于4整个集群也变为不可用的状态了。
所以在决定集群中的节点数时,奇数要优于偶数。
ETCD 访问
可以通过两种方式访问ETCD
通过 HTTP API 接口直接访问 etcd
通过 etcdctl 客户端命令行操作和访问 etcd 中的数据
etcd 相关工具
etcdctl 和 etcdutl 工具安装
范例: 包安装 etcdctl 工具:包安装的版本可能不被新的k8集群支持(不建议)
kubectl exec -n kube-system etcd-master1.org -- /usr/local/bin/etcd --version
[root@master1 ~]# kubectl exec -n kube-system etcd-master1.org -- /usr/local/bin/etcd --version etcd Version: 3.6.6 Git SHA: d2809cf Go Version: go1.24.10 Go OS/Arch: linux/amd64
kubectl exec -n kube-system etcd-master1.org -- /usr/local/bin/etcdctl version
[root@master1 ~]# kubectl exec -n kube-system etcd-master1.org -- /usr/local/bin/etcdctl version etcdctl version: 3.6.6 API version: 3.6
ls /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/46/fs/usr/local/bin/etcdctl
[root@master1 ~]# ls /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/46/fs/usr/local/bin/etcdctl /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/46/fs/usr/local/bin/etcdctl
范例: 二进制安装
https://github.com/etcd-io/etcd/releases
#指定下载K8s的ETCD版本一致的etcdctl工具版本
ETCD_VER=v3.6.12
#代理下载
curl -L https://mirror.ghproxy.com/${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linuxamd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linuxamd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
#注意:k8s-1.34以后版本etcdutl替换etcdctl工具实现还原
cd etcd-v3.6.12-linux-amd64
mv etcdutl /usr/local/bin/
etcdctl 和 etcdutl 工具说明
https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/
etcdctl 是一个命令行工具,用于与 etcd 分布式键值存储系统进行交互。 etcd 是一个高可用的分布
式键值存储系统,通常用于配置共享和服务发现。 etcdctl 提供了多种命令,允许用户读取、写入、删
除键值对,以及执行其他管理操作。
注意:k8s-1.34以后版本的etcdutl 工具替代etcdctl实现还原功能
相关环境变量
在使用 etcdctl 时,可以通过设置环境变量来指定 etcd 集群的地址和认证信息:
- ETCD_API: 新版变量 指定ETCD的版本,支持2和3两个版本
- ETCDCTL_API : 指定ETCD的版本,支持2和3两个版本
- ETCDCTL_ENDPOINTS : 指定 etcd 集群的地址,多个地址用逗号分隔。
- ETCDCTL_CACERT : 指定 CA 证书文件路径。
- ETCDCTL_CERT : 指定客户端证书文件路径。
- ETCDCTL_KEY : 指定客户端私钥文件路径。
假设 etcd 集群的地址为 http://127.0.0.1:2379 ,可以通过以下命令设置环境变量:
export ETCDCTL_ENDPOINTS=http://127.0.0.1:2379
然后可以使用 etcdctl 命令与 etcd 集群进行交互。
etcdctl 使用案例
#查看健康性
#k8s-v1.34以后版本
etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key -w table endpoint health
root@master1 ~]# etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key -w table endpoint health +------------------------+--------+-------------+-------+ | ENDPOINT | HEALTH | TOOK | ERROR | +------------------------+--------+-------------+-------+ | https://127.0.0.1:2379 | true | 14.737649ms | | +------------------------+--------+-------------+-------+
#查看节点状态和leader角色
#k8s-v1.34以后版本
etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key -w table endpoint status
[root@master1 ~]# etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key -w table endpoint status +------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+ | ENDPOINT | ID | VERSION | STORAGE VERSION | DB SIZE | IN USE | PERCENTAGE NOT IN USE | QUOTA | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | DOWNGRADE TARGET VERSION | DOWNGRADE ENABLED | +------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+ | https://127.0.0.1:2379 | 30035185a83c6bab | 3.6.6 | 3.6.0 | 33 MB | 7.6 MB | 78% | 2.1 GB | true | false | 41 | 507170 | 507170 | | | false | +------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+ [root@master1 ~]#
[root@master1 ~]# etcdctl --endpoints=https://192.168.3.62:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key -w table endpoint status +---------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+ | ENDPOINT | ID | VERSION | STORAGE VERSION | DB SIZE | IN USE | PERCENTAGE NOT IN USE | QUOTA | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | DOWNGRADE TARGET VERSION | DOWNGRADE ENABLED | +---------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+ | https://192.168.3.62:2379 | 28172196807c670e | 3.6.6 | 3.6.0 | 33 MB | 7.8 MB | 77% | 2.1 GB | false | false | 41 | 507411 | 507411 | | | false | +---------------------------+------------------+---------+-----------------+---------+--------+-----------------------+--------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
#百看成员
#k8s-v1.34以后版本
#一个master节点
etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --write-out=table member list
[root@master1 ~]# etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --write-out=table member list +------------------+---------+-------------+---------------------------+---------------------------+------------+ | ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER | +------------------+---------+-------------+---------------------------+---------------------------+------------+ | 28172196807c670e | started | master3.org | https://192.168.3.62:2380 | https://192.168.3.62:2379 | false | | 30035185a83c6bab | started | master1.org | https://192.168.3.60:2380 | https://192.168.3.60:2379 | false | | b034099815698f01 | started | master2.org | https://192.168.3.61:2380 | https://192.168.3.61:2379 | false | +------------------+---------+-------------+---------------------------+---------------------------+------------+
使用 etcdctl 和 etcdutl 工具实现 ETCD 备份和还原
https://etcd.io/docs/v3.4/op-guide/recovery/
https://etcd.io/docs/v3.5/op-guide/recovery/
https://kubernetes.io/docs/tasks/administer-cluster/configure-upgradeetcd/#replacing-a-failed-etcd-member
https://kubernetes.io/docs/tasks/administer-cluster/configure-upgradeetcd/#backing-up-an-etcd-cluster
ETCD 集群本身就具有高可用性,只有当ETCD集群节点出现超过半数以上的节点宕机才需要进行ETCD的
还原
ETCD 数据备份和还原可以通过如下方式实现
- etcdctl 和 etcdutl
- velero
备份和还原流程说明
准备ETCD相关工具和环境
案例: 利用 etcdctl和etcdutl 命令实现备份还原数据
例: 基于Kubeadm安装查看ETCD数据存放目录
cat /etc/kubernetes/manifests/etcd.yaml
[root@master1 ~]# cat /etc/kubernetes/manifests/etcd.yaml apiVersion: v1 kind: Pod metadata: annotations: kubeadm.kubernetes.io/etcd.advertise-client-urls: https://192.168.3.60:2379 labels: component: etcd tier: control-plane name: etcd namespace: kube-system spec: containers: - command: - etcd - --advertise-client-urls=https://192.168.3.60:2379 - --cert-file=/etc/kubernetes/pki/etcd/server.crt - --client-cert-auth=true - --data-dir=/var/lib/etcd #Pod内数据存放位置 - --feature-gates=InitialCorruptCheck=true - --initial-advertise-peer-urls=https://192.168.3.60:2380 - --initial-cluster=master1.org=https://192.168.3.60:2380 - --key-file=/etc/kubernetes/pki/etcd/server.key - --listen-client-urls=https://127.0.0.1:2379,https://192.168.3.60:2379 - --listen-metrics-urls=http://127.0.0.1:2381 - --listen-peer-urls=https://192.168.3.60:2380 - --name=master1.org - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt - --peer-client-cert-auth=true - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - --snapshot-count=10000 - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - --watch-progress-notify-interval=5s image: registry.aliyuncs.com/google_containers/etcd:3.6.6-0 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 8 httpGet: host: 127.0.0.1 path: /livez port: probe-port scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 15 name: etcd ports: - containerPort: 2381 name: probe-port protocol: TCP readinessProbe: failureThreshold: 3 httpGet: host: 127.0.0.1 path: /readyz port: probe-port scheme: HTTP periodSeconds: 1 timeoutSeconds: 15 resources: requests: cpu: 100m memory: 100Mi startupProbe: failureThreshold: 24 httpGet: host: 127.0.0.1 path: /readyz port: probe-port scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 15 volumeMounts: - mountPath: /var/lib/etcd #Pod内数据存放位置 name: etcd-data - mountPath: /etc/kubernetes/pki/etcd name: etcd-certs hostNetwork: true priority: 2000001000 priorityClassName: system-node-critical securityContext: seccompProfile: type: RuntimeDefault volumes: - hostPath: path: /etc/kubernetes/pki/etcd type: DirectoryOrCreate name: etcd-certs - hostPath: path: /var/lib/etcd #Master节点的数据目录 type: DirectoryOrCreate name: etcd-data status: {}
范例: 基于kubeadm安装kubernetes 备份还原
#在所有Master节点安装etcdctl或从etcd的Pod获取此工具,包安装的etcdctl版本和ETCD的版本不一
致,建议从官方网络下载对应的版本使用
#备份:在任意一个master节点备份ETCD数据都可以
etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot save etcd-backup-`date +%F_%H-%M-%S`.db
#校验,使用etcdutl代替etcdctl
etcdutl --write-out=table snapshot status etcd-backup-2026-07-19_15-31-03.db
[root@master1 ~]# etcdutl --write-out=table snapshot status etcd-backup-2026-07-19_15-31-03.db +----------+----------+------------+------------+---------+ | HASH | REVISION | TOTAL KEYS | TOTAL SIZE | VERSION | +----------+----------+------------+------------+---------+ | 37efe034 | 468758 | 2184 | 33 MB | 3.6.0 | +----------+----------+------------+------------+---------+
ll -h etcd-backup-2026-07-19_15-31-03.db
#生成新Pod
kubectl create deployment myapp --image registry.cn-beijing.aliyuncs.com/wangxiaochun/pod-test:v0.1 --replicas 3
root@master1 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-7b478c76d7-6lr6c 1/1 Running 0 13s 10.244.1.90 node1.org <none> <none> myapp-7b478c76d7-jvpqd 1/1 Running 0 13s 10.244.8.5 node3.org <none> <none> myapp-7b478c76d7-plnjd 1/1 Running 0 13s 10.244.3.14 node2.org <none> <none>
etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot save etcd-backup-`date +%F_%H-%M-%S`.db
#模拟破坏
kubectl delete deployments.apps myapp
kubectl get pod -o wide
#还原前停止所有etcd节点和master节点的相关服务
#方法1: 在所有master节点执行
systemctl stop kubelet
docker stop $(docker ps -q --filter name=k8s_etcd_etcd)
docker stop $(docker ps -q --filter name=k8s_kube-apiserver)
#还原前需要删除所有Master节点的数据
mv /var/lib/etcd/member /srv/
#将备份复制到所有Master节点
scp etcd-backup-2026-07-19_16-17-40.db 192.168.3.61:/root/
scp etcd-backup-2026-07-19_16-17-40.db 192.168.3.62:/root/
#还原,在每个Master节点分别还原,新版本使用etcdutl代替etcdctl
#还原前需要删除所有Master节点的数据
rm -rf /var/lib/etcd/member
etcdutl snapshot restore etcd-backup-2026-07-19_16-17-40.db \
--name master1 \
--data-dir=/var/lib/etcd \
--initial-cluster master1=https://192.168.3.60:2380,master2=https://192.168.3.61:2380,master3=https://192.168.3.62:2380 \
--initial-cluster-token etcd-cluster-restore-2026-07-19 \
--initial-advertise-peer-urls https://192.168.3.60:2380
#说明 #--name master1 指定每个节点的唯一名称 #--initial-cluster master1=https://10.0.0.201:2380,master2=https://10.0.0.202:2380,master3=https:// 10.0.0.203:2380 所有节点地址 #--initial-advertise-peer-urls https://10.0.0.201:2380 每个节点自已的地址
scp /usr/local/bin/etcd* 192.168.3.61:/usr/local/bin/
scp /usr/local/bin/etcd* 192.168.3.62:/usr/local/bin/
rm -rf /var/lib/etcd/member
etcdutl snapshot restore etcd-backup-2026-07-19_16-17-40.db \
--name master2 \
--data-dir=/var/lib/etcd \
--initial-cluster master1=https://192.168.3.60:2380,master2=https://192.168.3.61:2380,master3=https://192.168.3.62:2380 \
--initial-cluster-token etcd-cluster-restore-2026-07-19 \
--initial-advertise-peer-urls https://192.168.3.61:2380
rm -rf /var/lib/etcd/member
etcdutl snapshot restore etcd-backup-2026-07-19_16-17-40.db \
--name master3 \
--data-dir=/var/lib/etcd \
--initial-cluster master1=https://192.168.3.60:2380,master2=https://192.168.3.61:2380,master3=https://192.168.3.62:2380 \
--initial-cluster-token etcd-cluster-restore-2026-07-19 \
--initial-advertise-peer-urls https://192.168.3.62:2380
#所有节点上启动服务
#方法1
systemctl start kubelet
#验证etcd集群
etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --write-out=table member list
[root@master1 ~]# etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --write-out=table member list +------------------+---------+-------------+---------------------------+---------------------------+------------+ | ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER | +------------------+---------+-------------+---------------------------+---------------------------+------------+ | 202107f5e35ecf2b | started | master1.org | https://192.168.3.60:2380 | https://192.168.3.60:2379 | false | | 840238f8668b2f2d | started | master2.org | https://192.168.3.61:2380 | https://192.168.3.61:2379 | false | | d5d7a6267b2aafbd | started | master3.org | https://192.168.3.62:2380 | https://192.168.3.62:2379 | false | +------------------+---------+-------------+---------------------------+---------------------------+------------+ [root@master1 ~]#
#检查Pod还原
kubectl get pod -o wide
[root@master1 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-7b478c76d7-6lr6c 1/1 Running 0 31m 10.244.1.90 node1.org <none> <none> myapp-7b478c76d7-jvpqd 1/1 Running 0 31m 10.244.8.5 node3.org <none> <none> myapp-7b478c76d7-plnjd 1/1 Running 0 31m 10.244.3.14 node2.org <none> <none>
kubectl scale deploy myapp --replicas 5
浙公网安备 33010602011771号