Kubernetes控制平面组件:Kubernetes如何使用etcd

云原生学习路线导航页(持续更新中)

本文主要对etcd在kubernetes中的应用进行介绍,包括二者的关系、kubernetes对象存储路径、二者如何交互、生产环境如何部署、最佳实践 以及 一些故障案例分析

1.ETCD 与 Kubernetes 的关系

1.1.ETCD 是 Kubernetes的 默认存储后端

  • 默认后端:ETCD 是 Kubernetes 默认的存储后端

  • 对象映射

    • Kubernetes 中每个对象都有对应的 storage.go 实现与 ETCD 的交互逻辑(增删改查)

    • 比如 Pod 的 pkg/registry/core/pod/storage/storage.go

    • CRD:API Server 根据 CRD 定义自动生成对应的 REST endpoint,统一存储接口 复用 apiserver/pkg/registry/generic/registry/store.go 的通用存储实现

      go 复制代码
      // 伪代码展示存储注册过程
      crdStorage := registry.NewREST(scheme, opts)
      apiGroupInfo.VersionedResourcesStorageMap["v1"] = map[string]rest.Storage{
          "customresources": crdStorage,
      }
  • 能否替换kubernetes的后端存储

    • 重写 storage 层成本极高
    • 推荐优化 ETCD 底层存储(如更换 BoltDB)

1.2.ETCD在Kubernetes集群中的位置

  • etcd属于 Kubernetes集群的 管控组件,apiserver是唯一与其交互的组件

2.API Server 在 ETCD 中对象存储路径

  • Key 结构:

    shell 复制代码
    /registry/<对象类型>/<namespace>/<name>
    
    # 示例
    etcdctl get /registry/pods/default/myapp-pod
  • 历史特性:

    • 早期版本的 selfLink 字段与 ETCD key 路径一致
    • 新版本已弃用该字段
  • 特殊目录说明

    • /registry:Kubernetes 主数据目录
    • /events:事件数据(可分离存储)

3.API Server 与 ETCD 的交互

3.1.连接配置

  • apiserver 启动参数-关于etcd的连接配置参数:

    shell 复制代码
    # API Server 启动参数示例
    --etcd-servers=https://etcd1:2379,https://etcd2:2379
    --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
  • API Server 对 ETCD 的健康检查演进:

    • 早期:通过端口探活的简单检测,但端口存活不代表etcd一定可用。不准确
    • 现在:通过调用 ETCD 健康检查 API。准确

3.2.API Server 对 多 ETCD 实例支持

3.2.1.什么是 多ETCD的支持?

  • 如果其他组件也想用ETCD,怎么办?
    • 可以自己再启动一个,不要使用管控端的etcd,只要保证端口不冲突即可
    • 防止有问题影响到kubernetes集群的稳定性
  • 如果Kubernetes中有些数据,数据量大,频繁写,怎么办
    • 可以使用 API Server 的多实例分流机制

3.2.2.什么是多实例分流?

  • 多实例分流概念
    • 在多实例分流模式下,Kubernetes 可以将不同类型的对象存储到不同的 ETCD 实例中。
    • 通过这种分离,可以减少主 ETCD 集群的压力,提高整体性能和稳定性。
  • 为什么需要多实例分流?
    • 性能优化:高频变更对象(如 Events)会占用大量资源,影响主 ETCD 性能。
    • 故障隔离:将非核心数据(如审计日志)分离到独立 ETCD,避免影响核心业务。
    • 扩展性:支持大规模集群(如 10万+ Pods)的场景。

3.2.3.如何配置多实例分流?

  • 在 API Server 的启动参数中,通过 --etcd-servers-overrides 指定特定对象的存储位置。

  • 示例配置

    shell 复制代码
    # 主 ETCD 集群
    --etcd-servers=https://etcd-main:2379
    
    # 将 events 对象存储到独立 ETCD 集群
    --etcd-servers-overrides=events#https://etcd-events:2379

3.2.4.支持分流的对象类型

3.2.5.分流后的架构

text 复制代码
┌───────────┐       ┌──────────────┐
│ API Server├──────►│ 主 ETCD 集群 │
└───────────┘       └──────────────┘
       │
       │ 分流
       ▼
┌──────────────┐
│ 独立 ETCD 集群│
└──────────────┘

3.2.6.实际应用场景

  • 大规模集群:
    • 分离 Events 和 CRD 数据
    • 减轻主 ETCD 压力
  • 审计日志:
    • 将审计日志存储到独立 ETCD
    • 避免日志写入影响核心业务
  • 多租户环境:
    • 不同租户使用不同 ETCD 集群
    • 实现资源隔离

3.2.7.注意事项

  • 数据一致性:分流后需确保跨集群数据一致性
  • 运维复杂度:增加独立 ETCD 集群的运维成本
  • 监控报警:需单独监控每个 ETCD 集群的健康状态

3.3.API Server无法实现对象的批处理

  • kubernetes的资源锁resourceVersion,是对象级别的,因此做不到很多对象的批处理
  • 如果自己编写Operator,注意不能在短时间内 进行大量写操作,会影响etcd响应速度

3.4.API Server 与 ETCD 交互原理

3.4.1.交互过程

gRPC over HTTP/2 复用TCP连接 Stream流式处理 API Server ETCD Cluster 客户端请求 资源对象

  • 通信协议特性:
    • 使用 gRPC 协议(基于 HTTP/2)
    • 报文格式为 Protocol Buffers
    • HTTP/2特性:连接复用
      • 同一个Group下的所有资源,在API Server 与 ETCD 的通信中,都会复用同一个 TCP连接,即 TCP连接复用 特性

3.4.2.连接复用风险场景

shell 复制代码
# 问题复现条件
集群规模:5000 Nodes
Pod数量:1万+
List操作频率:5000次/分钟(带 --no-cache 参数)
数据量:单次List约100MB
  • Http2 连接复用特性 导致的故障链
    • 同一个Group下的所有资源,在API Server 与 ETCD 的通信中,都会复用同一个 TCP连接
    • 如果当前有Pod资源大量发起请求(比如DemonSet Pod 高频 List 操作占用连接通道),可能就会造成网络拥堵
    • Node资源的请求就发不过去了,节点心跳超时被标记为 NotReady
    • Eviction Controller 驱逐所有节点 Pod
    • 集群服务大面积中断

3.5.什么时候需要到ETCD中查数据?

  • 当我们怀疑apiserver的数据有问题,或者怀疑和etcd数据不一致时,就可以到etcd中查看数据

3.6.API Server中watch对象

  • API Server中也可以watch一个对象,也可以指定resourceVersion来watch
  • 不过我们控制器一般不带resourceVersion,默认是信任apiserver的

3.7.API Server支持分页查询

  • 分页查询会返回一个token,将token提交到apiserver,就会自动帮我们返回下一页

4.生产环境部署注意事项

4.1.集群规模选择

  • 生产上建议部署5个etcd节点
    • 1个节点,一旦坏掉,数据就可能丢失了,服务也不可用了
    • 3个节点,如果坏了一个,你需要立马人工介入处理,优先级会非常高。不然再坏一个的话raft投票就无法达到大多数了,etcd集群就变成只读集群了
    • 5个节点,如果坏了一个,没关系,优先级还没有那么高,因为再坏一个raft协议的投票也能正常进行
  • 一般来说,ETCD的节点数量要在规划阶段确定好,尽量避免后期扩冲节点数量
    • 加节点一定是2个2个的加,因为要保证总节点是奇数个
    • 而且扩充节点还需要重新生成证书,很麻烦
  • 补充
    • 节点数越多,就会越慢,因为协商的节点数变多了

4.2.存储优化实践


4.2.1.存储方案对比

  • 不能直接全部使用remote storage,写的速度会比较慢,大量请求时可能造成请求积压,影响稳定性
  • 也不能一部分节点用local ssd,一部分用远程,这样的话,远程存储的节点数据永远跟不上,leader要一直向其同步数据

4.2.2.存储配置最佳实践

bash 复制代码
# 推荐配置参数
--quota-backend-bytes=8589934592  # 8GB存储配额
--auto-compaction-retention=72h   # 72小时自动压缩
--snapshot-count=10000            # 每10000条日志做快照(修正:原文误作1000)
  • 关键优化点:
    • 使用 本地NVMe SSD(专有磁盘,不要其他进程使用,避免IO竞争)
    • 通过 ionice 提升ETCD进程IO优先级
    • 监控 etcd_debugging_mvcc_db_total_size_in_bytes 指标,如果发现etcd的存储快满了,就及时的压缩或整理碎片
  • 补充:
    • etcd节点的存储默认2GB,不过生产上一般拉满:8GB

4.3.备份与恢复策略


4.3.1.备份方案设计

每小时 流式采集 定时快照 Snapshot保存 实时日志 WAL记录 混合恢复方案

4.3.2.备份命令示例

bash 复制代码
# 创建快照
ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS snapshot save snapshot.db

# 恢复流程
etcdctl snapshot restore snapshot.db \
  --data-dir=/var/lib/etcd-restore \
  --initial-cluster-token=etcd-cluster-1

4.3.3.备份策略参数

4.4.证书管理与监控

  • 证书管理:使用自动轮换工具(如 cert-manager)
  • 监控指标:重点关注 etcd_server_leader_changes(Leader 切换次数)

4.5.ETCD 数据操作与恢复

4.5.1.危险操作示例

bash 复制代码
# 删除所有 Pod 数据(慎用!)
etcdctl del /registry/pods --prefix

4.5.2.灾难恢复流程

  • 停止所有 API Server

  • 恢复快照:

    bash 复制代码
    etcdctl snapshot restore /backup/etcd.db
  • 重启 ETCD 集群

  • 验证数据一致性

4.6.生产环境调优

4.6.1.关键性能参数

bash 复制代码
# Raft协议参数调优(跨地域部署示例)
--heartbeat-interval=300ms     # 心跳间隔(默认100ms)
--election-timeout=3000ms      # 选举超时(默认1000ms)

4.6.2.网络优化措施

  • 使用 tc 命令优先保障 ETCD 流量
bash 复制代码
tc qdisc add dev eth0 root handle 1: prio bands 3
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 2379 0xffff flowid 1:1
  • 跨地域部署保持 RTT < 50ms
  • 禁用 swap 确保内存稳定性

4.7.安全增强方案

4.7.1.数据加密层级

应用层 KMS加密Secret 传输层 mTLS双向认证 存储层 LUKS磁盘加密

4.7.2.审计日志配置

yaml 复制代码
# 审计策略示例
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  resources:
  - group: ""
    resources: ["secrets"]

5.Kubernetes生产集群中如何搭建ETCD集群

5.1.堆叠式etcd集群的高可用拓扑

5.1.1.定义

  • 在堆叠式架构中,etcd 集群Kubernetes 控制平面组件部署在同一组节点上。
  • apiserver 到 etcd 的调用,变成本地调用,速度和稳定性很好

5.1.2.特点

  • 每个节点同时运行 etcdKubernetes 控制平面组件
  • 通常用于小型或中等规模的集群。
  • 部署简单,资源利用率高。

5.1.3.优点

  • 部署和维护相对简单。
  • 节省硬件资源,适合资源有限的场景。

5.1.4.缺点

  • 耦合性较高,etcdKubernetes 控制平面组件共享资源,可能相互影响。
  • 扩展性较差,随着集群规模增大,性能可能成为瓶颈。

5.1.5.适用场景

  • 小型或测试环境。
  • 资源有限的场景。

5.2.外部ETCD集群的高可用拓扑-非堆叠式(External)

5.2.1.定义

在非堆叠式架构中,etcd 集群Kubernetes 控制平面组件分别部署在不同的节点上。

5.2.2.特点

  • etcd 集群独立运行,不与 Kubernetes 控制平面组件共享节点。
  • 通常用于大规模生产环境。

5.2.3.优点

  • 解耦 etcdKubernetes 控制平面组件,避免资源竞争。
  • 扩展性好,可以独立扩展 etcd 集群或 Kubernetes 控制平面。
  • 更高的可靠性和性能。

5.2.4.缺点

  • 需要更多的硬件资源。
  • 部署和维护复杂度较高。

5.2.5.适用场景

  • 大规模生产环境。
  • 对高可用性和性能要求较高的场景。

5.3.对比总结

特性 堆叠式(Stacked) 非堆叠式(External)
部署方式 etcd 和控制平面组件部署在同一节点 etcd 和控制平面组件分别部署在不同节点
资源占用 较少 较多
耦合性
扩展性 较差 较好
复杂度 简单 复杂
适用场景 小型集群、测试环境 大规模生产环境
  • 选择建议
    • 如果是 小型集群测试环境 ,可以选择 堆叠式,以节省资源并简化部署。
    • 如果是 大规模生产环境 ,建议选择 非堆叠式,以提高可靠性和性能。
    • 不过,如果你的资源并不紧缺,还是更推荐 堆叠式

6.经典故障案例分析

6.1.大规模 List 操作雪崩

  • 场景复现:

    • 5000 节点集群

    • 每个节点上的 DaemonSet 每分钟执行:

      bash 复制代码
      kubectl get pods --all-namespaces --watch
  • 后果:

    • ETCD 连接数暴增
    • 节点心跳更新阻塞
    • 集群误判节点离线
  • 解决方案:

    • 优化 List 操作使用缓存
    • 分离高频访问对象到独立 ETCD

6.2.证书过期故障

  • 典型现象:
    • API Server 日志报错 "x509: certificate has expired"
    • 集群突然不可写
  • 处理步骤:
    • 紧急更新 ETCD 证书
    • 滚动重启 API Server

6.3.ETCD分裂

  • 5个节点,4个local storage,1个remote storage
  • 导致这个节点数据一直跟不上

6.4.少数ETCD 出现 成员DOWN

6.5.Master节点出现网络分区

相关推荐
终端行者14 小时前
k8s之Ingress服务接入控制器
云原生·容器·kubernetes
学Linux的语莫19 小时前
k8s的nodeport和ingress
网络·rpc·kubernetes
aashuii1 天前
k8s通过NUMA亲和分配GPU和VF接口
云原生·容器·kubernetes
Most661 天前
kubesphere安装使用
kubernetes
Kentos(acoustic ver.)1 天前
云原生 —— K8s 容器编排系统
云原生·容器·kubernetes·云计算·k8s
哈里谢顿2 天前
Kubernetes 简介
kubernetes
__Smile°2 天前
k8s-MongoDB 副本集部署
云原生·容器·kubernetes
Jy_06222 天前
k8s 中的 deployment,statefulset,daemonset 控制器的区别
云原生·容器·kubernetes
超龄超能程序猿2 天前
图片查重从设计到实现(2)Milvus安装准备etcd介绍、应用场景及Docker安装配置
docker·etcd·milvus
果子⌂2 天前
Kubernetes 服务发布进阶
linux·运维·服务器·云原生·容器·kubernetes·云计算