Kubernetes高可用架构设计:多Master节点部署与etcd集群运维深度指南
目录
引言:高可用——Kubernetes生产环境的基石
一、 Kubernetes高可用架构设计原理
1.1 为什么需要高可用架构?
1.2 高可用架构的核心目标
1.3 高可用架构的两种主流模式
模式一:堆叠(Stacked)etcd拓扑
模式二:外部(External)etcd拓扑
二、 多Master节点部署:控制平面的冗余与协作
2.1 多Master架构的核心组件与角色
2.2 核心组件的高可用实现机制
2.2.1 kube-apiserver:负载均衡是关键
2.2.2 kube-controller-manager & kube-scheduler:Leader Election保障唯一性
2.2.3 etcd:外部集群保障数据基石(详见第三部分)
2.3 多Master部署的关键配置与注意事项
2.3.1 网络规划
2.3.2 部署工具选择
2.3.3 证书管理
2.3.4 kubelet配置(Master节点)
三、 etcd集群运维:高可用的数据基石
3.1 etcd核心原理:Raft一致性协议深度解析
3.1.1 Raft核心概念
3.1.2 Raft在etcd中的关键参数与影响
3.2 etcd集群部署最佳实践(外部拓扑)
3.2.1 节点规划
3.2.2 部署步骤(以kubeadm外部etcd为例)
3.3 etcd集群日常运维核心操作
3.3.1 备份与恢复:灾难恢复的生命线
3.3.2 节点管理:扩容与缩容
3.3.3 升级与维护
3.3.4 性能监控与调优
3.3.5 安全加固
四、 实战实验:搭建高可用Kubernetes集群(外部etcd)
4.1 实验环境规划
4.2 实验步骤(30%)
步骤1:基础环境准备(所有节点)
步骤2:部署etcd集群(etcd1, etcd2, etcd3)
步骤3:部署负载均衡器(Keepalived + HAProxy)
步骤4:部署Kubernetes Master节点
步骤5:加入Worker节点(可选)
步骤6:高可用性测试
五、 总结与展望:迈向Kubernetes架构师之路
核心要点回顾
架构师成长之路
专栏: Kubernetes架构师之路:系统化学习与实践
作者: 庸子
用户ID: 2401_86478612
首发平台: CSDN
引言:高可用——Kubernetes生产环境的基石
在容器化与云原生技术席卷全球的今天,Kubernetes(K8s)已成为企业构建现代化应用基础设施的事实标准。然而,单Master节点的Kubernetes集群如同“单点故障”的定时炸弹,一旦Master节点宕机,整个集群将陷入瘫痪,导致服务中断、业务受损。高可用(High Availability, HA)架构正是解决这一痛点的核心方案,它通过冗余设计、故障转移和负载均衡,确保集群在部分组件失效时仍能持续提供服务。
本文将深入剖析Kubernetes高可用架构的核心原理,重点讲解多Master节点部署的架构设计与实现细节,并聚焦于集群状态存储大脑——etcd集群的运维实践。我们将遵循70%理论深度与30%实战验证的原则,为您构建从理论到实践的完整知识体系,助您迈向Kubernetes架构师之路。
一、 Kubernetes高可用架构设计原理
1.1 为什么需要高可用架构?
- 单点故障风险: 单Master节点承载着API Server、Controller Manager、Scheduler等核心组件,其故障将导致集群控制平面完全失效。
- 业务连续性要求: 现代应用对服务可用性要求极高(如99.95%、99.99%),单Master无法满足SLA。
- 维护窗口压力: 升级、配置变更等操作需要停机,影响业务运行。
- 扩展性瓶颈: 单Master在处理大规模集群(节点数、Pod数激增)时,API Server可能成为性能瓶颈。
1.2 高可用架构的核心目标
- 消除单点故障: 关键组件(Master节点、etcd)冗余部署。
- 故障自动转移: 当主节点或组件故障时,系统能自动切换到备用节点/组件。
- 负载均衡: 将客户端(kubectl、kubelet、调度器)请求均匀分发到多个健康的API Server实例。
- 数据一致性: 确保集群状态(存储在etcd中)在所有节点间保持一致。
- 最小化中断: 故障发生时,服务中断时间(RTO)和数据丢失量(RPO)尽可能小。
1.3 高可用架构的两种主流模式
Kubernetes高可用架构主要围绕控制平面(Control Plane)的冗余设计展开,核心是Master节点和etcd的部署方式。业界主要有两种成熟模式:
模式一:堆叠(Stacked)etcd拓扑
- 架构描述: 每个Master节点上同时运行一个etcd实例。etcd实例与Master控制平面组件(API Server, Controller Manager, Scheduler)部署在同一台物理机或虚拟机上。
- 优点:部署相对简单: 资源需求相对集中,管理节点较少。
- 配置简化: etcd与控制平面组件间通信通常通过本地回环地址(127.0.0.1),网络配置简单。
- 缺点:耦合度高: Master节点故障同时影响etcd和控制平面组件,风险集中。
- 资源竞争: etcd(尤其是I/O密集型)与控制平面组件(CPU/内存密集型)争抢主机资源,可能互相影响性能。
- 扩展性受限: 增加Master节点必须同时增加etcd节点,扩展不够灵活。
- 故障域大: 一台主机故障同时失去一个etcd成员和一个Master节点。
- 适用场景: 中小型集群,资源有限,对部署简易性要求高于极致隔离性。
模式二:外部(External)etcd拓扑
- 架构描述: etcd集群独立部署在专用的服务器(或虚拟机)上,与Master控制平面节点完全分离。Master节点只运行控制平面组件。
- 优点:高隔离性: etcd集群与控制平面组件物理或逻辑隔离,故障域分离。Master节点故障不影响etcd,etcd节点故障不影响Master(只要etcd集群仍可用)。
- 资源优化: 可为etcd集群和Master集群分别配置最合适的硬件资源(如etcd节点使用SSD、优化网络)。
- 独立扩展: 可根据需要独立扩展etcd集群规模(增加节点)或Master节点规模,灵活性高。
- 性能优化: 避免etcd与控制平面组件的资源竞争,有助于提升整体性能和稳定性。
- 运维清晰: etcd集群的运维(备份、恢复、升级、监控)与控制平面运维解耦,职责更清晰。
- 缺点:部署复杂度高: 需要管理两套独立的集群(etcd集群、Master集群),节点数量更多,初始配置更复杂。
- 网络要求高: etcd集群内部通信、Master节点与etcd集群之间的通信对网络延迟和稳定性要求极高。
- 成本更高: 需要更多的服务器资源。
- 适用场景: 生产环境首选! 中大型集群,对高可用性、性能、隔离性、扩展性有严格要求的企业级部署。
架构师视角: 对于追求极致稳定性和可扩展性的生产环境,外部etcd拓扑是强烈推荐的最佳实践。它提供了更清晰的故障边界、更优的资源利用和更灵活的运维能力。本文后续将主要基于外部etcd拓扑进行深入讲解,因其代表了生产级高可用的标准范式。
二、 多Master节点部署:控制平面的冗余与协作
2.1 多Master架构的核心组件与角色
在多Master(外部etcd)架构中,控制平面由多个Master节点组成,每个节点运行相同的核心组件:
- kube-apiserver: 集群的唯一入口,提供RESTful API,负责处理所有资源对象的增删改查(CRUD)操作,是状态变更的发起者和协调者。高可用关键点: 需要负载均衡。
- kube-controller-manager: 运行控制器进程,负责维护集群的期望状态(如Pod副本数、节点状态、服务端点等)。通过Leader Election机制确保同一时间只有一个实例在工作。高可用关键点: Leader Election。
- kube-scheduler: 负责为新创建的Pod选择合适的Node节点进行调度。同样通过Leader Election确保只有一个活跃调度器。高可用关键点: Leader Election。
- kubelet(可选但推荐): 在Master节点上运行kubelet,使其本身也成为集群的一个Node。这有助于监控Master节点自身状态(如通过Node对象),并允许在Master节点上运行系统级Pod(如监控Agent、网络插件DaemonSet)。高可用关键点: 提升Master节点可观测性和管理能力。
- 容器运行时(Container Runtime): 如containerd、CRI-O、Docker Engine(已弃用),负责运行容器。高可用关键点: 稳定可靠的运行时环境。
2.2 核心组件的高可用实现机制
2.2.1 kube-apiserver:负载均衡是关键
- 问题: 客户端(kubectl, kubelet, scheduler, controllers)需要访问API Server。多个API Server实例如何被统一访问?如何确保请求只发往健康的实例?
-
- 解决方案: 负载均衡器(Load Balancer)作用:提供一个虚拟IP(VIP) 或稳定的DNS名称作为集群API Server的统一入口。
- 监控后端多个API Server实例的健康状态(通常通过TCP端口检查或HTTP健康检查端点,如
/healthz
)。 - 将进入的客户端请求智能分发到当前健康的API Server实例上(常用算法:轮询Round Robin、最少连接Least Connections)。
- 在检测到某个API Server实例故障时,自动将其从服务池中移除,停止向其转发流量。
- 实现方式:硬件负载均衡器: F5 BIG-IP, Citrix ADC等。性能强大,功能丰富,成本高。
- 软件负载均衡器:云厂商LB: AWS NLB/ALB, GCP Internal TCP/UDP LB, Azure Load Balancer。与云平台深度集成,管理便捷。
- 开源软件:HAProxy: 高性能、高可靠性的TCP/HTTP负载均衡器,配置灵活,是Kubernetes HA部署的经典选择。
- Nginx: 功能强大的Web服务器和反向代理,也可配置为TCP/UDP负载均衡器。
- Keepalived + HAProxy/Nginx: Keepalived负责实现VIP的高可用(使用VRRP协议),配合HAProxy/Nginx提供实际的后端服务健康检查和负载分发。这是在私有云或裸金属环境中非常流行的纯软件高可用方案。
- 软件负载均衡器:云厂商LB: AWS NLB/ALB, GCP Internal TCP/UDP LB, Azure Load Balancer。与云平台深度集成,管理便捷。
- 配置要点:健康检查: 必须配置准确的健康检查(如检查API Server的
/healthz
端点),确保故障实例被及时剔除。 - 会话保持(Session Affinity): 通常需要禁用! Kubernetes API设计是无状态的,客户端应能连接到任何健康的API Server实例。启用会话保持可能导致请求集中到某个实例,破坏负载均衡效果,并在该实例故障时导致大量会话中断。
- 超时设置: 合理设置连接超时、服务器超时等参数,避免因个别慢请求影响整体性能。
- SSL/TLS终结: 负载均衡器可以配置为SSL终结点(处理HTTPS流量),将解密后的HTTP流量转发给后端API Server(使用HTTP),简化后端证书管理。也可配置为SSL透传(Pass-Through),将加密流量直接转发给后端API Server处理。
-
2.2.2 kube-controller-manager & kube-scheduler:Leader Election保障唯一性
- 问题: Controller Manager和Scheduler的设计原则是同一时间只能有一个活跃实例在工作。如果多个实例同时运行,它们会竞争修改同一资源(如尝试调度同一个Pod到不同节点),导致状态混乱甚至数据损坏。如何在多个实例中选出唯一的Leader?
- 解决方案: Leader Election(领导者选举)原理: 所有Controller Manager/Scheduler实例启动时,都会尝试在etcd中创建一个特定的资源锁(Resource Lock)(通常是
Lease
对象或Endpoint
对象)。第一个成功创建锁的实例成为Leader。其他实例成为Candidate(候选者)。 - 续租(Lease Renewal): Leader实例需要定期(如几秒一次)更新(续租)这个锁,表明自己仍然存活。
- 故障检测与重新选举: Candidate实例会持续监听这个锁的状态。如果发现锁在指定时间内(如15秒)没有被更新(Leader故障或网络分区),它们会认为Leader已失效,并立即尝试重新获取锁。第一个成功获取锁的Candidate成为新的Leader。
- 实现: Kubernetes提供了
k8s.io/client-go/tools/leaderelection
包,组件通过配置--leader-elect=true
(默认启用)即可自动参与选举。选举使用的资源对象、租约时长等参数可配置(如--leader-elect-resource-lock
,--leader-elect-lease-duration
)。 - 高可用效果: 当Leader实例所在的Master节点故障或组件崩溃时,其他Candidate实例会快速(通常在几秒到十几秒内)检测到并选举出新的Leader,恢复控制功能。整个过程对用户透明,集群控制能力得以持续。
- 解决方案: Leader Election(领导者选举)原理: 所有Controller Manager/Scheduler实例启动时,都会尝试在etcd中创建一个特定的资源锁(Resource Lock)(通常是
2.2.3 etcd:外部集群保障数据基石(详见第三部分)
etcd作为集群的唯一可信数据源,其高可用是整个Kubernetes集群高可用的绝对前提。在多Master(外部etcd)架构中,etcd以独立集群形式部署,通常由3或5个(推荐奇数个)节点组成,利用Raft协议保证数据一致性和高可用。
2.3 多Master部署的关键配置与注意事项
2.3.1 网络规划
- Master节点间网络: Master节点之间需要稳定、低延迟的网络通信,用于组件间协作(如Controller Manager/Scheduler的Leader Election心跳、API Server之间的状态同步)。
- Master到etcd集群网络: 至关重要! 所有Master节点上的API Server实例必须能够稳定、低延迟地访问etcd集群的所有节点。这是API Server读写集群状态的关键路径。网络抖动或高延迟会严重影响集群性能和稳定性。建议使用专用网络或高质量的网络连接。
- 负载均衡器网络: 负载均衡器需要能访问所有后端API Server实例的健康检查端口(通常6443)。客户端(用户、kubelet、其他组件)需要能访问负载均衡器的VIP/DNS。
- Node节点到API Server网络: 所有工作节点(Node)上的kubelet、kube-proxy以及Pod内的应用(如果需要直接访问API Server)都需要能够访问负载均衡器提供的VIP/DNS。这是集群正常工作的基础。
2.3.2 部署工具选择
- kubeadm: 官方推荐的集群部署工具,从v1.12版本开始原生支持高可用部署(堆叠和外部etcd模式)。通过
kubeadm init
和kubeadm join
命令配合配置文件(如kubeadm-config.yaml
)可以较方便地搭建多Master集群。优点: 标准化、自动化程度高、社区支持好。缺点: 灵活性相对较低,复杂网络配置可能需要额外脚本。 - kops: 在AWS上生产级部署Kubernetes的利器,内置完善的高可用支持(包括自动配置负载均衡器、etcd集群等)。优点: 云原生、自动化程度极高、声明式管理。缺点: 主要面向AWS,其他云平台或裸金属支持有限。
- kubespray: 基于Ansible的集群部署工具,支持多种平台(公有云、私有云、裸金属),高度可定制,对高可用架构支持非常完善。优点: 灵活性强、平台无关、社区活跃。缺点: 需要一定的Ansible基础,配置相对复杂。
- 手动部署: 通过下载二进制文件、编写systemd服务文件、手动配置证书和组件参数来部署。优点: 理解最深、控制最细。缺点: 极其繁琐、易出错、维护成本高,不推荐用于生产环境。
架构师建议: 对于大多数生产环境,kubeadm(外部etcd模式) 或 kubespray 是平衡易用性、标准化和灵活性的较好选择。kops是AWS用户的理想选择。
2.3.3 证书管理
- 重要性: Kubernetes组件间通信(API Server <-> etcd, API Server <-> kubelet, kubelet <-> API Server等)以及客户端访问API Server都依赖TLS证书进行加密和认证。证书管理混乱是集群故障的常见原因。
- 最佳实践:使用PKI: 建立或使用现有的公钥基础设施(PKI)。
- 集中管理: 使用如
cfssl
,cert-manager
(Kubernetes原生证书管理控制器)等工具进行证书的创建、分发、轮换自动化。 - 明确有效期: 为所有证书设置合理的有效期(如1年),并建立自动化轮换机制。避免证书过期导致集群组件无法通信。
- 安全存储: 私钥必须严格保密,妥善存储(如使用Kubernetes Secrets、Vault等)。
- 最小权限原则: 为不同组件签发具有最小必要权限的证书(如API Server证书需要能访问etcd,kubelet证书需要能访问API Server)。
2.3.4 kubelet配置(Master节点)
- 推荐配置: 在Master节点上也运行kubelet,并将其注册为集群的Node。
-
- 优点:可观测性: Master节点本身的状态(如Ready状态、资源使用情况)可以通过
kubectl get nodes
查看,便于监控。 - DaemonSet部署: 允许在Master节点上部署系统级DaemonSet Pod(如监控Agent Prometheus Node Exporter、日志收集Fluentd、网络插件Calico/Cilium的DaemonSet),统一管理。
- 污点(Taints)与容忍(Tolerations): 可以给Master节点添加污点(如
node-role.kubernetes.io/master:NoSchedule
),防止普通业务Pod被调度到Master节点(除非Pod明确容忍该污点),保证控制平面资源。
- 优点:可观测性: Master节点本身的状态(如Ready状态、资源使用情况)可以通过
- 配置要点: 在kubelet的启动参数中,需要正确配置
--register-node=true
(默认),并提供连接API Server的证书(kubelet client cert)和CA证书。确保kubelet能通过负载均衡器的VIP访问API Server。
-
三、 etcd集群运维:高可用的数据基石
etcd是Kubernetes集群的唯一可信数据源,存储了集群的所有状态信息:节点信息、Pod配置、Service定义、Secret、ConfigMap、RoleBinding、Deployment状态等等。可以说,etcd的可用性和一致性直接决定了整个Kubernetes集群的可用性和一致性。运维好etcd集群是保障Kubernetes高可用的重中之重。
3.1 etcd核心原理:Raft一致性协议深度解析
etcd的高可用和强一致性能力源于其使用的Raft一致性算法。理解Raft是理解etcd运维的基础。
3.1.1 Raft核心概念
-
- 节点状态:Leader(领导者): 唯一负责处理所有客户端写请求(通过API Server发起)、复制日志到Followers、提交日志条目的节点。集群中同一时间最多只有一个Leader。
- Follower(追随者): 被动接收并复制来自Leader的日志条目。如果Leader失效,可参与选举成为Candidate。
- Candidate(候选者): 当Follower在选举超时(election timeout)内未收到Leader的心跳时,会转变为Candidate,发起选举请求投票。
- Term(任期): Raft将时间划分为连续的任期(Term),用单调递增的整数表示。每个Term最多选举出一个Leader。Term在Raft中充当逻辑时钟,用于检测过时的Leader(如网络分区后恢复的旧Leader)。
- 日志(Log): etcd的核心数据结构。由按顺序编号的**日志条目(Entry)**组成。每个条目包含:
- 命令(Command): 实际要存储的键值对数据(如
/registry/pods/default/nginx
的JSON数据)。 - Term(任期号): 该条目被Leader创建时的Term。
- 日志复制:客户端(API Server)向Leader发起写请求(如创建一个Pod)。
- Leader将请求内容(键值对操作)封装成一个日志条目,追加到自己的本地日志中。
- Leader将该日志条目并行的发送(AppendEntries RPC)给集群中所有的Follower。
- Follower收到条目后,将其追加到自己的本地日志中(如果条目索引和Term匹配),并向Leader回复成功。
- Leader等待大多数(Quorum,即 (N/2)+1 个节点,N为集群节点总数) 的Follower成功复制该条目后,认为该条目已提交(Committed)。
- Leader将已提交的条目应用到其状态机(etcd的内存B树存储),此时数据才真正可读。
- Leader在后续的心跳(AppendEntries RPC)中会携带已提交的最高索引,通知Followers它们也可以安全地提交并应用这些条目。
- Leader选举:Follower在选举超时(election timeout,随机值,如150ms-300ms) 内未收到来自Leader的AppendEntries RPC(心跳)或Candidate的RequestVote RPC。
- Follower递增当前Term,转变为Candidate。
- Candidate给自己投票,并并行地向集群中其他节点发送
RequestVote
RPC请求投票。 - 其他节点收到请求后,在以下条件下会投票给该Candidate:
- Candidate的Term >= 自己的当前Term。
- 自己的日志中,最后一条日志条目的Term >= Candidate的
lastLogTerm
,或者Term相同但索引 >= Candidate的lastLogIndex
(确保新Leader的日志至少和自己一样新)。 - 在当前Term中尚未投过票。
- Candidate收到大多数节点的投票后,转变为Leader,开始发送心跳(AppendEntries RPC)阻止新的选举。
- 如果选举超时内未获得多数票(如平票、网络分区),Candidate重新开始新一轮选举(Term递增)。
- 安全性:选举安全: 在一个给定的Term内,最多只能选举出一个Leader。
- Leader只追加日志: Leader从不覆盖或删除其日志中的条目,只追加。
- 日志匹配: 如果两个日志在某个索引上的条目Term相同,那么它们在该索引之前的所有条目也完全相同。这保证了日志复制的正确性。
- Leader完备性: 如果一个日志条目在某个Term被提交,那么它将出现在所有任期更长的Leader的日志中。这保证了已提交的数据不会丢失。
- 命令(Command): 实际要存储的键值对数据(如
3.1.2 Raft在etcd中的关键参数与影响
--heartbeat-interval
:Leader发送心跳(AppendEntries RPC)的间隔。影响: 较短的间隔能更快检测到Leader故障,但增加网络带宽和CPU开销。默认100ms。--election-timeout
:Follower触发选举的超时时间。影响: 较短的值能更快发起选举,但容易在短暂网络抖动时导致不必要的选举。默认1000ms。实际超时是此值的随机倍数(如1x-2x)。--snapshot-count
:触发内存快照(Snapshot)的日志条目数阈值。影响: 较小的值更频繁生成快照,减少日志大小和恢复时间,但增加I/O压力。默认100000。--quota-backend-bytes
:etcd后端数据库(bbolt)大小限制。影响: 达到限制后写操作将被拒绝,用于防止etcd耗尽磁盘空间。需根据集群规模和存储容量合理设置(如8GB)。
架构师理解: Raft协议通过强Leader、日志复制、多数派投票等机制,在分布式节点间实现了线性一致性(Linearizability)。这意味着:
- 写操作一旦被Leader确认提交(收到多数派复制成功),后续所有读操作(无论访问哪个节点)都必须能看到这个写的结果。
- 集群能容忍最多
(N-1)/2
个节点故障(N为节点总数)。 例如,3节点集群可容忍1个节点故障,5节点集群可容忍2个节点故障。因此,生产环境etcd集群节点数必须为奇数(3, 5, 7),且至少3个节点。
3.2 etcd集群部署最佳实践(外部拓扑)
3.2.1 节点规划
- 节点数量: 强烈推荐3个或5个节点。 3节点提供基础高可用(容忍1节点故障),是性价比最高的选择。5节点提供更高容错能力(容忍2节点故障),但增加复杂性和资源开销。7节点及以上通常只在超大规模或特殊地理分布场景下使用。
- 硬件要求:CPU: etcd不是CPU密集型,但Leader需要处理所有写请求和复制。建议2-4核。
- 内存: etcd将整个数据集(包括历史版本)加载到内存中。内存大小需远大于预期数据集大小(建议至少是活跃数据集的2-4倍)。例如,如果集群数据约2GB,建议配置8GB或以上内存。内存不足会导致频繁磁盘交换,性能急剧下降。
- 磁盘: 最关键! etcd对磁盘延迟和IOPS极其敏感。
- 类型: 必须使用SSD(NVMe优先)! 机械硬盘(HDD)的高延迟会严重拖慢etcd性能,甚至导致集群不稳定。
- 性能: 选择高IOPS、低延迟的SSD。关注顺序写和随机读性能。
- 容量: 预留足够空间。除了活跃数据,还需考虑:
- 历史版本数据(由
--auto-compaction-retention
控制保留时长)。 - WAL(Write-Ahead Log)文件。
- 快照文件。
- 空间用于压缩和碎片整理。
- 建议至少是预期活跃数据集的3-5倍,并设置监控(如
etcd_disk_wal_fsync_duration_seconds
)。
- 历史版本数据(由
- 专用: 强烈建议为etcd使用独立的物理磁盘或高性能云盘(如AWS io2 Block Express, GCP Hyperdisk Extreme)。 避免与操作系统日志、其他应用(如数据库)争抢I/O。
- 网络:低延迟: etcd节点间(Raft通信)以及Master节点到etcd节点(API Server读写)的网络延迟必须尽可能低(目标 < 10ms,最好 < 5ms)。跨机房、跨地域部署需谨慎评估。
- 高带宽: 虽然单次请求不大,但集群规模大、操作频繁时,网络带宽也可能成为瓶颈。
- 稳定性: 网络抖动会触发不必要的Leader选举或导致操作超时。确保网络连接稳定可靠。
- 安全: 使用TLS加密节点间通信(
--peer-auto-tls
或手动配置证书)。
3.2.2 部署步骤(以kubeadm外部etcd为例)
- 准备环境: 准备3台(或5台)满足硬件要求的专用服务器/虚拟机。安装操作系统(如Ubuntu 20.04/22.04, CentOS 7/8/9),配置好主机名、网络(静态IP)、时间同步(NTP)、防火墙规则(开放2379客户端端口,2380集群通信端口)。
- 安装etcd: 在每台etcd节点上安装etcd二进制文件(下载官方Release包或使用包管理器如
apt install etcd
)。 - 生成证书: 为etcd集群生成TLS证书:
- CA证书: 用于签发etcd服务器和客户端证书。
- 服务器证书(Peer Cert): 用于etcd节点间通信(2380端口)。需包含所有etcd节点的IP和主机名作为SAN(Subject Alternative Name)。
- 客户端证书(Client Cert): 用于API Server连接etcd(2379端口)。CN通常设置为
kube-apiserver
。 - 工具: 使用
cfssl
,easyrsa
,openssl
等工具生成。
- 创建etcd配置文件: 在每个etcd节点上创建配置文件(如
/etc/etcd.conf
或通过systemd unit文件指定参数)。关键参数:
# 节点1 (etcd1) 示例配置 name: etcd1 data-dir: /var/lib/etcd listen-peer-urls: https://192.168.1.101:2380 # 本地监听集群通信 listen-client-urls: https://192.168.1.101:2379, https://127.0.0.1:2379 # 本地监听客户端 initial-advertise-peer-urls: https://192.168.1.101:2380 # 告知其他节点自己的集群通信地址 advertise-client-urls: https://192.168.1.101:2379 # 告知客户端自己的访问地址 initial-cluster: etcd1=https://192.168.1.101:2380,etcd2=https://192.168.1.102:2380,etcd3=https://192.168.1.103:2380 initial-cluster-state: new initial-cluster-token: etcd-cluster-1 # TLS配置 peer-cert-file: /etc/etcd/pki/peer.crt peer-key-file: /etc/etcd/pki/peer.key peer-trusted-ca-file: /etc/etcd/pki/ca.crt peer-client-cert-auth: true cert-file: /etc/etcd/pki/server.crt key-file: /etc/etcd/pki/server.key trusted-ca-file: /etc/etcd/pki/ca.crt client-cert-auth: true # 安全加固 auto-tls: false peer-auto-tls: false # 性能调优 snapshot-count: 10000 heartbeat-interval: 100 election-timeout: 1000 quota-backend-bytes: 8589934592 # 8GB
- 启动etcd服务: 使用systemd管理etcd服务。创建
/etc/systemd/system/etcd.service
文件:
[Unit] Description=etcd key-value store Documentation=https://github.com/etcd-io/etcd After=network.target[Service] Type=notify User=etcd Group=etcd ExecStart=/usr/local/bin/etcd --config-file /etc/etcd.conf Restart=on-failure RestartSec=5s LimitNOFILE=65536 LimitNPROC=65536[Install] WantedBy=multi-user.target
- 执行
systemctl daemon-reload && systemctl enable --now etcd
启动服务。 - 验证集群状态: 在任意etcd节点或配置好证书的客户端机器上执行:
ETCDCTL_API=3 etcdctl --endpoints=https://192.168.1.101:2379,https://192.168.1.102:2379,https://192.168.1.103:2379 \--cacert=/etc/etcd/pki/ca.crt \--cert=/etc/etcd/pki/client.crt \--key=/etc/etcd/pki/client.key \endpoint health
- 输出应显示所有节点
healthy
。执行etcdctl member list
查看成员状态。 - 部署Kubernetes Master节点: 使用kubeadm部署Master节点时,在
kubeadm-config.yaml
中指定外部etcd集群的端点:
apiVersion: kubeadm.k8s.io/v1beta3 kind: InitConfiguration localAPIEndpoint:advertiseAddress: "192.168.1.11" # 本Master节点IPbindPort: 6443 --- apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.28.0 controlPlaneEndpoint: "192.168.1.100:6443" # 负载均衡器VIP:Port etcd:external:endpoints:- https://192.168.1.101:2379- https://192.168.1.102:2379- https://192.168.1.103:2379caFile: /etc/kubernetes/pki/etcd/ca.crtcertFile: /etc/kubernetes/pki/etcd/server.crtkeyFile: /etc/kubernetes/pki/etcd/server.key # ... 其他配置如networking, certSANs等
- 然后执行
kubeadm init --config kubeadm-config.yaml
初始化第一个Master节点。后续Master节点使用kubeadm join
命令加入,并携带--control-plane
标志。
3.3 etcd集群日常运维核心操作
3.3.1 备份与恢复:灾难恢复的生命线
-
- 备份策略:频率: 根据集群变更频率和RPO(恢复点目标)要求确定。高活跃集群可能需要每小时甚至更频繁备份。低活跃集群可每天备份。
- 方式:快照备份(推荐): 使用
etcdctl snapshot save
命令。这是最常用、最可靠的备份方式。它会创建一个包含etcd数据完整状态的点-in-time快照文件。
- 方式:快照备份(推荐): 使用
- 备份策略:频率: 根据集群变更频率和RPO(恢复点目标)要求确定。高活跃集群可能需要每小时甚至更频繁备份。低活跃集群可每天备份。
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \--cacert=/etc/etcd/pki/ca.crt \--cert=/etc/etcd/pki/client.crt \--key=/etc/etcd/pki/client.key \snapshot save /backups/etcd-snapshot-$(date +%Y%m%d%H%M%S).db
-
-
- 数据目录备份: 直接复制
--data-dir
指定的整个目录(如/var/lib/etcd
)。风险较高! 需确保etcd进程已停止或处于只读模式,否则可能备份到不一致的数据。不推荐作为常规备份手段。
- 数据目录备份: 直接复制
- 存储: 将备份文件存储在安全、可靠、异地的位置(如对象存储S3/OSS、异地备份服务器)。确保备份文件本身也受到保护(加密、访问控制)。
- 验证: 定期(如每月)验证备份文件的可用性,尝试在测试环境中恢复。
- 恢复操作:场景: etcd集群严重故障(如多数节点永久丢失、数据损坏)且无法修复时,需要从备份恢复整个集群。
- 步骤:停止所有etcd进程: 在所有etcd节点上停止etcd服务(
systemctl stop etcd
)。 - 移除旧数据目录: 在所有etcd节点上备份并移除旧的数据目录(
mv /var/lib/etcd /var/lib/etcd.bak
)。 - 恢复数据到第一个节点: 选择一个节点(通常是etcd1),使用
etcdctl snapshot restore
命令将快照恢复到其数据目录:
- 步骤:停止所有etcd进程: 在所有etcd节点上停止etcd服务(
-
ETCDCTL_API=3 etcdctl snapshot restore /backups/etcd-snapshot-20230825120000.db \--name etcd1 \--initial-cluster etcd1=https://192.168.1.101:2380,etcd2=https://192.168.1.102:2380,etcd3=https://192.168.1.103:2380 \--initial-cluster-token etcd-cluster-1 \--initial-advertise-peer-urls https://192.168.1.101:2380 \--data-dir /var/lib/etcd
-
-
-
- 关键:
--initial-cluster
必须包含所有成员(包括后续要加入的节点)的初始信息,且名称和URL必须与原集群一致(或按新规划配置)。
- 关键:
- 启动第一个节点: 在恢复数据的节点(etcd1)上启动etcd服务(
systemctl start etcd
)。此时它将成为单节点集群的Leader。 - 添加其他成员: 在其他节点(etcd2, etcd3)上,不要再次执行restore!而是使用
etcdctl member add
命令将它们作为新成员添加到已恢复的单节点集群中:
-
-
# 在etcd2节点上,先启动一个临时的单点etcd(仅用于加入集群) # 然后在etcd1节点或任意有权限的客户端上执行: ETCDCTL_API=3 etcdctl --endpoints=https://192.168.1.101:2379 \--cacert=/etc/etcd/pki/ca.crt \--cert=/etc/etcd/pki/client.crt \--key=/etc/etcd/pki/client.key \member add etcd2 --peer-urls=https://192.168.1.102:2380
-
-
- 命令会输出etcd2节点启动时需要的
--initial-cluster
和--initial-cluster-state
参数。在etcd2节点上使用这些参数启动etcd服务(无需restore)。 - 重复步骤5: 为etcd3节点执行
member add
并启动服务。 - 验证集群: 使用
etcdctl endpoint health
和member list
验证集群是否恢复为3节点健康状态。
- 命令会输出etcd2节点启动时需要的
- 影响: 恢复操作会导致集群状态回退到备份时间点。在备份时间点之后发生的所有变更(如新创建的Pod、更新的配置)都会丢失。这是恢复的固有代价(RPO)。
-
3.3.2 节点管理:扩容与缩容
- 添加节点(扩容):
- 场景: 提升集群容错能力(如从3节点扩到5节点)或增加读吞吐量。
- 步骤:准备新节点: 按照部署要求准备新服务器(硬件、OS、网络、证书)。
- 获取加入信息: 在现有集群的任意Leader节点上,使用
etcdctl member add
命令添加新成员:
- 场景: 提升集群容错能力(如从3节点扩到5节点)或增加读吞吐量。
ETCDCTL_API=3 etcdctl --endpoints=https://192.168.1.101:2379 \--cacert=/etc/etcd/pki/ca.crt \--cert=/etc/etcd/pki/client.crt \--key=/etc/etcd/pki/client.key \member add etcd4 --peer-urls=https://192.168.1.104:2380
-
-
- 命令会输出新节点启动所需的
--initial-cluster
(包含所有成员,包括新成员)和--initial-cluster-state=existing
。 - 启动新节点: 在新节点(etcd4)上,使用上一步输出的参数启动etcd服务(无需执行
snapshot restore
)。 - 验证: 使用
etcdctl member list
确认新节点状态变为started
,endpoint health
确认其健康。
- 命令会输出新节点启动所需的
- 注意: 扩容会增加Raft协议的通信开销(需要更多节点达成共识),可能略微降低写延迟。扩容后需更新所有Kubernetes Master节点配置中指向etcd的端点列表(如果之前未包含新节点)。
-
- 移除节点(缩容):
- 场景: 节点硬件故障且无法修复、降低成本、调整集群规模。
- 步骤:确认移除目标: 确定要移除的节点ID(通过
etcdctl member list
获取)。 - 移除成员: 在集群的任意Leader节点上,使用
etcdctl member remove
命令:
- 步骤:确认移除目标: 确定要移除的节点ID(通过
- 场景: 节点硬件故障且无法修复、降低成本、调整集群规模。
ETCDCTL_API=3 etcdctl --endpoints=https://192.168.1.101:2379 \--cacert=/etc/etcd/pki/ca.crt \--cert=/etc/etcd/pki/client.crt \--key=/etc/etcd/pki/client.key \member remove <member_id>
-
-
- 停止节点服务: 在被移除的节点上停止etcd服务(
systemctl stop etcd
)。 - 清理数据: (可选但推荐)备份并移除该节点上的etcd数据目录(
/var/lib/etcd
)。 - 验证: 使用
etcdctl member list
确认该节点已从列表中消失,endpoint health
确认剩余节点健康。
- 停止节点服务: 在被移除的节点上停止etcd服务(
- 关键: 移除节点后,集群的可用节点数必须仍然满足多数派要求(> N/2)! 例如,3节点集群移除1个节点后,剩余2个节点,仍能工作(2 > 3/2)。但5节点集群移除2个节点后,剩余3个节点(3 > 5/2),仍可工作。如果5节点集群移除3个节点,剩余2个节点(2 <= 5/2),集群将失去法定人数(Quorum),无法进行写操作或选举新Leader,集群只读,需要恢复或添加节点。因此,缩容操作必须谨慎,确保剩余节点数 > N/2。
-
3.3.3 升级与维护
- 版本兼容性: 严格遵循etcd官方的版本兼容性策略。通常只支持升级到次版本(minor version),不支持跨主版本(major version)升级(如v3.4直接升级到v3.6)。升级前务必阅读目标版本的Release Notes。
- 滚动升级(推荐):备份: 升级前必须进行完整备份!
- 升级顺序: 一次升级一个节点。强烈建议从Follower节点开始,最后升级Leader节点。
- 步骤(单个节点):
- a. 在待升级节点上停止etcd服务(
systemctl stop etcd
)。 - b. 备份etcd二进制文件和数据目录(
cp /usr/local/bin/etcd /usr/local/bin/etcd.bak
)。 - c. 下载并替换为新版本的etcd二进制文件。
- d. 启动etcd服务(
systemctl start etcd
)。 - e. 使用
etcdctl endpoint status --cluster
或etcdctl version
确认该节点已升级并加入集群。 - 重复: 对下一个节点重复步骤3,直到所有节点升级完毕。
- 验证: 确认整个集群版本一致,功能正常。
- 维护窗口: 对于关键业务,选择低峰期进行升级。虽然滚动升级能保持集群可用,但升级过程中短暂的网络分区或节点重启可能对性能有轻微影响。
- 降级: 官方不支持降级! 升级后如遇问题,通常需要回滚到备份或寻求其他解决方案。
3.3.4 性能监控与调优
-
-
- 关键监控指标(Prometheus + Grafana):集群健康:
etcd_server_has_leader
: 1表示有Leader,0表示无(集群不可用)。 etcd_server_leader_changes_seen_total
: Leader变更次数。频繁变更说明集群不稳定(网络、资源问题)。etcd_disk_wal_fsync_duration_seconds
: WAL文件fsync操作耗时。核心指标! 持续高值(如>100ms)表明磁盘性能瓶颈。etcd_mvcc_db_total_size_in_bytes
: etcd后端数据库大小。监控增长趋势,避免达到--quota-backend-bytes
限制。- 延迟:
etcd_disk_backend_commit_duration_seconds
: 后端数据库提交耗时。反映写性能。 etcd_network_peer_round_trip_time_seconds
: 节点间Raft消息往返时间。反映网络延迟。etcd_grpc_proxy_unary_requests_duration_seconds
: API请求处理延迟(通过grpc-proxy)。- 吞吐量:
etcd_grpc_proxy_unary_requests_total
: API请求总数(按方法分类)。 etcd_debugging_mvcc_keys_total
: 键值对总数。etcd_debugging_mvcc_put_total
: 写操作总数。- 资源:
process_cpu_seconds_total
: CPU使用率。 process_resident_memory_bytes
: 内存使用量(RSS)。process_virtual_memory_bytes
: 虚拟内存使用量。etcd_disk_wal_fsync_duration_seconds
(再次强调): 磁盘I/O延迟。
- 关键监控指标(Prometheus + Grafana):集群健康:
- 调优建议:磁盘: 优先解决
etcd_disk_wal_fsync_duration_seconds
高的问题。升级到更快的SSD(NVMe),确保磁盘专用,检查文件系统(推荐ext4/xfs),关闭磁盘写缓存(如果控制器支持电池备份)。 - 内存: 确保内存充足,避免交换(swap)。监控
etcd_mvcc_db_total_size_in_bytes
,必要时增加内存或调整--auto-compaction-retention
减少历史数据保留。 - 网络: 优化网络配置,确保低延迟、高带宽。检查防火墙、QoS设置。
- Raft参数: 在极端情况下,可微调
--heartbeat-interval
(默认100ms)和--election-timeout
(默认1000ms)。需谨慎! 过短的值可能增加不必要的选举和网络开销。通常默认值在大多数场景下工作良好。 - 客户端: 优化Kubernetes组件(如API Server)的etcd客户端缓存(
--etcd-servers-overrides
),减少不必要的etcd请求。使用etcdctl
的--endpoints
负载均衡到多个etcd节点。 - 压缩: 定期执行
etcdctl compact
手动压缩历史版本(或依赖--auto-compaction-retention
自动压缩),减少数据库大小。压缩后执行etcdctl defrag
碎片整理回收空间。
-
3.3.5 安全加固
- TLS: 强制启用TLS加密所有通信(客户端-服务器、服务器-服务器)。使用强密码套件,定期轮换证书。
- 认证与授权:启用客户端证书认证(
--client-cert-auth=true
)。 - 配置基于用户名/密码的认证(
--auth-token-ttl
)。 - 启用RBAC(Role-Based Access Control),为不同用户/服务(如kube-apiserver)分配最小必要权限。
- 认证与授权:启用客户端证书认证(
- 网络隔离: 使用防火墙(iptables, firewalld, 云安全组)严格限制访问etcd端口(2379, 2380)的源IP地址。只允许Master节点(API Server)和必要的运维工具访问2379;只允许etcd节点之间访问2380。
- 审计日志: 启用etcd审计日志(
--log-package-levels=etcdserver=debug
或更高版本支持审计配置),记录所有关键操作,用于安全审计和故障排查。 - 定期更新: 及时跟进etcd安全补丁和版本更新。
四、 实战实验:搭建高可用Kubernetes集群(外部etcd)
4.1 实验环境规划
-
- 节点角色与IP:etcd节点 (3台):
etcd1 (192.168.1.101)
,etcd2 (192.168.1.102)
,etcd3 (192.168.1.103)
- Master节点 (3台):
master1 (192.168.1.11)
,master2 (192.168.1.12)
,master3 (192.168.1.13)
- 负载均衡器 (VIP):
192.168.1.100
(使用Keepalived + HAProxy实现) - Worker节点 (2台,可选):
worker1 (192.168.1.21)
,worker2 (192.168.1.22)
- 软件版本:OS: Ubuntu 22.04 LTS
- etcd: v3.5.9
- Kubernetes: v1.28.0
- Docker: 24.0.5 (作为容器运行时)
- Keepalived: v2.2.8
- HAProxy: 2.6.12
- 节点角色与IP:etcd节点 (3台):
- 网络: 所有节点位于同一局域网
192.168.1.0/24
,确保节点间网络互通。
4.2 实验步骤(30%)
步骤1:基础环境准备(所有节点)
更新系统: sudo apt update && sudo apt upgrade -y sudo reboot 设置主机名: # 在etcd1上 sudo hostnamectl set-hostname etcd1 # 在master1上 sudo hostnamectl set-hostname master1 # ... 其他节点同理
- 配置
/etc/hosts
: 在所有节点添加所有主机名和IP映射。
关闭Swap: sudo swapoff -a sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab 安装Docker: sudo apt install -y docker.io docker-compose sudo systemctl enable --now docker # 配置Docker cgroup driver为systemd sudo mkdir -p /etc/docker cat <<EOF | sudo tee /etc/docker/daemon.json {"exec-opts": ["native.cgroupdriver=systemd"],"log-driver": "json-file","log-opts": {"max-size": "100m"},"storage-driver": "overlay2" } EOF sudo systemctl daemon-reload sudo systemctl restart docker 安装kubeadm, kubelet, kubectl: sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl 配置内核参数: cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF sudo sysctl --system
步骤2:部署etcd集群(etcd1, etcd2, etcd3)
安装etcd: ETCD_VER=v3.5.9 GITHUB_URL=https://github.com/etcd-io/etcd/releases/download DOWNLOAD_URL=${GITHUB_URL} curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz mkdir -p /tmp/etcd-download tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download --strip-components=1 sudo mv /tmp/etcd-download/etcd* /usr/local/bin/ 创建用户和目录: sudo useradd -r -s /bin/false etcd sudo mkdir -p /var/lib/etcd /etc/etcd/pki sudo chown -R etcd:etcd /var/lib/etcd /etc/etcd
-
- 生成证书(在master1上操作,然后分发):安装cfssl:
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssl_1.6.4_linux_amd64 -o cfssl curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssljson_1.6.4_linux_amd64 -o cfssljson curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssl-certinfo_1.6.4_linux_amd64 -o cfssl-certinfo chmod +x cfssl cfssljson cfssl-certinfo sudo mv cfssl cfssljson cfssl-certinfo /usr/local/bin/
-
- 创建CA配置:
mkdir ~/etcd-certs && cd ~/etcd-certs cat > ca-config.json <<EOF {"signing": {"default": {"expiry": "87600h"},"profiles": {"etcd": {"usages": ["signing", "key encipherment", "server auth", "client auth"],"expiry": "87600h"}}} } EOF cat > ca-csr.json <<EOF {"CN": "etcd CA","key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "Beijing","O": "Kubernetes","OU": "CA"}] } EOF cfssl gencert -initca ca-csr.json | cfssljson -bare ca
-
- 创建etcd服务器证书(包含所有节点IP和主机名):
cat > etcd-server-csr.json <<EOF {"CN": "etcd-server","hosts": ["127.0.0.1","192.168.1.101","192.168.1.102","192.168.1.103","etcd1","etcd2","etcd3"],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "Beijing","O": "Kubernetes","OU": "etcd"}] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd etcd-server-csr.json | cfssljson -bare etcd-server
-
- 创建etcd对等证书(用于节点间通信):
cat > etcd-peer-csr.json <<EOF {"CN": "etcd-peer","hosts": ["192.168.1.101","192.168.1.102","192.168.1.103","etcd1","etcd2","etcd3"],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "Beijing","O": "Kubernetes","OU": "etcd"}] } EOF cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=etcd etcd-peer-csr.json | cfssljson -bare etcd-peer
-
- 分发证书到所有etcd节点:
for NODE in etcd1 etcd2 etcd3; dossh ${NODE} "mkdir -p /etc/etcd/pki"scp ca.pem ${NODE}:/etc/etcd/pki/scp etcd-server.pem ${NODE}:/etc/etcd/pki/server.crtscp etcd-server-key.pem ${NODE}:/etc/etcd/pki/server.keyscp etcd-peer.pem ${NODE}:/etc/etcd/pki/peer.crtscp etcd-peer-key.pem ${NODE}:/etc/etcd/pki/peer.key done 创建etcd配置文件(以etcd1为例): sudo tee /etc/etcd.conf <<EOF name: etcd1 data-dir: /var/lib/etcd listen-peer-urls: https://192.168.1.101:2380 listen-client-urls: https://192.168.1.101:2379,https://127.0.0.1:2379 initial-advertise-peer-urls: https://192.168.1.101:2380 advertise-client-urls: https://192.168.1.101:2379 initial-cluster: etcd1=https://192.168.1.101:2380,etcd2=https://192.168.1.102:2380,etcd3=https://192.168.1.103:2380 initial-cluster-state: new initial-cluster-token: etcd-cluster-ha # TLS peer-cert-file: /etc/etcd/pki/peer.crt peer-key-file: /etc/etcd/pki/peer.key peer-trusted-ca-file: /etc/etcd/pki/ca.pem peer-client-cert-auth: true cert-file: /etc/etcd/pki/server.crt key-file: /etc/etcd/pki/server.key trusted-ca-file: /etc/etcd/pki/ca.pem client-cert-auth: true # Security auto-tls: false peer-auto-tls: false # Performance snapshot-count: 10000 heartbeat-interval: 100 election-timeout: 1000 quota-backend-bytes: 4294967296 # 4GB EOF
-
- 在
etcd2
和etcd3
上创建类似配置,修改name
,listen-peer-urls
,listen-client-urls
,initial-advertise-peer-urls
,advertise-client-urls
为对应节点的IP和主机名。
- 在
创建systemd服务文件: sudo tee /etc/systemd/system/etcd.service <<EOF [Unit] Description=etcd key-value store Documentation=https://github.com/etcd-io/etcd After=network.target[Service] Type=notify User=etcd Group=etcd ExecStart=/usr/local/bin/etcd --config-file /etc/etcd.conf Restart=on-failure RestartSec=5s LimitNOFILE=65536 LimitNPROC=65536[Install] WantedBy=multi-user.target EOF 启动并验证etcd集群: sudo systemctl daemon-reload sudo systemctl enable --now etcd # 在任意etcd节点上验证 ETCDCTL_API=3 etcdctl --endpoints=https://192.168.1.101:2379,https://192.168.1.102:2379,https://192.168.1.103:2379 \--cacert=/etc/etcd/pki/ca.pem \--cert=/etc/etcd/pki/server.crt \--key=/etc/etcd/pki/server.key \endpoint health # 预期输出:所有节点 healthy ETCDCTL_API=3 etcdctl --endpoints=https://192.168.1.101:2379 \--cacert=/etc/etcd/pki/ca.pem \--cert=/etc/etcd/pki/server.crt \--key=/etc/etcd/pki/server.key \member list # 预期输出:3个成员,状态为started
步骤3:部署负载均衡器(Keepalived + HAProxy)
- 在
master1
,master2
,master3
上安装并配置Keepalived和HAProxy。
安装: sudo apt install -y keepalived haproxy 配置HAProxy(所有Master节点相同配置): sudo tee /etc/haproxy/haproxy.cfg <<EOF globallog /dev/log local0log /dev/log local1 noticechroot /var/lib/haproxystats socket /run/haproxy/admin.sock mode 660 level adminstats timeout 30suser haproxygroup haproxydaemondefaultslog globalmode tcpoption tcplogoption dontlognulltimeout connect 5000timeout client 50000timeout server 50000frontend kubernetes-apiserverbind *:6443mode tcpoption tcplogdefault_backend kubernetes-apiserverbackend kubernetes-apiservermode tcpoption tcplogoption tcp-checkbalance roundrobindefault-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100server master1 192.168.1.11:6443 checkserver master2 192.168.1.12:6443 checkserver master3 192.168.1.13:6443 check EOF sudo systemctl enable --now haproxy 配置Keepalived(master1 - BACKUP, master2 - BACKUP, master3 - MASTER):master1 (BACKUP, priority 100): sudo tee /etc/keepalived/keepalived.conf <<EOF global_defs {router_id LVS_DEVEL } vrrp_script check_haproxy {script "killall -0 haproxy"interval 2weight 2 } vrrp_instance VI_1 {state BACKUPinterface eth0 # 替换为实际网卡名virtual_router_id 51priority 100advert_int 1authentication {auth_type PASSauth_pass K8s_HA_PASS}virtual_ipaddress {192.168.1.100/24 dev eth0}track_script {check_haproxy} } EOF
-
- master2 (BACKUP, priority 90): 配置类似,修改
priority 90
。 - master3 (MASTER, priority 110): 配置类似,修改
state MASTER
和priority 110
。
- master2 (BACKUP, priority 90): 配置类似,修改
启动Keepalived并验证VIP: sudo systemctl enable --now keepalived # 在master3上执行 ip addr show eth0 # 预期输出:应能看到 192.168.1.100/24 # 模拟故障:在master3上停止keepalived (sudo systemctl stop keepalived) # 检查master1或master2,VIP应漂移到priority最高的BACKUP节点(master1)
步骤4:部署Kubernetes Master节点
准备kubeadm配置文件(在master1上): mkdir ~/k8s-ha && cd ~/k8s-ha tee kubeadm-config.yaml <<EOF apiVersion: kubeadm.k8s.io/v1beta3 kind: InitConfiguration localAPIEndpoint:advertiseAddress: "192.168.1.11"bindPort: 6443 --- apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.28.0 controlPlaneEndpoint: "192.168.1.100:6443" imageRepository: registry.aliyuncs.com/google_containers etcd:external:endpoints:- https://192.168.1.101:2379- https://192.168.1.102:2379- https://192.168.1.103:2379caFile: /etc/kubernetes/pki/etcd/ca.pemcertFile: /etc/kubernetes/pki/etcd/server.crtkeyFile: /etc/kubernetes/pki/etcd/server.key networking:podSubnet: "10.244.0.0/16"serviceSubnet: "10.96.0.0/12"dnsDomain: "cluster.local" apiServer:certSANs:- "192.168.1.100"- "192.168.1.11"- "192.168.1.12"- "192.168.1.13"- "master1"- "master2"- "master3"- "127.0.0.1" controllerManager:extraArgs:bind-address: "0.0.0.0" scheduler:extraArgs:bind-address: "0.0.0.0" --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd EOF 初始化第一个Master节点(master1): sudo kubeadm init --config kubeadm-config.yaml --upload-certs # 记录输出中的 join 命令(包含 --control-plane --certificate-key 和 --token) # 配置kubectl mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
-
- 加入其他Master节点(master2, master3):将
/etc/kubernetes/pki
目录下的证书(ca., sa., front-proxy-ca.*, etcd/ca.pem)从master1安全地复制到master2和master3的/etc/kubernetes/pki
目录(注意权限)。 - 在master2和master3上执行记录的
kubeadm join
命令(包含--control-plane
标志)。
- 加入其他Master节点(master2, master3):将
安装网络插件(如Calico): kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml 验证Master集群: kubectl get nodes # 预期输出:3个Master节点状态为 Ready kubectl get pods -n kube-system # 预期输出:所有核心组件(kube-apiserver-* x3, kube-controller-manager-* x3, kube-scheduler-* x3, etcd-* x3, coredns, calico) Running # 检查Leader kubectl get endpoints kube-controller-manager -n kube-system # 预期输出:只有一个地址(Leader) kubectl get endpoints kube-scheduler -n kube-system # 预期输出:只有一个地址(Leader)
步骤5:加入Worker节点(可选)
在worker1, worker2上执行: # 使用master1初始化时输出的普通节点join命令(无--control-plane) sudo kubeadm join 192.168.1.100:6443 --token <token> --discovery-token-ca-cert-hash <hash> 验证: kubectl get nodes # 预期输出:5个节点(3 Master, 2 Worker)状态为 Ready
步骤6:高可用性测试
-
- 模拟Master节点故障:停止
master1
上的kube-apiserver服务:sudo systemctl stop kube-apiserver
- 观察负载均衡器(HAProxy状态页或日志):应将流量自动切换到
master2
和master3
。 - 在客户端(如
worker1
)执行kubectl get nodes
:应能正常工作(可能短暂延迟)。 - 检查Leader选举:
kubectl get endpoints kube-controller-manager -n kube-system
,Leader应已切换到其他Master节点。 - 恢复
master1
:sudo systemctl start kube-apiserver
,观察其重新加入集群。 - 模拟etcd节点故障:停止
etcd2
上的etcd服务:sudo systemctl stop etcd
- 在任意Master节点执行
ETCDCTL_API=3 etcdctl --endpoints=... endpoint health
:应显示etcd2
为unhealthy
,但etcd1
和etcd3
仍为healthy
,集群可读写(因为2/3 > 1.5)。 - 在Kubernetes集群中创建一个测试Pod:
kubectl run nginx --image=nginx
,应能成功创建并运行。 - 恢复
etcd2
:sudo systemctl start etcd
,观察其重新加入集群并同步数据。 - 模拟负载均衡器故障(VIP漂移):在当前持有VIP的节点(如
master3
)上停止Keepalived:sudo systemctl stop keepalived
- 观察VIP漂移到其他Master节点(如
master1
)。 - 在客户端执行
kubectl get nodes
:应能正常工作(短暂网络中断后恢复)。 - 恢复
master3
的Keepalived:sudo systemctl start keepalived
。
- 模拟Master节点故障:停止
五、 总结与展望:迈向Kubernetes架构师之路
本文系统性地阐述了Kubernetes高可用架构设计的核心原理与最佳实践,重点剖析了多Master节点部署的架构细节、组件协作机制(负载均衡、Leader Election)以及etcd集群的深度运维(Raft协议、部署、备份恢复、节点管理、监控调优、安全)。通过70%的理论深度剖析与30%的实战实验验证,我们构建了一个从理解到实践的完整知识闭环。
核心要点回顾
- 高可用是生产刚需: 单Master架构存在致命单点故障,多Master+外部etcd是生产环境标准范式。
- 控制平面高可用关键:kube-apiserver: 依赖负载均衡器(HAProxy/Nginx/Keepalived/云LB)实现流量分发与健康检查。
- kube-controller-manager & kube-scheduler: 依赖Leader Election机制确保唯一活跃实例。
- 网络规划: Master间、Master-etcd间、Node-API Server间网络质量至关重要。
- etcd是集群基石:Raft协议: 理解Leader选举、日志复制、多数派原则是运维基础。
- 部署原则: 奇数节点(3/5)、专用SSD、充足内存、低延迟网络。
- 运维核心: 定期备份(快照)、掌握恢复流程、安全扩缩容、滚动升级、深度监控(尤其磁盘延迟)、严格安全加固。
- 实战验证: 通过kubeadm + Keepalived/HAProxy + 外部etcd成功搭建了具备故障转移能力的高可用集群,并验证了Master、etcd、LB故障场景下的自动恢复。
架构师成长之路
掌握Kubernetes高可用架构设计与etcd运维,是成为Kubernetes架构师的关键一步。但这仅仅是起点。要持续精进,您还需关注:
- 高级网络方案: 深入理解CNI插件(Calico, Cilium, Antrea)的BGP、eBGP、IPVLAN、Macvlan等高级模式,优化集群网络性能与安全策略。
- 存储深度优化: 掌握CSI驱动开发与调优,理解分布式存储(Rook/Ceph, Longhorn)在K8s中的集成与高可用设计。
- 多集群管理: 探索Cluster API, Karmada, Rancher等工具,实现跨区域、跨云的Kubernetes集群联邦管理与应用分发。
- 性能极致优化: 针对超大规模集群(万级节点、十万级Pod)进行API Server、etcd、调度器、kubelet的性能瓶颈分析与调优。
- 安全纵深防御: 构建从容器镜像安全、运行时安全(Falco, Policy Controller)、网络策略(Network Policy)、零信任网络(SPIFFE/SPIRE)到供应链安全(Sigstore, Cosign)的全方位安全体系。
- GitOps与云原生生态: 精通Argo CD, Flux等GitOps工具,实现基础设施与应用的声明式管理与自动化交付。深入服务网格(Istio, Linkerd)、Serverless(Knative, OpenFaaS)等云原生技术。
立即行动,开启您的Kubernetes架构师成长之旅! 订阅本专栏,我们将持续为您提供系统化、实战化的深度内容,助您在云原生浪潮中乘风破浪,成为真正的Kubernetes专家。下一期,我们将深入探讨《Kubernetes网络模型深度解析与CNI插件实战》,敬请期待!