使用 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` 可以滿足此要求。

設定叢集

通常的方法是在一個節點上生成所有證書,然後只將**必要**的檔案分發到其他節點。

  1. 配置 kubelet 作為 etcd 的服務管理器。

    由於 etcd 是首先建立的,你必須透過建立一個新的單元檔案來覆蓋服務優先順序,該單元檔案具有比 kubeadm 提供的 kubelet 單元檔案更高的優先順序。

    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
    
  2. 為 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
    
  3. 生成證書頒發機構。

    如果你已經有 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
  4. 為每個成員建立證書。

    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
    
  5. 複製證書和 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/
    
  6. 確保所有預期檔案都存在。

    `$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
    
  7. 建立靜態 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
    
  8. 可選:檢查叢集健康狀況。

    如果 `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 方法設定高可用控制平面。

上次修改時間:太平洋標準時間 2024 年 10 月 2 日凌晨 12:45:在“使用 kubeadm 設定高可用 etcd 叢集”頁面上移除已棄用的註釋 (#48120) (40419a5ef5)