Menu Close

Red Hat Training

A Red Hat training course is available for OpenShift Container Platform

第 38 章 恢复 etcd 仲裁

如果丢失了 etcd 仲裁,可以恢复它。

  • 如果您在单独的主机上运行 etcd,则必须备份 etcd,关闭 etcd 集群,并形成一个新集群。您可以使用一个健康的 etcd 节点组成一个新集群,但您必须删除所有其他健康节点。
  • 如果您在 master 节点上运行 etcd 作为静态 pod,请停止 etcd pod,创建一个临时集群,然后重启 etcd pod。
注意

在 etcd 仲裁丢失过程中,在 OpenShift Container Platform 上运行的应用程序不会受到影响。但是,平台功能仅限于只读操作。您无法执行诸如扩展或缩减应用、更改部署、运行或修改构建等操作。

要确认 etcd 仲裁的丢失,请运行以下命令之一并确认集群不健康:

  • 如果使用 etcd v2 API,请运行以下命令:

    # etcd_ctl=2 etcdctl  --cert-file=/etc/origin/master/master.etcd-client.crt  \
              --key-file /etc/origin/master/master.etcd-client.key \
              --ca-file /etc/origin/master/master.etcd-ca.crt \
              --endpoints="https://*master-0.example.com*:2379,\
              https://*master-1.example.com*:2379,\
              https://*master-2.example.com*:2379"\
              cluster-health
    
    member 165201190bf7f217 is unhealthy: got unhealthy result from https://master-0.example.com:2379
    member b50b8a0acab2fa71 is unreachable: [https://master-1.example.com:2379] are all unreachable
    member d40307cbca7bc2df is unreachable: [https://master-2.example.com:2379] are all unreachable
    cluster is unhealthy
  • 如果使用 v3 API,请运行以下命令:

    # ETCDCTL_API=3 etcdctl --cert=/etc/origin/master/master.etcd-client.crt  \
              --key=/etc/origin/master/master.etcd-client.key \
              --cacert=/etc/origin/masterca.crt \
              --endpoints="https://*master-0.example.com*:2379,\
              https://*master-1.example.com*:2379,\
              https://*master-2.example.com*:2379"\
              endpoint health
    https://master-0.example.com:2379 is unhealthy: failed to connect: context deadline exceeded
    https://master-1.example.com:2379 is unhealthy: failed to connect: context deadline exceeded
    https://master-2.example.com:2379 is unhealthy: failed to connect: context deadline exceeded
    Error:  unhealthy cluster

注意主机的成员 ID 和主机名。您可以使用可访问的其中一个节点组成新集群。

38.1. 为独立服务恢复 etcd 仲裁

38.1.1. 备份 etcd

备份 etcd 时,您必须备份 etcd 配置文件和 etcd 数据。

38.1.1.1. 备份 etcd 配置文件

要保留的 etcd 配置文件都存储在运行 etcd 的实例的 /etc/etcd 目录中。这包括 etcd 配置文件(/etcd/etcd.conf)以及集群通信所需的证书。所有这些文件在安装时由 Ansible 安装程序生成。

流程

对于集群的每个 etcd 成员,备份 etcd 配置。

$ ssh master-0 1
# mkdir -p /backup/etcd-config-$(date +%Y%m%d)/
# cp -R /etc/etcd/ /backup/etcd-config-$(date +%Y%m%d)/
1
master-0 替换为 etcd 成员的名称。
注意

每个 etcd 集群成员上的证书和配置文件都是唯一的。

38.1.1.2. 备份 etcd 数据

先决条件
注意

OpenShift Container Platform 安装程序会创建别名,以避免为 etcd v2 任务输入名为 etcdctl2 的所有标记,并为 etcd v3 任务输入 etcdctl 3。

但是,etcdctl3 别名不会向 etcdctl 命令提供完整的端点列表,因此您必须指定 --endpoints 选项并列出所有端点。

在备份 etcd 前:

  • etcdctl 二进制文件必须可用,或者在容器化安装中,rhel7/etcd 容器必须可用。
  • 确保 OpenShift Container Platform API 服务正在运行。
  • 确保与 etcd 集群的连接(端口 2379/tcp)。
  • 确保连接 etcd 集群的正确证书。
流程
注意

尽管 etcdctl backup 命令用于执行备份,但 etcd v3 没有 备份 的概念。相反,您可以使用 etcdctl snapshot save 命令 live 成员生成快照,或者从 etcd 数据目录中复制 member/snap/db 文件。

etcdctl backup 命令重写备份中包含的一些元数据,特别是节点 ID 和集群 ID,这意味着在备份中节点会丢失其以前的身份。要从备份重新创建集群,需要创建新的单节点集群,然后将其余节点添加到集群中。元数据会被重写,以防止新节点加入现有集群。

备份 etcd 数据:

重要

从以前版本的 OpenShift Container Platform 升级的集群可能会包含 v2 数据存储。备份所有 etcd 数据存储。

  1. 从静态 pod 清单获取 etcd 端点 IP 地址:

    $ export ETCD_POD_MANIFEST="/etc/origin/node/pods/etcd.yaml"
    $ export ETCD_EP=$(grep https ${ETCD_POD_MANIFEST} | cut -d '/' -f3)
  2. 以管理员身份登录:

    $ oc login -u system:admin
  3. 获取 etcd pod 名称:

    $ export ETCD_POD=$(oc get pods -n kube-system | grep -o -m 1 '^master-etcd\S*')
  4. 进入 kube-system 项目:

    $ oc project kube-system
  5. 在 pod 中生成 etcd 数据快照并将其存储在本地:

    $ oc exec ${ETCD_POD} -c etcd -- /bin/bash -c "ETCDCTL_API=3 etcdctl \
        --cert /etc/etcd/peer.crt \
        --key /etc/etcd/peer.key \
        --cacert /etc/etcd/ca.crt \
        --endpoints $ETCD_EP \
        snapshot save /var/lib/etcd/snapshot.db" 1
    1
    您必须将快照写入 /var/lib/etcd/ 下的目录中。

38.1.2. 删除 etcd 主机

如果 etcd 主机在恢复后失败,请将其从集群中移除。要从 etcd 仲裁丢失中恢复,还必须从集群中删除所有健康的 etcd 节点。

在所有 master 主机上执行的步骤

流程
  1. 从 etcd 集群中删除其他 etcd 主机。对每个 etcd 节点运行以下命令:

    # etcdctl -C https://<surviving host IP address>:2379 \
      --ca-file=/etc/etcd/ca.crt     \
      --cert-file=/etc/etcd/peer.crt     \
      --key-file=/etc/etcd/peer.key member remove <failed member ID>
  2. 从每个 master 上的 /etc/origin/master/master-config.yaml +master 配置文件中删除其他 etcd 主机:

    etcdClientInfo:
      ca: master.etcd-ca.crt
      certFile: master.etcd-client.crt
      keyFile: master.etcd-client.key
      urls:
        - https://master-0.example.com:2379
        - https://master-1.example.com:2379 1
        - https://master-2.example.com:2379 2
    1 2
    要删除的主机。
  3. 重启每个 master 上的 master API 服务:

    # master-restart api restart-master controller

在当前 etcd 集群中执行的步骤

流程
  1. 从集群中删除失败的主机:

    # etcdctl2 cluster-health
    member 5ee217d19001 is healthy: got healthy result from https://192.168.55.12:2379
    member 2a529ba1840722c0 is healthy: got healthy result from https://192.168.55.8:2379
    failed to check the health of member 8372784203e11288 on https://192.168.55.21:2379: Get https://192.168.55.21:2379/health: dial tcp 192.168.55.21:2379: getsockopt: connection refused
    member 8372784203e11288 is unreachable: [https://192.168.55.21:2379] are all unreachable
    member ed4f0efd277d7599 is healthy: got healthy result from https://192.168.55.13:2379
    cluster is healthy
    
    # etcdctl2 member remove 8372784203e11288 1
    Removed member 8372784203e11288 from cluster
    
    # etcdctl2 cluster-health
    member 5ee217d19001 is healthy: got healthy result from https://192.168.55.12:2379
    member 2a529ba1840722c0 is healthy: got healthy result from https://192.168.55.8:2379
    member ed4f0efd277d7599 is healthy: got healthy result from https://192.168.55.13:2379
    cluster is healthy
    1
    remove 命令需要 etcd ID,而不是主机名。
  2. 要确保 etcd 服务重启时 etcd 配置不使用失败的主机,修改所有剩余 etcd 主机上的 /etc/etcd/etcd.conf 文件,并在 ETCD_INITIAL_CLUSTER 变量的值中删除失败的主机:

    # vi /etc/etcd/etcd.conf

    例如:

    ETCD_INITIAL_CLUSTER=master-0.example.com=https://192.168.55.8:2380,master-1.example.com=https://192.168.55.12:2380,master-2.example.com=https://192.168.55.13:2380

    变为:

    ETCD_INITIAL_CLUSTER=master-0.example.com=https://192.168.55.8:2380,master-1.example.com=https://192.168.55.12:2380
    注意

    不需要重启 etcd 服务,因为失败的主机使用 etcdctl 被删除。

  3. 修改 Ansible 清单文件,以反映集群的当前状态,并避免在重新运行 playbook 时出现问题:

    [OSEv3:children]
    masters
    nodes
    etcd
    
    ... [OUTPUT ABBREVIATED] ...
    
    [etcd]
    master-0.example.com
    master-1.example.com
  4. 如果您使用 Flannel,修改每个主机上的 / etc/sysconfig/flanneld 中的 flanneld 服务配置并删除 etcd 主机:

    FLANNEL_ETCD_ENDPOINTS=https://master-0.example.com:2379,https://master-1.example.com:2379,https://master-2.example.com:2379
  5. 重启 flanneld 服务:

    # systemctl restart flanneld.service

38.1.3. 创建单节点 etcd 集群

要恢复 OpenShift Container Platform 实例的完整功能,使剩余的 etcd 节点成为独立的 etcd 集群。

流程
  1. 在您没有从集群中删除的 etcd 节点上,通过删除 etcd pod 定义来停止所有 etcd 服务:

    # mkdir -p /etc/origin/node/pods-stopped
    # mv /etc/origin/node/pods/etcd.yaml /etc/origin/node/pods-stopped/
    # systemctl stop atomic-openshift-node
    # mv /etc/origin/node/pods-stopped/etcd.yaml /etc/origin/node/pods/
  2. 在主机上运行 etcd 服务,强制创建新集群。

    这些命令为 etcd 服务创建一个自定义文件,它会在 etcd start 命令中添加 --force-new-cluster 选项:

    # 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
  3. 列出 etcd 成员,并确认成员列表只包含您的单一 etcd 主机:

    # etcdctl member list
    165201190bf7f217: name=192.168.34.20 peerURLs=http://localhost:2380 clientURLs=https://master-0.example.com:2379 isLeader=true
  4. 恢复数据并创建新集群后,您必须更新 peerURLs 参数值,以使用 etcd 侦听对等通信的 IP 地址:

    # etcdctl member update 165201190bf7f217 https://192.168.34.20:2380 1
    1
    165201190bf7f217 是上一命令的输出中显示的成员 ID ,https://192.168.34.20:2380 是它的 IP 地址。
  5. 要验证,请检查 IP 是否在成员列表中:

    $ 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

38.1.4. 在恢复后添加 etcd 节点

第一个实例运行后,您可以在集群中添加多个 etcd 服务器。

流程
  1. ETCD_NAME 变量中获取实例的 etcd 名称:

    # grep ETCD_NAME /etc/etcd/etcd.conf
  2. 获取 etcd 侦听对等通信的 IP 地址:

    # grep ETCD_INITIAL_ADVERTISE_PEER_URLS /etc/etcd/etcd.conf
  3. 如果节点以前是 etcd 集群的一部分,请删除以前的 etcd 数据:

    # rm -Rf /var/lib/etcd/*
  4. 在 etcd 正确运行的 etcd 主机上,添加新成员:

    # etcdctl3 member add *<name>* \
      --peer-urls="*<advertise_peer_urls>*"

    命令输出一些变量。例如:

    ETCD_NAME="master2"
    ETCD_INITIAL_CLUSTER="master-0.example.com=https://192.168.55.8:2380"
    ETCD_INITIAL_CLUSTER_STATE="existing"
  5. 将上一命令中的值添加到新主机的 /etc/etcd/etcd.conf 文件中:

    # vi /etc/etcd/etcd.conf
  6. 在加入集群中的节点中启动 etcd 服务:

    # systemctl start etcd.service
  7. 检查错误消息:

    # master-logs etcd etcd
  8. 添加所有节点后,验证集群状态和集群健康状况:

    # etcdctl3 endpoint health --endpoints="https://<etcd_host1>:2379,https://<etcd_host2>:2379,https://<etcd_host3>:2379"
    https://master-0.example.com:2379 is healthy: successfully committed proposal: took = 1.423459ms
    https://master-1.example.com:2379 is healthy: successfully committed proposal: took = 1.767481ms
    https://master-2.example.com:2379 is healthy: successfully committed proposal: took = 1.599694ms
    
    # etcdctl3 endpoint status --endpoints="https://<etcd_host1>:2379,https://<etcd_host2>:2379,https://<etcd_host3>:2379"
    https://master-0.example.com:2379, 40bef1f6c79b3163, 3.2.5, 28 MB, true, 9, 2878
    https://master-1.example.com:2379, 1ea57201a3ff620a, 3.2.5, 28 MB, false, 9, 2878
    https://master-2.example.com:2379, 59229711e4bc65c8, 3.2.5, 28 MB, false, 9, 2878
  9. 将剩余的对等点重新添加到集群中。