敏捷自动化

阅读前说明

  • 按照官网提供的文档操作能够恢复etcd数据,但是由于证书的问题,恢复的集群并不能正常使用,需要单独对集群的token进行清理。
  • 官方文档中没有明确恢复etcd集群的部署,经过多次验证,确认了恢复etcd集群需要以下三步:1. 部署1台节点的etcd;2. 在当前1台etcd节点上恢复数据;3. 使用ansible扩容的方式,将etcd节点扩展到3台。
  • 可以更新/etc/etcd/etcd.conf文件更改etcd name,进而解决etcd客户端访问服务器端证书不匹配的问题。
  • 文章最后附上了经过测试认证的根据备份一键恢复etcd集群的脚本。

Openshift集群平台能够使用备份完整恢复集群。Openshift集群全环境备份

在恢复集群之前,请确保对集群做过完成的备份,并重新安装Openshift集群。

恢复Master节点

创建Master主机文件的备份后,如果它们被损坏或意外删除,就可以通过这些文件复制回Master主机来恢复文件,然后重新启动受影响的服务。

恢复过程

  1. 恢复/etc/origin/master/master-config.yaml文件

    1
    2
    3
    4
    5
    $ MYBACKUPDIR=*/backup/$(hostname)/$(date +%Y%m%d)*
    $ cp /etc/origin/master/master-config.yaml /etc/origin/master/master-config.yaml.old
    $ cp /backup/$(hostname)/$(date +%Y%m%d)/origin/master/master-config.yaml /etc/origin/master/master-config.yaml
    $ master-restart api
    $ master-restart controllers

    重启master服务可能会导致停机,此时可以将该主机从负载均衡池中删除,再恢复主机,待恢复完成后,Master服务也起来了,再将它添加到负载均衡池中。

  2. 如果因为缺少一些二进制包,而导致无法启动Master服务,那么重新安装缺少的包

    • 获得当前已有的包

      1
      $ rpm -qa | sort > /tmp/current_packages.txt
    • 与之前备份的包列表作比较,得到缺少的包

      1
      2
      $ diff /tmp/current_packages.txt ${MYBACKUPDIR}/packages.txt
      > ansible-2.4.0.0-5.el7.noarch
    • 安装缺少的包

      1
      $ yum reinstall -y <packages>
  3. 恢复系统信任的证书

    1
    2
    3
    $ MYBACKUPDIR=*/backup/$(hostname)/$(date +%Y%m%d)*
    $ sudo cp ${MYBACKUPDIR}/external_certificates/my_company.crt /etc/pki/ca-trust/source/anchors/
    $ sudo update-ca-trust

恢复计算节点

一般计算节点不需要做恢复,但是如果有特殊的重要节点需要恢复的话,与Master节点恢复过程类似。

恢复过程

  1. 恢复/etc/origin/node/node-config.yaml文件

    1
    2
    3
    4
    5
    $ MYBACKUPDIR=/backup/$(hostname)/$(date +%Y%m%d)
    $ cp /etc/origin/node/node-config.yaml /etc/origin/node/node-config.yaml.old
    $ cp /backup/$(hostname)/$(date +%Y%m%d)/etc/origin/node/node-config.yaml /etc/origin/node/node-config.yaml
    $ reboot

  2. 如果因为缺少一些二进制包,而导致无法启动Master服务,那么重新安装缺少的包

    • 获得当前已有的包

      1
      $ rpm -qa | sort > /tmp/current_packages.txt
    • 与之前备份的包列表作比较,得到缺少的包

      1
      2
      $ diff /tmp/current_packages.txt ${MYBACKUPDIR}/packages.txt
      > ansible-2.4.0.0-5.el7.noarch
    • 安装缺少的包

      1
      $ yum reinstall -y <packages>
  3. 恢复系统信任的证书

    1
    2
    3
    $ MYBACKUPDIR=*/backup/$(hostname)/$(date +%Y%m%d)*
    $ sudo cp ${MYBACKUPDIR}/external_certificates/my_company.crt /etc/pki/ca-trust/source/anchors/
    $ sudo update-ca-trust

恢复etcd数据

恢复过程

  • 恢复etcd配置文件

    用备份中的etcd配置文件替换掉当前集群的配置文件,然后重启服务或者静态Pod。

    1
    2
    3
    4
    $  ssh master-0
    $ cp /backup/yesterday/master-0-files/etcd.conf /etc/etcd/etcd.conf
    $ restorecon -Rv /etc/etcd/etcd.conf
    $ systemctl restart etcd.service
  • 恢复etcd数据

    • 根据etcd v2 和 v3数据恢复

      该恢复过程必须,在单独的一台主机上恢复数据,再通过扩容的方式加入剩下的主机

      1. 通过将pod的yaml文件移出来暂停etcd pod

        1
        2
        3
        $ mkdir -p /etc/origin/node/pods-stopped
        $ mv /etc/origin/node/pods/* /etc/origin/node/pods-stopped/
        $ reboot
      2. 清除之前的数据

        • 对当前数据做备份

          1
          2
          3
          4
          $ mv /var/lib/etcd /var/lib/etcd.old
          $ mkdir /var/lib/etcd
          $ restorecon -Rv /var/lib/etcd/

        • 直接清除当前数据

          1
          2
          $ rm -rf /var/lib/etcd

      3. 在所有的etcd节点做如下操作,恢复数据

        1
        2
        3
        4
        $ cp -R /backup/etcd-xxx/* /var/lib/etcd/
        $ mv /var/lib/etcd/db /var/lib/etcd/member/snap/db
        $ chcon -R --reference /backup/etcd-xxx/* /var/lib/etcd/

      4. 在每台etcd主机上执行以下操作,强制创建一个新的etcd集群

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        $ mkdir -p /etc/systemd/system/etcd.service.d/
        $ echo "[Service]" > /etc/systemd/system/etcd.service.d/temp.conf
        $ echo "ExecStart=" >> /etc/systemd/system/etcd.service.d/temp.conf
        $ sed -n '/ExecStart/s/"$/ --force-new-cluster"/p' \
        /usr/lib/systemd/system/etcd.service \
        >> /etc/systemd/system/etcd.service.d/temp.conf

        $ systemctl daemon-reload
        $ master-restart etcd

      5. 检查错误日志

        1
        2
        $ master-logs etcd etcd

      6. 检查etcd集群的状态

        1
        2
        3
        4
        # etcdctl2 cluster-health
        member 5ee217d17301 is healthy: got healthy result from https://192.168.55.8:2379
        cluster is healthy

      7. 集群默认配置下启动etcd

        1
        2
        3
        4
        $ rm -f /etc/systemd/system/etcd.service.d/temp.conf
        $ systemctl daemon-reload
        $ master-restart etcd

      8. 检查etcd状态,查看member list

        1
        2
        3
        4
        5
        6
        7
        $ etcdctl2 cluster-health
        member 5ee217d17301 is healthy: got healthy result from https://192.168.55.8:2379
        cluster is healthy

        $ etcdctl2 member list
        5ee217d17301: name=master-0.example.com peerURLs=http://localhost:2380 clientURLs=https://192.168.55.8:2379 isLeader=true

      9. 第一个实例运行后,就可以还原其余的etcd服务器

      修复PEERURL参数问题

      在恢复数据后,新的etcd集群参数peerurl为localhost而不是ip地址,我们需要将它修改为ip地址

      1. 执行etcdctl member list获得member ID

        1
        2
        $ etcdctl member list

      2. 获得etcd通信的IP

        1
        2
        $ ss -l4n | grep 2380

      3. 更新对应member的peer地址

        1
        2
        3
        $ etcdctl2 member update 5ee217d17301 https://192.168.55.8:2380
        Updated member with ID 5ee217d17301 in cluster

      4. 查看新的peer地址进行校验

        1
        2
        $ etcdctl2 member list
        5ee217d17301: name=master-0.example.com peerURLs=https://*192.168.55.8*:2380 clientURLs=https://192.168.55.8:2379 isLeader=true
    • 根据v3的快照snapshot恢复

      如果是使用etcdctl snapshot save的方式备份的snapshot,etcdctl snapshot restore恢复数据时会去校验数据的hash,但是如果直接从数据目录中拷贝出来的就无法校验hash,这时恢复数据时需要加上**–skip-hash-check**

      该恢复过程必须,在单独的一台主机上恢复数据,再通过扩容的方式加入剩下的主机

      1. 通过将pod的yaml文件移出来暂停etcd pod

        1
        2
        3
        $ mkdir -p /etc/origin/node/pods-stopped
        $ mv /etc/origin/node/pods/* /etc/origin/node/pods-stopped/
        $ reboot
      2. 清除之前的数据

        1
        $ rm -rf /var/lib/etcd
      3. 使用snapshot restore命令来恢复数据

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        # etcdctl3 snapshot restore /backup/etcd-xxxxxx/backup.db \
        --data-dir /var/lib/etcd \
        --name master-0.example.com \
        --initial-cluster "master-0.example.com=https://192.168.55.8:2380" \
        --initial-cluster-token "etcd-cluster-1" \
        --initial-advertise-peer-urls https://192.168.55.8:2380 \
        --skip-hash-check=true

        2017-10-03 08:55:32.440779 I | mvcc: restore compact to 1041269
        2017-10-03 08:55:32.468244 I | etcdserver/membership: added member 40bef1f6c79b3163 [https://192.168.55.8:2380] to cluster 26841ebcf610583c

        相关配置从/etc/etcd/etcd.conf获取

      4. 给相关文件及目录设置相关的selinux权限

        1
        $ restorecon -Rv /var/lib/etcd/
      5. 启动etcd服务

        1
        $ systemctl start etcd
      6. 检查错误日志

        1
        $ master-logs etcd etcd
    • 在静态etcd pod恢复etcd

      1. 通过将pod的yaml文件移出来暂停etcd pod

        1
        $ mv /etc/origin/node/pods/etcd.yaml .
      2. 清除之前的数据

        1
        $ rm -rf /var/lib/etcd
      3. 使用snapshot恢复集群数据

        1
        2
        3
        4
        5
        6
        7
        8
        $ export ETCDCTL_API=3
        $ etcdctl snapshot restore /etc/etcd/backup/etcd/snapshot.db
        --data-dir /var/lib/etcd/
        --name ip-172-18-3-48.ec2.internal
        --initial-cluster "ip-172-18-3-48.ec2.internal=https://172.18.3.48:2380"
        --initial-cluster-token "etcd-cluster-1"
        --initial-advertise-peer-urls https://172.18.3.48:2380
        --skip-hash-check=true

        从**$/backup_files/etcd.conf** 文件中获得相关的参数

      4. 给相关文件及目录设置相关的selinux权限

        1
        $ restorecon -Rv /var/lib/etcd/
      5. 通过将etcd pod的yaml文件恢复到静态pod目录下来重启etcd数据

        1
        $ mv etcd.yaml /etc/origin/node/pods/.

使用Ansible添加etcd节点

还原etcd数据后,可以使用ansible或者手动的方式对etcd进行扩容。

添加过程

  1. 在inventory的hosts中添加[new_etcd]服务器组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [OSEv3:children]
    masters
    nodes
    etcd
    new_etcd

    ... [OUTPUT ABBREVIATED] ...

    [etcd]
    master-0.example.com
    master-1.example.com
    master-2.example.com

    [new_etcd]
    etcd0.example.com
  2. 执行ansible扩容ansible脚本

    1
    2
    $ cd /usr/share/ansible/openshift-ansible
    $ ansible-playbook playbooks/openshift-etcd/scaleup.yml
  3. 将[new_etcd]服务器组的主机移到[etcd]组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [OSEv3:children]
    masters
    nodes
    etcd
    new_etcd

    ... [OUTPUT ABBREVIATED] ...

    [etcd]
    master-0.example.com
    master-1.example.com
    master-2.example.com
    etcd0.example.com

恢复Openshift集群节点上的服务

恢复过程

  1. 在每一个Master节点恢复配置文件及重启相关服务

    1
    2
    3
    4
    5
    6
    7
    $ cp ${MYBACKUPDIR}/etc/origin/node/pods/* /etc/origin/node/pods/
    $ cp ${MYBACKUPDIR}/etc/origin/master/master.env /etc/origin/master/master.env
    $ cp ${MYBACKUPDIR}/etc/origin/master/master-config.yaml.<timestamp> /etc/origin/master/master-config.yaml
    $ cp ${MYBACKUPDIR}/etc/origin/node/node-config.yaml.<timestamp> /etc/origin/node/node-config.yaml
    $ cp ${MYBACKUPDIR}/etc/origin/master/scheduler.json.<timestamp> /etc/origin/master/scheduler.json
    $ master-restart api
    $ master-restart controllers
  2. 在每一个Node节点,恢复配置文件,并重启origin-node服务

    1
    2
    3
    $ cp /etc/origin/node/node-config.yaml.<timestamp> /etc/origin/node/node-config.yaml
    $ systemctl enable atomic-openshift-node
    $ systemctl start atomic-openshift-node

恢复项目Project

恢复项目前,先创建项目,再通过oc create -f命令将项目中的对象恢复。恢复项目时要注意对象的依赖关系,比如说pod依赖configmap资源,就需要先创建configmap。

恢复过程

1
2
3
4
5
6
$ oc new-project <projectname>
$ oc create -f project.yaml
$ oc create -f secret.yaml
$ oc create -f serviceaccount.yaml
$ oc create -f pvc.yaml
$ oc create -f rolebindings.yaml

恢复应用数据

与备份应用数据类似,可以使用oc rsync命令来恢复应用数据。

以下是一个利用jenkins应用的备份数据恢复应用的例子。

恢复过程

  1. 检查备份数据

    1
    2
    3
    4
    5
    $ ls -la /tmp/jenkins-backup/
    total 8
    drwxrwxr-x. 3 user user 20 Sep 6 11:14 .
    drwxrwxrwt. 17 root root 4096 Sep 6 11:16 ..
    drwxrwsrwx. 12 user user 4096 Sep 6 11:14 jenkins
  2. 使用oc rsync恢复应用数据

    1
    $ oc rsync /tmp/jenkins-backup/jenkins jenkins-1-37nux:/var/lib
  3. 重启应用

    1
    $ oc delete pod jenkins-1-37nux

    或者使用oc scale命令将pod数调整为0,再调整为1,实现应用的重启

    1
    2
    $ oc scale --replicas=0 dc/jenkins
    $ oc scale --replicas=1 dc/jenkins

恢复持久化卷数据

如果应用已挂载了新的PV,那就将该PV原来的数据删除,之后将备份的数据拷贝到对应的目录;如果应用没有挂载PV,那就先挂载一个PV,再恢复数据。

恢复过程

  1. 如果没有挂载PV执行创建新的挂载

    1
    2
    $ oc set volume dc/demo --add --name=persistent-volume \
    --type=persistentVolumeClaim --claim-name=filestore \ --mount-path=/opt/app-root/src/uploaded --overwrite
  2. 删除当前PV挂载目录下的数据

    1
    2
    3
    4
    5
    6
    $ oc rsh demo-2-fxx6d
    sh-4.2$ ls */opt/app-root/src/uploaded/*
    lost+found ocp_sop.txt
    sh-4.2$ *rm -rf /opt/app-root/src/uploaded/ocp_sop.txt*
    sh-4.2$ *ls /opt/app-root/src/uploaded/*
    lost+found
  3. 将之前备份的数据拷贝到对应的目录下

    1
    $ oc rsync uploaded demo-2-fxx6d:/opt/app-root/src/
  4. 验证应用数据

    1
    2
    3
    $ oc rsh demo-2-fxx6d
    sh-4.2$ *ls /opt/app-root/src/uploaded/*
    lost+found ocp_sop.txt

实战演练步骤

  1. 部署安装3Master 1etcd及2个Node节点的Openshift集群
  2. 使用恢复etcd数据中的根据v3的快照snapshot恢复恢复etcd数据
    如果此时pod无法正常启动,可以执行以下命令
    1
    $ echo "ETCD_FORCE_NEW_CLUSTER=true" >> /etc/etcd/etcd.conf
    再重启Pod,待etcd正常运行后,将刚才添加的ETCD_FORCE_NEW_CLUSTER=true从/etc/etcd/etcd.conf文件中删除。
  3. 按照使用Ansible添加etcd节点中的步骤将1个etcd节点扩容为3个etcd节点
  4. 清理恢复中的Openshift集群中的token,并重启相关pod,实现Openshift集群的完整恢复。

一键恢复与解决证书问题的脚本

一键恢复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
[root@master01 ~]# cat restore_etcd.sh 
#!/bin/bash
snapshot_file_dir=$1
if [ $# -lt 1 ]
then
echo "Please input snapshot file path"
exit 2
fi

export ETCD_POD_MANIFEST="/etc/origin/node/pods/etcd.yaml"
mv ${ETCD_POD_MANIFEST} .
rm -rf /var/lib/etcd

## 获取etcd相关初始化配置项
ETCD_CONFIG_FILE="/etc/etcd/etcd.conf"
etcd_data_dir=$(grep ^ETCD_DATA_DIR= $ETCD_CONFIG_FILE|cut -d= -f2)
etcd_name=$(grep ^ETCD_NAME= $ETCD_CONFIG_FILE|cut -d= -f2)
etcd_initial_cluster=$(grep ^ETCD_INITIAL_CLUSTER= $ETCD_CONFIG_FILE|awk -F'ETCD_INITIAL_CLUSTER=' '{print $2}')
etcd_initial_cluster_token=$(grep ^ETCD_INITIAL_CLUSTER_TOKEN= $ETCD_CONFIG_FILE|cut -d= -f2)
etcd_initial_advertise_peer_urls=$(grep ^ETCD_INITIAL_ADVERTISE_PEER_URLS= $ETCD_CONFIG_FILE|cut -d= -f2)

## 恢复etcd数据
export ETCDCTL_API=3
etcdctl snapshot restore $snapshot_file_dir --data-dir $etcd_data_dir --name $etcd_name --initial-cluster "$etcd_initial_cluster" --initial-cluster-token "$etcd_initial_cluster_token" --initial-advertise-peer-urls $etcd_initial_advertise_peer_urls --skip-hash-check=true

restorecon -Rv /var/lib/etcd

mv etcd.yaml $ETCD_POD_MANIFEST

一键整理etcd数据,解决证书问题

1
2
3
4
5
6
7
8
9
10
11
[root@master01 ~]# cat reset.sh 
#!/bin/bash
oc login -u system:admin

projects=$(oc get projects | awk '{print $1}' | grep -v kube-system|grep -v NAME)

for project in $(echo $projects)
do
oc delete secret $(oc get secret -n $project | grep token | awk '{print $1}') -n $project
oc delete pod $(oc get pod -n $project | grep -v NAME | awk '{print $1}') -n $project --force --grace-period=0
done

参考文章

Openshift官方文档之恢复集群