备份etcd及相关证书

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  

|

#!/bin/bash  
set -eux  
  
mkdir -p /cpaas/{etcd_bak,pki_bak}  
BACKUP_ETC_DIR=/cpaas/etcd_bak  
BACKUP_PKI_DIR=/cpaas/pki_bak/  
IP=`/usr/sbin/ifconfig eth0 | grep -w 'inet' | awk '{print $2}'`  
ETCDCTL=/usr/local/bin/etcdctl  
TAR=/usr/bin/tar  
  
backup_etcd()  
{  
    ETCDCTL_API=3 ${ETCDCTL} --endpoints ${IP}:2379 \  
        --cert="/etc/kubernetes/pki/etcd/server.crt" \  
        --key="/etc/kubernetes/pki/etcd/server.key" \  
        --cacert="/etc/kubernetes/pki/etcd/ca.crt" \  
    snapshot save ${BACKUP_ETC_DIR}/snap-$(date +%Y%m%d%H%M).db  
}  
  
backup_pki()  
{  
    ${TAR} -cvf ${BACKUP_PKI_DIR}pki-$(date +%Y%m%d%H%M).tar /etc/kubernetes/pki/  
}  
  
del_backup()  
{  
    find ${BACKUP_ETC_DIR} -mtime +5 -a -name '*.db' | xargs rm -rf  
    find ${BACKUP_PKI_DIR} -mtime +5 -a -name '*.tar' | xargs rm -rf  
}  
  
backup_etcd ## 备份etcd  
backup_pki ## 备份证书  
del_backup ## 删除7天前日志  
  

—|—

恢复

** 注意:** 恢复的顺序是 global 集群 、 业务集群。如果只有业务集群升级失败,不支持只回滚业务集群,必须都要回滚,因为 global 集群上,存有业务集群的 hr 资源。

  1. 获取 etcd 地址,并停掉所有(业务集群和 global 集群) master 节点上的 kubelet 服务。

    • 执行命令的环境: 业务集群和 global 集群的所有 master 节点上

    • 执行的命令:

      1  
      2  
      3  
      4  
      5  
      6  
      7
      

|

       ETCD_SERVER=($(kubectl get pod -n kube-system $(kubectl get pod -n kube-system | \  
       grep etcd | awk 'NR==1 {print $1}') -o yaml | \  
       awk '/--initial-cluster=/{print}' | \  
       sed -e 's/,/ /g' -e's/^.*cluster=//' | \  
       sed -e 's#[0-9\.]*=https://##g' -e 's/:2380//g'))  
         
       systemctl stop kubelet  
         

—|—
2. 删掉 kube-apiserver 容器,目的是恢复过程和恢复之后,global 不要通过调用 kubeapi 写数据到业务集群的 etcd 内。

 * **执行命令的环境:** 要恢复 Kubernetes 集群的所有 master 节点上

 * **执行的命令:**

docker rm -f $(docker ps -a | awk '/_kube-api/{print $NF}')

 * **命令的结果:** 所有 kube-api 的容器都被删除。
  1. 判断 etcdctl 命令是否存在第一台 master 节点上,一般执行 backup_recovery.sh 这个备份 etcd 的脚本,会自动将 etcdctl 拷贝到 /usr/bin/etcdctl,如果不存在,需要自行手动拷贝出来。

    • 执行命令的环境: 要恢复 Kubernetes 集群的第一台 master 节点上

    • 执行的命令: whereis etcdctl

    • 命令的结果: 应该打印处 etcdctl 的路径,如果没有就表明是错的。

  2. 通过备份的快照恢复 etcd。

    • 执行命令的环境: 要恢复 Kubernetes 集群的第一台 master 节点上

    • 执行的命令:

      1  
      2  
      3  
      4  
      5  
      6  
      7  
      8  
      9  
      10  
      11  
      12  
      13  
      14  
      15  
      16
      

|

       mkdir /tmp/dd  
       ETCD_SERVER=($(kubectl get pod -n kube-system $(kubectl get pod -n kube-system | grep etcd | awk 'NR==1 {print $1}') -o yaml | awk '/--initial-cluster=/{print}' | sed -e 's/,/ /g' -e's/^.*cluster=//' | sed -e 's#[0-9\.]*=https://##g' -e 's/:2380//g'))  ## 这个地址在回滚的第一步已经获取了,执行回滚之前,echo 这个变量检查地址是否获取成功  
       snapshot_db=<备份时,导出的 etcd 快照文件名,必须是绝对路径>  
       for i in ${ETCD_SERVER[@]}  
       do  
           export ETCDCTL_API=3  
           etcdctl snapshot restore ${snapshot_db} \  
           --cert=/etc/kubernetes/pki/etcd/server.crt \  
           --key=/etc/kubernetes/pki/etcd/server.key \  
           --cacert=/etc/kubernetes/pki/etcd/ca.crt \  
           --data-dir=/tmp/dd/etcd \  
           --name ${i} \  
           --initial-cluster ${ETCD_SERVER[0]}=https://${ETCD_SERVER[0]}:2380,${ETCD_SERVER[1]}=https://${ETCD_SERVER[1]}:2380,${ETCD_SERVER[2]}=https://${ETCD_SERVER[2]}:2380 \  
           --initial-advertise-peer-urls https://$i:2380 && \  
       mv /tmp/dd/etcd etcd_$i  
       done  
         

—|—
* 命令的结果: 会生成 etcd_<ip 地址> 这样的三个目录,将这三个目录拷贝到对应ip的服务器的 /root 内。

  1. 删掉 etcd 容器。

    • 执行命令的环境: 要恢复 Kubernetes 集群的所有 master 节点上

    • 执行的命令: docker rm -f $(docker ps -a | awk '/_etcd/{print $NF}')

    • 命令的结果: 所有 etcd 的容器都被删除。

  2. 迁移恢复的数据。

    • 执行命令的环境: 要恢复 Kubernetes 集群的所有 master 节点上

    • 执行的命令:

      1  
      2  
      3
      

|

       docker ps -a | awk '/_etcd/{print $NF}' ##确保没有 etcd 容器  
       mv /var/lib/etcd/member /cpaas/backup  
       mv /root/var/lib/etcd/member  /var/lib/etcd  
         

—|—
* 命令的结果: 会把 etcd 的数据挪到备份目录下,然后将上一步生成的目录拷贝到 /var/lib/etcd 里。

  1. 启动 etcd 和 kube-api。

    • 执行命令的环境: 要恢复 Kubernetes 集群的所有 master 节点上

    • 执行的命令: systemctl start kubelet

    • 命令的结果: kubelet 服务启动后,会自动创建 etcd 的 pod,这个时候执行 docker ps -a | grep -E 'etcd|kube-api' 会找到 etcd 和 kube-api 容器。

  2. 问题解决

    • 回滚之后,如果出现在kubelet和页面查看所有资源都存在,但是在业务节点没有资源的情况,重启k8s 集群内所有节点的 kubelet 和 docker 服务,也可采用重启集群内所有服务器的方式来解决