目录、参考文献
使用 kubeadm
设置高可用的 Kubernetes 集群的两种不同方式:
- 堆叠的控制平面节点
这种方法需要较少的基础设施,etcd 成员与控制平面节点位于同一个地方 - 外部集群
这种方法需要的基础设施较多,控制平面的节点和 etcd 成员是分开的
注意:
本文的目的不是在云供应商上运行集群
在云环境中,这里的方法不适用于类型为 LoadBalancer 的服务对象
也不适用于具有动态 PersistentVolume 的对象
1. 前提条件
前提条件取决于为集群控制平面选择的拓扑
1.1. 外部 etcd 与堆叠 etcd 的共同前提条件
- 3 台或更多满足
kubeadm
对控制平面节点的最低要求的机器
奇数个控制平面节点有助于在机器故障或出现分区问题时重新选主
- 已安装容器运行时,且已进行配置并处于正常工作状态
- 3 台或更多满足
kubeadm
对工作节点的最低要求的机器
- 已安装容器运行时,且已进行配置并处于正常工作状态
- 集群中的所有机器互相之间都能通过网络进行通信(公有或私有网络)
- 在所有机器上具有 sudo 超级用户权限
- 也可以使用不同的工具,本文以 sudo 举例
- 从某台设备通过 SSH 访问系统中所有节点的能力
- 所有机器上已安装
kubeadm
与kubelet
1.2. 外部 etcd 特有的前提条件
- 3 台或更多额外的机器,用作 etcd 集群成员
为了让分布式一致性算法达到更好的投票效果,集群应该由奇数个节点组成
- 机器上已安装
kubeadm
与kubelet
- 已安装容器运行时,且已进行配置并处于正常工作状态
1.3. 容器镜像
每台主机要能够从 Kubernetes 容器镜像仓库(k8s.gcr.io)拉取镜像
要在无法拉取 Kubernetes 仓库镜像的机器上部署高可用集群
需要事先通过其它方式确保主机上已经有对应的容器镜像
1.4. 命令行接口
集群创建成功后,可以在 PC 上安装 kubectl 用于管理 Kubernetes
为了方便故障排查,也可以在每个控制平面节点上安装 kubectl
2. 第一步(两种拓扑都适用)
2.1. 为 kube-apiserver 创建负载均衡器
注意:
负载均衡器有非常多的配置,下边的例子只是一个选项
实际的集群搭建可能需要不同的配置
2.1.1. 创建一个名称能被 DNS 解析的 kube-apiserver 负载均衡器
- 在云环境中,应该将控制平面节点放在一个 TCP 转发负载均衡器的后边
该负载均衡器将流量分发给其目标列表下的所有健康的控制平面节点
对 API 服务器的健康检查是一个对 kube-apiserver 监听的端口(默认:6443
)的 TCP 检查 - 不推荐在云环境中直接使用 IP 地址
- 负载均衡器必须能与所有控制平面节点上的 API 服务器端口通信
同时,负载均衡器必须允许流量从其监听的端口进入 - 确保负载均衡器的地址始终与
kubeadm
的ControlPlaneEndpoint
地址匹配 - 请阅读软件负载均衡选项了解更详细的信息
2.1.2. 向负载均衡器加入第一个控制平面节点,并测试连接:
nc -v <LOAD_BALANCER_IP> <PORT>
返回拒绝连接的错误是正常的,因为 API 服务器还没有运行
但如果是超时则表示负载均衡器无法连接到控制平面节点
如果发生了超时,则需要重新配置以让负载均衡器能够连接到控制平面节点
2.1.3. 将剩下的控制平面节点加入负载均衡器的目标组
3. 堆叠控制平面与 etcd 节点
3.1. 添加第一个控制平面节点的步骤
3.1.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 配置 必须在正确的位置(InitConfiguration
与JoinConfiguration: controlPlane
下边)
加上certificateKey
字段注意:
一些 CNI 网络插件需要一些额外的配置,如指定 pod IP CIDR,见 CNI 网络文档 要添加一个 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
- 将输出复制到一个文本文件中,之后在向集群添加控制平面节点与工作节点时会用到
- 当
kubeadm init
使用--upload-certs
时
主控制平面的证书被加密并上传到kubeadm-certs
Secret 中 - 要重新上传证书并生成新的解密密钥
请在一个已经加入了集群的控制平面节点上执行以下命令:
sudo kubeadm init phase upload-certs --upload-certs
- 你还可以在
init
期间指定自定义的--certificate-key
,以后join
可以使用
要生成这样的密钥,可以使用以下命令:
kubeadm certs certificate-key
注意:
kubeadm-certs
Secret 与解密密钥会在两小时后过期💡 提醒:
如命令输出中所述,证书密钥可用于访问集群敏感信息,谨防泄露!
3.1.2. 选用一个 CNI 插件
遵循操作指南安装 CNI 驱动
请确保配置与 kubeadm
配置文件中指定的 Pod CIDR 相匹配
注意:
请根据具体使用场景选择一个合适的网络插件
并在进行下一步之前部署好选择的网络插件
如果没有完成这一步,将无法正常启动集群
3.1.3. 输入下边的命令,等待控制平面组件的 pod 启动
kubectl get pod -n kube-system -w
3.2. 添加剩下的控制平面节点的步骤
每添加一个额外的控制平面节点,执行以下步骤:
执行第一个节点的 kubeadm init
命令输出的 kubeadm 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 下载控制平面证书
并用给定的密钥解码
可以并行地加入多个控制平面节点
2. 外部 etcd 节点
让集群采用外部 etcd 节点的设置步骤与堆叠 etcd 类似
不同的是应该先设置 etcd,并在 kubeadm
配置文件中设置 etcd 信息
2.1. 设置 etcd 集群
2.1.1. 按照操作指南设置 etcd 集群
2.1.2. 按照下文手动分发证书的描述设置 SSH
2.1.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
2.2. 设置第一个控制平面节点
2.2.1. 创建一个 kubeadm-config.yaml
文件,内容如下:
---
apiVersion: kubeadm.k8s.io/v1beta3
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
下的external
对象下的 etcd 端点(endpoints
)
在堆叠 etcd 拓扑中,这些是被自动管理的
将下边这些配置模板中的变量替换为实际集群中对应的值:
LOAD_BALANCER_DNS
LOAD_BALANCER_PORT
ETCD_0_IP
ETCD_1_IP
ETCD_2_IP
2.2.2. 下边这些步骤与堆叠 etcd 类似
- 在节点上运行
sudo kubeadm init --config kubeadm-config.yaml --upload-certs
- 记下输出的
join
命令,这些命令将在后边使用 - 应用选择的 CNI 插件
注意:
请根据具体使用场景选择一个合适的网络插件
并在进行下一步之前部署好选择的网络插件
如果没有完成这一步,将无法正常启动集群
2.3. 添加剩下的控制平面节点的步骤
与堆叠 etcd 的设置步骤相同
- 确定第一个控制平面节点已经完全初始化了
- 根据前边报错的
join
命令将每个控制平面节点加入集群
建议一次加入一个节点 - 注意,默认情况下
--certificate-key
中的解密秘钥两小时后过期
3. 启动控制平面之后的常见任务
3.1 安装工作节点
通过之前保存的 kubeadm init
命令输出的命令将工作节点加入集群:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
4. 手动分发证书
如果 kubeadm init
没有使用 --upload-certs
标志
则必须从主控制平面节点手动复制证书到新加入的控制平面节点
有许多方法都可以做到这件事情,下边介绍用 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
后,运行下边的脚步
这个脚步会从第一个控制平面节点复制证书到其它控制平面节点:
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
将 CONTROL_PLANE_IPS
修改为其它控制平面节点的 IP 地址
💡 提醒:
只需要复制上面列出的证书kubeadm
将负责生成其余证书以及加入控制平面实例所需的 SAN
如果错误地复制了所有证书,由于缺少所需的 SAN,在创建其它节点时可能会失败
- 在运行
kubeadm join
之前,在每个加入的控制平面节点上运行下边的脚步
这个脚本将把之前复制的证书从 home 目录移动到/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