使用 kubeadm 設定高可用 etcd 叢集
預設情況下,kubeadm 在每個控制平面節點上執行一個本地 etcd 例項。也可以將 etcd 叢集視為外部叢集,並在獨立的宿主機上提供 etcd 例項。這兩種方法之間的差異在高可用拓撲選項頁面有介紹。
此任務將引導你完成建立一個包含三個成員的高可用外部 etcd 叢集的過程,該叢集可供 kubeadm 在叢集建立期間使用。
準備工作
- 三個主機可以透過 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: - name: initial-cluster value: ${NAMES[0]}=https://${HOSTS[0]}:2380,${NAMES[1]}=https://${HOSTS[1]}:2380,${NAMES[2]}=https://${HOSTS[2]}:2380 - name: initial-cluster-state value: new - name: name value: ${NAME} - name: listen-peer-urls value: https://${HOST}:2380 - name: listen-client-urls value: https://${HOST}:2379 - name: advertise-client-urls value: https://${HOST}:2379 - name: initial-advertise-peer-urls value: 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 方法設定高可用控制平面。