使用 kubeadm 创建高可用性集群

本页介绍了使用 kubeadm 设置高可用 Kubernetes 集群的两种不同方法

  • 堆叠式控制平面节点。此方法所需基础设施较少。etcd 成员和控制平面节点共置。
  • 外部 etcd 集群。此方法需要更多基础设施。控制平面节点和 etcd 成员是分离的。

在继续之前,您应该仔细考虑哪种方法最能满足您的应用和环境需求。高可用拓扑选项 概述了每种方法的优缺点。

如果您在设置 HA 集群时遇到问题,请在 kubeadm 问题追踪器 中报告。

另请参阅 升级文档

注意

本页不涉及如何在云服务提供商上运行您的集群。在云环境中,此处记录的两种方法均不适用于 LoadBalancer 类型的 Service 对象或动态 PersistentVolumes。

开始之前

前提条件取决于您为集群控制平面选择的拓扑

您需要

  • 三台或更多符合 kubeadm 最小要求 的控制平面节点机器。拥有奇数个控制平面节点有助于在机器或区域故障时进行领导者选举。
  • 三台或更多符合 kubeadm 最小要求 的工作节点机器
    • 包括已安装并能正常工作的容器运行时
  • 集群中所有机器之间的完全网络连通性(公网或私网)
  • 所有机器上使用 sudo 的超级用户权限
    • 您可以使用不同的工具;本指南在示例中使用 sudo
  • 从一台设备到系统中所有节点的 SSH 访问权限
  • 所有机器上已安装 kubeadmkubelet

请参阅 堆叠式 etcd 拓扑 了解背景。

您需要

  • 三台或更多符合 kubeadm 最小要求 的控制平面节点机器。拥有奇数个控制平面节点有助于在机器或区域故障时进行领导者选举。
  • 三台或更多符合 kubeadm 最小要求 的工作节点机器
    • 包括已安装并能正常工作的容器运行时
  • 集群中所有机器之间的完全网络连通性(公网或私网)
  • 所有机器上使用 sudo 的超级用户权限
    • 您可以使用不同的工具;本指南在示例中使用 sudo
  • 从一台设备到系统中所有节点的 SSH 访问权限
  • 所有机器上已安装 kubeadmkubelet

您还需要

  • 三台或更多额外的机器,它们将成为 etcd 集群成员。在 etcd 集群中拥有奇数个成员是实现最佳投票法定人数的要求。
    • 这些机器同样需要安装 kubeadmkubelet
    • 这些机器还需要一个已安装并能正常工作的容器运行时。

请参阅 外部 etcd 拓扑 了解背景。

容器镜像

每个主机都应能够读取并从 Kubernetes 容器镜像仓库 registry.k8s.io 拉取镜像。如果您想部署一个高可用的集群,而这些主机无法拉取镜像,这也是可能的。您必须通过其他方式确保相关的容器镜像已在相关主机上就绪。

命令行界面

集群设置完成后,为了管理 Kubernetes,您应该在您的 PC 上 安装 kubectl。在每个控制平面节点上安装 kubectl 工具也很有用,因为它有助于故障排查。

两种方法的初始步骤

为 kube-apiserver 创建负载均衡器

说明

负载均衡器有许多配置方式。以下示例仅为一个选项。您的集群需求可能需要不同的配置。
  1. 创建一个名称可解析为 DNS 的 kube-apiserver 负载均衡器。

    • 在云环境中,您应该将控制平面节点放在 TCP 转发负载均衡器后面。此负载均衡器将流量分发到目标列表中的所有健康控制平面节点。API 服务器的健康检查是对 kube-apiserver 监听端口(默认值为 :6443)的 TCP 检查。

    • 不建议在云环境中直接使用 IP 地址。

    • 负载均衡器必须能够通过 API 服务器端口与所有控制平面节点通信。它还必须允许在其监听端口上的传入流量。

    • 确保负载均衡器的地址始终与 kubeadm 的 ControlPlaneEndpoint 地址匹配。

    • 阅读 软件负载均衡选项 指南以了解更多详情。

  2. 将第一个控制平面节点添加到负载均衡器,并测试连接

    nc -zv -w 2 <LOAD_BALANCER_IP> <PORT>
    

    出现连接拒绝错误是预料之中的,因为 API 服务器尚未运行。但是,如果出现超时,则意味着负载均衡器无法与控制平面节点通信。如果发生超时,请重新配置负载均衡器以与控制平面节点通信。

  3. 将剩余的控制平面节点添加到负载均衡器目标组。

堆叠式控制平面和 etcd 节点

第一个控制平面节点的步骤

  1. 初始化控制平面

    sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
    
    • 您可以使用 --kubernetes-version 标志设置要使用的 Kubernetes 版本。建议 kubeadm、kubelet、kubectl 和 Kubernetes 的版本保持一致。

    • --control-plane-endpoint 标志应设置为负载均衡器的地址或 DNS 以及端口。

    • --upload-certs 标志用于将需要跨所有控制平面实例共享的证书上传到集群。如果您更喜欢手动复制证书或使用自动化工具分发,请移除此标志,并参考下文的 手动分发证书 部分。

    说明

    kubeadm init--config--certificate-key 标志不能混用。因此,如果您想使用 kubeadm 配置,则必须在适当的配置位置(在 InitConfigurationJoinConfiguration: controlPlane 下)添加 certificateKey 字段。

    说明

    某些 CNI 网络插件需要额外配置,例如指定 Pod IP CIDR,而其他插件则不需要。请参阅 CNI 网络文档。要添加 Pod CIDR,请传递 --pod-network-cidr 标志,或者如果您使用 kubeadm 配置文件,请在 ClusterConfigurationnetworking 对象下设置 podSubnet 字段。

    输出内容类似于

    ...
    You can now join any number of control-plane node by running the following command on each as a root:
        kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
    
    Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
    As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use kubeadm init phase upload-certs to reload certs afterward.
    
    Then you can join any number of worker nodes by running the following on each as root:
        kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
    
    • 将此输出复制到文本文件中。稍后您将需要它来将控制平面和工作节点加入到集群中。

    • --upload-certskubeadm init 一起使用时,主控制平面的证书会被加密并上传到 kubeadm-certs Secret 中。

    • 要重新上传证书并生成新的解密密钥,请在已加入集群的控制平面节点上使用以下命令

      sudo kubeadm init phase upload-certs --upload-certs
      
    • 您还可以在 init 期间指定自定义 --certificate-key,以后可供 join 使用。要生成此类密钥,您可以使用以下命令

      kubeadm certs certificate-key
      

    证书密钥是一个十六进制编码的 32 字节 AES 密钥。

    说明

    kubeadm-certs Secret 和解密密钥在两小时后过期。

    注意

    正如命令输出中所述,证书密钥可访问集群敏感数据,请妥善保管!
  2. 应用您选择的 CNI 插件:按照这些说明安装 CNI 提供程序。确保配置与 kubeadm 配置文件中指定的 Pod CIDR 相对应(如果适用)。

    说明

    您必须选择适合您用例的网络插件,并在进入下一步之前部署它。如果您不这样做,将无法正确启动集群。
  3. 输入以下内容并观察控制平面组件的 Pod 开始启动

    kubectl get pod -n kube-system -w
    

其余控制平面节点的步骤

对于每个额外的控制平面节点,您应该

  1. 在第一个节点上执行 kubeadm init 输出之前给您的 join 命令。它看起来应该像这样

    sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
    
    • --control-plane 标志告诉 kubeadm join 创建一个新的控制平面。
    • --certificate-key ... 会导致控制平面证书从集群中的 kubeadm-certs Secret 中下载,并使用给定的密钥进行解密。

说明

由于集群节点通常是按顺序初始化的,CoreDNS Pod 很可能全部运行在第一个控制平面节点上。为了提供更高的可用性,请在至少有一个新节点加入后,使用 kubectl -n kube-system rollout restart deployment coredns 重新平衡 CoreDNS Pod。

外部 etcd 节点

使用外部 etcd 节点设置集群的过程与堆叠式 etcd 的过程类似,区别在于您应该先设置 etcd,并且应在 kubeadm 配置文件中传递 etcd 信息。

设置 etcd 集群

  1. 按照这些 说明 设置 etcd 集群。

  2. 此处 所述设置 SSH。

  3. 将以下文件从集群中的任何 etcd 节点复制到第一个控制平面节点

    export CONTROL_PLANE="ubuntu@10.0.0.7"
    scp /etc/kubernetes/pki/etcd/ca.crt "${CONTROL_PLANE}":
    scp /etc/kubernetes/pki/apiserver-etcd-client.crt "${CONTROL_PLANE}":
    scp /etc/kubernetes/pki/apiserver-etcd-client.key "${CONTROL_PLANE}":
    
    • CONTROL_PLANE 的值替换为第一个控制平面节点的 user@host

设置第一个控制平面节点

  1. 创建一个名为 kubeadm-config.yaml 的文件,其内容如下

    ---
    apiVersion: kubeadm.k8s.io/v1beta4
    kind: ClusterConfiguration
    kubernetesVersion: stable
    controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" # change this (see below)
    etcd:
      external:
        endpoints:
          - https://ETCD_0_IP:2379 # change ETCD_0_IP appropriately
          - https://ETCD_1_IP:2379 # change ETCD_1_IP appropriately
          - https://ETCD_2_IP:2379 # change ETCD_2_IP appropriately
        caFile: /etc/kubernetes/pki/etcd/ca.crt
        certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt
        keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
    

    说明

    此处堆叠式 etcd 和外部 etcd 的区别在于,外部 etcd 设置需要一个在 etcd 下的 external 对象中包含 etcd 端点的配置文件。在堆叠式 etcd 拓扑的情况下,这是自动管理的。
    • 将配置模板中的以下变量替换为您集群的适当值

      • LOAD_BALANCER_DNS
      • LOAD_BALANCER_PORT
      • ETCD_0_IP
      • ETCD_1_IP
      • ETCD_2_IP

以下步骤与堆叠式 etcd 设置类似

  1. 在此节点上运行 sudo kubeadm init --config kubeadm-config.yaml --upload-certs

  2. 将返回的 join 命令写入文本文件以备后用。

  3. 应用您选择的 CNI 插件。

    说明

    您必须选择适合您用例的网络插件,并在进入下一步之前部署它。如果您不这样做,将无法正确启动集群。

其余控制平面节点的步骤

步骤与堆叠式 etcd 设置相同

  • 确保第一个控制平面节点已完全初始化。
  • 使用您保存到文本文件中的 join 命令加入每个控制平面节点。建议一次加入一个控制平面节点。
  • 别忘了 --certificate-key 的解密密钥默认在两小时后过期。

引导控制平面后的常见任务

安装工作节点

工作节点可以使用您之前存储的 kubeadm init 命令的输出结果加入集群

sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866

手动分发证书

如果您选择不在 kubeadm init 中使用 --upload-certs 标志,这意味着您必须手动将证书从主控制平面节点复制到加入的控制平面节点。

有多种方法可以做到这一点。以下示例使用 sshscp

如果您想从一台机器控制所有节点,则需要 SSH。

  1. 在具有对系统中所有其他节点访问权限的主设备上启用 ssh-agent

    eval $(ssh-agent)
    
  2. 将您的 SSH 身份添加到会话中

    ssh-add ~/.ssh/path_to_private_key
    
  3. 在节点之间使用 SSH 以检查连接是否工作正常。

    • 通过 SSH 连接到任何节点时,请添加 -A 标志。此标志允许您通过 SSH 登录的节点访问您 PC 上的 SSH 代理。如果您不完全信任节点上用户会话的安全性,请考虑其他方法。

      ssh -A 10.0.0.7
      
    • 在任何节点上使用 sudo 时,请确保保留环境变量,以便 SSH 转发正常工作

      sudo -E -s
      
  4. 在所有节点上配置 SSH 后,您应该在运行 kubeadm init 后在第一个控制平面节点上运行以下脚本。此脚本将把证书从第一个控制平面节点复制到其他控制平面节点

    在以下示例中,将 CONTROL_PLANE_IPS 替换为其他控制平面节点的 IP 地址。

    USER=ubuntu # customizable
    CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8"
    for host in ${CONTROL_PLANE_IPS}; do
        scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
        scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
        scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
        scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
        scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
        scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
        scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
        # Skip the next line if you are using external etcd
        scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
    done
    

    注意

    仅复制上述列表中的证书。kubeadm 会负责为加入的控制平面实例生成带有所需 SAN 的其余证书。如果您误复制了所有证书,由于缺乏所需的 SAN,添加节点的创建可能会失败。
  5. 然后,在运行 kubeadm join 之前,您必须在每个加入的控制平面节点上运行以下脚本。此脚本将把之前复制的证书从主目录移动到 /etc/kubernetes/pki

    USER=ubuntu # customizable
    mkdir -p /etc/kubernetes/pki/etcd
    mv /home/${USER}/ca.crt /etc/kubernetes/pki/
    mv /home/${USER}/ca.key /etc/kubernetes/pki/
    mv /home/${USER}/sa.pub /etc/kubernetes/pki/
    mv /home/${USER}/sa.key /etc/kubernetes/pki/
    mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
    mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/
    mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
    # Skip the next line if you are using external etcd
    mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
    

最后修改于 2025 年 8 月 31 日太平洋标准时间下午 6:55:移除并行加入说明 (abf3d4dfb3)