运行 Kubernetes 集群的 etcd

etcd 是一个一致且高可用的键值存储,用作 Kubernetes 所有集群数据的后端存储。

如果你的 Kubernetes 集群使用 etcd 作为后端存储,请确保你已为数据制定备份计划。

你可以在 etcd 官方文档中找到关于 etcd 的深入信息。

准备工作

在遵循本页面中的步骤来部署、管理、备份或恢复 etcd 之前,你需要了解运维 etcd 集群的典型预期。有关更多背景信息,请参阅 etcd 文档

关键细节包括

  • 建议用于生产环境的最低 etcd 版本是 3.4.22+3.5.6+

  • etcd 是一个基于领导者的分布式系统。确保领导者定期及时地向所有跟随者发送心跳以保持集群稳定。

  • 你应该以奇数成员来运行 etcd 集群。

  • 确保不会发生资源匮乏。

    集群的性能和稳定性对网络和磁盘 I/O 非常敏感。任何资源匮乏都可能导致心跳超时,从而引起集群不稳定。不稳定的 etcd 表明未选出领导者。在这种情况下,集群无法对其当前状态进行任何更改,这意味着无法调度新的 Pod。

etcd 资源需求

在资源有限的环境下运行 etcd 仅适用于测试目的。在生产环境中部署需要高级硬件配置。在生产环境中部署 etcd 之前,请参阅资源需求参考

保持 etcd 集群的稳定对 Kubernetes 集群的稳定至关重要。因此,为了确保资源需求,请在专用机器或隔离环境中运行 etcd 集群。

工具

根据你要实现的具体目标,你可能需要 etcdctl 工具或 etcdutl 工具(或者两者都需要)。

理解 etcdctl 和 etcdutl

etcdctletcdutl 是用于与 etcd 集群交互的命令行工具,但它们用途不同

  • etcdctl: 这是用于通过网络与 etcd 交互的主要命令行客户端。它用于日常操作,例如管理键值、管理集群、检查健康状况等。

  • etcdutl: 这是一个管理工具,旨在直接操作 etcd 数据文件,包括在 etcd 版本之间迁移数据、对数据库进行碎片整理、恢复快照以及验证数据一致性。对于网络操作,应使用 etcdctl

有关 etcdutl 的更多信息,你可以参阅etcd 恢复文档

启动 etcd 集群

本节介绍如何启动单节点和多节点 etcd 集群。

本指南假设 etcd 已安装。

单节点 etcd 集群

仅将单节点 etcd 集群用于测试目的。

  1. 运行以下命令

    etcd --listen-client-urls=http://$PRIVATE_IP:2379 \
       --advertise-client-urls=http://$PRIVATE_IP:2379
    
  2. 使用标志 --etcd-servers=$PRIVATE_IP:2379 启动 Kubernetes API Server。

    确保 PRIVATE_IP 已设置为你的 etcd 客户端 IP。

多节点 etcd 集群

为了持久性和高可用性,请在生产环境中以多节点集群形式运行 etcd 并定期备份。建议在生产环境中运行五成员集群。有关更多信息,请参阅常见问题文档

使用 Kubernetes 时,你可以选择将 etcd 作为容器在单个或多个 Pod 中运行。默认情况下,kubeadm 工具会设置 etcd 静态 Pod,或者你可以部署一个独立的集群,并指示 kubeadm 使用该 etcd 集群作为控制平面的后端存储。

你可以通过静态成员信息或动态发现来配置 etcd 集群。有关集群的更多信息,请参阅etcd 集群文档

举例来说,考虑一个具有以下客户端 URL 的五成员 etcd 集群:http://$IP1:2379http://$IP2:2379http://$IP3:2379http://$IP4:2379http://$IP5:2379。要启动 Kubernetes API Server

  1. 运行以下命令

    etcd --listen-client-urls=http://$IP1:2379,http://$IP2:2379,http://$IP3:2379,http://$IP4:2379,http://$IP5:2379 --advertise-client-urls=http://$IP1:2379,http://$IP2:2379,http://$IP3:2379,http://$IP4:2379,http://$IP5:2379
    
  2. 使用标志 --etcd-servers=$IP1:2379,$IP2:2379,$IP3:2379,$IP4:2379,$IP5:2379 启动 Kubernetes API Server。

    确保 IP<n> 变量设置为你的客户端 IP 地址。

使用负载均衡器的多节点 etcd 集群

要运行负载均衡 etcd 集群

  1. 搭建 etcd 集群。
  2. 在 etcd 集群前配置负载均衡器。例如,将负载均衡器的地址设置为 $LB
  3. 使用标志 --etcd-servers=$LB:2379 启动 Kubernetes API Server。

保护 etcd 集群

访问 etcd 等同于在集群中获得 root 权限,因此理想情况下只有 API Server 应该访问它。考虑到数据的敏感性,建议仅授予需要访问 etcd 集群的节点权限。

要保护 etcd,可以设置防火墙规则或使用 etcd 提供的安全特性。etcd 安全特性依赖于 x509 公钥基础设施 (PKI)。首先,通过生成密钥和证书对来建立安全的通信通道。例如,使用密钥对 peer.keypeer.cert 来保护 etcd 成员之间的通信,使用 client.keyclient.cert 来保护 etcd 与其客户端之间的通信。请参阅 etcd 项目提供的示例脚本,以生成用于客户端身份验证的密钥对和 CA 文件。

保护通信

要使用安全的对等通信配置 etcd,请指定标志 --peer-key-file=peer.key--peer-cert-file=peer.cert,并使用 HTTPS 作为 URL 模式。

类似地,要使用安全的客户端通信配置 etcd,请指定标志 --key=k8sclient.key--cert=k8sclient.cert,并使用 HTTPS 作为 URL 模式。以下是一个使用安全通信的客户端命令示例

ETCDCTL_API=3 etcdctl --endpoints 10.2.0.9:2379 \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  member list

限制 etcd 集群访问

配置安全通信后,使用 TLS 身份验证将 etcd 集群的访问限制为仅允许 Kubernetes API Server。

例如,考虑被 CA etcd.ca 信任的密钥对 k8sclient.keyk8sclient.cert。当 etcd 使用 --client-cert-auth 和 TLS 进行配置时,它会使用系统 CA 或通过 --trusted-ca-file 标志传入的 CA 来验证来自客户端的证书。指定标志 --client-cert-auth=true--trusted-ca-file=etcd.ca 将限制只有持有证书 k8sclient.cert 的客户端才能访问。

正确配置 etcd 后,只有持有有效证书的客户端才能访问它。要授予 Kubernetes API Server 访问权限,请使用标志 --etcd-certfile=k8sclient.cert--etcd-keyfile=k8sclient.key--etcd-cafile=ca.cert 配置它们。

替换失败的 etcd 成员

etcd 集群通过容忍少量成员故障来实现高可用性。但是,为了提高集群的整体健康状况,请立即替换失败的成员。当多个成员失败时,请逐个替换它们。替换失败的成员包括两个步骤:移除失败的成员和添加一个新成员。

尽管 etcd 在内部保留唯一的成员 ID,但建议为每个成员使用唯一的名称以避免人为错误。例如,考虑一个三成员 etcd 集群。假设 URL 为 member1=http://10.0.0.1member2=http://10.0.0.2member3=http://10.0.0.3。当 member1 失败时,将其替换为 member4=http://10.0.0.4

  1. 获取失败的 member1 的成员 ID

    etcdctl --endpoints=http://10.0.0.2,http://10.0.0.3 member list
    

    显示以下消息

    8211f1d0f64f3269, started, member1, http://10.0.0.1:2380, http://10.0.0.1:2379
    91bc3c398fb3c146, started, member2, http://10.0.0.2:2380, http://10.0.0.2:2379
    fd422379fda50e48, started, member3, http://10.0.0.3:2380, http://10.0.0.3:2379
    
  2. 执行以下任一操作

    1. 如果每个 Kubernetes API Server 配置为与所有 etcd 成员通信,则从 --etcd-servers 标志中移除失败的成员,然后重启每个 Kubernetes API Server。
    2. 如果每个 Kubernetes API Server 与单个 etcd 成员通信,则停止与失败 etcd 通信的 Kubernetes API Server。
  3. 在发生故障的节点上停止 etcd 服务。除了 Kubernetes API Server 之外,可能还有其他客户端导致 etcd 流量,停止所有流量以防止写入数据目录是可取的。

  4. 移除失败的成员

    etcdctl member remove 8211f1d0f64f3269
    

    显示以下消息

    Removed member 8211f1d0f64f3269 from cluster
    
  5. 添加新成员

    etcdctl member add member4 --peer-urls=http://10.0.0.4:2380
    

    显示以下消息

    Member 2be1eb8f84b7f63e added to cluster ef37ad9dc622a7c4
    
  6. 在 IP 为 10.0.0.4 的机器上启动新添加的成员

    export ETCD_NAME="member4"
    export ETCD_INITIAL_CLUSTER="member2=http://10.0.0.2:2380,member3=http://10.0.0.3:2380,member4=http://10.0.0.4:2380"
    export ETCD_INITIAL_CLUSTER_STATE=existing
    etcd [flags]
    
  7. 执行以下任一操作

    1. 如果每个 Kubernetes API Server 配置为与所有 etcd 成员通信,则将新添加的成员添加到 --etcd-servers 标志中,然后重启每个 Kubernetes API Server。
    2. 如果每个 Kubernetes API Server 与单个 etcd 成员通信,则启动在步骤 2 中停止的 Kubernetes API Server。然后将 Kubernetes API Server 客户端配置为再次将请求路由到已停止的 Kubernetes API Server。这通常可以通过配置负载均衡器来完成。

有关集群重新配置的更多信息,请参阅etcd 重新配置文档

备份 etcd 集群

所有 Kubernetes 对象都存储在 etcd 中。定期备份 etcd 集群数据对于在灾难场景下(例如丢失所有控制平面节点)恢复 Kubernetes 集群至关重要。快照文件包含所有 Kubernetes 状态和关键信息。为了保证敏感的 Kubernetes 数据安全,请加密快照文件。

备份 etcd 集群可以通过两种方式完成:etcd 内置快照和卷快照。

内置快照

etcd 支持内置快照。快照可以通过 etcdctl snapshot save 命令从运行中的成员创建,也可以通过从未被 etcd 进程使用的 etcd 数据目录复制 member/snap/db 文件来创建。创建快照不会影响成员的性能。

以下是一个示例,演示如何将 $ENDPOINT 服务的键空间创建快照到文件 snapshot.db

ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshot.db

验证快照

以下示例描述了使用 etcdutl 工具验证快照的方法

etcdutl --write-out=table snapshot status snapshot.db 

这将生成类似于下面提供的示例的输出

+----------+----------+------------+------------+
|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| fe01cf57 |       10 |          7 | 2.1 MB     |
+----------+----------+------------+------------+

以下示例描述了使用 etcdctl 工具验证快照的方法

export ETCDCTL_API=3
etcdctl --write-out=table snapshot status snapshot.db

这将生成类似于下面提供的示例的输出

Deprecated: Use `etcdutl snapshot status` instead.

+----------+----------+------------+------------+
|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| fe01cf57 |       10 |          7 | 2.1 MB     |
+----------+----------+------------+------------+

卷快照

如果 etcd 运行在支持备份的存储卷上,例如 Amazon Elastic Block Store,可以通过创建存储卷的快照来备份 etcd 数据。

使用 etcdctl 选项创建快照

我们还可以使用 etcdctl 提供的各种选项来创建快照。例如

ETCDCTL_API=3 etcdctl -h 

将列出 etcdctl 提供的各种选项。例如,你可以通过指定端点、证书和密钥来创建快照,如下所示

ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=<trusted-ca-file> --cert=<cert-file> --key=<key-file> \
  snapshot save <backup-file-location>

其中,trusted-ca-filecert-filekey-file 可以从 etcd Pod 的描述中获取。

扩展 etcd 集群

扩展 etcd 集群通过牺牲性能来提高可用性。扩缩容并不会提升集群性能或能力。通常的规则是不对 etcd 集群进行横向扩缩容。不要为 etcd 集群配置任何自动扩缩容组。对于任何官方支持规模的生产环境 Kubernetes 集群,强烈建议始终运行静态的五成员 etcd 集群。

当需要更高可靠性时,合理的扩缩容是将三成员集群升级到五成员集群。有关如何向现有集群添加成员的信息,请参阅etcd 重新配置文档

恢复 etcd 集群

etcd 支持从 major.minor 版本 etcd 进程拍摄的快照进行恢复。也支持从不同补丁版本的 etcd 恢复。恢复操作用于恢复失败集群的数据。

在开始恢复操作之前,必须存在快照文件。它可以是先前备份操作中的快照文件,也可以是来自剩余的数据目录

使用 etcdutl 恢复集群时,使用 --data-dir 选项指定应将集群恢复到哪个文件夹

etcdutl --data-dir <data-dir-location> snapshot restore snapshot.db

其中 <data-dir-location> 是在恢复过程中将创建的目录。

以下示例描述了使用 etcdctl 工具进行恢复操作的方法

export ETCDCTL_API=3
etcdctl --data-dir <data-dir-location> snapshot restore snapshot.db

如果 <data-dir-location> 与之前是同一个文件夹,请在恢复集群之前删除它并停止 etcd 进程。否则,在恢复后更改 etcd 配置并重启 etcd 进程,使其使用新的数据目录:首先将 /etc/kubernetes/manifests/etcd.yamlname: etcd-datavolumes.hostPath.path 改为 <data-dir-location>,然后执行 kubectl -n kube-system delete pod <name-of-etcd-pod>systemctl restart kubelet.service(或两者都执行)。

有关从快照文件恢复集群的更多信息和示例,请参阅etcd 灾难恢复文档

如果恢复的集群的访问 URL 与之前的集群不同,则必须相应地重新配置 Kubernetes API Server。在这种情况下,请使用标志 --etcd-servers=$NEW_ETCD_CLUSTER 而不是标志 --etcd-servers=$OLD_ETCD_CLUSTER 重启 Kubernetes API Server。将 $NEW_ETCD_CLUSTER$OLD_ETCD_CLUSTER 替换为相应的 IP 地址。如果在 etcd 集群前使用了负载均衡器,则可能需要更新负载均衡器。

如果大多数 etcd 成员永久性地失败,则 etcd 集群被视为失败。在这种情况下,Kubernetes 无法对其当前状态进行任何更改。虽然已调度的 Pod 可能继续运行,但无法调度新的 Pod。在这种情况下,恢复 etcd 集群并可能重新配置 Kubernetes API Server 以解决问题。

升级 etcd 集群

有关 etcd 升级的详细信息,请参阅etcd 升级文档。

维护 etcd 集群

有关 etcd 维护的更多详细信息,请参阅etcd 维护文档。

集群碎片整理

碎片整理是一项开销较大的操作,因此应尽可能少地执行。另一方面,也有必要确保任何 etcd 成员不会超出存储配额。Kubernetes 项目建议你在执行碎片整理时使用诸如 etcd-defrag 之类的工具。

你还可以将碎片整理工具作为 Kubernetes CronJob 运行,以确保碎片整理定期进行。有关详细信息,请参阅etcd-defrag-cronjob.yaml

本页面上的项目引用了提供 Kubernetes 所需功能的第三方产品或项目。Kubernetes 项目作者不对这些第三方产品或项目负责。有关更多详细信息,请参阅 CNCF 网站指南

在提议添加额外第三方链接的更改之前,你应该阅读内容指南

上次修改时间:2025 年 1 月 23 日太平洋标准时间下午 4:39:docs: flags for etcdctl (87ceff5dd5)