使用 kubeadm 创建高可用集群

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

  • 使用堆叠的控制平面节点。这种方法需要更少的基础设施。etcd 成员和控制平面节点位于同一位置。
  • 使用外部 etcd 集群。这种方法需要更多的基础设施。控制平面节点和 etcd 成员是分开的。

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

如果您在设置高可用集群时遇到问题,请在 kubeadm 问题跟踪器中报告这些问题。

另请参阅升级文档

开始之前

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

你需要

  • 三台或更多满足 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 转发负载均衡器之后。此负载均衡器将流量分配到其目标列表中的所有健康控制平面节点。apiserver 的运行状况检查是对 kube-apiserver 侦听的端口进行的 TCP 检查(默认值为 :6443)。

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

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

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

    • 有关更多详细信息,请阅读软件负载均衡的选项指南。

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

    nc -v <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 标志用于将应在所有控制平面实例之间共享的证书上传到集群。如果相反,您更喜欢手动或使用自动化工具跨控制平面节点复制证书,请删除此标志并参阅下面的手动证书分发部分。

    输出看起来类似于:

    ...
    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 密钥。

  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 下载控制平面证书,并使用给定的密钥进行解密。

您可以并行加入多个控制平面节点。

外部 etcd 节点

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

设置 etcd 集群

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

  2. 此处所述设置 SSH。

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

    export CONTROL_PLANE="[email protected]"
    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
    
    • 使用适合您的集群的值替换配置模板中的以下变量:

      • 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

手动证书分发

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

有很多方法可以做到这一点。以下示例使用 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
    
  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
    
上次修改时间:2024 年 10 月 16 日,上午 9:28 PST: 调整并清理四个 kubeadm 文件 (67c5917e32)