備份及還原管理員叢集

本文說明如何備份及還原使用 Google Distributed Cloud (僅限軟體) for VMware 建立的管理員叢集 etcd 儲存區。本文也提供指令碼,可用於自動備份叢集的 etcd 存放區。您也可以使用 gkectl 指令列工具備份及還原管理員叢集。

您可以建立備份檔案,以便在發生可能損毀叢集 etcd 資料的意外災害時進行復原。將備份檔案儲存在叢集外部的位置,且不依附於叢集運作。

限制

本文所述的備份和還原程序有下列限制:

  • 這項程序不會備份應用程式專屬資料。

  • 這項程序不會備份 PersistentVolume。

  • 備份建立後排定的工作負載不會透過該備份還原。

  • 升級失敗後,您無法還原叢集。

  • 這項程序無法還原已刪除的叢集。

  • 如果叢集已啟用進階叢集,請勿使用這個程序。請改為參閱「使用 gkectl 備份及還原進階叢集」。

如要進一步瞭解相關限制,請參閱「基礎架構不相容」一文。

備份管理員叢集

管理員叢集備份包含下列項目:

  • 管理員叢集 etcd 的快照。
  • 管理員控制層的密鑰,用於向管理員和使用者叢集進行驗證。

建立管理員叢集備份前,請完成下列步驟:

  1. 找出管理員叢集的外部 IP 位址,用於透過 SSH 連線至管理員叢集控制層:

    kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] get nodes -n kube-system -o wide | grep master

    其中 [ADMIN_CLUSTER_KUBECONFIG] 是管理員叢集的 kubeconfig 檔案。

  2. 從管理員叢集的私密金鑰建立名為 vsphere_tmp 的 SSH 金鑰。

    您可以從管理員叢集的密鑰中找到私密金鑰:

    kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] get secrets sshkeys -n kube-system -o yaml

    在指令輸出中,您可以在 vsphere_tmp 欄位中找到私密金鑰。

    將私密金鑰複製到 vsphere_tmp

    echo "[PRIVATE_KEY]" | base64 -d > vsphere_tmp; chmod 600 vsphere_tmp
  3. 確認您可以使用這個私密金鑰進入管理控制平面:

    ssh -i vsphere_tmp ubuntu@[EXTERNAL_IP]
    
  4. 結束容器:

    exit

備份管理員叢集的 etcd 存放區

如要備份管理員叢集的 etcd 存放區,請按照下列步驟操作:

  1. 取得 etcd Pod 的名稱:

    kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] get pods \
        -n kube-system -l component=etcd,tier=control-plane -ojsonpath='{$.items[*].metadata.name}{"\n"}'
  2. 進入 Pod 的 kube-etcd 容器殼層:

    kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG]  exec -it \
        -n kube-system [ADMIN_ETCD_POD] -- bin/sh

    其中 [ADMIN_ETCD_POD] 是 etcd Pod 的名稱。

  3. 在 Shell 中,使用 etcdctl 在本機目錄中建立名為 snapshot.db 的備份:

    ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt \
        --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
        --key=/etc/kubernetes/pki/etcd/healthcheck-client.key snapshot save /tmp/snapshot.db
    
  4. 結束容器:

    exit
  5. 使用 kubectl cp 將備份檔從 kube-etcd 容器複製出來:

    kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] cp \
    kube-system/[ADMIN_ETCD_POD]:tmp/snapshot.db [RELATIVE_DIRECTORY]
    

    其中 [RELATIVE_DIRECTORY] 是您要儲存備份的路徑。

備份管理員叢集的 Secret

如要備份管理員控制層的密鑰,請執行下列操作:

  1. 使用 SSH 連線至管理員控制層節點:

    ssh -i vsphere_tmp ubuntu@EXTERNAL_IP
    

    EXTERNAL_IP 換成您先前記下的管理控制平面外部 IP 位址。

  2. 建議您執行以下非強制步驟:建立本機備份目錄。

    您需要變更備份 Secret 的權限,才能將其從節點複製出來。

    mkdir backup
  3. 將密鑰複製到本機備份目錄:

    sudo cp -r /etc/kubernetes/pki/* backup/
  4. 變更備份密鑰的權限:

    sudo chmod -R a+rX backup/
  5. 退出管理員控制層節點:

    exit
  6. 執行 scp,將備份資料夾複製到管理控制平面節點外:

    sudo scp -r -i vsphere_tmp  ubuntu@EXTERNAL_IP:backup/ RELATIVE_DIRECTORY
    

    RELATIVE_DIRECTORY 替換為您要儲存備份的路徑。

還原管理員叢集

以下程序會重建備份的管理員叢集,以及建立 etcd 快照時管理的所有使用者控制層。

  1. 執行 scp,將 snapshot.db 複製到管理控制層:

    sudo scp -i vsphere_tmp snapshot.db ubuntu@[EXTERNAL_IP]:

    其中 [EXTERNAL_IP] 是您先前收集的管理控制層外部 IP 位址。

  2. 進入管理控制層的殼層:

    sudo ssh -i vsphere_tmp ubuntu@[EXTERNAL_IP]
    
  3. snapshot.db/ 複製到 /mnt

    sudo cp snapshot.db /mnt/
  4. 建立臨時目錄,例如 backup

    mkdir backup
  5. 退出管理控制層:

    exit
  6. 將憑證複製到 backup/

    sudo scp -r -i vsphere_tmp [BACKUP_CERT_FILE] ubuntu@[EXTERNAL_IP]:backup/
  7. 進入管理員控制層節點的 Shell:

    ssh -i vsphere_tmp ubuntu@[EXTERNAL_IP]
    

    其中 [EXTERNAL_IP] 是您先前收集的管理控制層外部 IP 位址。

  8. 停止 kube-etcdkube-apiserver

    sudo mv /etc/kubernetes/manifests/etcd.yaml /tmp/etcd.yaml
    sudo mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/kube-apiserver.yaml
  9. 將備份的密鑰複製到 /etc/kubernetes/pki/

    sudo cp -r backup/* /etc/kubernetes/pki/
  10. 使用 Docker 執行 etcdctl restore

    sudo docker run --rm \
    -v '/mnt:/backup' \
    -v '/var/lib/etcd:/var/lib/etcd' --env ETCDCTL_API=3 'gcr.io/gke-on-prem-release/etcd-util:GKE_ON_PREM_VERSION' /bin/sh -c "etcdctl snapshot restore '/backup/snapshot.db'; rm -r /var/lib/etcd/*; mv /default.etcd/member/ /var/lib/etcd/"
  11. 重新啟動 kube-etcdkube-apiserver

    sudo mv /tmp/etcd.yaml /etc/kubernetes/manifests/etcd.yaml
    sudo mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml
  12. 確認 kube-etcdkube-apiserver 已啟動。

    sudo crictl ps -a
  13. /etc/kubernetes/admin.conf 複製到 .kube 資料夾,以便從管理員工作站存取:

    mkdir -p [HOME]/.kube
    sudo cp -i /etc/kubernetes/admin.conf [HOME]/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
  14. 退出管理控制層:

    exit
  15. 將新產生的 kubeconfig 檔案從管理員節點複製出來:

    sudo scp -i vsphere_tmp ubuntu@[EXTERNAL_IP]:[HOME]/.kube/config kubeconfig
    sudo chown $(id -u):$(id -g) kubeconfig

    其中:

    • [EXTERNAL_IP] 是管理員控制層的外部 IP 位址。
    • [HOME] 是管理員節點上的主目錄。

    現在您可以使用這個新的 kubeconfig 檔案存取還原的叢集。

排解管理員叢集還原問題

如果在還原管理員叢集時發生問題,請務必與 Google 支援團隊聯絡,解決管理員叢集的問題。

同時建議您嘗試透過下列方式進一步排解問題。

  1. 找出 etcd 容器 ID

    sudo crictl ps -a | grep [ADMIN_ETCD_POD]

    其中 [ADMIN_ETCD_POD] 是 etcd Pod 的名稱。

  2. 檢查 etc 容器的記錄

    sudo crictl logs [ETCD_CONTAINER_ID]

    其中 [ETCD_CONTAINER_ID] 是 etcd 容器的 ID。

  3. 尋找下列權限遭拒的記錄訊息,例如

    etcdserver: create snapshot directory error:mkdir /var/lib/etcd/member/snap: permission denied

  4. 如果發現權限遭拒訊息,請更新 /opt/data/var/lib/etcd/ 的擁有權

    sudo chown -R 2001:2001 /opt/data/var/lib/etcd/

  5. 確認 kube-etcdkube-apiserver 已啟動。

    sudo crictl ps

自動叢集備份

您可以參考這裡的指令碼範例,瞭解如何自動備份叢集。請注意,系統不支援下列指令碼,僅供您參考,以便編寫更完善、更強大且更完整的指令碼。執行指令碼前,請先填入指令碼開頭五個變數的值:

  • BACKUP_DIR 設為您要儲存管理員和使用者叢集備份的路徑。這個路徑不應存在。
  • ADMIN_CLUSTER_KUBECONFIG 設為管理員叢集 kubeconfig 檔案的路徑
  • USER_CLUSTER_NAMESPACE 設為使用者叢集名稱。使用者叢集名稱是管理員叢集中的命名空間。
  • EXTERNAL_IP 設為您為管理員控制層服務保留的 VIP。
  • SSH_PRIVATE_KEY 設為安全殼層金鑰的路徑。
  • 如果您使用私人網路,請將 JUMP_IP 設為網路的跳躍伺服器 IP 位址。
#!/usr/bin/env bash
 
# Automates manual steps for taking backups of user and admin clusters.
# Fill in the variables below before running the script.
 
BACKUP_DIR=""                       # path to store user and admin cluster backups
ADMIN_CLUSTER_KUBECONFIG=""         # path to admin cluster kubeconfig
USER_CLUSTER_NAMESPACE=""           # user cluster namespace
EXTERNAL_IP=""                      # admin control plane node external ip - follow steps in documentation
SSH_PRIVATE_KEY=""                  # path to vsphere_tmp ssh private key - follow steps in documentation
JUMP_IP=""                          # network jump server IP - leave empty string if not using private network.
 
mkdir -p $BACKUP_DIR
mkdir $BACKUP_DIR/pki
 
# USER CLUSTER BACKUP
 
# Snapshot user cluster etcd
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} exec -it -n ${USER_CLUSTER_NAMESPACE} kube-etcd-0 -c kube-etcd -- /bin/sh -ec "export ETCDCTL_API=3; etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etcd.local.config/certificates/etcdCA.crt --cert=/etcd.local.config/certificates/etcd.crt --key=/etcd.local.config/certificates/etcd.key snapshot save /tmp/${USER_CLUSTER_NAMESPACE}_snapshot.db"
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} cp ${USER_CLUSTER_NAMESPACE}/kube-etcd-0:tmp/${USER_CLUSTER_NAMESPACE}_snapshot.db $BACKUP_DIR/user-cluster_${USER_CLUSTER_NAMESPACE}_snapshot.db 
 
# ADMIN CLUSTER BACKUP
 
# Set up ssh options
SSH_OPTS=(-oStrictHostKeyChecking=no -i ${SSH_PRIVATE_KEY})
if [ "${JUMP_IP}" != "" ]; then
    SSH_OPTS+=(-oProxyCommand="ssh -oStrictHostKeyChecking=no -i ${SSH_PRIVATE_KEY} -W %h:%p ubuntu@${JUMP_IP}")
fi
 
# Copy admin certs
ssh "${SSH_OPTS[@]}" ubuntu@${EXTERNAL_IP} 'sudo chmod -R a+rX /etc/kubernetes/pki/*'
scp -r "${SSH_OPTS[@]}" ubuntu@${EXTERNAL_IP}:/etc/kubernetes/pki/* ${BACKUP_DIR}/pki/
 
# Snapshot admin cluster etcd
admin_etcd=$(kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} get pods -n kube-system -l component=etcd,tier=control-plane -ojsonpath='{$.items[*].metadata.name}{"\n"}')
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} exec -it -n kube-system ${admin_etcd} -- /bin/sh -ec "export ETCDCTL_API=3; etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key snapshot save /tmp/admin_snapshot.db"
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} cp -n kube-system ${admin_etcd}:tmp/admin_snapshot.db $BACKUP_DIR/admin-cluster_snapshot.db

後續步驟