【K8s生产环境】使用 kubeadm 引导集群系列 -- 5.利用 kubeadm 创建高可用集群(堆叠 etcd 拓扑)
参考:https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/high-availability/
准备开始
需要以下基础设施:
- 配置满足 kubeadm 的最低要求 的三台机器作为控制面节点
- 配置满足 kubeadm 的最低要求 的三台机器作为工作节点
- 在集群中,确保所有计算机之间存在全网络连接(公网或私网)
- 在所有机器上具有 sudo 权限
- 从某台设备通过 SSH 访问系统中所有节点的能力
- 所有机器上已经安装 kubeadm 和 kubelet,kubectl 是可选的。
为 kube-apiserver 创建负载均衡器
1.创建一个名为 kube-apiserver 的负载均衡器解析 DNS。
-
在云环境中,应该将控制平面节点放置在 TCP 后面转发负载平衡。 该负载均衡器将流量分配给目标列表中所有运行状况良好的控制平面节点。 API 服务器的健康检查是在 kube-apiserver 的监听端口(默认值 :6443) 上进行的一个 TCP 检查。
-
不建议在云环境中直接使用 IP 地址。
-
负载均衡器必须能够在 API 服务器端口上与所有控制平面节点通信。 它还必须允许其监听端口的入站流量。
-
确保负载均衡器的地址始终匹配 kubeadm 的 ControlPlaneEndpoint 地址。
-
阅读软件负载平衡选项指南 以获取更多详细信息。参考:https://github.com/kubernetes/kubeadm/blob/master/docs/ha-considerations.md#options-for-software-load-balancing
2.添加第一个控制平面节点到负载均衡器并测试连接:
nc -v LOAD_BALANCER_IP PORT
- 由于 apiserver 尚未运行,预期会出现一个连接拒绝错误。 然而超时意味着负载均衡器不能和控制平面节点通信。 如果发生超时,请重新配置负载均衡器与控制平面节点进行通信。
3.将其余控制平面节点添加到负载均衡器目标组。
一个 keepalived 和 haproxy 高可用负载均衡配置示例:
## keepalived配置
! /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL
}
vrrp_script check_apiserver {
script "/etc/keepalived/check_apiserver.sh"
interval 3
weight -2
fall 10
rise 2
}
vrrp_instance VI_1 {
state ${STATE}
interface ${INTERFACE}
virtual_router_id ${ROUTER_ID}
priority ${PRIORITY}
authentication {
auth_type PASS
auth_pass ${AUTH_PASS}
}
virtual_ipaddress {
${APISERVER_VIP}
}
track_script {
check_apiserver
}
}
## /etc/keepalived/check_apiserver.sh脚本内容
#!/bin/sh
errorExit() {
echo "*** $*" 1>&2
exit 1
}
curl --silent --max-time 2 --insecure https://localhost:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://localhost:${APISERVER_DEST_PORT}/"
if ip addr | grep -q ${APISERVER_VIP}; then
curl --silent --max-time 2 --insecure https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/"
fi
## haproxy配置
# /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
log /dev/log local0
log /dev/log local1 notice
daemon
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 1
timeout http-request 10s
timeout queue 20s
timeout connect 5s
timeout client 20s
timeout server 20s
timeout http-keep-alive 10s
timeout check 10s
#---------------------------------------------------------------------
# apiserver frontend which proxys to the control plane nodes
#---------------------------------------------------------------------
frontend apiserver
bind *:${APISERVER_DEST_PORT}
mode tcp
option tcplog
default_backend apiserver
#---------------------------------------------------------------------
# round robin balancing for apiserver
#---------------------------------------------------------------------
backend apiserver
option httpchk GET /healthz
http-check expect status 200
mode tcp
option ssl-hello-chk
balance roundrobin
server ${HOST1_ID} ${HOST1_ADDRESS}:${APISERVER_SRC_PORT} check
# [...]
第一个控制平面节点
1.初始化控制平面:
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
- 你可以使用 --kubernetes-version 标志来设置要使用的 Kubernetes 版本。 建议将 kubeadm、kebelet、kubectl 和 Kubernetes 的版本匹配。
- 这个 --control-plane-endpoint 标志应该被设置成负载均衡器的地址或 DNS 和端口。
- 这个 --upload-certs 标志用来将在所有控制平面实例之间的共享证书上传到集群。如果正好相反,你更喜欢手动地通过控制平面节点或者使用自动化 工具复制证书,请删除此标志并参考如下部分证书分配手册:https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/high-availability/#manual-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-certs 与 kubeadm init 一起使用时,主控制平面的证书 被加密并上传到 kubeadm-certs Secret 中。
- 要重新上传证书并生成新的解密密钥,请在已加入集群节点的控制平面上使用以下命令:
sudo kubeadm init phase upload-certs --upload-certs
说明:
kubeadm-certs
密钥和解密密钥会在两个小时后失效。
注意:正如命令输出中所述,证书密钥可访问群集敏感数据。请妥善保管!
2.应用你所选择的 CNI 插件。如果适用,请确保配置与 kubeadm 配置文件中指定的 Pod CIDR 相对应。
3.输入以下内容,并查看控制平面组件的 Pods 启动:
kubectl get pod -n kube-system -w
其余控制平面节点的步骤
说明:从 kubeadm 1.15 版本开始,你可以并行加入多个控制平面节点。 在此版本之前,你必须在第一个节点初始化后才能依序的增加新的控制平面节点。
对于每个其他控制平面节点,你应该:
执行先前由第一个节点上的 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 下载 控制平面证书并使用给定的密钥进行解密。
列举控制平面之后的常见任务
1.安装工作节点
你可以使用之前存储的 kubeadm init 命令的输出将工作节点加入集群中:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866