创建 HA 集群的一般步骤:
● 设置负载均衡器。有许多开源选项可用于负载均衡:HAproxy、Envoy 或来自云提供商的类似负载均衡器效果很好。
● 在第一个控制平面节点上运行 kubeadm init
,并进行以下修改:
① 创建 kubeadm 配置文件
② 在配置文件中,将 controlPlaneEndpoint 字段设置为可以访问负载均衡器的位置。
③ 运行 init,带有如下--upload-certs
标志:sudo kubeadm init --config=kubeadm-config.yaml --upload-certs
● kubeadm join –control-plane
在您想要扩展控制平面节点集时随时运行。控制平面和普通节点可以随时以任何顺序加入。
1 创建前检查
① 3 台机器作为控制面节点、3 台机器作为工作节点、3 台机器作为外部 etcd 集群(外部 etcd 拓扑方案)
② 在集群中,确保所有计算机之间存在全网络连接(公网或私网)
③ 在所有机器上具有 sudo
权限
④ 从某台设备通过 ssh
访问系统中所有节点的能力
⑤ 所有机器上已经安装 kubeadm
和 kubelet
,kubectl
是可选的
2 为 kube-apiserver 创建负载均衡器
### 创建高可用的负载均衡器
# 例如 ip 和 port 为 LOAD_BALANCER_IP 和 LOAD_BALANCER_PORT
$kubeadm init --control-plane-endpoint=LOAD_BALANCER_IP:LOAD_BALANCER_PORT
### 逐个添加控制平面节点到负载均衡器并测试连接
nc -v LOAD_BALANCER_IP PORT
3 初始化和添加多个控制平面节点
### 初始化控制平面
$sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_IP:LOAD_BALANCER_PORT" --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
### 逐个添加控制平面
# --control-plane 命令通知 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
$sudo kubeadm join 192.168.0.300:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
$sudo kubeadm join 192.168.0.400:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
4 创建和配置 ectd 集群
堆叠(Stacked) etcd 拓扑方案
每个控制平面节点创建一个本地 etcd
成员(member)。该 etcd
成员只与该节点的 kube-apiserver
、kube-controller-manager
、kube-scheduler
实例通信。
堆叠(stacked) etcd 方案,在控制平面设置负载均衡后,自动管理 etcd 的 external
对象下带有 endpoints
的配置文件。
外部 etcd 拓扑方案
etcd 分布式数据存储集群在独立于控制平面节点的其他节点上运行。每个控制平面节点都运行 kube-apiserver
,kube-scheduler
和 kube-controller-manager
实例。每个 etcd
主机与每个控制平面节点的 kube-apiserver
通信。
① 设置 ectd 集群
● 利用 kubeadm 创建高可用 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}":
#说明:第一台控制平面机的 user@host 替换 CONTROL_PLANE
② 控制平面对接外部 ectd 集群
### 步骤 1:创建 kubeadm-config.yaml
$vi kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: stable
controlPlaneEndpoint: "LOAD_BALANCER_IP:LOAD_BALANCER_PORT"
etcd:
external:
endpoints:
- https://ETCD_0_IP:2379
- https://ETCD_1_IP:2379
- https://ETCD_2_IP:2379
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_IP、LOAD_BALANCER_PORT、ETCD_0_IP、ETCD_1_IP、ETCD_2_IP
### 步骤 2:使得 kubeadm 命令生效
$sudo kubeadm init --config kubeadm-config.yaml --upload-certs
#说明:记下输出的 join 命令,然后根据 3 个控制平面的 ip 逐个对接 etcd 集群
注意:外部 etcd 拓扑方案类似堆叠 etcd 拓扑方案,不同点是需要首先设置 etcd,并在 kubeadm 配置文件中传递 etcd 信息。如上所示,堆叠(stacked) etcd 和外部 etcd 之前的区别在于设置外部 etcd 需要一个
etcd
的external
对象下带有 etcd 端点的配置文件。如果是堆叠 etcd,则自动管理的。
5 利用 kubeadm 创建高可用 etcd 集群
前提条件
① 3 个可以通过 2379 和 2380 端口相互通信的主机
② 已经安装 kubernetes 集群,即每台主机有可以运行 Pod、执行命令 kubeadm、kubelet
③ 每台主机有复制文件的工具。例如ssh
、scp
5.1 将 kubelet 配置为 etcd 的服务管理器
$cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
[Service]
ExecStart=
# 将下面的 "systemd" 替换为你的容器运行时所使用的 cgroup 驱动。
# kubelet 的默认值为 "cgroupfs"。
ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd
Restart=always
EOF
$systemctl daemon-reload
$systemctl restart kubelet
# 检查 kubelet 的状态以确保其处于运行状态
$systemctl status kubelet
5.2 创建 kubeadm 配置文件
# 使用 IP 或可解析的主机名替换 HOST0、HOST1 和 HOST2
export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8
# 创建临时目录来存储将被分发到其它主机上的文件
mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/
ETCDHOSTS=(${HOST0} ${HOST1} ${HOST2})
NAMES=("infra0" "infra1" "infra2")
for i in "${!ETCDHOSTS[@]}"; do
HOST=${ETCDHOSTS[$i]}
NAME=${NAMES[$i]}
cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
apiVersion: "kubeadm.k8s.io/v1beta3"
kind: ClusterConfiguration
etcd:
local:
serverCertSANs:
- "${HOST}"
peerCertSANs:
- "${HOST}"
extraArgs:
initial-cluster: infra0=https://${ETCDHOSTS[0]}:2380,infra1=https://${ETCDHOSTS[1]}:2380,infra2=https://${ETCDHOSTS[2]}:2380
initial-cluster-state: new
name: ${NAME}
listen-peer-urls: https://${HOST}:2380
listen-client-urls: https://${HOST}:2379
advertise-client-urls: https://${HOST}:2379
initial-advertise-peer-urls: https://${HOST}:2380
EOF
done
5.3 证书配置
参考 kubeadm init 命令
### 创建/复制证书到目录 /etc/kubernetes/pki/etcd/ca.crt /etc/kubernetes/pki/etcd/ca.key
$cd /etc/kubernetes/pki/etcd
$kubeadm init phase certs etcd-ca
### 为成员创建证书
$kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml
$kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml
$kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
$kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
$cp -R /etc/kubernetes/pki /tmp/${HOST2}/
# 清理不可重复使用的证书
$find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
$kubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml
$kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml
$kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
$kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
$cp -R /etc/kubernetes/pki /tmp/${HOST1}/
$find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
$kubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml
$kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml
$kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
$kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
# 不需要移动 certs 因为它们是给 HOST0 使用的
# 清理不应从此主机复制的证书
$find /tmp/${HOST2} -name ca.key -type f -delete
$find /tmp/${HOST1} -name ca.key -type f -delete
5.4 复制证书和 kubeadm 配置到 3 个 etcd 节点
USER=ubuntu
HOST=${HOST1}
scp -r /tmp/${HOST}/* ${USER}@${HOST}:
ssh ${USER}@${HOST}
USER@HOST $ sudo -Es
root@HOST $ chown -R root:root pki
root@HOST $ mv pki /etc/kubernetes/
### 查看预期文件都存在
# 节点 $HOST0 所需文件的完整列表
/tmp/${HOST0}
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── ca.key
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
# 同理节点 $HOST1、$HOST2
5.5 指定配置创建 etcd pod
# 在对应的节点上,使用从配置文件 kubeadmcfg.yaml 读取的选项为 etcd 生成静态 Pod 清单文件
root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml
root@HOST1 $ kubeadm init phase etcd local --config=/tmp/${HOST1}/kubeadmcfg.yaml
root@HOST2 $ kubeadm init phase etcd local --config=/tmp/${HOST2}/kubeadmcfg.yaml
5.6 检查 etcd 集群状态
### 查询 etcd 镜像版本 ETCD_TAG
$kubeadm config images list
k8s.gcr.io/kube-apiserver:v1.20.0
k8s.gcr.io/kube-controller-manager:v1.20.0
k8s.gcr.io/kube-scheduler:v1.20.0
k8s.gcr.io/kube-proxy:v1.20.0
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.13-0
k8s.gcr.io/coredns:1.7.0
### 运行 etcd 容器
$docker run --rm -it \
--net host \
-v /etc/kubernetes:/etc/kubernetes k8s.gcr.io/etcd:${ETCD_TAG} etcdctl \
--cert /etc/kubernetes/pki/etcd/peer.crt \
--key /etc/kubernetes/pki/etcd/peer.key \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--endpoints https://${HOST0}:2379 endpoint health --cluster
...
https://[HOST0 IP]:2379 is healthy: successfully committed proposal: took = 16.283339ms
https://[HOST1 IP]:2379 is healthy: successfully committed proposal: took = 19.44402ms
https://[HOST2 IP]:2379 is healthy: successfully committed proposal: took = 35.926451ms