使用 kubeadm 设置高可用 etcd 集群
注意
虽然在本指南中 kubeadm 被用作外部 etcd 节点的管理工具,但请注意,kubeadm 不打算支持此类节点的证书轮换或升级。长期计划是赋予工具 etcdadm 管理这些方面的能力。默认情况下,kubeadm 在每个控制平面节点上运行本地 etcd 实例。也可以将 etcd 集群视为外部集群,并在单独的主机上配置 etcd 实例。两种方法的区别在 高可用性拓扑选项 页面中介绍。
此任务将逐步介绍创建由 kubeadm 在集群创建期间使用的三个成员的高可用性外部 etcd 集群的过程。
开始之前
- 三个主机,可以通过 TCP 端口 2379 和 2380 互相通信。本文档假设使用这些默认端口。但是,它们可以通过 kubeadm 配置文件进行配置。
- 每个主机必须安装 systemd 和一个与 bash 兼容的 shell。
- 每个主机必须 安装容器运行时、kubelet 和 kubeadm。
- 每个主机应该可以访问 Kubernetes 容器镜像仓库 (
registry.k8s.io
) 或使用kubeadm config images list/pull
列出/拉取所需的 etcd 镜像。本指南将设置 etcd 实例作为由 kubelet 管理的 静态 Pod。 - 一些基础设施可以在主机之间复制文件。例如,
ssh
和scp
可以满足此要求。
设置集群
一般方法是在一个节点上生成所有证书,并将仅必需的文件分发到其他节点。
注意
kubeadm 包含生成下面描述的证书所需的所有加密机制;此示例不需要其他加密工具。注意
下面的示例使用 IPv4 地址,但您也可以配置 kubeadm、kubelet 和 etcd 以使用 IPv6 地址。双栈受某些 Kubernetes 选项支持,但不受 etcd 支持。有关 Kubernetes 双栈支持的更多详细信息,请参阅 使用 kubeadm 的双栈支持。配置 kubelet 作为 etcd 的服务管理器。
由于 etcd 是先创建的,因此您必须通过创建一个优先级高于 kubeadm 提供的 kubelet 单位文件的新单位文件来覆盖服务优先级。注意
您必须在每个应运行 etcd 的主机上执行此操作。cat << EOF > /etc/systemd/system/kubelet.service.d/kubelet.conf # Replace "systemd" with the cgroup driver of your container runtime. The default value in the kubelet is "cgroupfs". # Replace the value of "containerRuntimeEndpoint" for a different container runtime if needed. # apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration authentication: anonymous: enabled: false webhook: enabled: false authorization: mode: AlwaysAllow cgroupDriver: systemd address: 127.0.0.1 containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock staticPodPath: /etc/kubernetes/manifests EOF cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf [Service] ExecStart= ExecStart=/usr/bin/kubelet --config=/etc/systemd/system/kubelet.service.d/kubelet.conf Restart=always EOF systemctl daemon-reload systemctl restart kubelet
检查 kubelet 状态以确保它正在运行。
systemctl status kubelet
创建 kubeadm 的配置文件。
使用以下脚本为将在其上运行 etcd 成员的每个主机生成一个 kubeadm 配置文件。
# Update HOST0, HOST1 and HOST2 with the IPs of your hosts export HOST0=10.0.0.6 export HOST1=10.0.0.7 export HOST2=10.0.0.8 # Update NAME0, NAME1 and NAME2 with the hostnames of your hosts export NAME0="infra0" export NAME1="infra1" export NAME2="infra2" # Create temp directories to store files that will end up on other hosts mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/ HOSTS=(${HOST0} ${HOST1} ${HOST2}) NAMES=(${NAME0} ${NAME1} ${NAME2}) for i in "${!HOSTS[@]}"; do HOST=${HOSTS[$i]} NAME=${NAMES[$i]} cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml --- apiVersion: "kubeadm.k8s.io/v1beta4" kind: InitConfiguration nodeRegistration: name: ${NAME} localAPIEndpoint: advertiseAddress: ${HOST} --- apiVersion: "kubeadm.k8s.io/v1beta4" kind: ClusterConfiguration etcd: local: serverCertSANs: - "${HOST}" peerCertSANs: - "${HOST}" extraArgs: initial-cluster: ${NAMES[0]}=https://${HOSTS[0]}:2380,${NAMES[1]}=https://${HOSTS[1]}:2380,${NAMES[2]}=https://${HOSTS[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
生成证书颁发机构。
如果您已经拥有 CA,那么唯一的操作是将 CA 的
crt
和key
文件复制到/etc/kubernetes/pki/etcd/ca.crt
和/etc/kubernetes/pki/etcd/ca.key
。复制完这些文件后,继续执行下一步,“为每个成员创建证书”。如果您还没有 CA,请在
$HOST0
(您在其中生成 kubeadm 配置文件的地方)上运行此命令。kubeadm init phase certs etcd-ca
这将创建两个文件
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
为每个成员创建证书。
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}/ # cleanup non-reusable certificates 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 # No need to move the certs because they are for HOST0 # clean up certs that should not be copied off this host find /tmp/${HOST2} -name ca.key -type f -delete find /tmp/${HOST1} -name ca.key -type f -delete
复制证书和 kubeadm 配置。
证书已生成,现在必须将其移至各自的主机。
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
上$HOME └── kubeadmcfg.yaml --- /etc/kubernetes/pki ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key └── etcd ├── ca.crt ├── healthcheck-client.crt ├── healthcheck-client.key ├── peer.crt ├── peer.key ├── server.crt └── server.key
在
$HOST2
上$HOME └── kubeadmcfg.yaml --- /etc/kubernetes/pki ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key └── etcd ├── ca.crt ├── healthcheck-client.crt ├── healthcheck-client.key ├── peer.crt ├── peer.key ├── server.crt └── server.key
创建静态 Pod 清单。
现在证书和配置已到位,现在是时候创建清单了。在每个主机上运行
kubeadm
命令以生成 etcd 的静态清单。root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml root@HOST1 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml root@HOST2 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml
可选:检查集群运行状况。
如果
etcdctl
不可用,您可以在容器镜像中运行此工具。您将使用crictl run
等工具直接通过容器运行时执行此操作,而不是通过 Kubernetes。ETCDCTL_API=3 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 ... 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
- 将
${HOST0}
设置为您正在测试的主机的 IP 地址。
- 将
下一步
拥有一个包含 3 个工作成员的 etcd 集群后,您可以继续使用 使用 kubeadm 的外部 etcd 方法 设置高可用性控制平面。