使用 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
之類的工具直接透過容器執行階段執行此操作,而不是透過 KubernetesETCDCTL_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 方法設定高可用性控制平面。