Red Hat Training

A Red Hat training course is available for OpenShift Container Platform

第38章 etcd のクォーラム(定足数) の復元

etcd のクォーラム(定足数) を失う場合、それを復元できます。

  • etcd を別のホストで実行する場合、etcd をバックアップし、etcd クラスターを停止してからこれを新たに作成する必要があります。1 つの正常な etcd ノードを使用して新規クラスターを作成することができますが、他のすべての正常なノードを削除する必要があります。
  • 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 設定ファイル (/etc/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 インストーラーはエイリアスを作成するため、etcdctl2 (etcd v2 タスクの場合) と etcdctl3 (etcd v3 タスクの場合) という名前のすべてのフラグを入力しなくて済みます。

ただし、etcdctl3 エイリアスは etcdctl コマンドに詳細なエンドポイント一覧を提供しないため、--endpoints オプションを指定し、すべてのエンドポイントを一覧表示する必要があります。

etcd をバックアップする前に、以下を確認してください。

  • etcdctl バイナリーが利用可能であるか、またはコンテナー化インストールの場合は rhel7/etcd コンテナーが利用可能でなければなりません。
  • OpenShift Container Platform API サービスが実行中であることを確認します。
  • etcd クラスターとの接続を確認します (ポート 2379/tcp)。
  • etcd クラスターに接続するために使用する適切な証明書があることを確認します。
手順
注記

etcdctl backup コマンドはバックアップを実行するために使用されますが、etcd v3 には バックアップ の概念がありません。代わりに etcdctl snapshot save コマンドを使用してライブメンバーの スナップショット を取るか、または 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 のクォーラム(定足数) が失われた状態から回復するには、クラスターから 1 つの etcd ノード以外のすべての正常な etcd ノードを削除する必要もあります。

すべてのマスターホストで実行する手順

手順
  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. すべてのマスターの /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. すべてのマスターでマスター 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
    注記

    失敗したホストは etcdctl を使用して削除されているので、etcd サービスの再起動は不要です。

  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 サービスを実行し、新規クラスターを強制的に実行します。

    これらのコマンドは、--force-new-cluster オプションを etcd 起動コマンドに追加する etcd サービスのカスタムファイルを作成します。

    # 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. 残りのピアをクラスターに戻します。

38.2. 静的 Pod の etcd クォーラム(定足数) の復元

etcd に静的 Pod を使用するクラスターで etcd のクォーラム(定足数) を失う場合、以下の手順を実行します。

手順

  1. etcd Pod を停止します。

    mv /etc/origin/node/pods/etcd.yaml .
  2. etcd ホスト上で新規クラスターを一時的に強制します。

    $ cp /etc/etcd/etcd.conf etcd.conf.bak
    $ echo "ETCD_FORCE_NEW_CLUSTER=true" >> /etc/etcd/etcd.conf
  3. etcd Pod を再起動します。

    $ mv etcd.yaml /etc/origin/node/pods/.
  4. etcd Pod を停止し、FORCE_NEW_CLUSTER コマンドを削除します。

    $ mv /etc/origin/node/pods/etcd.yaml .
    $ rm /etc/etcd/etcd.conf
    $ mv etcd.conf.bak /etc/etcd/etcd.conf
  5. etcd Pod を再起動します。

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