3.2. マスターホストの失われた状態からのリカバリー

以下では、マスターホストの完全に失われた状態からのリカバリープロセスについて説明します。大多数のマスターホストが失われたために etcd クォーラム(定足数) が失われ、クラスターがオフラインになる状態などがこれに該当します。この手順では、少なくとも 1 つ以上の正常なマスターホストがあることを前提とします。

概観すると、この手順では以下を実行します。

  1. 残りのマスターホストでクォーラム(定足数) を復元します。
  2. 新規マスターホストを作成します。
  3. DNS およびロードバランサーエントリーを修正します。
  4. etcd をフルメンバーシップに拡張します。

大多数のマスターホストが失われた場合、etcd スナップショットのバックアップ が必要となり、残りのマスターホストで etcd クォーラム (定足数) を復元する必要があります。

注記

大多数のマスターが依然として利用可能であり、etcd のクォーラムがある場合は、手順に従って単一の失敗したマスターホストの置き換えを実行します。

3.2.1. マスターホストの失われた状態からのリカバリー

以下の手順に従って、etcd のクォーラム (定足数) が失われる状態をもたらす大多数のマスターホストの失われた状態からのリカバリーを実行します。

前提条件

  • cluster-admin ロールを持つユーザーとしてのクラスターへのアクセスがあること。
  • 残りのマスターホストへの SSH アクセス。
  • バックアップされた etcd スナップショット。

手順

  1. 残りのマスターホストでクォーラム(定足数) を復元します。

    1. etcd スナップショットファイルを残りのマスターホストにコピーします。

      この手順では、snapshot.db というスナップショットを、マスターホストの /home/core/ ディレクトリーにコピーしていることを前提とします。

    2. 残りのマスターホストにアクセスします。
    3. INITIAL_CLUSTER 変数を、 <name>=<url> 形式でメンバー一覧に追加します。この変数は復元スクリプトに渡されます。 この手順では、この時点で単一メンバーのみが存在することを前提とします。

      [core@ip-10-0-143-125 ~]$ export INITIAL_CLUSTER="etcd-member-ip-10-0-143-125.ec2.internal=https://etcd-0.clustername.devcluster.openshift.com:2380"
    4. クラスター全体のプロキシーが有効になっている場合は、 NO_PROXYHTTP_PROXY、および HTTPS_PROXY 環境変数をエクスポートしていることを確認します。

      ヒント

      oc get proxy cluster -o yaml の出力を確認して、プロキシーが有効にされているかどうかを確認できます。プロキシーは、httpProxyhttpsProxy、および noProxy フィールドに値が設定されている場合に有効にされます。

    5. etcd-snapshot-restore.sh スクリプトを実行します。

      2 つのパラメーターを etcd-snapshot-restore.sh スクリプトに渡します。 それらは、バックアップされた etcd スナップショットファイルへのパスと、INITIAL_CLUSTER 変数で定義されるメンバーの一覧です。

      -E フラグを sudo に渡し、環境変数がスクリプトに適切に渡されるようにします。

      [core@ip-10-0-143-125 ~]$ sudo -E /usr/local/bin/etcd-snapshot-restore.sh /home/core/snapshot.db $INITIAL_CLUSTER
      Creating asset directory ./assets
      Downloading etcdctl binary..
      etcdctl version: 3.3.10
      API version: 3.3
      Backing up /etc/kubernetes/manifests/etcd-member.yaml to ./assets/backup/
      Stopping all static pods..
      ..stopping kube-scheduler-pod.yaml
      ..stopping kube-controller-manager-pod.yaml
      ..stopping kube-apiserver-pod.yaml
      ..stopping etcd-member.yaml
      Stopping etcd..
      Waiting for etcd-member to stop
      Stopping kubelet..
      Stopping all containers..
      bd44e4bc942276eb1a6d4b48ecd9f5fe95570f54aa9c6b16939fa2d9b679e1ea
      d88defb9da5ae623592b81619e3690faeb4fa645440e71c029812cb960ff586f
      3920ced20723064a379739c4a586f909497a7b6705a5b3cf367d9b930f23a5f1
      d470f7a2d962c90f3a21bcc021970bde96bc8908f317ec70f1c21720b322c25c
      Backing up etcd data-dir..
      Removing etcd data-dir /var/lib/etcd
      Restoring etcd member etcd-member-ip-10-0-143-125.ec2.internal from snapshot..
      2019-05-15 19:03:34.647589 I | pkg/netutil: resolving etcd-0.clustername.devcluster.openshift.com:2380 to 10.0.143.125:2380
      2019-05-15 19:03:34.883545 I | mvcc: restore compact to 361491
      2019-05-15 19:03:34.915679 I | etcdserver/membership: added member cbe982c74cbb42f [https://etcd-0.clustername.devcluster.openshift.com:2380] to cluster 807ae3bffc8d69ca
      Starting static pods..
      ..starting kube-scheduler-pod.yaml
      ..starting kube-controller-manager-pod.yaml
      ..starting kube-apiserver-pod.yaml
      ..starting etcd-member.yaml
      Starting kubelet..

      etcd-snapshot-restore.sh スクリプトが完了すると、クラスターでは単一メンバーの etcd クラスターを確認でき、API サービスは再起動を開始します。これには最長 15 分の時間がかかる可能性があります。

      クラスターにアクセスできるターミナルで、以下のコマンドを実行し、クラスターが準備状態にあることを確認します。

      $ oc get nodes -l node-role.kubernetes.io/master
      NAME                                         STATUS   ROLES    AGE   VERSION
      ip-10-0-143-125.us-east-2.compute.internal   Ready    master   46m   v1.14.6+c4799753c
      注記

      置き換えられる古い etcd メンバーがすべてシャットダウンしていることを確認します。シャットダウンしていない場合には、それらが新規クラスターへの接続を試行し、以下のようなエラーをログに報告します。

      2019-05-20 15:33:17.648445 E | rafthttp: request cluster ID mismatch (got 9f5f9f05e4d43b7f want 807ae3bffc8d69ca)
  2. 新規マスターホストを作成します。

    クラスターでマシン API が有効にされており、かつ機能する場合、OpenShift machine-api Operator が復元すると、新規マスターが作成されます。しかし、machine-api Operator が有効にされていない場合は、最初にマスターを作成するために使用した方法と同じ方法を使って新規マスターを作成する必要があります。

    また、これらの新規マスターホストの証明書署名要求 (CSR) を承認する必要もあります。クラスターに追加された各マシンについて 2 つの保留状態の CSR が生成されます。

    1. クラスターにアクセスできるターミナルで、以下のコマンドを実行し、CSR を承認します。

      1. 現在の CSR の一覧を取得します。

        $ oc get csr
      2. CSR の詳細をレビューし、これが有効であることを確認します。

        $ oc describe csr <csr_name> 1
        1
        <csr_name> は、現行の CSR の一覧からの CSR の名前です。
      3. それぞれの有効な CSR を承認します。

        $ oc adm certificate approve <csr_name>

        クラスターに追加されたそれぞれのマスターについての保留状態のクライアントおよびサーバー CSR の両方を承認します。

    2. クラスターにアクセスできるターミナルで、以下のコマンドを実行し、マスターが準備状態にあることを確認します。

      $ oc get nodes -l node-role.kubernetes.io/master
      NAME                                         STATUS   ROLES    AGE   VERSION
      ip-10-0-143-125.us-east-2.compute.internal   Ready    master   50m   v1.14.6+c4799753c
      ip-10-0-156-255.us-east-2.compute.internal   Ready    master   92s   v1.14.6+c4799753c
      ip-10-0-162-178.us-east-2.compute.internal   Ready    master   70s   v1.14.6+c4799753c
  3. DNS エントリーを修正します。

    1. AWS コンソールで、プライベート DNS ゾーンにある etcd-0、etcd-1、および etcd-2 Route 53 レコードを確認し、必要な場合には、値を適切な新規のプライベート IP アドレスに更新します。具体的な方法については、AWS ドキュメントの「 Editing Records 」を参照してください。

      クラスターにアクセスできるターミナルで以下のコマンドを実行して、インスタンスのプライベート IP アドレスを取得できます。

      $ oc get node ip-10-0-143-125.us-east-2.compute.internal -o  jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}'
      10.0.143.125
  4. ロードバランサーのエントリーを更新します。

    クラスターで管理されるロードバランサーを使用している場合、エントリーは自動的に更新されます。このロードバランサーを使用していない場合には、お使いのロードバランサーをマスターホストの現在のアドレスで更新してください。

    負荷分散が AWS によって管理されている場合には、ロードバランサーのエントリーを更新する方法について、AWS ドキュメントの「Register or Deregister Targets by IP Address 」を参照してください。

  5. etcd をフルメンバーシップに拡張します。

    1. etcd を復元したマスターで、一時的な etcd の証明書に署名するサービスをセットアップします。

      1. 元のマスターにアクセスし、以下のコマンドを使用して cluster-admin ユーザーとしてクラスターにログインします。

        [core@ip-10-0-143-125 ~]$ sudo oc login https://localhost:6443
        Authentication required for https://localhost:6443 (openshift)
        Username: kubeadmin
        Password:
        Login successful.
      2. kube-etcd-signer-server イメージのプル仕様を取得します。

        [core@ip-10-0-143-125 ~]$ export KUBE_ETCD_SIGNER_SERVER=$(sudo oc adm release info --image-for kube-etcd-signer-server --registry-config=/var/lib/kubelet/config.json)
      3. tokenize-signer.sh スクリプトを実行します。

        -E フラグを sudo に渡し、環境変数がスクリプトに適切に渡されるようにします。

        [core@ip-10-0-143-125 ~]$ sudo -E /usr/local/bin/tokenize-signer.sh ip-10-0-143-125 1
        Populating template /usr/local/share/openshift-recovery/template/kube-etcd-cert-signer.yaml.template
        Populating template ./assets/tmp/kube-etcd-cert-signer.yaml.stage1
        Tokenized template now ready: ./assets/manifests/kube-etcd-cert-signer.yaml
        1
        復元したばかりの元のマスターのホスト名です。 ここに署名側のデプロイが行われる必要があります。
      4. 生成されたファイルを使用して、署名側の Pod を作成します。

        [core@ip-10-0-143-125 ~]$ sudo oc create -f assets/manifests/kube-etcd-cert-signer.yaml
        pod/etcd-signer created
      5. 署名側がこのマスターノードでリッスンしていることを確認します。

        [core@ip-10-0-143-125 ~]$ ss -ltn | grep 9943
        LISTEN   0         128                       *:9943                   *:*
    2. 新規マスターホストを etcd クラスターに追加します。

      1. 新規マスターホストの 1 つにアクセスし、以下のコマンドを使用して cluster-admin ユーザーとしてクラスターにログインします。

        [core@ip-10-0-156-255 ~]$ sudo oc login https://localhost:6443
        Authentication required for https://localhost:6443 (openshift)
        Username: kubeadmin
        Password:
        Login successful.
      2. etcd-member-recover.sh スクリプトで必要な 2 つの環境変数をエクスポートします。

        [core@ip-10-0-156-255 ~]$ export SETUP_ETCD_ENVIRONMENT=$(sudo oc adm release info --image-for machine-config-operator --registry-config=/var/lib/kubelet/config.json)
        [core@ip-10-0-156-255 ~]$ export KUBE_CLIENT_AGENT=$(sudo oc adm release info --image-for kube-client-agent --registry-config=/var/lib/kubelet/config.json)
      3. etcd-member-recover.sh スクリプトを実行します。

        -E フラグを sudo に渡し、環境変数がスクリプトに適切に渡されるようにします。

        [core@ip-10-0-156-255 ~]$ sudo -E /usr/local/bin/etcd-member-recover.sh 10.0.143.125 etcd-member-ip-10-0-156-255.ec2.internal 1
        Downloading etcdctl binary..
        etcdctl version: 3.3.10
        API version: 3.3
        etcd-member.yaml found in ./assets/backup/
        etcd.conf backup upready exists ./assets/backup/etcd.conf
        Trying to backup etcd client certs..
        etcd client certs already backed up and available ./assets/backup/
        Stopping etcd..
        Waiting for etcd-member to stop
        etcd data-dir backup found ./assets/backup/etcd..
        etcd TLS certificate backups found in ./assets/backup..
        Removing etcd certs..
        Populating template /usr/local/share/openshift-recovery/template/etcd-generate-certs.yaml.template
        Populating template ./assets/tmp/etcd-generate-certs.stage1
        Populating template ./assets/tmp/etcd-generate-certs.stage2
        Starting etcd client cert recovery agent..
        Waiting for certs to generate..
        Waiting for certs to generate..
        Waiting for certs to generate..
        Waiting for certs to generate..
        Stopping cert recover..
        Waiting for generate-certs to stop
        Patching etcd-member manifest..
        Updating etcd membership..
        Member 249a4b9a790b3719 added to cluster 807ae3bffc8d69ca
        
        ETCD_NAME="etcd-member-ip-10-0-156-255.ec2.internal"
        ETCD_INITIAL_CLUSTER="etcd-member-ip-10-0-143-125.ec2.internal=https://etcd-0.clustername.devcluster.openshift.com:2380,etcd-member-ip-10-0-156-255.ec2.internal=https://etcd-1.clustername.devcluster.openshift.com:2380"
        ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd-1.clustername.devcluster.openshift.com:2380"
        ETCD_INITIAL_CLUSTER_STATE="existing"
        Starting etcd..
        1
        署名側のサーバーが実行されている元のマスターの IP アドレスと、新規メンバーの etcd 名の両方を指定します。
      4. 新規マスターホストが etcd メンバーの一覧に追加されていることを確認します。

        1. 元のマスターにアクセスし、実行中の etcd コンテナーに接続します。

          [core@ip-10-0-143-125 ~] id=$(sudo crictl ps --name etcd-member | awk 'FNR==2{ print $1}') && sudo crictl exec -it $id /bin/sh
        2. etcd コンテナーで、etcd に接続するために必要な変数をエクスポートします。

          sh-4.2# export ETCDCTL_API=3 ETCDCTL_CACERT=/etc/ssl/etcd/ca.crt ETCDCTL_CERT=$(find /etc/ssl/ -name *peer*crt) ETCDCTL_KEY=$(find /etc/ssl/ -name *peer*key)
        3. etcd コンテナーで、etcdctl member list を実行し、新規メンバーが一覧表示されていることを確認します。

          sh-4.2#  etcdctl member list -w table
          
          +------------------+---------+------------------------------------------+----------------------------------------------------------------+---------------------------+
          |        ID        | STATUS  |                   NAME                   |                           PEER ADDRS                           |       CLIENT ADDRS        |
          +------------------+---------+------------------------------------------+----------------------------------------------------------------+---------------------------+
          |  cbe982c74cbb42f | started |  etcd-member-ip-10-0-156-255.ec2.internal | https://etcd-0.clustername.devcluster.openshift.com:2380 |  https://10.0.156.255:2379 |
          | 249a4b9a790b3719 | started | etcd-member-ip-10-0-143-125.ec2.internal | https://etcd-1.clustername.devcluster.openshift.com:2380 | https://10.0.143.125:2379 |
          +------------------+---------+------------------------------------------+----------------------------------------------------------------+---------------------------+

          新規メンバーが起動するまで最長 10 分の時間がかかる可能性があります。

      5. これらの手順を繰り返し実行し、etcd のフルメンバーシップに達するまで他の新規マスターホストを追加します。
    3. すべてのメンバーが復元された後に、署名側 Pod は不要になるため、これを削除します。

      クラスターにアクセスできるターミナルで、以下のコマンドを実行します。

      $ oc delete pod -n openshift-config etcd-signer

この手順の完了後、すべてのサービスを復元するまでに数分かかる場合があります。たとえば、oc login を使用した認証は、OAuth サーバー Pod が再起動するまですぐに機能しない可能性があります。