5.4. 障害復旧


5.4.1. 障害復旧について

この障害復旧ドキュメントでは、OpenShift Container Platform クラスターで発生する可能性のある複数の障害のある状態からの復旧方法に関する管理者向けの情報を提供しています。管理者は、クラスターの状態を機能する状態に戻すために、以下の 1 つまたは複数の手順を実行する必要がある場合があります。

重要

障害復旧には、少なくとも 1 つの正常なコントロールプレーンホストが必要です。

クラスターの直前の状態への復元

このソリューションは、管理者が重要なものを削除した場合など、クラスターを直前の状態に復元する必要がある状態に対応します。これには、大多数のコントロールプレーンホストが失われたために etcd クォーラム (定足数) が失われ、クラスターがオフラインになる状態も含まれます。etcd バックアップを取得している限り、以下の手順に従ってクラスターを直前の状態に復元できます。

該当する場合は、コントロールプレーン証明書の期限切れの状態からのリカバリーが必要になる場合もあります。

警告

クラスターの直前の状態への復元は、実行中のクラスターで行う破壊的で、不安定なアクションです。この手順は、最後の手段としてのみ使用してください。

復元の実行前に、クラスターへの影響の詳細についてクラスターの復元を参照してください。

注記

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

コントロールプレーン証明書の期限切れの状態からのリカバリー
このソリューションは、コントロールプレーン証明書の期限が切れた状態に対応します。たとえば、インストールの 24 時間後に行われる最初の証明書のローテーション前にクラスターをシャットダウンする場合、証明書はローテーションされず、期限切れになります。以下の手順に従って、コントロールプレーン証明書の期限切れの状態からのリカバリーを実行できます。

5.4.2. クラスターの直前の状態への復元

クラスターを直前の状態に復元するには、スナップショットを作成して、事前に etcd データのバックアップを行っている必要があります。このスナップショットを使用して、クラスターの状態を復元します。

5.4.2.1. クラスターの状態の復元について

etcd バックアップを使用して、クラスターを直前の状態に復元できます。これは、以下の状況から回復するために使用できます。

  • クラスターは、大多数のコントロールプレーンホストを失いました (クォーラムの喪失)。
  • 管理者が重要なものを削除し、クラスターを復旧するために復元する必要があります。
警告

クラスターの直前の状態への復元は、実行中のクラスターで行う破壊的で、不安定なアクションです。これは、最後の手段としてのみ使用してください。

Kubernetes API サーバーを使用してデータを取得できる場合は、etcd が利用できるため、etcd バックアップを使用して復元することはできません。

etcd を効果的に復元すると、クラスターが時間内に元に戻され、すべてのクライアントは競合する並列履歴が発生します。これは、kubelet、Kubernetes コントローラーマネージャー、SDN コントローラー、永続ボリュームコントローラーなどのコンポーネントを監視する動作に影響を与える可能性があります。

etcd のコンテンツがディスク上の実際のコンテンツと一致しないと、Operator チャーンが発生し、ディスク上のファイルが etcd のコンテンツと競合すると、Kubernetes API サーバー、Kubernetes コントローラーマネージャー、Kubernetes スケジューラーなどの Operator が停止する場合があります。この場合は、問題の解決に手動のアクションが必要になる場合があります。

極端な場合、クラスターは永続ボリュームを追跡できなくなり、存在しなくなった重要なワークロードを削除し、マシンのイメージを再作成し、期限切れの証明書を使用して CA バンドルを書き換えることができます。

5.4.2.2. クラスターの直前の状態への復元

保存された etcd のバックアップを使用して、クラスターの以前の状態を復元したり、大多数のコントロールプレーンホストが失われたクラスターを復元したりできます。

注記

クラスターがコントロールプレーンマシンセットを使用している場合、より簡単な etcd リカバリー手順については、コントロールプレーンマシンセットのトラブルシューティングを参照してください。

重要

クラスターを復元する際に、同じ z-stream リリースから取得した etcd バックアップを使用する必要があります。たとえば、OpenShift Container Platform 4.7.2 クラスターは、4.7.2 から取得した etcd バックアップを使用する必要があります。

前提条件

  • インストール時に使用したものと同様、証明書ベースの kubeconfig ファイルを介して、cluster-admin ロールを持つユーザーとしてクラスターにアクセスします。
  • リカバリーホストとして使用する正常なコントロールプレーンホストがあること。
  • コントロールプレーンホストへの SSH アクセス。
  • etcd スナップショットと静的 Pod のリソースの両方を含むバックアップディレクトリー (同じバックアップから取られるもの)。ディレクトリー内のファイル名は、snapshot_<datetimestamp>.db および static_kuberesources_<datetimestamp>.tar.gz の形式にする必要があります。
重要

非リカバリーコントロールプレーンノードの場合は、SSH 接続を確立したり、静的 Pod を停止したりする必要はありません。他のリカバリー以外のコントロールプレーンマシンを 1 つずつ削除し、再作成します。

手順

  1. リカバリーホストとして使用するコントロールプレーンホストを選択します。これは、復元操作を実行するホストです。
  2. リカバリーホストを含む、各コントロールプレーンノードへの SSH 接続を確立します。

    Kubernetes API サーバーは復元プロセスの開始後にアクセスできなくなるため、コントロールプレーンノードにはアクセスできません。このため、別のターミナルで各コントロールプレーンホストに SSH 接続を確立することが推奨されます。

    重要

    この手順を完了しないと、復元手順を完了するためにコントロールプレーンホストにアクセスすることができなくなり、この状態からクラスターを回復できなくなります。

  3. etcd バックアップディレクトリーをリカバリーコントロールプレーンホストにコピーします。

    この手順では、etcd スナップショットおよび静的 Pod のリソースを含む backup ディレクトリーを、リカバリーコントロールプレーンホストの /home/core/ ディレクトリーにコピーしていることを前提としています。

  4. 他のすべてのコントロールプレーンノードで静的 Pod を停止します。

    注記

    リカバリーホストで静的 Pod を停止する必要はありません。

    1. リカバリーホストではないコントロールプレーンホストにアクセスします。
    2. 既存の etcd Pod ファイルを kubelet マニフェストディレクトリーから移動します。

      $ sudo mv -v /etc/kubernetes/manifests/etcd-pod.yaml /tmp
    3. etcd Pod が停止していることを確認します。

      $ sudo crictl ps | grep etcd | egrep -v "operator|etcd-guard"

      コマンドの出力は空であるはずです。空でない場合は、数分待機してから再度確認します。

    4. 既存の Kubernetes API サーバー Pod ファイルを kubelet マニフェストディレクトリーから移動します。

      $ sudo mv -v /etc/kubernetes/manifests/kube-apiserver-pod.yaml /tmp
    5. Kubernetes API サーバー Pod が停止していることを確認します。

      $ sudo crictl ps | grep kube-apiserver | egrep -v "operator|guard"

      コマンドの出力は空であるはずです。空でない場合は、数分待機してから再度確認します。

    6. etcd データディレクトリーを別の場所に移動します。

      $ sudo mv -v /var/lib/etcd/ /tmp
    7. /etc/kubernetes/manifests/keepalived.yaml ファイルが存在し、ノードが削除された場合は、次の手順に従います。

      1. /etc/kubernetes/manifests/keepalived.yaml ファイルを kubelet マニフェストディレクトリーから移動します。

        $ sudo mv -v /etc/kubernetes/manifests/keepalived.yaml /tmp
      2. keepalived デーモンによって管理されているコンテナーが停止していることを確認します。

        $ sudo crictl ps --name keepalived

        コマンドの出力は空であるはずです。空でない場合は、数分待機してから再度確認します。

      3. コントロールプレーンに仮想 IP (VIP) が割り当てられているかどうかを確認します。

        $ ip -o address | egrep '<api_vip>|<ingress_vip>'
      4. 報告された仮想 IP ごとに、次のコマンドを実行して仮想 IP を削除します。

        $ sudo ip address del <reported_vip> dev <reported_vip_device>
    8. リカバリーホストではない他のコントロールプレーンホストでこの手順を繰り返します。
  5. リカバリーコントロールプレーンホストにアクセスします。
  6. keepalived デーモンが使用されている場合は、リカバリーコントロールプレーンノードが仮想 IP を所有していることを確認します。

    $ ip -o address | grep <api_vip>

    仮想 IP のアドレスが存在する場合、出力内で強調表示されます。仮想 IP が設定されていないか、正しく設定されていない場合、このコマンドは空の文字列を返します。

  7. クラスター全体のプロキシーが有効になっている場合は、NO_PROXYHTTP_PROXY、および HTTPS_PROXY 環境変数をエクスポートしていることを確認します。

    ヒント

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

  8. リカバリーコントロールプレーンホストで復元スクリプトを実行し、パスを etcd バックアップディレクトリーに渡します。

    $ sudo -E /usr/local/bin/cluster-restore.sh /home/core/assets/backup

    スクリプトの出力例

    ...stopping kube-scheduler-pod.yaml
    ...stopping kube-controller-manager-pod.yaml
    ...stopping etcd-pod.yaml
    ...stopping kube-apiserver-pod.yaml
    Waiting for container etcd to stop
    .complete
    Waiting for container etcdctl to stop
    .............................complete
    Waiting for container etcd-metrics to stop
    complete
    Waiting for container kube-controller-manager to stop
    complete
    Waiting for container kube-apiserver to stop
    ..........................................................................................complete
    Waiting for container kube-scheduler to stop
    complete
    Moving etcd data-dir /var/lib/etcd/member to /var/lib/etcd-backup
    starting restore-etcd static pod
    starting kube-apiserver-pod.yaml
    static-pod-resources/kube-apiserver-pod-7/kube-apiserver-pod.yaml
    starting kube-controller-manager-pod.yaml
    static-pod-resources/kube-controller-manager-pod-7/kube-controller-manager-pod.yaml
    starting kube-scheduler-pod.yaml
    static-pod-resources/kube-scheduler-pod-8/kube-scheduler-pod.yaml

    注記

    最後の etcd バックアップの後にノード証明書が更新された場合、復元プロセスによってノードが NotReady 状態になる可能性があります。

  9. ノードをチェックして、Ready 状態であることを確認します。

    1. 以下のコマンドを実行します。

      $ oc get nodes -w

      出力例

      NAME                STATUS  ROLES          AGE     VERSION
      host-172-25-75-28   Ready   master         3d20h   v1.25.0
      host-172-25-75-38   Ready   infra,worker   3d20h   v1.25.0
      host-172-25-75-40   Ready   master         3d20h   v1.25.0
      host-172-25-75-65   Ready   master         3d20h   v1.25.0
      host-172-25-75-74   Ready   infra,worker   3d20h   v1.25.0
      host-172-25-75-79   Ready   worker         3d20h   v1.25.0
      host-172-25-75-86   Ready   worker         3d20h   v1.25.0
      host-172-25-75-98   Ready   infra,worker   3d20h   v1.25.0

      すべてのノードが状態を報告するのに数分かかる場合があります。

    2. NotReady 状態のノードがある場合は、ノードにログインし、各ノードの /var/lib/kubelet/pki ディレクトリーからすべての PEM ファイルを削除します。ノードに SSH 接続するか、Web コンソールのターミナルウィンドウを使用できます。

      $  ssh -i <ssh-key-path> core@<master-hostname>

      サンプル pki ディレクトリー

      sh-4.4# pwd
      /var/lib/kubelet/pki
      sh-4.4# ls
      kubelet-client-2022-04-28-11-24-09.pem  kubelet-server-2022-04-28-11-24-15.pem
      kubelet-client-current.pem              kubelet-server-current.pem

  10. すべてのコントロールプレーンホストで kubelet サービスを再起動します。

    1. リカバリーホストから以下のコマンドを実行します。

      $ sudo systemctl restart kubelet.service
    2. 他のすべてのコントロールプレーンホストでこの手順を繰り返します。
  11. 保留中の CSR を承認します。

    注記

    単一ノードクラスターや 3 つのスケジュール可能なコントロールプレーンノードで構成されるクラスターなど、ワーカーノードを持たないクラスターには、承認する保留中の CSR はありません。この手順にリストされているすべてのコマンドをスキップできます。

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

      $ oc get csr

      出力例

      NAME        AGE    SIGNERNAME                                    REQUESTOR                                                                   CONDITION
      csr-2s94x   8m3s   kubernetes.io/kubelet-serving                 system:node:<node_name>                                                     Pending 1
      csr-4bd6t   8m3s   kubernetes.io/kubelet-serving                 system:node:<node_name>                                                     Pending 2
      csr-4hl85   13m    kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending 3
      csr-zhhhp   3m8s   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending 4
      ...

      1 2
      保留中の kubelet サービス CSR (ユーザーがプロビジョニングしたインストール用)。
      3 4
      保留中の node-bootstrapper CSR。
    2. CSR の詳細をレビューし、これが有効であることを確認します。

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

      $ oc adm certificate approve <csr_name>
    4. ユーザーによってプロビジョニングされるインストールの場合は、それぞれの有効な kubelet 提供の CSR を承認します。

      $ oc adm certificate approve <csr_name>
  12. 単一メンバーのコントロールプレーンが正常に起動していることを確認します。

    1. リカバリーホストから etcd コンテナーが実行中であることを確認します。

      $ sudo crictl ps | grep etcd | egrep -v "operator|etcd-guard"

      出力例

      3ad41b7908e32       36f86e2eeaaffe662df0d21041eb22b8198e0e58abeeae8c743c3e6e977e8009                                                         About a minute ago   Running             etcd                                          0                   7c05f8af362f0

    2. リカバリーホストから、etcd Pod が実行されていることを確認します。

      $ oc -n openshift-etcd get pods -l k8s-app=etcd

      出力例

      NAME                                             READY   STATUS      RESTARTS   AGE
      etcd-ip-10-0-143-125.ec2.internal                1/1     Running     1          2m47s

      ステータスが Pending の場合や出力に複数の実行中の etcd Pod が一覧表示される場合、数分待機してから再度チェックを行います。

  13. OVNKubernetes ネットワークプラグインを使用している場合は、リカバリーコントロールプレーンホストではないコントロールプレーンホストに関連付けられているノードオブジェクトを削除します。

    $ oc delete node <non-recovery-controlplane-host-1> <non-recovery-controlplane-host-2>
  14. Cluster Network Operator (CNO) が OVN-Kubernetes コントロールプレーンを再デプロイし、回復していないコントローラー IP アドレスを参照していないことを確認します。この結果を確認するには、以下のコマンドの出力を定期的に確認します。空の結果が返されるまで待ってから、次の手順ですべてのホスト上の Open Virtual Network (OVN) Kubernetes Pod の再起動に進みます。

    $ oc -n openshift-ovn-kubernetes get ds/ovnkube-master -o yaml | grep -E '<non-recovery_controller_ip_1>|<non-recovery_controller_ip_2>'
    注記

    OVN-Kubernetes コントロールプレーンが再デプロイされ、直前のコマンドが空の出力を返すまでに 5-10 分以上かかる場合があります。

  15. OVN-Kubernetes ネットワークプラグインを使用している場合は、すべてのホストで Open Virtual Network (OVN) Kubernetes Pod を再起動します。

    注記

    検証および変更用の受付 Webhook は Pod を拒否することができます。failurePolicyFail に設定して追加の Webhook を追加すると、Pod が拒否され、復元プロセスが失敗する可能性があります。これは、クラスターの状態の復元中に Webhook を保存および削除することで回避できます。クラスターの状態が正常に復元された後に、Webhook を再度有効にできます。

    または、クラスターの状態の復元中に failurePolicy を一時的に Ignore に設定できます。クラスターの状態が正常に復元された後に、failurePolicyFail にすることができます。

    1. ノースバウンドデータベース (nbdb) とサウスバウンドデータベース (sbdb) を削除します。Secure Shell (SSH) を使用してリカバリーホストと残りのコントロールプレーンノードにアクセスし、次のコマンドを実行します。

      $ sudo rm -f /var/lib/ovn/etc/*.db
    2. 次のコマンドを実行して、すべての OVN-Kubernetes コントロールプレーン Pod を削除します。

      $ oc delete pods -l app=ovnkube-master -n openshift-ovn-kubernetes
    3. 次のコマンドを実行して、OVN-Kubernetes コントロールプレーン Pod が再度デプロイされ、Running 状態になっていることを確認します。

      $ oc get pods -l app=ovnkube-master -n openshift-ovn-kubernetes

      出力例

      NAME                   READY   STATUS    RESTARTS   AGE
      ovnkube-master-nb24h   4/4     Running   0          48s

    4. 次のコマンドを実行して、すべての ovnkube-node Pod を削除します。

      $ oc get pods -n openshift-ovn-kubernetes -o name | grep ovnkube-node | while read p ; do oc delete $p -n openshift-ovn-kubernetes ; done
    5. 次のコマンドを実行して、すべての ovnkube-node Pod が再度デプロイされ、Running 状態になっていることを確認します。

      $ oc get  pods -n openshift-ovn-kubernetes | grep ovnkube-node
  16. 他の非復旧のコントロールプレーンマシンを 1 つずつ削除して再作成します。マシンが再作成された後、新しいリビジョンが強制され、etcd が自動的にスケールアップします。

    • ユーザーがプロビジョニングしたベアメタルインストールを使用する場合は、最初に作成したときと同じ方法を使用して、コントロールプレーンマシンを再作成できます。詳細は、「ユーザーによってプロビジョニングされるクラスターのベアメタルへのインストール」を参照してください。

      警告

      リカバリーホストのマシンを削除し、再作成しないでください。

    • installer-provisioned infrastructure を実行している場合、またはマシン API を使用してマシンを作成している場合は、以下の手順を実行します。

      警告

      リカバリーホストのマシンを削除し、再作成しないでください。

      installer-provisioned infrastructure でのベアメタルインストールの場合、コントロールプレーンマシンは再作成されません。詳細は、「ベアメタルコントロールプレーンノードの交換」を参照してください。

      1. 失われたコントロールプレーンホストのいずれかのマシンを取得します。

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

        $ oc get machines -n openshift-machine-api -o wide

        出力例:

        NAME                                        PHASE     TYPE        REGION      ZONE         AGE     NODE                           PROVIDERID                              STATE
        clustername-8qw5l-master-0                  Running   m4.xlarge   us-east-1   us-east-1a   3h37m   ip-10-0-131-183.ec2.internal   aws:///us-east-1a/i-0ec2782f8287dfb7e   stopped 1
        clustername-8qw5l-master-1                  Running   m4.xlarge   us-east-1   us-east-1b   3h37m   ip-10-0-143-125.ec2.internal   aws:///us-east-1b/i-096c349b700a19631   running
        clustername-8qw5l-master-2                  Running   m4.xlarge   us-east-1   us-east-1c   3h37m   ip-10-0-154-194.ec2.internal    aws:///us-east-1c/i-02626f1dba9ed5bba  running
        clustername-8qw5l-worker-us-east-1a-wbtgd   Running   m4.large    us-east-1   us-east-1a   3h28m   ip-10-0-129-226.ec2.internal   aws:///us-east-1a/i-010ef6279b4662ced   running
        clustername-8qw5l-worker-us-east-1b-lrdxb   Running   m4.large    us-east-1   us-east-1b   3h28m   ip-10-0-144-248.ec2.internal   aws:///us-east-1b/i-0cb45ac45a166173b   running
        clustername-8qw5l-worker-us-east-1c-pkg26   Running   m4.large    us-east-1   us-east-1c   3h28m   ip-10-0-170-181.ec2.internal   aws:///us-east-1c/i-06861c00007751b0a   running
        1
        これは、失われたコントロールプレーンホストのコントロールプレーンマシンです (ip-10-0-131-183.ec2.internal)。
      2. 以下を実行して、失われたコントロールプレーンホストのマシンを削除します。

        $ oc delete machine -n openshift-machine-api clustername-8qw5l-master-0 1
        1
        失われたコントロールプレーンホストのコントロールプレーンマシンの名前を指定します。

        失われたコントロールプレーンホストのマシンを削除すると、新しいマシンが自動的にプロビジョニングされます。

      3. 以下を実行して、新しいマシンが作成されたことを確認します。

        $ oc get machines -n openshift-machine-api -o wide

        出力例:

        NAME                                        PHASE          TYPE        REGION      ZONE         AGE     NODE                           PROVIDERID                              STATE
        clustername-8qw5l-master-1                  Running        m4.xlarge   us-east-1   us-east-1b   3h37m   ip-10-0-143-125.ec2.internal   aws:///us-east-1b/i-096c349b700a19631   running
        clustername-8qw5l-master-2                  Running        m4.xlarge   us-east-1   us-east-1c   3h37m   ip-10-0-154-194.ec2.internal    aws:///us-east-1c/i-02626f1dba9ed5bba  running
        clustername-8qw5l-master-3                  Provisioning   m4.xlarge   us-east-1   us-east-1a   85s     ip-10-0-173-171.ec2.internal    aws:///us-east-1a/i-015b0888fe17bc2c8  running 1
        clustername-8qw5l-worker-us-east-1a-wbtgd   Running        m4.large    us-east-1   us-east-1a   3h28m   ip-10-0-129-226.ec2.internal   aws:///us-east-1a/i-010ef6279b4662ced   running
        clustername-8qw5l-worker-us-east-1b-lrdxb   Running        m4.large    us-east-1   us-east-1b   3h28m   ip-10-0-144-248.ec2.internal   aws:///us-east-1b/i-0cb45ac45a166173b   running
        clustername-8qw5l-worker-us-east-1c-pkg26   Running        m4.large    us-east-1   us-east-1c   3h28m   ip-10-0-170-181.ec2.internal   aws:///us-east-1c/i-06861c00007751b0a   running
        1
        新規マシン clustername-8qw5l-master-3 が作成され、Provisioning から Running にフェーズが変更されると準備状態になります。

        新規マシンが作成されるまでに数分の時間がかかる場合があります。etcd クラスター Operator はマシンまたはノードが正常な状態に戻ると自動的に同期します。

      4. リカバリーホストではない喪失したコントロールプレーンホストで、これらのステップを繰り返します。
  17. 次のコマンドを入力して、クォーラムガードをオフにします。

    $ oc patch etcd/cluster --type=merge -p '{"spec": {"unsupportedConfigOverrides": {"useUnsupportedUnsafeNonHANonProductionUnstableEtcd": true}}}'

    このコマンドにより、シークレットを正常に再作成し、静的 Pod をロールアウトできるようになります。

  18. リカバリーホスト内の別のターミナルウィンドウで、次のコマンドを実行してリカバリー kubeconfig ファイルをエクスポートします。

    $ export KUBECONFIG=/etc/kubernetes/static-pod-resources/kube-apiserver-certs/secrets/node-kubeconfigs/localhost-recovery.kubeconfig
  19. etcd の再デプロイメントを強制的に実行します。

    リカバリー kubeconfig ファイルをエクスポートしたのと同じターミナルウィンドウで、次のコマンドを実行します。

    $ oc patch etcd cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge 1
    1
    forceRedeploymentReason 値は一意である必要があります。そのため、タイムスタンプが付加されます。

    etcd クラスター Operator が再デプロイメントを実行すると、初期ブートストラップのスケールアップと同様に、既存のノードが新規 Pod と共に起動します。

  20. 次のコマンドを入力して、クォーラムガードをオンに戻します。

    $ oc patch etcd/cluster --type=merge -p '{"spec": {"unsupportedConfigOverrides": null}}'
  21. 次のコマンドを入力して、unsupportedConfigOverrides セクションがオブジェクトから削除されたことを確認できます。

    $ oc get etcd/cluster -oyaml
  22. すべてのノードが最新のリビジョンに更新されていることを確認します。

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

    $ oc get etcd -o=jsonpath='{range .items[0].status.conditions[?(@.type=="NodeInstallerProgressing")]}{.reason}{"\n"}{.message}{"\n"}'

    etcd の NodeInstallerProgressing 状況条件を確認し、すべてのノードが最新のリビジョンであることを確認します。更新が正常に実行されると、この出力には AllNodesAtLatestRevision が表示されます。

    AllNodesAtLatestRevision
    3 nodes are at revision 7 1
    1
    この例では、最新のリビジョン番号は 7 です。

    出力に 2 nodes are at revision 6; 1 nodes are at revision 7 などの複数のリビジョン番号が含まれる場合、これは更新が依然として進行中であることを意味します。数分待機した後に再試行します。

  23. etcd の再デプロイ後に、コントロールプレーンの新規ロールアウトを強制的に実行します。kubelet が内部ロードバランサーを使用して API サーバーに接続されているため、Kubernetes API サーバーは他のノードに再インストールされます。

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

    1. Kubernetes API サーバーの新規ロールアウトを強制的に実行します。

      $ oc patch kubeapiserver cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge

      すべてのノードが最新のリビジョンに更新されていることを確認します。

      $ oc get kubeapiserver -o=jsonpath='{range .items[0].status.conditions[?(@.type=="NodeInstallerProgressing")]}{.reason}{"\n"}{.message}{"\n"}'

      NodeInstallerProgressing 状況条件を確認し、すべてのノードが最新のリビジョンであることを確認します。更新が正常に実行されると、この出力には AllNodesAtLatestRevision が表示されます。

      AllNodesAtLatestRevision
      3 nodes are at revision 7 1
      1
      この例では、最新のリビジョン番号は 7 です。

      出力に 2 nodes are at revision 6; 1 nodes are at revision 7 などの複数のリビジョン番号が含まれる場合、これは更新が依然として進行中であることを意味します。数分待機した後に再試行します。

    2. Kubernetes コントローラーマネージャーの新規ロールアウトを強制的に実行します。

      $ oc patch kubecontrollermanager cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge

      すべてのノードが最新のリビジョンに更新されていることを確認します。

      $ oc get kubecontrollermanager -o=jsonpath='{range .items[0].status.conditions[?(@.type=="NodeInstallerProgressing")]}{.reason}{"\n"}{.message}{"\n"}'

      NodeInstallerProgressing 状況条件を確認し、すべてのノードが最新のリビジョンであることを確認します。更新が正常に実行されると、この出力には AllNodesAtLatestRevision が表示されます。

      AllNodesAtLatestRevision
      3 nodes are at revision 7 1
      1
      この例では、最新のリビジョン番号は 7 です。

      出力に 2 nodes are at revision 6; 1 nodes are at revision 7 などの複数のリビジョン番号が含まれる場合、これは更新が依然として進行中であることを意味します。数分待機した後に再試行します。

    3. Kubernetes スケジューラーの新規ロールアウトを強制的に実行します。

      $ oc patch kubescheduler cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge

      すべてのノードが最新のリビジョンに更新されていることを確認します。

      $ oc get kubescheduler -o=jsonpath='{range .items[0].status.conditions[?(@.type=="NodeInstallerProgressing")]}{.reason}{"\n"}{.message}{"\n"}'

      NodeInstallerProgressing 状況条件を確認し、すべてのノードが最新のリビジョンであることを確認します。更新が正常に実行されると、この出力には AllNodesAtLatestRevision が表示されます。

      AllNodesAtLatestRevision
      3 nodes are at revision 7 1
      1
      この例では、最新のリビジョン番号は 7 です。

      出力に 2 nodes are at revision 6; 1 nodes are at revision 7 などの複数のリビジョン番号が含まれる場合、これは更新が依然として進行中であることを意味します。数分待機した後に再試行します。

  24. すべてのコントロールプレーンホストが起動しており、クラスターに参加していることを確認します。

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

    $ oc -n openshift-etcd get pods -l k8s-app=etcd

    出力例

    etcd-ip-10-0-143-125.ec2.internal                2/2     Running     0          9h
    etcd-ip-10-0-154-194.ec2.internal                2/2     Running     0          9h
    etcd-ip-10-0-173-171.ec2.internal                2/2     Running     0          9h

復元手順の後にすべてのワークロードが通常の動作に戻るようにするには、Kubernetes API 情報を保存している各 Pod を再起動します。これには、ルーター、Operator、サードパーティーコンポーネントなどの OpenShift Container Platform コンポーネントが含まれます。

注記

前の手順が完了したら、すべてのサービスが復元された状態に戻るまで数分間待つ必要がある場合があります。たとえば、oc login を使用した認証は、OAuth サーバー Pod が再起動するまですぐに機能しない可能性があります。

即時認証に system:admin kubeconfig ファイルを使用することを検討してください。この方法は、OAuth トークンではなく SSL/TLS クライアント証明書に基づいて認証を行います。以下のコマンドを実行し、このファイルを使用して認証できます。

$ export KUBECONFIG=<installation_directory>/auth/kubeconfig

以下のコマンドを実行て、認証済みユーザー名を表示します。

$ oc whoami

5.4.2.3. 関連情報

5.4.2.4. 永続ストレージの状態復元に関する問題および回避策

OpenShift Container Platform クラスターがいずれかの形式の永続ストレージを使用する場合に、クラスターの状態は通常 etcd 外に保存されます。たとえば、Pod で実行されている Elasticsearch クラスター、または StatefulSet オブジェクトで実行されているデータベースなどである可能性があります。etcd バックアップから復元する場合には、OpenShift Container Platform のワークロードのステータスも復元されます。ただし、etcd スナップショットが古い場合には、ステータスは無効または期限切れの可能性があります。

重要

永続ボリューム (PV) の内容は etcd スナップショットには含まれません。etcd スナップショットから OpenShift Container Platform クラスターを復元する時に、重要ではないワークロードから重要なデータにアクセスしたり、その逆ができたりする場合があります。

以下は、古いステータスを生成するシナリオ例です。

  • MySQL データベースが PV オブジェクトでバックアップされる Pod で実行されている。etcd スナップショットから OpenShift Container Platform を復元すると、Pod の起動を繰り返し試行しても、ボリュームをストレージプロバイダーに戻したり、実行中の MySQL Pod が生成したりされるわけではありません。この Pod は、ストレージプロバイダーでボリュームを復元し、次に PV を編集して新規ボリュームを参照するように手動で復元する必要があります。
  • Pod P1 は、ノード X に割り当てられているボリューム A を使用している。別の Pod がノード Y にある同じボリュームを使用している場合に etcd スナップショットが作成された場合に、etcd の復元が実行されると、ボリュームがノード Y に割り当てられていることが原因で Pod P1 が正常に起動できなくなる可能性があります。OpenShift Container Platform はこの割り当てを認識せず、ボリュームが自動的に切り離されるわけではありません。これが生じる場合には、ボリュームをノード Y から手動で切り離し、ノード X に割り当ててることで Pod P1 を起動できるようにします。
  • クラウドプロバイダーまたはストレージプロバイダーの認証情報が etcd スナップショットの作成後に更新された。これが原因で、プロバイダーの認証情報に依存する CSI ドライバーまたは Operator が機能しなくなります。これらのドライバーまたは Operator で必要な認証情報を手動で更新する必要がある場合があります。
  • デバイスが etcd スナップショットの作成後に OpenShift Container Platform ノードから削除されたか、名前が変更された。ローカルストレージ Operator で、/dev/disk/by-id または /dev ディレクトリーから管理する各 PV のシンボリックリンクが作成されます。この状況では、ローカル PV が存在しないデバイスを参照してしまう可能性があります。

    この問題を修正するには、管理者は以下を行う必要があります。

    1. デバイスが無効な PV を手動で削除します。
    2. 各ノードからシンボリックリンクを削除します。
    3. LocalVolume または LocalVolumeSet オブジェクトを削除します (ストレージ 永続ストレージの設定 ローカルボリュームを使用した永続ストレージ ローカルストレージ Operator のリソースの削除 を参照)。

5.4.3. コントロールプレーン証明書の期限切れの状態からのリカバリー

5.4.3.1. コントロールプレーン証明書の期限切れの状態からのリカバリー

クラスターはコントロールプレーン証明書の期限切れの状態から自動的に回復できます。

ただし、kubelet 証明書を回復するために保留状態の node-bootstrapper 証明書署名要求 (CSR) を手動で承認する必要があります。ユーザーによってプロビジョニングされるインストールの場合は、保留中の kubelet 提供の CSR を承認しないといけない場合があります。

保留中の CSR を承認するには、以下の手順に従います。

手順

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

    $ oc get csr

    出力例

    NAME        AGE    SIGNERNAME                                    REQUESTOR                                                                   CONDITION
    csr-2s94x   8m3s   kubernetes.io/kubelet-serving                 system:node:<node_name>                                                     Pending 1
    csr-4bd6t   8m3s   kubernetes.io/kubelet-serving                 system:node:<node_name>                                                     Pending
    csr-4hl85   13m    kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending 2
    csr-zhhhp   3m8s   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending
    ...

    1
    保留中の kubelet サービス CSR (ユーザーがプロビジョニングしたインストール用)。
    2
    保留中の node-bootstrapper CSR。
  2. CSR の詳細をレビューし、これが有効であることを確認します。

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

    $ oc adm certificate approve <csr_name>
  4. ユーザーによってプロビジョニングされるインストールの場合は、それぞれの有効な kubelet 提供の CSR を承認します。

    $ oc adm certificate approve <csr_name>

5.4.4. AWS リージョン内のホストされたクラスターの障害復旧

ホストされたクラスターの障害復旧 (DR) が必要な状況では、ホストされたクラスターを AWS 内の同じリージョンに回復できます。たとえば、管理クラスターのアップグレードが失敗し、ホストされているクラスターが読み取り専用状態になっている場合、DR が必要です。

重要

Hosted Control Plane は、テクノロジープレビュー機能としてのみ利用できます。テクノロジープレビュー機能は、Red Hat 製品サポートのサービスレベルアグリーメント (SLA) の対象外であり、機能的に完全ではない場合があります。Red Hat は、実稼働環境でこれらを使用することを推奨していません。テクノロジープレビューの機能は、最新の製品機能をいち早く提供して、開発段階で機能のテストを行いフィードバックを提供していただくことを目的としています。

Red Hat のテクノロジープレビュー機能のサポート範囲に関する詳細は、テクノロジープレビュー機能のサポート範囲 を参照してください。

DR プロセスには、次の 3 つの主要な手順が含まれます。

  1. ソース管理クラスターでのホストされたクラスターのバックアップ
  2. 宛先管理クラスターでのホストされたクラスターの復元
  3. ホストされたクラスターのソース管理クラスターからの削除

プロセス中、ワークロードは引き続き実行されます。クラスター API は一定期間使用できない場合がありますが、ワーカーノードで実行されているサービスには影響しません。

重要

次の例に示すように、ソース管理クラスターと宛先管理クラスターの両方に --external-dns フラグを設定して、API サーバー URL を維持する必要があります。

例: 外部 DNS フラグ

--external-dns-provider=aws \
--external-dns-credentials=<AWS Credentials location> \
--external-dns-domain-filter=<DNS Base Domain>

これにより、サーバー URL は https://api-sample-hosted.sample-hosted.aws.openshift.com で終わります。

API サーバー URL を維持するために --external-dns フラグを含めない場合、ホストされたクラスターを移行することはできません。

5.4.4.1. 環境とコンテキストの例

復元するクラスターが 3 つあるシナリオを考えてみます。2 つは管理クラスターで、1 つはホストされたクラスターです。コントロールプレーンのみ、またはコントロールプレーンとノードのいずれかを復元できます。開始する前に、以下の情報が必要です。

  • ソース MGMT namespace: ソース管理 namespace
  • ソース MGMT ClusterName: ソース管理クラスター名
  • ソース MGMT Kubeconfig: ソース管理 kubeconfig ファイル
  • 宛先 MGMT Kubeconfig: 宛先管理 kubeconfig ファイル
  • HC Kubeconfig: ホストされたクラスターの kubeconfig ファイル
  • SSH 鍵ファイル: SSH 公開鍵
  • プルシークレット: リリースイメージにアクセスするためのプルシークレットファイル
  • AWS 認証情報
  • AWS リージョン
  • ベースドメイン: 外部 DNS として使用する DNS ベースドメイン
  • S3 バケット名: etcd バックアップをアップロードする予定の AWS リージョンのバケット

この情報は、次の環境変数の例に示されています。

環境変数の例

SSH_KEY_FILE=${HOME}/.ssh/id_rsa.pub
BASE_PATH=${HOME}/hypershift
BASE_DOMAIN="aws.sample.com"
PULL_SECRET_FILE="${HOME}/pull_secret.json"
AWS_CREDS="${HOME}/.aws/credentials"
AWS_ZONE_ID="Z02718293M33QHDEQBROL"

CONTROL_PLANE_AVAILABILITY_POLICY=SingleReplica
HYPERSHIFT_PATH=${BASE_PATH}/src/hypershift
HYPERSHIFT_CLI=${HYPERSHIFT_PATH}/bin/hypershift
HYPERSHIFT_IMAGE=${HYPERSHIFT_IMAGE:-"quay.io/${USER}/hypershift:latest"}
NODE_POOL_REPLICAS=${NODE_POOL_REPLICAS:-2}

# MGMT Context
MGMT_REGION=us-west-1
MGMT_CLUSTER_NAME="${USER}-dev"
MGMT_CLUSTER_NS=${USER}
MGMT_CLUSTER_DIR="${BASE_PATH}/hosted_clusters/${MGMT_CLUSTER_NS}-${MGMT_CLUSTER_NAME}"
MGMT_KUBECONFIG="${MGMT_CLUSTER_DIR}/kubeconfig"

# MGMT2 Context
MGMT2_CLUSTER_NAME="${USER}-dest"
MGMT2_CLUSTER_NS=${USER}
MGMT2_CLUSTER_DIR="${BASE_PATH}/hosted_clusters/${MGMT2_CLUSTER_NS}-${MGMT2_CLUSTER_NAME}"
MGMT2_KUBECONFIG="${MGMT2_CLUSTER_DIR}/kubeconfig"

# Hosted Cluster Context
HC_CLUSTER_NS=clusters
HC_REGION=us-west-1
HC_CLUSTER_NAME="${USER}-hosted"
HC_CLUSTER_DIR="${BASE_PATH}/hosted_clusters/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}"
HC_KUBECONFIG="${HC_CLUSTER_DIR}/kubeconfig"
BACKUP_DIR=${HC_CLUSTER_DIR}/backup

BUCKET_NAME="${USER}-hosted-${MGMT_REGION}"

# DNS
AWS_ZONE_ID="Z07342811SH9AA102K1AC"
EXTERNAL_DNS_DOMAIN="hc.jpdv.aws.kerbeross.com"

5.4.4.2. バックアップおよび復元プロセスの概要

バックアップと復元のプロセスは、以下のような仕組みとなっています。

  1. 管理クラスター 1 (ソース管理クラスターと見なすことができます) では、コントロールプレーンとワーカーが外部 DNS API を使用して対話します。外部 DNS API はアクセス可能で、管理クラスター間にロードバランサーが配置されています。

    外部 DNS API にアクセスするワーカーと、ロードバランサーを介してコントロールプレーンを参照する外部 DNS API を示す図
  2. ホストされたクラスターのスナップショットを作成します。これには、etcd、コントロールプレーン、およびワーカーノードが含まれます。このプロセスの間、ワーカーノードは外部 DNS API にアクセスできなくても引き続きアクセスを試みます。また、ワークロードが実行され、コントロールプレーンがローカルマニフェストファイルに保存され、etcd が S3 バケットにバックアップされます。データプレーンはアクティブで、コントロールプレーンは一時停止しています。

    298 OpenShift バックアップの復元 0123 01
  3. 管理クラスター 2 (宛先管理クラスターと見なすことができます) では、S3 バケットから etcd を復元し、ローカルマニフェストファイルからコントロールプレーンを復元します。このプロセスの間、外部 DNS API は停止し、ホストされたクラスター API にアクセスできなくなり、API を使用するワーカーはマニフェストファイルを更新できなくなりますが、ワークロードは引き続き実行されます。

    298 OpenShift バックアップの復元 0123 02
  4. 外部 DNS API に再びアクセスできるようになり、ワーカーノードはそれを使用して管理クラスター 2 に移動します。外部 DNS API は、コントロールプレーンを参照するロードバランサーにアクセスできます。

    298 OpenShift バックアップの復元 0123 03
  5. 管理クラスター 2 では、コントロールプレーンとワーカーノードが外部 DNS API を使用して対話します。リソースは、etcd の S3 バックアップを除いて、管理クラスター 1 から削除されます。ホストされたクラスターを管理クラスター 1 で再度設定しようとしても、機能しません。

    298 OpenShift バックアップの復元 0123 04

ホストされたクラスターを手動でバックアップおよび復元するか、スクリプトを実行してプロセスを完了することができます。スクリプトの詳細については、「ホストされたクラスターをバックアップおよび復元するためのスクリプトの実行」を参照してください。

5.4.4.3. ホストされたクラスターのバックアップ

ターゲット管理クラスターでホストされたクラスターを復元するには、最初にすべての関連データをバックアップする必要があります。

手順

  1. 以下のコマンドを入力して、configmap ファイルを作成し、ソース管理クラスターを宣言します。

    $ oc create configmap mgmt-parent-cluster -n default --from-literal=from=${MGMT_CLUSTER_NAME}
  2. 以下のコマンドを入力して、ホストされたクラスターとノードプールの調整をシャットダウンします。

    $ PAUSED_UNTIL="true"
    $ oc patch -n ${HC_CLUSTER_NS} hostedclusters/${HC_CLUSTER_NAME} -p '{"spec":{"pausedUntil":"'${PAUSED_UNTIL}'"}}' --type=merge
    $ oc scale deployment -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --replicas=0 kube-apiserver openshift-apiserver openshift-oauth-apiserver control-plane-operator
    $ PAUSED_UNTIL="true"
    $ oc patch -n ${HC_CLUSTER_NS} hostedclusters/${HC_CLUSTER_NAME} -p '{"spec":{"pausedUntil":"'${PAUSED_UNTIL}'"}}' --type=merge
    $ oc patch -n ${HC_CLUSTER_NS} nodepools/${NODEPOOLS} -p '{"spec":{"pausedUntil":"'${PAUSED_UNTIL}'"}}' --type=merge
    $ oc scale deployment -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --replicas=0 kube-apiserver openshift-apiserver openshift-oauth-apiserver control-plane-operator
  3. 以下の bash スクリプトを実行して、etcd をバックアップし、データを S3 バケットにアップロードします。

    ヒント

    このスクリプトを関数でラップし、メイン関数から呼び出します。

    # ETCD Backup
    ETCD_PODS="etcd-0"
    if [ "${CONTROL_PLANE_AVAILABILITY_POLICY}" = "HighlyAvailable" ]; then
      ETCD_PODS="etcd-0 etcd-1 etcd-2"
    fi
    
    for POD in ${ETCD_PODS}; do
      # Create an etcd snapshot
      oc exec -it ${POD} -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -- env ETCDCTL_API=3 /usr/bin/etcdctl --cacert /etc/etcd/tls/client/etcd-client-ca.crt --cert /etc/etcd/tls/client/etcd-client.crt --key /etc/etcd/tls/client/etcd-client.key --endpoints=localhost:2379 snapshot save /var/lib/data/snapshot.db
      oc exec -it ${POD} -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -- env ETCDCTL_API=3 /usr/bin/etcdctl -w table snapshot status /var/lib/data/snapshot.db
    
      FILEPATH="/${BUCKET_NAME}/${HC_CLUSTER_NAME}-${POD}-snapshot.db"
      CONTENT_TYPE="application/x-compressed-tar"
      DATE_VALUE=`date -R`
      SIGNATURE_STRING="PUT\n\n${CONTENT_TYPE}\n${DATE_VALUE}\n${FILEPATH}"
    
      set +x
      ACCESS_KEY=$(grep aws_access_key_id ${AWS_CREDS} | head -n1 | cut -d= -f2 | sed "s/ //g")
      SECRET_KEY=$(grep aws_secret_access_key ${AWS_CREDS} | head -n1 | cut -d= -f2 | sed "s/ //g")
      SIGNATURE_HASH=$(echo -en ${SIGNATURE_STRING} | openssl sha1 -hmac "${SECRET_KEY}" -binary | base64)
      set -x
    
      # FIXME: this is pushing to the OIDC bucket
      oc exec -it etcd-0 -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -- curl -X PUT -T "/var/lib/data/snapshot.db" \
        -H "Host: ${BUCKET_NAME}.s3.amazonaws.com" \
        -H "Date: ${DATE_VALUE}" \
        -H "Content-Type: ${CONTENT_TYPE}" \
        -H "Authorization: AWS ${ACCESS_KEY}:${SIGNATURE_HASH}" \
        https://${BUCKET_NAME}.s3.amazonaws.com/${HC_CLUSTER_NAME}-${POD}-snapshot.db
    done

    etcd のバックアップの詳細は、「ホストされたクラスターでの etcd のバックアップと復元」を参照してください。

  4. 以下のコマンドを入力して、Kubernetes および OpenShift Container Platform オブジェクトをバックアップします。次のオブジェクトをバックアップする必要があります。

    • HostedCluster namespace の HostedCluster および NodePool オブジェクト
    • HostedCluster namespace の HostedCluster シークレット
    • Hosted Control Plane namespace の HostedControlPlane
    • Hosted Control Plane namespace の Cluster
    • Hosted Control Plane namespace の AWSClusterAWSMachineTemplate、および AWSMachine
    • Hosted Control Plane namespace の MachineDeploymentsMachineSets、および Machines
    • Hosted Control Plane namespace の ControlPlane シークレット

      $ mkdir -p ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS} ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}
      $ chmod 700 ${BACKUP_DIR}/namespaces/
      
      # HostedCluster
      $ echo "Backing Up HostedCluster Objects:"
      $ oc get hc ${HC_CLUSTER_NAME} -n ${HC_CLUSTER_NS} -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/hc-${HC_CLUSTER_NAME}.yaml
      $ echo "--> HostedCluster"
      $ sed -i '' -e '/^status:$/,$d' ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/hc-${HC_CLUSTER_NAME}.yaml
      
      # NodePool
      $ oc get np ${NODEPOOLS} -n ${HC_CLUSTER_NS} -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/np-${NODEPOOLS}.yaml
      $ echo "--> NodePool"
      $ sed -i '' -e '/^status:$/,$ d' ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/np-${NODEPOOLS}.yaml
      
      # Secrets in the HC Namespace
      $ echo "--> HostedCluster Secrets:"
      for s in $(oc get secret -n ${HC_CLUSTER_NS} | grep "^${HC_CLUSTER_NAME}" | awk '{print $1}'); do
          oc get secret -n ${HC_CLUSTER_NS} $s -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/secret-${s}.yaml
      done
      
      # Secrets in the HC Control Plane Namespace
      $ echo "--> HostedCluster ControlPlane Secrets:"
      for s in $(oc get secret -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} | egrep -v "docker|service-account-token|oauth-openshift|NAME|token-${HC_CLUSTER_NAME}" | awk '{print $1}'); do
          oc get secret -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} $s -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/secret-${s}.yaml
      done
      
      # Hosted Control Plane
      $ echo "--> HostedControlPlane:"
      $ oc get hcp ${HC_CLUSTER_NAME} -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/hcp-${HC_CLUSTER_NAME}.yaml
      
      # Cluster
      $ echo "--> Cluster:"
      $ CL_NAME=$(oc get hcp ${HC_CLUSTER_NAME} -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o jsonpath={.metadata.labels.\*} | grep ${HC_CLUSTER_NAME})
      $ oc get cluster ${CL_NAME} -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/cl-${HC_CLUSTER_NAME}.yaml
      
      # AWS Cluster
      $ echo "--> AWS Cluster:"
      $ oc get awscluster ${HC_CLUSTER_NAME} -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/awscl-${HC_CLUSTER_NAME}.yaml
      
      # AWS MachineTemplate
      $ echo "--> AWS Machine Template:"
      $ oc get awsmachinetemplate ${NODEPOOLS} -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/awsmt-${HC_CLUSTER_NAME}.yaml
      
      # AWS Machines
      $ echo "--> AWS Machine:"
      $ CL_NAME=$(oc get hcp ${HC_CLUSTER_NAME} -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o jsonpath={.metadata.labels.\*} | grep ${HC_CLUSTER_NAME})
      for s in $(oc get awsmachines -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --no-headers | grep ${CL_NAME} | cut -f1 -d\ ); do
          oc get -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} awsmachines $s -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/awsm-${s}.yaml
      done
      
      # MachineDeployments
      $ echo "--> HostedCluster MachineDeployments:"
      for s in $(oc get machinedeployment -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o name); do
          mdp_name=$(echo ${s} | cut -f 2 -d /)
          oc get -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} $s -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/machinedeployment-${mdp_name}.yaml
      done
      
      # MachineSets
      $ echo "--> HostedCluster MachineSets:"
      for s in $(oc get machineset -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o name); do
          ms_name=$(echo ${s} | cut -f 2 -d /)
          oc get -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} $s -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/machineset-${ms_name}.yaml
      done
      
      # Machines
      $ echo "--> HostedCluster Machine:"
      for s in $(oc get machine -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o name); do
          m_name=$(echo ${s} | cut -f 2 -d /)
          oc get -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} $s -o yaml > ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/machine-${m_name}.yaml
      done
  5. 次のコマンドを入力して、ControlPlane ルートをクリーンアップします。

    $ oc delete routes -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --all

    このコマンドを入力すると、ExternalDNS Operator が Route53 エントリーを削除できるようになります。

  6. 次のスクリプトを実行して、Route53 エントリーがクリーンであることを確認します。

    function clean_routes() {
    
        if [[ -z "${1}" ]];then
            echo "Give me the NS where to clean the routes"
            exit 1
        fi
    
        # Constants
        if [[ -z "${2}" ]];then
            echo "Give me the Route53 zone ID"
            exit 1
        fi
    
        ZONE_ID=${2}
        ROUTES=10
        timeout=40
        count=0
    
        # This allows us to remove the ownership in the AWS for the API route
        oc delete route -n ${1} --all
    
        while [ ${ROUTES} -gt 2 ]
        do
            echo "Waiting for ExternalDNS Operator to clean the DNS Records in AWS Route53 where the zone id is: ${ZONE_ID}..."
            echo "Try: (${count}/${timeout})"
            sleep 10
            if [[ $count -eq timeout ]];then
                echo "Timeout waiting for cleaning the Route53 DNS records"
                exit 1
            fi
            count=$((count+1))
            ROUTES=$(aws route53 list-resource-record-sets --hosted-zone-id ${ZONE_ID} --max-items 10000 --output json | grep -c ${EXTERNAL_DNS_DOMAIN})
        done
    }
    
    # SAMPLE: clean_routes "<HC ControlPlane Namespace>" "<AWS_ZONE_ID>"
    clean_routes "${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}" "${AWS_ZONE_ID}"

検証

すべての OpenShift Container Platform オブジェクトと S3 バケットをチェックし、すべてが想定どおりであることを確認します。

次のステップ

ホストされたクラスターを復元します。

5.4.4.4. ホストされたクラスターの復元

バックアップしたすべてのオブジェクトを収集し、宛先管理クラスターに復元します。

前提条件

ソース管理クラスターからデータをバックアップしている。

ヒント

宛先管理クラスターの kubeconfig ファイルが、KUBECONFIG 変数に設定されているとおりに、あるいは、スクリプトを使用する場合は MGMT2_KUBECONFIG 変数に設定されているとおりに配置されていることを確認します。export KUBECONFIG=<Kubeconfig FilePath> を使用するか、スクリプトを使用する場合は export KUBECONFIG=${MGMT2_KUBECONFIG} を使用します。

手順

  1. 以下のコマンドを入力して、新しい管理クラスターに、復元するクラスターの namespace が含まれていないことを確認します。

    # Just in case
    $ export KUBECONFIG=${MGMT2_KUBECONFIG}
    $ BACKUP_DIR=${HC_CLUSTER_DIR}/backup
    
    # Namespace deletion in the destination Management cluster
    $ oc delete ns ${HC_CLUSTER_NS} || true
    $ oc delete ns ${HC_CLUSTER_NS}-{HC_CLUSTER_NAME} || true
  2. 以下のコマンドを入力して、削除された namespace を再作成します。

    # Namespace creation
    $ oc new-project ${HC_CLUSTER_NS}
    $ oc new-project ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}
  3. 次のコマンドを入力して、HC namespace のシークレットを復元します。

    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/secret-*
  4. 以下のコマンドを入力して、HostedCluster コントロールプレーン namespace のオブジェクトを復元します。

    # Secrets
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/secret-*
    
    # Cluster
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/hcp-*
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/cl-*
  5. ノードとノードプールを復元して AWS インスタンスを再利用する場合は、次のコマンドを入力して、HC コントロールプレーン namespace のオブジェクトを復元します。

    # AWS
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/awscl-*
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/awsmt-*
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/awsm-*
    
    # Machines
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/machinedeployment-*
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/machineset-*
    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}/machine-*
  6. 次の bash スクリプトを実行して、etcd データとホストされたクラスターを復元します。

    ETCD_PODS="etcd-0"
    if [ "${CONTROL_PLANE_AVAILABILITY_POLICY}" = "HighlyAvailable" ]; then
      ETCD_PODS="etcd-0 etcd-1 etcd-2"
    fi
    
    HC_RESTORE_FILE=${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/hc-${HC_CLUSTER_NAME}-restore.yaml
    HC_BACKUP_FILE=${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/hc-${HC_CLUSTER_NAME}.yaml
    HC_NEW_FILE=${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/hc-${HC_CLUSTER_NAME}-new.yaml
    cat ${HC_BACKUP_FILE} > ${HC_NEW_FILE}
    cat > ${HC_RESTORE_FILE} <<EOF
        restoreSnapshotURL:
    EOF
    
    for POD in ${ETCD_PODS}; do
      # Create a pre-signed URL for the etcd snapshot
      ETCD_SNAPSHOT="s3://${BUCKET_NAME}/${HC_CLUSTER_NAME}-${POD}-snapshot.db"
      ETCD_SNAPSHOT_URL=$(AWS_DEFAULT_REGION=${MGMT2_REGION} aws s3 presign ${ETCD_SNAPSHOT})
    
      # FIXME no CLI support for restoreSnapshotURL yet
      cat >> ${HC_RESTORE_FILE} <<EOF
        - "${ETCD_SNAPSHOT_URL}"
    EOF
    done
    
    cat ${HC_RESTORE_FILE}
    
    if ! grep ${HC_CLUSTER_NAME}-snapshot.db ${HC_NEW_FILE}; then
      sed -i '' -e "/type: PersistentVolume/r ${HC_RESTORE_FILE}" ${HC_NEW_FILE}
      sed -i '' -e '/pausedUntil:/d' ${HC_NEW_FILE}
    fi
    
    HC=$(oc get hc -n ${HC_CLUSTER_NS} ${HC_CLUSTER_NAME} -o name || true)
    if [[ ${HC} == "" ]];then
        echo "Deploying HC Cluster: ${HC_CLUSTER_NAME} in ${HC_CLUSTER_NS} namespace"
        oc apply -f ${HC_NEW_FILE}
    else
        echo "HC Cluster ${HC_CLUSTER_NAME} already exists, avoiding step"
    fi
  7. ノードとノードプールを復元して AWS インスタンスを再利用する場合は、次のコマンドを入力してノードプールを復元します。

    $ oc apply -f ${BACKUP_DIR}/namespaces/${HC_CLUSTER_NS}/np-*

検証

  • ノードが完全に復元されたことを確認するには、次の関数を使用します。

    timeout=40
    count=0
    NODE_STATUS=$(oc get nodes --kubeconfig=${HC_KUBECONFIG} | grep -v NotReady | grep -c "worker") || NODE_STATUS=0
    
    while [ ${NODE_POOL_REPLICAS} != ${NODE_STATUS} ]
    do
        echo "Waiting for Nodes to be Ready in the destination MGMT Cluster: ${MGMT2_CLUSTER_NAME}"
        echo "Try: (${count}/${timeout})"
        sleep 30
        if [[ $count -eq timeout ]];then
            echo "Timeout waiting for Nodes in the destination MGMT Cluster"
            exit 1
        fi
        count=$((count+1))
        NODE_STATUS=$(oc get nodes --kubeconfig=${HC_KUBECONFIG} | grep -v NotReady | grep -c "worker") || NODE_STATUS=0
    done

次のステップ

クラスターをシャットダウンして削除します。

5.4.4.5. ホストされたクラスターのソース管理クラスターからの削除

ホストされたクラスターをバックアップして宛先管理クラスターに復元した後、ソース管理クラスターのホストされたクラスターをシャットダウンして削除します。

前提条件

データをバックアップし、ソース管理クラスターに復元している。

ヒント

宛先管理クラスターの kubeconfig ファイルが、KUBECONFIG 変数に設定されているとおりに、あるいは、スクリプトを使用する場合は MGMT_KUBECONFIG 変数に設定されているとおりに配置されていることを確認します。export KUBECONFIG=<Kubeconfig FilePath> を使用するか、スクリプトを使用する場合は export KUBECONFIG=${MGMT_KUBECONFIG} を使用します。

手順

  1. 以下のコマンドを入力して、deployment および statefulset オブジェクトをスケーリングします。

    # Just in case
    $ export KUBECONFIG=${MGMT_KUBECONFIG}
    
    # Scale down deployments
    $ oc scale deployment -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --replicas=0 --all
    $ oc scale statefulset.apps -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --replicas=0 --all
    $ sleep 15
  2. 次のコマンドを入力して、NodePool オブジェクトを削除します。

    NODEPOOLS=$(oc get nodepools -n ${HC_CLUSTER_NS} -o=jsonpath='{.items[?(@.spec.clusterName=="'${HC_CLUSTER_NAME}'")].metadata.name}')
    if [[ ! -z "${NODEPOOLS}" ]];then
        oc patch -n "${HC_CLUSTER_NS}" nodepool ${NODEPOOLS} --type=json --patch='[ { "op":"remove", "path": "/metadata/finalizers" }]'
        oc delete np -n ${HC_CLUSTER_NS} ${NODEPOOLS}
    fi
  3. 次のコマンドを入力して、machine および machineset オブジェクトを削除します。

    # Machines
    for m in $(oc get machines -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o name); do
        oc patch -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} ${m} --type=json --patch='[ { "op":"remove", "path": "/metadata/finalizers" }]' || true
        oc delete -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} ${m} || true
    done
    
    $ oc delete machineset -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --all || true
  4. 次のコマンドを入力して、クラスターオブジェクトを削除します。

    # Cluster
    $ C_NAME=$(oc get cluster -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o name)
    $ oc patch -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} ${C_NAME} --type=json --patch='[ { "op":"remove", "path": "/metadata/finalizers" }]'
    $ oc delete cluster.cluster.x-k8s.io -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --all
  5. 次のコマンドを入力して、AWS マシン (Kubernetes オブジェクト) を削除します。実際の AWS マシンの削除を心配する必要はありません。クラウドインスタンスへの影響はありません。

    # AWS Machines
    for m in $(oc get awsmachine.infrastructure.cluster.x-k8s.io -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} -o name)
    do
        oc patch -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} ${m} --type=json --patch='[ { "op":"remove", "path": "/metadata/finalizers" }]' || true
        oc delete -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} ${m} || true
    done
  6. 次のコマンドを入力して、HostedControlPlane および ControlPlane HC namespace オブジェクトを削除します。

    # Delete HCP and ControlPlane HC NS
    $ oc patch -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} hostedcontrolplane.hypershift.openshift.io ${HC_CLUSTER_NAME} --type=json --patch='[ { "op":"remove", "path": "/metadata/finalizers" }]'
    $ oc delete hostedcontrolplane.hypershift.openshift.io -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} --all
    $ oc delete ns ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME} || true
  7. 次のコマンドを入力して、HostedCluster および HC namespace オブジェクトを削除します。

    # Delete HC and HC Namespace
    $ oc -n ${HC_CLUSTER_NS} patch hostedclusters ${HC_CLUSTER_NAME} -p '{"metadata":{"finalizers":null}}' --type merge || true
    $ oc delete hc -n ${HC_CLUSTER_NS} ${HC_CLUSTER_NAME}  || true
    $ oc delete ns ${HC_CLUSTER_NS} || true

検証

  • すべてが機能することを確認するには、次のコマンドを入力します。

    # Validations
    $ export KUBECONFIG=${MGMT2_KUBECONFIG}
    
    $ oc get hc -n ${HC_CLUSTER_NS}
    $ oc get np -n ${HC_CLUSTER_NS}
    $ oc get pod -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}
    $ oc get machines -n ${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}
    
    # Inside the HostedCluster
    $ export KUBECONFIG=${HC_KUBECONFIG}
    $ oc get clusterversion
    $ oc get nodes

次のステップ

ホストされたクラスター内の OVN Pod を削除して、新しい管理クラスターで実行される新しい OVN コントロールプレーンに接続できるようにします。

  1. ホストされたクラスターの kubeconfig パスを使用して KUBECONFIG 環境変数を読み込みます。
  2. 以下のコマンドを入力します。

    $ oc delete pod -n openshift-ovn-kubernetes --all

5.4.4.6. ホストされたクラスターをバックアップおよび復元するためのスクリプトの実行

ホストされたクラスターをバックアップし、AWS の同じリージョン内で復元するプロセスを迅速化するために、スクリプトを修正して実行できます。

手順

  1. 次のスクリプトの変数を独自の情報に置き換えます。

    # Fill the Common variables to fit your environment, this is just a sample
    SSH_KEY_FILE=${HOME}/.ssh/id_rsa.pub
    BASE_PATH=${HOME}/hypershift
    BASE_DOMAIN="aws.sample.com"
    PULL_SECRET_FILE="${HOME}/pull_secret.json"
    AWS_CREDS="${HOME}/.aws/credentials"
    CONTROL_PLANE_AVAILABILITY_POLICY=SingleReplica
    HYPERSHIFT_PATH=${BASE_PATH}/src/hypershift
    HYPERSHIFT_CLI=${HYPERSHIFT_PATH}/bin/hypershift
    HYPERSHIFT_IMAGE=${HYPERSHIFT_IMAGE:-"quay.io/${USER}/hypershift:latest"}
    NODE_POOL_REPLICAS=${NODE_POOL_REPLICAS:-2}
    
    # MGMT Context
    MGMT_REGION=us-west-1
    MGMT_CLUSTER_NAME="${USER}-dev"
    MGMT_CLUSTER_NS=${USER}
    MGMT_CLUSTER_DIR="${BASE_PATH}/hosted_clusters/${MGMT_CLUSTER_NS}-${MGMT_CLUSTER_NAME}"
    MGMT_KUBECONFIG="${MGMT_CLUSTER_DIR}/kubeconfig"
    
    # MGMT2 Context
    MGMT2_CLUSTER_NAME="${USER}-dest"
    MGMT2_CLUSTER_NS=${USER}
    MGMT2_CLUSTER_DIR="${BASE_PATH}/hosted_clusters/${MGMT2_CLUSTER_NS}-${MGMT2_CLUSTER_NAME}"
    MGMT2_KUBECONFIG="${MGMT2_CLUSTER_DIR}/kubeconfig"
    
    # Hosted Cluster Context
    HC_CLUSTER_NS=clusters
    HC_REGION=us-west-1
    HC_CLUSTER_NAME="${USER}-hosted"
    HC_CLUSTER_DIR="${BASE_PATH}/hosted_clusters/${HC_CLUSTER_NS}-${HC_CLUSTER_NAME}"
    HC_KUBECONFIG="${HC_CLUSTER_DIR}/kubeconfig"
    BACKUP_DIR=${HC_CLUSTER_DIR}/backup
    
    BUCKET_NAME="${USER}-hosted-${MGMT_REGION}"
    
    # DNS
    AWS_ZONE_ID="Z026552815SS3YPH9H6MG"
    EXTERNAL_DNS_DOMAIN="guest.jpdv.aws.kerbeross.com"
  2. スクリプトをローカルファイルシステムに保存します。
  3. 次のコマンドを入力して、スクリプトを実行します。

    source <env_file>

    ここの env_file は、スクリプトを保存したファイルの名前になります。

    移行スクリプトは、https://github.com/openshift/hypershift/blob/main/contrib/migration/migrate-hcp.sh のリポジトリーで管理されています。

Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

© 2024 Red Hat, Inc.