TT Lab
はじめる
学ぶ 学習パス コース

Kubernetes運用実務

削除事故をスナップショットで戻す

TT Labで続きを見る

目標

実際にオブジェクトを削除したあと、スナップショットからよみがえらせます。復旧したデータディレクトリで2つ目のetcdを自分で起動し、「本当に戻ってきた」ことを目で確かめます。

なぜ重要なのか

復旧手順をドキュメントだけで知っていることと、一度やってみたことの差は大きいものです。特にsnapshot restoreがデータを巻き戻すコマンドではなく、新しいetcdクラスターを作るコマンドであるという事実は、自分の手でやってみて初めて身に付きます。だからこそ--name、--initial-cluster、--initial-advertise-peer-urls、--initial-cluster-tokenのようなアイデンティティ用のフラグを要求し、--data-dirには空の新しいパスを要求します。既存の/var/lib/etcdをそのまま指定した瞬間に、稼働中のデータに触れてしまいます。もう1つ重要なのが順序です。スナップショットをまず検証し、apiserverを止めて書き込みを止め、復旧し、マニフェストのhostPathを新しいパスに変え、最後にkubectlで確認します。この順序を逆にすると、使えないスナップショットでクラスターを立ち上げたり、復旧中に入った書き込みを失ったり、古いデータで再び起動したりすることになります。このラボでは、ライブクラスターを止めずに別のポートで復旧データを起動し、同じ結論にたどり着きます。

ステップ

  1. ネームスペースetcd-labと、その中のConfigMapetcd-lab-marker(data.owner=platform)を作成してください。そのあと/root/etcd/restore/out/pre.jsonに、事故前の状態をJSONで記録してください。キーはmarker_owner(値はplatform)、registry_keys(/registryの下のキーの数、20以上)、revision(現在のetcdのrevision、0より大きい)の3つです。
  2. 復旧に使うスナップショットを/root/etcd/restore/before.dbとして取り(20000バイト以上)、検証結果をJSONで/root/etcd/restore/out/before.jsonに保存してください。revisionが0より大きい必要があります。
  3. ConfigMapetcd-lab-markerを削除して、事故を再現してください。削除後にそのオブジェクトを取得した出力を/root/etcd/restore/out/gone.txtに残してください。ファイルにはNotFoundまたはnot foundのような「存在しない」という応答が含まれている必要があり、ライブクラスターにこのConfigMapが再び作られていてはいけません。
  4. before.dbを/root/etcd/restore/dataへ復旧してください。復旧後に/root/etcd/restore/data/member/snap/dbと/root/etcd/restore/data/member/walができている必要があります。復旧コマンドの出力(標準エラー出力を含む)を/root/etcd/restore/out/restore.txtに保存してください。
  5. 今度はアイデンティティ用のフラグをすべて付けて、/root/etcd/restore/data2へもう一度復旧してください。--data-dir、--name、--initial-cluster、--initial-advertise-peer-urls、--initial-cluster-tokenの5つのフラグがすべて含まれている必要があり、名前はrestored、ピアアドレスはhttp://127.0.0.1:12380、トークンはetcd-restore-labにしてください。実際に実行したコマンド全体を/root/etcd/restore/out/restore-cmd.txtにそのまま残してください(--data-dirに/var/lib/etcdを指定してはいけません)。
  6. /root/etcd/restore/data2をデータディレクトリとする2つ目のetcdプロセスをバックグラウンドで起動してください。クライアントアドレスはhttp://127.0.0.1:12379、ピアアドレスはhttp://127.0.0.1:12380、名前はrestored、初期メンバーはrestored=http://127.0.0.1:12380、トークンはetcd-restore-labです。採点が終わるまでこのプロセスを終了しないでください。起動に使ったコマンドを/root/etcd/restore/out/second-etcd.txtに保存してください(ファイルに12379と--data-dirが見えている必要があります)。
  7. 復旧データから/registry/configmaps/etcd-lab/etcd-lab-markerキーを読み取り、値にplatformが含まれているか確認して、その出力を/root/etcd/restore/out/recovered.txtに保存してください。取得先は127.0.0.1:12379で、ライブクラスター(2379)にはこのオブジェクトが依然として存在しない必要があります。
  8. /root/etcd/restore/runbook.mdに、復旧ランブックを400バイト以上で書いてください。各ステップは別々の行に置き、次の順序を守る必要があります。(1)スナップショットの検証(snapshot status)、(2)kube-apiserverの停止、(3)snapshot restore、(4)etcdマニフェストのhostPath/data-dirを新しいパスに置き換える、(5)kubectl getで確認。最後に、復旧が失敗した場合のロールバック方法も必ず書いてください。

参考

事故前の状態を数値で記録する

ネームスペースetcd-labと、その中のConfigMapetcd-lab-marker(data.owner=platform)を作成してください。そのあと/root/etcd/restore/out/pre.jsonに、事故前の状態をJSONで記録してください。キーはmarker_owner(値はplatform)、registry_keys(/registryの下のキーの数、20以上)、revision(現在のetcdのrevision、0より大きい)の3つです。

復旧は「何があったのか」を知ることから始まります。マーカーの値、/registryのキーの数、現在のrevisionの3つを1つのJSONにまとめてください。revisionはendpoint statusのヘッダーにあります。

復旧に使うスナップショットを確保して検証する

復旧に使うスナップショットを/root/etcd/restore/before.dbとして取り(20000バイト以上)、検証結果をJSONで/root/etcd/restore/out/before.jsonに保存してください。revisionが0より大きい必要があります。

復旧用のスナップショットは、取ったらすぐに検証します。事故が起きてからファイルが壊れていたと知っても、もう手遅れです。

削除事故を再現して痕跡を残す

ConfigMapetcd-lab-markerを削除して、事故を再現してください。削除後にそのオブジェクトを取得した出力を/root/etcd/restore/out/gone.txtに残してください。ファイルにはNotFoundまたはnot foundのような「存在しない」という応答が含まれている必要があり、ライブクラスターにこのConfigMapが再び作られていてはいけません。

オブジェクトを削除してから取得してみてください。存在しないリソースを取得したときのメッセージは標準エラー出力に出るので、リダイレクトに標準エラー出力も含めないとファイルに残りません。

スナップショットを新しいデータディレクトリへ復旧する

before.dbを/root/etcd/restore/dataへ復旧してください。復旧後に/root/etcd/restore/data/member/snap/dbと/root/etcd/restore/data/member/walができている必要があります。復旧コマンドの出力(標準エラー出力を含む)を/root/etcd/restore/out/restore.txtに保存してください。

復旧は既存のパスを上書きするのではなく、新しいパスを作る作業です。復旧ログも標準エラー出力に出ます。結果のディレクトリの中にmemberの構造ができているか確認してください。

クラスターのアイデンティティ用フラグを付けて復旧し直す

今度はアイデンティティ用のフラグをすべて付けて、/root/etcd/restore/data2へもう一度復旧してください。--data-dir、--name、--initial-cluster、--initial-advertise-peer-urls、--initial-cluster-tokenの5つのフラグがすべて含まれている必要があり、名前はrestored、ピアアドレスはhttp://127.0.0.1:12380、トークンはetcd-restore-labにしてください。実際に実行したコマンド全体を/root/etcd/restore/out/restore-cmd.txtにそのまま残してください(--data-dirに/var/lib/etcdを指定してはいけません)。

restoreは実は「新しいクラスターを1つ作る」コマンドです。名前、初期メンバー一覧、ピアアドレス、トークンの4つを明示すると、そのあとそのデータでetcdを起動できます。

復旧データで2つ目のetcdを起動する

/root/etcd/restore/data2をデータディレクトリとする2つ目のetcdプロセスをバックグラウンドで起動してください。クライアントアドレスはhttp://127.0.0.1:12379、ピアアドレスはhttp://127.0.0.1:12380、名前はrestored、初期メンバーはrestored=http://127.0.0.1:12380、トークンはetcd-restore-labです。採点が終わるまでこのプロセスを終了しないでください。起動に使ったコマンドを/root/etcd/restore/out/second-etcd.txtに保存してください(ファイルに12379と--data-dirが見えている必要があります)。

復旧したデータディレクトリを実際のプロセスに読み込ませて初めて、確認ができます。クライアントポートとピアポートをライブのetcdと重ならないようにし、採点が終わるまでプロセスを生かしておいてください。

削除したオブジェクトが復旧データに残っていることを確認する

復旧データから/registry/configmaps/etcd-lab/etcd-lab-markerキーを読み取り、値にplatformが含まれているか確認して、その出力を/root/etcd/restore/out/recovered.txtに保存してください。取得先は127.0.0.1:12379で、ライブクラスター(2379)にはこのオブジェクトが依然として存在しない必要があります。

Kubernetesのオブジェクトのetcdキーは/registry/<종류>/<네임스페이스>/<이름>です。値はprotobufなので人間には読みにくいですが、文字列はそのまま見えます。

復旧ランブックを書く

/root/etcd/restore/runbook.mdに、復旧ランブックを400バイト以上で書いてください。各ステップは別々の行に置き、次の順序を守る必要があります。(1)スナップショットの検証(snapshot status)、(2)kube-apiserverの停止、(3)snapshot restore、(4)etcdマニフェストのhostPath/data-dirを新しいパスに置き換える、(5)kubectl getで確認。最後に、復旧が失敗した場合のロールバック方法も必ず書いてください。

午前3時に読むドキュメントです。ステップの順序が重要で、失敗したときにどこへ戻るのかも書いておく必要があります。