为 Kubernetes 操作 etcd 集群

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

如果您的 Kubernetes 集群使用 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 服务器。

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

多节点 etcd 集群

为了持久性和高可用性,在生产环境中将 etcd 作为多节点集群运行,并定期对其进行备份。建议在生产环境中使用五个节点的集群。有关更多信息,请参阅常见问题解答文档

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

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

例如,考虑一个包含五个节点的 etcd 集群,使用以下客户端 URL 运行:http://$IP1:2379http://$IP2:2379http://$IP3:2379http://$IP4:2379http://$IP5:2379。要启动 Kubernetes API 服务器

  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 服务器。

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

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

要运行负载均衡的 etcd 集群

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

保护 etcd 集群

访问 etcd 等同于集群中的 root 权限,因此理想情况下,只有 API 服务器应该可以访问它。考虑到数据的敏感性,建议只授予那些需要访问 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-file=k8sclient.key--cert-file=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 服务器。

例如,考虑由 CAetcd.ca信任的密钥对k8sclient.keyk8sclient.cert。当 etcd 与 TLS 以及--client-cert-auth一起配置时,它会使用系统 CA 或由--trusted-ca-file标志传递的 CA 来验证来自客户端的证书。指定标志--client-cert-auth=true--trusted-ca-file=etcd.ca将访问权限限制为使用证书k8sclient.cert的客户端。

etcd 配置正确后,只有具有有效证书的客户端才能访问它。要授予 Kubernetes API 服务器访问权限,请使用标志--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 服务器都配置为与所有 etcd 成员进行通信,请从--etcd-servers标志中删除故障成员,然后重新启动每个 Kubernetes API 服务器。
    2. 如果每个 Kubernetes API 服务器都与单个 etcd 成员进行通信,请停止与故障 etcd 通信的 Kubernetes API 服务器。
  3. 停止故障节点上的 etcd 服务器。除了 Kubernetes API 服务器之外,其他客户端也可能导致 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 服务器都配置为与所有 etcd 成员进行通信,请将新添加的成员添加到--etcd-servers标志中,然后重新启动每个 Kubernetes API 服务器。
    2. 如果每个 Kubernetes API 服务器都与单个 etcd 成员进行通信,请启动在步骤 2 中停止的 Kubernetes API 服务器。然后,配置 Kubernetes API 服务器客户端以再次将请求路由到已停止的 Kubernetes API 服务器。这通常可以通过配置负载均衡器来完成。

有关集群重新配置的更多信息,请参阅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-file`、`cert-file` 和 `key-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.yaml` 中 `volumes.hostPath.path` 的 `name: etcd-data` 为 `<data-dir-location>`,然后执行 `kubectl -n kube-system delete pod <name-of-etcd-pod>` 或 `systemctl restart kubelet.service`(或两者)。

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

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

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

升级 etcd 集群

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

维护 etcd 集群

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

集群碎片整理

碎片整理是一个代价高昂的操作,因此应该尽可能少地执行。另一方面,必须确保任何 etcd 成员都不会超过存储配额。Kubernetes 项目建议,在执行碎片整理时,使用诸如 etcd-defrag 之类的工具。

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

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

在提出添加第三方链接的更改之前,您应该阅读 内容指南

上次修改时间:2024 年 7 月 26 日 下午 1:31 PST:指定基于 etcdctl 的恢复的可能 etcd 重启步骤。(#47167) (0e551120a2)