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

Kubernetesディストリビューション — 自分で立てる

スナップショットを実行したらデータストアが SQLite だった

TT Labで続きを見る

目標

k3sサーバー1台のデータストアがSQLite(kine)であることを確認し、etcdのスナップショットが拒否される理由を見たうえで、--cluster-initで再起動して内蔵etcdへ移行します。 スナップショットをトークンと一緒にバックアップし、--cluster-resetで復元して、スナップショット以降の変更が消えることと、以前のデータがどこに残るかを記録します。

なぜ重要なのか

k3sは1台で始めると、etcdの代わりにSQLiteを使います。軽量で高速ですが、複数のサーバーで共有できず、k3s etcd-snapshotのようなetcdのツールが動作しません。 そのため「バックアップを導入しよう」という日になって初めてデータストアが何かを確認することになり、そのときの選択肢は、ファイルを丸ごとコピーするSQLiteのバックアップか、etcdへの移行です。 etcdへの移行は再起動1回で済みますが、復元は「その時点へ戻すこと」なので、スナップショット以降に作ったものは消えます。そして、サーバートークンがないとスナップショットは役に立ちません。 このラボでは、その3つ、すなわちデータストアの確認、移行、復元が元に戻す範囲を、本物のk3sで1回ずつ体験します。etcdを最初から使うk0sのラボと違い、データストアを切り替える過程そのものを扱います。

ステップ

  1. ネームスペースk3s-dsにConfigMapmarker(stage=sqlite)を作成してください。そして次のフィールドを書いてください(書き込み先: /root/k3s-ds/datastore.json)。datastore(sqliteまたはetcd)、db_files(/var/lib/rancher/k3s/server/dbのファイル名をソートした配列)、kine_table(state.dbの中のテーブル名のうちkineが使うもの)、kine_endpoint(k3sのログのKine available atの後のアドレス)、marker_uid(markerのUID)です。
  2. 現在の状態でk3s etcd-snapshot saveを実行し、標準出力と標準エラー出力をまとめて保存してください(保存先: /root/k3s-ds/snapshot-refused.txt)。そして、SQLiteのデータストアをバックアップするためにコピーすべきディレクトリとファイルの絶対パスを、1行に1つずつ書いてください(書き込み先: /root/k3s-ds/sqlite-backup.txt)。
  3. /etc/rancher/k3s/config.yamlにcluster-init: trueを書いて、k3sを再起動してください。markerが残っていることを確認し、次のフィールドを書いてください(書き込み先: /root/k3s-ds/migrate.json)。marker_uid(再起動後のmarkerのUID)、sqlite_file_now(dbディレクトリで元のstate.dbが変わった名前)、node_roles(ノードのnode-role.kubernetes.io/ラベルの名前をソートした配列。例: ["control-plane"])、member_name(db/etcd/nameファイルの内容)です。
  4. markerのstageをsnapshottedに変更してから、k3s etcd-snapshot save --name lab-beforeでスナップショットを取得してください。次のフィールドを書いてください(書き込み先: /root/k3s-ds/snapshot.json)。name(作成されたスナップショット名の全体)、path(ファイルの絶対パス)、size(バイト数、整数)、sha256(ファイルのSHA-256)です。
  5. /root/k3s-ds/backup/ディレクトリに、ステップ4のスナップショットファイル(同じ名前)とサーバートークンファイル(名前はtoken、権限は600)をコピーしてください。次のフィールドを書いてください(書き込み先: /root/k3s-ds/token-backup.json)。token_source(トークンの元ファイルの絶対パス)、token_sha256(トークンファイルのSHA-256)、snapshot_sha256(バックアップしたスナップショットのSHA-256)です。トークンの値そのものは、どこにも書かないでください。
  6. スナップショットの後に、ネームスペースk3s-dsにConfigMapafter-snap(x=1)を作成し、markerのstageをchangedに変更してください。次のフィールドを書いてください(書き込み先: /root/k3s-ds/after.json)。after_uid(after-snapのUID)、after_created(そのcreationTimestamp)、marker_stage(現在のmarkerのstage)です。
  7. k3sを停止し、k3s server --cluster-reset --cluster-reset-restore-path=<4단계 스냅숏 경로>で復元してから(プレースホルダーはステップ4のスナップショットのパスです。出力の全体を/root/k3s-ds/reset.logに保存します)、k3sを再び起動してください。次のフィールドを書いてください(書き込み先: /root/k3s-ds/restore.json)。old_dir(復元が以前のetcdデータを移したディレクトリ名)、restart_hint(reset.logの中で、k3sが次にすることを知らせている文のうち、restart withoutを含む部分までの最初の1文)、after_snap_exists(ブール値)、marker_stage(復元後のmarkerのstage)、member_name(復元後のdb/etcd/nameの内容)です。
  8. 次のフィールドを書いてください(書き込み先: /root/k3s-ds/report.json)。datastore_now(sqliteまたはetcd)、lost_objects(復元で消えたConfigMap名をソートした配列)、marker_stage(現在の値)、snapshot_dir(スナップショットが保存されたディレクトリの絶対パス)、restore_needs_token(別のサーバーで復元するときに元のトークンが必要かどうか、ブール値)、member_name_changed(復元の前後でetcdのメンバー名が変わったかどうか、ブール値)です。

参考

このクラスターのデータストアは何かを確認する

ネームスペースk3s-dsにConfigMapmarker(stage=sqlite)を作成してください。そして次のフィールドを書いてください(書き込み先: /root/k3s-ds/datastore.json)。datastore(sqliteまたはetcd)、db_files(/var/lib/rancher/k3s/server/dbのファイル名をソートした配列)、kine_table(state.dbの中のテーブル名のうちkineが使うもの)、kine_endpoint(k3sのログのKine available atの後のアドレス)、marker_uid(markerのUID)です。

k3sはSQLiteをAPIサーバーに直接接続せず、etcd APIを模倣するkineを間に置きます。APIサーバーの--etcd-serversが何を指しているかを、ログで確認してください。テーブル名はsqlite3 <파일> .tablesで見られます(プレースホルダーはファイル名です)。

スナップショットコマンドを実行したらデータストアがSQLiteだった

現在の状態でk3s etcd-snapshot saveを実行し、標準出力と標準エラー出力をまとめて保存してください(保存先: /root/k3s-ds/snapshot-refused.txt)。そして、SQLiteのデータストアをバックアップするためにコピーすべきディレクトリとファイルの絶対パスを、1行に1つずつ書いてください(書き込み先: /root/k3s-ds/sqlite-backup.txt)。

etcd-snapshotはサーバーにリクエストを送り、サーバーが内蔵etcdでスナップショットを取得します。データストアがSQLiteならサーバーが拒否し、詳しい理由はサーバーのログに残します。SQLiteは特別なコマンドなしにファイルをコピーしてバックアップしますが、データストア内の機密データを暗号化する値も一緒に保管する必要があります。

再起動1回でetcdへ移行する

/etc/rancher/k3s/config.yamlにcluster-init: trueを書いて、k3sを再起動してください。markerが残っていることを確認し、次のフィールドを書いてください(書き込み先: /root/k3s-ds/migrate.json)。marker_uid(再起動後のmarkerのUID)、sqlite_file_now(dbディレクトリで元のstate.dbが変わった名前)、node_roles(ノードのnode-role.kubernetes.io/ラベルの名前をソートした配列。例: ["control-plane"])、member_name(db/etcd/nameファイルの内容)です。

SQLiteで動いていたサーバーをcluster-initで起動すると、k3sがSQLiteの内容をetcdへ移します。すでにetcdのデータがディスクにある場合、この引数は無視されます。ログのMigrating content from sqlite to etcdを探してみてください。

名前を付けてスナップショットを取得する

markerのstageをsnapshottedに変更してから、k3s etcd-snapshot save --name lab-beforeでスナップショットを取得してください。次のフィールドを書いてください(書き込み先: /root/k3s-ds/snapshot.json)。name(作成されたスナップショット名の全体)、path(ファイルの絶対パス)、size(バイト数、整数)、sha256(ファイルのSHA-256)です。

--nameは名前の前半部分だけを決め、k3sがノード名と時刻を付け足します。保存場所は--etcd-snapshot-dirのデフォルト値です。k3s etcd-snapshot lsとkubectl get etcdsnapshotfileが、同じスナップショットを表示します。

スナップショットだけでは復元できない

/root/k3s-ds/backup/ディレクトリに、ステップ4のスナップショットファイル(同じ名前)とサーバートークンファイル(名前はtoken、権限は600)をコピーしてください。次のフィールドを書いてください(書き込み先: /root/k3s-ds/token-backup.json)。token_source(トークンの元ファイルの絶対パス)、token_sha256(トークンファイルのSHA-256)、snapshot_sha256(バックアップしたスナップショットのSHA-256)です。トークンの値そのものは、どこにも書かないでください。

k3sはサーバートークンで、データストア内の機密のブートストラップデータを暗号化します。別のトークンで復元すると、スナップショットは使えません。コピーするときに権限が広がらないようにしてください。

スナップショットの後にできたもの

スナップショットの後に、ネームスペースk3s-dsにConfigMapafter-snap(x=1)を作成し、markerのstageをchangedに変更してください。次のフィールドを書いてください(書き込み先: /root/k3s-ds/after.json)。after_uid(after-snapのUID)、after_created(そのcreationTimestamp)、marker_stage(現在のmarkerのstage)です。

次のステップの復元がこの2つをどう変えるかを見るためのものです。復元後にも、この記録が本物だったかを確認できるよう、UIDと時刻を正確に書いてください。

復元するとスナップショットの後の変更が消えた

k3sを停止し、k3s server --cluster-reset --cluster-reset-restore-path=<4단계 스냅숏 경로>で復元してから(プレースホルダーはステップ4のスナップショットのパスです。出力の全体を/root/k3s-ds/reset.logに保存します)、k3sを再び起動してください。次のフィールドを書いてください(書き込み先: /root/k3s-ds/restore.json)。old_dir(復元が以前のetcdデータを移したディレクトリ名)、restart_hint(reset.logの中で、k3sが次にすることを知らせている文のうち、restart withoutを含む部分までの最初の1文)、after_snap_exists(ブール値)、marker_stage(復元後のmarkerのstage)、member_name(復元後のdb/etcd/nameの内容)です。

復元は、サービスが停止した状態で、同じバイナリを1回だけ別に実行するものです。終わると自分で終了して、再起動するよう知らせます。以前のデータは削除せず、脇に移しておきます。連続した初期化を防ぐ目印のファイルが作られ、正常に起動すると削除されます。

何が残り、何が消えたのか

次のフィールドを書いてください(書き込み先: /root/k3s-ds/report.json)。datastore_now(sqliteまたはetcd)、lost_objects(復元で消えたConfigMap名をソートした配列)、marker_stage(現在の値)、snapshot_dir(スナップショットが保存されたディレクトリの絶対パス)、restore_needs_token(別のサーバーで復元するときに元のトークンが必要かどうか、ブール値)、member_name_changed(復元の前後でetcdのメンバー名が変わったかどうか、ブール値)です。

前のステップのjsonと、現在のディスクとクラスターを根拠にして書きます。採点ツールは、同じ値を記録ファイル・etcd-oldディレクトリ・クラスターからもう一度計算します。