使用 kubeadm 创建高可用集群
此页面介绍了使用 kubeadm 设置高可用 Kubernetes 集群的两种不同方法
- 使用堆叠的控制平面节点。这种方法需要更少的基础设施。etcd 成员和控制平面节点位于同一位置。
- 使用外部 etcd 集群。这种方法需要更多的基础设施。控制平面节点和 etcd 成员是分开的。
在继续之前,您应该仔细考虑哪种方法最能满足您的应用程序和环境的需求。高可用拓扑的选项概述了每种方法的优点和缺点。
如果您在设置高可用集群时遇到问题,请在 kubeadm 问题跟踪器中报告这些问题。
另请参阅升级文档。
注意
此页面不涉及在云提供商上运行集群。在云环境中,这里记录的任何一种方法都无法与类型为 LoadBalancer 的 Service 对象或动态 PersistentVolumes 一起使用。开始之前
先决条件取决于您为集群控制平面选择的拓扑
你需要
- 三台或更多满足 kubeadm 最低要求的机器,用于控制平面节点。在机器或区域发生故障时,使用奇数个控制平面节点有助于领导者选举。
- 包括一个已设置并运行的容器运行时
- 三台或更多满足 kubeadm 最低要求的机器,用于工作节点
- 包括一个已设置并运行的容器运行时
- 集群中所有机器之间的完全网络连接(公共或私有网络)
- 所有机器上使用
sudo
的超级用户权限- 您可以使用其他工具;本指南在示例中使用
sudo
。
- 您可以使用其他工具;本指南在示例中使用
- 从一台设备到系统中所有节点的 SSH 访问
- 所有机器上已安装
kubeadm
和kubelet
。
有关上下文,请参阅堆叠的 etcd 拓扑。
你需要
- 三台或更多满足 kubeadm 最低要求的机器,用于控制平面节点。在机器或区域发生故障时,使用奇数个控制平面节点有助于领导者选举。
- 包括一个已设置并运行的容器运行时
- 三台或更多满足 kubeadm 最低要求的机器,用于工作节点
- 包括一个已设置并运行的容器运行时
- 集群中所有机器之间的完全网络连接(公共或私有网络)
- 所有机器上使用
sudo
的超级用户权限- 您可以使用其他工具;本指南在示例中使用
sudo
。
- 您可以使用其他工具;本指南在示例中使用
- 从一台设备到系统中所有节点的 SSH 访问
- 所有机器上已安装
kubeadm
和kubelet
。
您还需要
- 三台或更多额外的机器,它们将成为 etcd 集群成员。在 etcd 集群中拥有奇数个成员是实现最佳投票仲裁的要求。
- 这些机器还需要安装
kubeadm
和kubelet
。 - 这些机器还需要一个已经设置并运行的容器运行时。
- 这些机器还需要安装
有关上下文,请参阅外部 etcd 拓扑。
容器镜像
每个主机都应该有权从 Kubernetes 容器镜像仓库 registry.k8s.io
读取和获取镜像。如果您想部署一个主机无法访问拉取镜像的高可用集群,这是可能的。您必须通过其他方式确保相关主机上已经提供了正确的容器镜像。
命令行界面
要在集群设置完成后管理 Kubernetes,您应该在 PC 上安装 kubectl。在每个控制平面节点上安装 kubectl
工具也很有用,因为这有助于进行故障排除。
两种方法的第一步
为 kube-apiserver 创建负载均衡器
注意
负载均衡器有很多配置。以下示例只是其中一种选择。您的集群要求可能需要不同的配置。创建一个名称解析为 DNS 的 kube-apiserver 负载均衡器。
在云环境中,您应该将控制平面节点置于 TCP 转发负载均衡器之后。此负载均衡器将流量分配到其目标列表中的所有健康控制平面节点。apiserver 的运行状况检查是对 kube-apiserver 侦听的端口进行的 TCP 检查(默认值为
:6443
)。不建议在云环境中直接使用 IP 地址。
负载均衡器必须能够通过 apiserver 端口与所有控制平面节点通信。它还必须允许在其侦听端口上接收传入流量。
确保负载均衡器的地址始终与 kubeadm 的
ControlPlaneEndpoint
地址匹配。有关更多详细信息,请阅读软件负载均衡的选项指南。
将第一个控制平面节点添加到负载均衡器,并测试连接
nc -v <LOAD_BALANCER_IP> <PORT>
由于 API 服务器尚未运行,因此会收到连接被拒绝的错误。但是,超时意味着负载均衡器无法与控制平面节点通信。如果发生超时,请重新配置负载均衡器以与控制平面节点通信。
将剩余的控制平面节点添加到负载均衡器目标组。
堆叠的控制平面和 etcd 节点
第一个控制平面节点的步骤
初始化控制平面
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 配置,您必须在适当的配置位置(在InitConfiguration
和JoinConfiguration: controlPlane
下)添加certificateKey
字段。注意
某些 CNI 网络插件需要额外的配置,例如指定 Pod IP CIDR,而其他插件则不需要。请参阅 CNI 网络文档。要添加 Pod CIDR,请传递--pod-network-cidr
标志,或者如果您正在使用 kubeadm 配置文件,请设置ClusterConfiguration
的networking
对象下的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-certs
与kubeadm 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 和解密密钥在两个小时后过期。注意
正如命令输出中所述,证书密钥可以访问集群敏感数据,请务必保密!应用您选择的 CNI 插件:按照这些说明安装 CNI 提供程序。请确保配置与 kubeadm 配置文件中指定的 Pod CIDR 相对应(如果适用)。
注意
您必须选择一个适合您用例的网络插件,并在继续下一步之前部署它。如果您不这样做,您将无法正确启动集群。输入以下命令,并观察控制平面组件的 Pod 启动:
kubectl get pod -n kube-system -w
其余控制平面节点的步骤:
对于每个额外的控制平面节点,您应该:
执行之前由第一个节点上的
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 集群
按照这些说明设置 etcd 集群。
如此处所述设置 SSH。
将集群中任何 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
。
- 将
设置第一个控制平面节点
创建一个名为
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 拓扑的情况下,这是自动管理的。使用适合您的集群的值替换配置模板中的以下变量:
LOAD_BALANCER_DNS
LOAD_BALANCER_PORT
ETCD_0_IP
ETCD_1_IP
ETCD_2_IP
以下步骤与堆叠 etcd 设置类似:
在此节点上运行
sudo kubeadm init --config kubeadm-config.yaml --upload-certs
。将返回的 join 命令输出写入文本文件以供稍后使用。
应用您选择的 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
,则意味着您必须手动将证书从主控制平面节点复制到要加入的控制平面节点。
有很多方法可以做到这一点。以下示例使用 ssh
和 scp
。
如果您想从一台机器控制所有节点,则需要 SSH。
在可以访问系统中所有其他节点的主设备上启用 ssh-agent:
eval $(ssh-agent)
将您的 SSH 身份添加到会话中:
ssh-add ~/.ssh/path_to_private_key
在节点之间进行 SSH 连接以检查连接是否正常工作。
当您 SSH 到任何节点时,添加
-A
标志。此标志允许您通过 SSH 登录的节点访问您 PC 上的 SSH 代理。如果您不完全信任节点上的用户会话的安全性,请考虑其他方法。ssh -A 10.0.0.7
在任何节点上使用 sudo 时,请确保保留环境,以便 SSH 转发正常工作。
sudo -E -s
在所有节点上配置 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,可能会导致创建其他节点失败。然后在每个要加入的控制平面节点上,您必须在运行
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