4.3.2.4. etcd バックアップからのクラスターの手動復元
「以前のクラスター状態への復元」セクションで説明されている復元手順は次のとおりです。
-
2 つのコントロールプレーンノードを完全に再作成する必要があります。ただし、UPI インストール方式でインストールされたクラスターでは複雑な手順になる可能性があります。UPI インストールでは、コントロールプレーンノード用の
MachineまたはControlPlaneMachinesetが作成されないためです。 - /usr/local/bin/cluster-restore.sh スクリプトを使用して、シングルメンバーの新しい etcd クラスターを起動し、それを 3 つのメンバーに拡張します。
これに対し、この手順は次の点が異なります。
- コントロールプレーンノードを再作成する必要はありません。
- 3 つのメンバーからなる etcd クラスターを直接起動します。
クラスターがコントロールプレーンに MachineSet を使用する場合は、etcd の回復手順を簡素化するために、「以前のクラスター状態への復元」を使用することを推奨します。
クラスターを復元する際に、同じ z-stream リリースから取得した etcd バックアップを使用する必要があります。たとえば、OpenShift Container Platform 4.7.2 クラスターは、4.7.2 から取得した etcd バックアップを使用する必要があります。
前提条件
-
cluster-adminロールを持つユーザー (例:kubeadminユーザー) としてクラスターにアクセスします。 -
すべて のコントロールプレーンホストへの SSH アクセス権があり、ホストユーザーが
root(デフォルトのcoreホストユーザーなど) になることが許可されている。 -
同じバックアップからの以前の etcd スナップショットと静的 Pod のリソースの両方を含むバックアップディレクトリー。ディレクトリー内のファイル名は、
snapshot_<datetimestamp>.dbおよびstatic_kuberesources_<datetimestamp>.tar.gzの形式にする必要があります。
手順
SSH を使用して各コントロールプレーンノードに接続します。
Kubernetes API サーバーは復元プロセスの開始後にアクセスできなくなるため、コントロールプレーンノードにはアクセスできません。このため、アクセスするコントロールプレーンホストごとに、別のターミナルで SSH 接続を使用することを推奨します。
重要この手順を完了しないと、復元手順を完了するためにコントロールプレーンホストにアクセスすることができなくなり、この状態からクラスターを回復できなくなります。
etcd バックアップディレクトリーを各コントロールプレーンホストにコピーします。
この手順では、etcd スナップショットと静的 Pod のリソースを含む
backupディレクトリーを各コントロールプレーンホストの/home/core/assetsディレクトリーにコピーしていることを前提としています。このassetsフォルダーがまだ存在しない場合は、作成する必要がある場合があります。すべてのコントロールプレーンノード上の静的 Pod を、一度に 1 つのホストずつ停止します。
既存の Kubernetes API サーバーの静的 Pod マニフェストを kubelet マニフェストディレクトリーから移動します。
$ mkdir -p /root/manifests-backup$ mv /etc/kubernetes/manifests/kube-apiserver-pod.yaml /root/manifests-backup/次のコマンドを使用して、Kubernetes API Server コンテナーが停止したことを確認します。
$ crictl ps | grep kube-apiserver | grep -E -v "operator|guard"コマンドの出力は空であるはずです。空でない場合は、数分待機してから再度確認します。
Kubernetes API サーバーコンテナーがまだ実行中の場合は、次のコマンドを使用して手動で終了します。
$ crictl stop <container_id>同じ手順を、
kube-controller-manager-pod.yaml、kube-scheduler-pod.yaml、最後にetcd-pod.yamlに対して繰り返します。次のコマンドで
kube-controller-managerPod を停止します。$ mv /etc/kubernetes/manifests/kube-controller-manager-pod.yaml /root/manifests-backup/次のコマンドを使用して、コンテナーが停止しているかどうかを確認します。
$ crictl ps | grep kube-controller-manager | grep -E -v "operator|guard"次のコマンドを使用して、
kube-schedulerPod を停止します。$ mv /etc/kubernetes/manifests/kube-scheduler-pod.yaml /root/manifests-backup/次のコマンドを使用して、コンテナーが停止しているかどうかを確認します。
$ crictl ps | grep kube-scheduler | grep -E -v "operator|guard"次のコマンドを使用して
etcdPod を停止します。$ mv /etc/kubernetes/manifests/etcd-pod.yaml /root/manifests-backup/次のコマンドを使用して、コンテナーが停止しているかどうかを確認します。
$ crictl ps | grep etcd | grep -E -v "operator|guard"
各コントロールプレーンホストで、現在の
etcdデータをbackupフォルダーに移動して保存します。$ mkdir /home/core/assets/old-member-data$ mv /var/lib/etcd/member /home/core/assets/old-member-dataこのデータは、
etcdバックアップの復元が機能せず、etcdクラスターを現在の状態に復元する必要がある場合に役立ちます。各コントロールプレーンホストの正しい etcd パラメーターを確認します。
<ETCD_NAME>の値は、各コントロールプレーンホストごとに一意であり、特定のコントロールプレーンホストのマニフェスト/etc/kubernetes/static-pod-resources/etcd-certs/configmaps/restore-etcd-pod/pod.yamlファイル内にあるETCD_NAME変数の値と同じです。次のコマンドで確認できます。RESTORE_ETCD_POD_YAML="/etc/kubernetes/static-pod-resources/etcd-certs/configmaps/restore-etcd-pod/pod.yaml" cat $RESTORE_ETCD_POD_YAML | \ grep -A 1 $(cat $RESTORE_ETCD_POD_YAML | grep 'export ETCD_NAME' | grep -Eo 'NODE_.+_ETCD_NAME') | \ grep -Po '(?<=value: ").+(?=")'<UUID>の値は、次のコマンドを使用してコントロールプレーンホストで生成できます。$ uuidgen注記<UUID>の値は 1 回だけ生成する必要があります。1 つのコントロールプレーンホストでUUIDを生成した後あ、他のホストで再度生成しないでください。次の手順では、すべてのコントロールプレーンホストで同じUUIDを使用します。ETCD_NODE_PEER_URLの値は、次の例のように設定する必要があります。https://<IP_CURRENT_HOST>:2380正しい IP は、次のコマンドを使用して、特定のコントロールプレーンホストの
<ETCD_NAME>から確認できます。$ echo <ETCD_NAME> | \ sed -E 's/[.-]/_/g' | \ xargs -I {} grep {} /etc/kubernetes/static-pod-resources/etcd-certs/configmaps/etcd-scripts/etcd.env | \ grep "IP" | grep -Po '(?<=").+(?=")'<ETCD_INITIAL_CLUSTER>の値は、次のように設定する必要があります。<ETCD_NAME_n>は各コントロールプレーンホストの<ETCD_NAME>です。注記使用するポートは 2379 ではなく 2380 である必要があります。ポート 2379 は etcd データベース管理に使用され、コンテナー内の etcd 起動コマンドで直接設定されます。
出力例
<ETCD_NAME_0>=<ETCD_NODE_PEER_URL_0>,<ETCD_NAME_1>=<ETCD_NODE_PEER_URL_1>,<ETCD_NAME_2>=<ETCD_NODE_PEER_URL_2>1 - 1
- 各コントロールプレーンホストの
ETCD_NODE_PEER_URL値を指定します。<ETCD_INITIAL_CLUSTER>値は、すべてのコントロールプレーンホストで同じです。次の手順では、すべてのコントロールプレーンホストで同じ値が必要です。
バックアップから etcd データベースを再生成します。
この操作は、各コントロールプレーンホストで実行する必要があります。
次のコマンドを使用して、
etcdバックアップを/var/lib/etcdディレクトリーにコピーします。$ cp /home/core/assets/backup/<snapshot_yyyy-mm-dd_hhmmss>.db /var/lib/etcd続行する前に、正しい
etcdctlイメージを特定します。次のコマンドを使用して、Pod マニフェストのバックアップからイメージを取得します。$ jq -r '.spec.containers[]|select(.name=="etcdctl")|.image' /root/manifests-backup/etcd-pod.yaml$ podman run --rm -it --entrypoint="/bin/bash" -v /var/lib/etcd:/var/lib/etcd:z <image-hash>etcdctlツールのバージョンが、バックアップが作成されたetcdサーバーのバージョンであることを確認します。$ etcdctl version現在のホストの正しい値を使用して次のコマンドを実行し、
etcdデータベースを再生成します。$ ETCDCTL_API=3 /usr/bin/etcdctl snapshot restore /var/lib/etcd/<snapshot_yyyy-mm-dd_hhmmss>.db \ --name "<ETCD_NAME>" \ --initial-cluster="<ETCD_INITIAL_CLUSTER>" \ --initial-cluster-token "openshift-etcd-<UUID>" \ --initial-advertise-peer-urls "<ETCD_NODE_PEER_URL>" \ --data-dir="/var/lib/etcd/restore-<UUID>" \ --skip-hash-check=true注記etcdデータベースを再生成する場合、引用符は必須です。
added memberログに出力される値を記録します。次に例を示します。出力例
2022-06-28T19:52:43Z info membership/cluster.go:421 added member {"cluster-id": "c5996b7c11c30d6b", "local-member-id": "0", "added-peer-id": "56cd73b614699e7", "added-peer-peer-urls": ["https://10.0.91.5:2380"], "added-peer-is-learner": false} 2022-06-28T19:52:43Z info membership/cluster.go:421 added member {"cluster-id": "c5996b7c11c30d6b", "local-member-id": "0", "added-peer-id": "1f63d01b31bb9a9e", "added-peer-peer-urls": ["https://10.0.90.221:2380"], "added-peer-is-learner": false} 2022-06-28T19:52:43Z info membership/cluster.go:421 added member {"cluster-id": "c5996b7c11c30d6b", "local-member-id": "0", "added-peer-id": "fdc2725b3b70127c", "added-peer-peer-urls": ["https://10.0.94.214:2380"], "added-peer-is-learner": false}- コンテナーから出ます。
-
この手順を他のコントロールプレーンホストでも繰り返し、
added memberログに出力される値がすべてのコントロールプレーンホストで同じであることを確認します。
再生成された
etcdデータベースをデフォルトの場所に移動します。この操作は、各コントロールプレーンホストで実行する必要があります。
再生成されたデータベース (以前の
etcdctl snapshot restoreコマンドによって作成されたmemberフォルダー) を、デフォルトの etcd の場所/var/lib/etcdに移動します。$ mv /var/lib/etcd/restore-<UUID>/member /var/lib/etcd/var/lib/etcdディレクトリーの/var/lib/etcd/memberフォルダーの SELinux コンテキストを復元します。$ restorecon -vR /var/lib/etcd/残りのファイルとディレクトリーを削除します。
$ rm -rf /var/lib/etcd/restore-<UUID>$ rm /var/lib/etcd/<snapshot_yyyy-mm-dd_hhmmss>.db重要完了すると、
/var/lib/etcdディレクトリーに含まれるフォルダーがmemberだけになります。- 他のコントロールプレーンホストでもこの手順を繰り返します。
etcd クラスターを再起動します。
- 次の手順は、すべてのコントロールプレーンホストで実行する必要があります。ただし、一度に 1 つのホストずつ 実行する必要があります。
kubelet が関連コンテナーを起動するように、
etcd静的 Pod マニフェストを kubelet マニフェストディレクトリーに戻します。$ mv /root/manifests-backup/etcd-pod.yaml /etc/kubernetes/manifestsすべての
etcdコンテナーが起動していることを確認します。$ crictl ps | grep etcd | grep -v operator出力例
38c814767ad983 f79db5a8799fd2c08960ad9ee22f784b9fbe23babe008e8a3bf68323f004c840 28 seconds ago Running etcd-health-monitor 2 fe4b9c3d6483c e1646b15207c6 9d28c15860870e85c91d0e36b45f7a6edd3da757b113ec4abb4507df88b17f06 About a minute ago Running etcd-metrics 0 fe4b9c3d6483c 08ba29b1f58a7 9d28c15860870e85c91d0e36b45f7a6edd3da757b113ec4abb4507df88b17f06 About a minute ago Running etcd 0 fe4b9c3d6483c 2ddc9eda16f53 9d28c15860870e85c91d0e36b45f7a6edd3da757b113ec4abb4507df88b17f06 About a minute ago Running etcdctlこのコマンドの出力が空の場合は、数分待ってからもう一度確認してください。
etcdクラスターのステータスを確認します。いずれかのコントロールプレーンホストで、次のコマンドを使用して
etcdクラスターのステータスを確認します。$ crictl exec -it $(crictl ps | grep etcdctl | awk '{print $1}') etcdctl endpoint status -w table出力例
+--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | +--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | https://10.0.89.133:2379 | 682e4a83a0cec6c0 | 3.5.0 | 67 MB | true | false | 2 | 218 | 218 | | | https://10.0.92.74:2379 | 450bcf6999538512 | 3.5.0 | 67 MB | false | false | 2 | 218 | 218 | | | https://10.0.93.129:2379 | 358efa9c1d91c3d6 | 3.5.0 | 67 MB | false | false | 2 | 218 | 218 | | +--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
他の静的 Pod を再起動します。
次の手順は、すべてのコントロールプレーンホストで実行する必要があります。ただし、一度に 1 つのホストずつ実行する必要があります。
次のコマンドを使用して、Kubernetes API サーバーの静的 Pod マニフェストを kubelet マニフェストディレクトリーに戻し、kubelet が関連するコンテナーを起動するようにします。
$ mv /root/manifests-backup/kube-apiserver-pod.yaml /etc/kubernetes/manifestsすべての Kubernetes API サーバーコンテナーが起動したことを確認します。
$ crictl ps | grep kube-apiserver | grep -v operator注記次のコマンドの出力が空の場合は、数分待ってからもう一度確認してください。
同じ手順を、
kube-controller-manager-pod.yamlファイルとkube-scheduler-pod.yamlファイルに対して繰り返します。次のコマンドを使用して、すべてのノードで kubelet を再起動します。
$ systemctl restart kubelet次のコマンドを使用して、残りのコントロールプレーン Pod を起動します。
$ mv /root/manifests-backup/kube-* /etc/kubernetes/manifests/kube-apiserver、kube-scheduler、およびkube-controller-managerPod が正しく起動しているかどうかを確認します。$ crictl ps | grep -E 'kube-(apiserver|scheduler|controller-manager)' | grep -v -E 'operator|guard'次のコマンドを使用して OVN データベースをワイプします。
for NODE in $(oc get node -o name | sed 's:node/::g') do oc debug node/${NODE} -- chroot /host /bin/bash -c 'rm -f /var/lib/ovn-ic/etc/ovn*.db && systemctl restart ovs-vswitchd ovsdb-server' oc -n openshift-ovn-kubernetes delete pod -l app=ovnkube-node --field-selector=spec.nodeName=${NODE} --wait oc -n openshift-ovn-kubernetes wait pod -l app=ovnkube-node --field-selector=spec.nodeName=${NODE} --for condition=ContainersReady --timeout=600s done