バックアップと復元
Rediaccは暗号化されたリポジトリをバックアップし、同じマシンまたは別のマシンで復元します。 バックアップが暗号化されているのは、リポジトリ自体が暗号化されているからです。マシンの外に出るのは暗号文であり、復元にはリポジトリのLUKS認証情報が必要です。
バックアップには2つの方法があり、それぞれ答える問いが異なります。
- チャンクストレージへのスナップショット(
rdc backup snapshot)は、さかのぼれる履歴を保持します。これが主な経路です。 - 別のマシンへのコピー(
rdc repo push、rdc repo pull)は、自分が管理するハードウェア上に、いまのリポジトリをそのまま保持します。クラウドアカウントは関与しません。
この2つは独立しています。一方の方法でバックアップしたリポジトリは、もう一方ではバックアップされていません。
スナップショットの仕組み
リポジトリイメージは固定サイズのグリッド上で固定サイズのセルに切り分けられます。各セルは、何も書き込まれたことがない穴であるか、そのセルの暗号文のSHA-256そのものであるキーの下に保存されているかのどちらかです。
この一つの決定から、すべての性質が生まれます。
課金されるのは本当の変更だけです。 初回のスナップショットは書き込み済みのセルをすべてアップロードします。それ以降の実行はすべて、どのエクステントが変更されたかをファイルシステムに問い合わせ、そこだけを読み取ってハッシュ化し、ストアがまだ持っていないセルだけをアップロードします。データがほとんど動いていないリポジトリはほぼ何もアップロードせず、実行時間はイメージのサイズに比例するのではなく、数分で終わります。
同一データは一度だけ保存されます。 キーがコンテンツのハッシュであるため、セルを共有する2つのスナップショットは同じオブジェクトを共有します。リポジトリとそのフォークも同様です。フォークファミリーは親を重複させることなく、一つの系統に対してバックアップされます。
古いスナップショットの復元は、新しいものより遅くなりません。 順番に再生すべき増分の連鎖は存在しません。復元はスナップショットを完全なセルのリストへ解決し、それらのセルを直接取得します。そのため復元にかかる時間はイメージのサイズと帯域幅で決まり、バックアップを取り始めてからの期間には左右されません。穴は穴のまま復元されるためスパースなイメージはスパースに復元され、イメージ内の複数箇所に現れるセルも一度だけダウンロードされます。
すべてのスナップショットはそれ単体で成立します。 失ってはならない「フルバックアップ」はなく、壊れた増分がその後すべてを無効化するような窓もありません。一覧にあるどのスナップショットも直接復元可能です。
検証は信頼ではなく再ハッシュです。 キーがコンテンツのハッシュである以上、バックアップの確認はセルを取得してハッシュ化することにほかなりません。rdc backup verifyはサンプリングし、rdc backup verify --deepは記録されたすべてのセルを再ハッシュ化します。
中断された実行は無駄になりません。 アップロードはすでに届いたセルを再送せずに再開され、途中で中断した復元を再開すると、すでにディスク上にあるものを再ハッシュ化して再利用し、再ダウンロードはしません。
コストの内訳
クォータは物理的に一意に保存されたバイト数で数えられます。これは重複排除後に実際に保持されている量であり、スナップショットが論理的に表す総量の合計ではありません。ゆっくり変化するリポジトリの30個のスナップショットは、1個分に近いコストで済みます。
rdc backup usageは保存済みバイト数をクォータと対比して表示します。クォータはサブスクリプションごとの数値で、Communityプランでは10 GBから始まります。
スナップショットに必要なもの
スナップショットのアップロードはアカウントサーバーを経由します。アカウントサーバーはリポジトリにインストールされたライセンスに対して各実行を認可し、マシンに書き込み用の短命な許可を発行します。そのためこの経路には、マシンが到達できるアカウントサーバーとライセンス済みのリポジトリが必要です。それらがなければ、スナップショットは黙ってスキップされるのではなく拒否され、rdc backup manifests、rdc backup usage、rdc backup retentionは読み取るものが何もない状態になります。
これは--dry-runにも当てはまります。実行が計画中なのかアップロード中なのかを判断する前にライセンスが読み取られるため、ドライランは認証情報なしでコマンドを試す方法ではなく、実際の作業のプレビューです。
マシン間のプッシュとプルはどちらも必要としません。すでに設定に含まれている2台のマシン間の直接転送です。
スナップショットが約束しないこと
- スナップショットは1つのリポジトリを対象とし、マシン全体を一度に対象とするものではありません。 各リポジトリはそれぞれの瞬間にキャプチャされます。2つのリポジトリが互いに依存している場合、それらのスナップショットは協調した組ではありません。
- 継続的なレプリケーションではありません。 スナップショットはある時点であり、最後にスナップショットを取ってから書き込まれたものはすべて失われる可能性があります。その量は実行頻度によって変わります。
- 保存されたオブジェクトは書き込み一回きりであり、認定されたWORMではありません。 セルは作成専用の条件付きで書き込まれ、マシンが受け取る許可には何かを削除する権限がありません。削除はサーバー側で保持ポリシーに従って行われます。これは侵害されたマシンが自分のバックアップを破壊することに対する現実的な障壁ですが、コンプライアンス認証ではなく、そのように監査されてもいません。
rcloneストレージ経路は廃止されました
rdc repo push --to <storage>とその関連コマンドは、かつては自分で登録したクラウドプロバイダにバックアップファイル全体をコピーしていました。これらは現在、ストレージ宛先を拒否し、代わりとなるコマンド名を示します。マシン間転送はもともとrcloneを経由していなかったため影響を受けません。その方法で書かれたアーカイブをまだ読む必要がある場合は、廃止前に書かれたアーカイブを読むを参照してください。
チャンクストレージのコマンド
# スナップショットをアップロードする。初回実行はシードし、以降は変更されたセルのみ送信する。
rdc backup snapshot my-app
# アップロードせずに計画する: 何が移動するかを報告する。
rdc backup snapshot my-app --dry-run
# コンテナを停止し、凍結し、再起動してからアップロードする。
rdc backup snapshot my-app --cold
# ローカルアンカーを信用せず、全インベントリを再アップロードする。
# これはすべてを再アップロードしてクォータを再課金するため、
# アンカーが不良であると分かっている場合にのみ使用する。
rdc backup snapshot my-app --reseed
# 保存されたインベントリとクォータを確認する。
rdc backup verify my-app
rdc backup manifests my-app
rdc backup usage
| オプション | 説明 |
|---|---|
<repo-ref>(位置引数) | スナップショットを取るリポジトリ |
--dry-run | 計画のみ: アップロードなし。何が移動するかを報告する |
--cold | コンテナを停止し、凍結し、再起動してからアップロードする。--dry-runとは併用できない |
--reseed | ローカルアンカーを信用せず、全インベントリをアップロードする。すべてを再アップロードしクォータを再課金する |
--debug | 詳細出力を有効化 |
コールドスナップショット(--cold)
コールドスナップショットは、凍結する前にリポジトリを停止します。そのため保存されるイメージはクラッシュ整合性ではなくアプリケーション整合性になります。コマンドはマシン上で直接実行します。
# 既定のデータストア上のすべてのリポジトリ。
sudo renet backup snapshot --cold
# 指定したリポジトリだけ。--repo はリポジトリのGUIDを取り、繰り返し指定できます。
sudo renet backup snapshot --cold --repo <guid> --repo <guid>
--coldは--dry-runと併用できません。コンテナを停止するドライランはドライではなく、停止しない実行はコールドではありません。そのためrenetは、意味を勝手に決めずにこの組み合わせを拒否します。
コールド実行の流れ
選択された各リポジトリについて、この順序で行われます。
- コンテナを停止する。
- リポジトリのマウントとデータストアをディスクに書き出す。
- コンテナが本当に停止したことを確認する。
- リポジトリイメージのコピーオンライトreflinkを取得する。
- コンテナを再び起動する。
アップロードが始まるのはその後で、そのときすべてのリポジトリはすでに稼働しています。
ダウンタイムは凍結であって転送ではありません。reflinkはメタデータだけなので、リポジトリが1 GBでも100 GBでも所要時間は変わりません。アップロードはそうはいきません。変更されたバイト数に応じて伸び、初回スナップショットは非ゼロのインベントリ全体を送ります。アップロードが終わるまでコンテナを止めたままにすると、ダウンタイムがデータ量に縛られ、初回シードでは数ミリ秒ではなく数時間になります。
選択されたリポジトリは1つずつではなく、1つのウィンドウでまとめて停止されます。リポジトリごとのダウンタイムはわずかに長くなりますが、その代わりに全体で1つの整合点が得られます。
コンテナが動いていないリポジトリはすでに静かな状態です。ダウンタイムなしでスナップショットが取られ、これは失敗ではなく正常な結果です。
ダウンタイムのコスト
実機で計測したところ、ダウンタイムの合計は222 msでした。
| フェーズ | 計測値 | 内容 |
|---|---|---|
cold_down | 64 ms | コンテナが停止する |
cold_sync | 26 ms | リポジトリのマウントとデータストアをディスクに書き出す |
cold_verify | 31 ms | コンテナの停止を確認する |
cold_stage | 0 ms | リポジトリイメージのreflink |
cold_up | 99 ms | コンテナが再び起動する |
大部分を占めるのはコンテナの再起動で、ステージングは事実上ゼロです。reflinkはミリ秒の分解能では現れません。ただし、このゼロは単独ではなくリポジトリごとのレコードと合わせて読んでください。すべてのリポジトリを拒否した実行もcold_stage=0msと報告するため、どちらの状況かはレコードだけが示します。
この内訳は飾りではなく根拠です。5つのフェーズはいずれもリポジトリのデータを読みも送りもしないため、バックアップが大きくなっても増えません。増えるのはアップロードだけで、それはダウンタイムが終わった後に走ります。
renetは実行の最後に同じ数値を出力するので、こちらの計測を信じる代わりに自分のマシンで測れます。
Cold backup: <n> repositories quiesced, outage 222ms (cold_down=64ms cold_sync=26ms cold_verify=31ms cold_stage=0ms cold_up=99ms)
各リポジトリのJSONレコードにも同じダウンタイムとフェーズが記録されるため、後から時間を頼りに推測しなくても、コールドかホットかを見分けられます。
コールドを選ぶ場面
既定はホットで、ほとんどのリポジトリにはそれが適しています。ホットスナップショットはクラッシュ整合性であり、停電後のリポジトリと同じ状態です。ダウンタイムはまったくかかりません。多くのデータベースやキューはその状態から自力で復旧します。
コールドは、書き込み中に安全に取得できないデータのために選びます。独自の先行書き込みログとメモリ上の状態を持つデータベースが典型例です。短くて計測済みのダウンタイムと引き換えに、アプリケーションが復旧処理なしで開けるスナップショットが手に入ります。
コールド実行が拒否するもの
拒否することこそが機能です。何も静止させていないのにコールドと名乗るバックアップは、復元のときにようやく判明する嘘です。そのためrenetはコールド実行を黙ってホットに格下げしません。
- 停止しなかったコンテナ。 停止のあと、renetはリポジトリ自身のDockerソケットに、まだ動いているものがあるかを尋ねます。あれば、そのリポジトリはスナップショットを取らずに拒否されます。この確認は安全側に倒れます。ソケットに到達できない場合やコンテナ一覧を読めない場合、静止は未確認とみなされ、未確認は拒否されます。
- 読み取れないライセンス。 ライセンスはダウンタイムの後ではなく前に確認されます。ライセンスを読めないリポジトリは、そもそも何もアップロードできなかったはずだからです。そうしたリポジトリは停止されることなくスキップされます。選択されたリポジトリのどれにも読めるライセンスがなければ、コンテナが1つも落ちないうちに実行全体が拒否されます。
- 同じデータストアに対する2つ目のコールド実行。 ロックはデータストア全体を覆い、ロックが使用中なら、何も停止しないまま即座に拒否されます。重なった2つの実行は、互いに相手のものだと思っているコンテナを止め合い、2つ目は1つ目がまだ凍結中のリポジトリを起動してしまいます。実行を見送って次を待つほうが安全です。
コンテナが停止している間にsystemctl stopや再起動で実行が中断された場合、renetは終了する前にコンテナを起動し直します。マシン側の復旧は最後の受け皿です。持ち主のいなくなったコールドバックアップを検知し、それらのリポジトリを起動し直します。
別のマシンへバックアップをプッシュする
SSH経由でリポジトリを2台目のマシンにコピーします。
rdc repo push my-app --to server-1
--to <machine>は設定から宛先を解決し、--to-machine <machine>は同じことを明示的に指定します。ストレージ名は拒否されます。その経路は廃止されました。
暗号化イメージは同じGUIDのままコピーされるため、これはフォークではなくバックアップまたは移行にあたります。独立したコピーが必要な場合は、先にrdc repo forkを実行してからフォークをプッシュしてください。
初回のプッシュはイメージ全体を運びます。それ以降の各プッシュは、両方のマシンに保持された不変のベースイメージに対する変更ブロックのみを、フラグ設定なしで送信します。ベースを自分で指定したい場合は--delta-base <guid>を使います。
プッシュされたコピーは、稼働中のリポジトリとしてではなく、バックアップ成果物としてターゲットに置かれます。rdc backup restoreでそれをリポジトリに変えます。
rdc backup restore my-app@server-1 --as my-app --machine server-1 --up
特定時点のバックアップには、代わりにチャンクストレージを使います。rdc backup snapshot my-appは変更されたセルのみをアップロードし、rdc backup restore my-app --at <snapshot>でそのいずれからでも復元できます。
| オプション | 説明 |
|---|---|
<ref>(位置引数) | プッシュするリポジトリの参照 |
--to <remote> | 宛先のマシンまたはクラスター |
--to-machine <machine> | 宛先マシン、明示的に指定 |
--provision <provider> | ターゲットマシンが存在しない場合、このクラウドプロバイダを通じてプロビジョニングする |
--checkpoint | プッシュ前にCRIUチェックポイントを作成する(rediacc.checkpoint=trueラベル付きコンテナ用)。ターゲットはrepo up時に自動復元する |
--force | 既存のバックアップを上書き |
--bwlimit <limit> | rsync転送の帯域幅制限(例: 10M、500K) |
--delta-base <guid> | この不変ベースGUIDに対して変更されたブロックのみを転送する。省略すると自動でベースが選ばれる |
--strategy <strategy> | デルタベースを使う際のブロックデルタ戦略: auto、physical、shared |
--debug | 詳細出力を有効化 |
--skip-router-restart | 操作後のルートサーバー再起動をスキップ |
別のマシンからバックアップをプルする
保持しているマシンからリポジトリを取り戻します。
rdc repo pull my-app --from server-1
--upを追加すると、同じコマンドでマウントとデプロイを行います。代わりにチャンクストレージから復元するには、rdc backup restore my-app --at <snapshot-id>を使います。
プルは現在マウントされているリポジトリの上書きを拒否します。先にアンマウントしてからプルを実行し、その後rdc repo upで再度起動してください。ディレクトリベースのリポジトリは例外で、マウントされたままその場で同期されます。
| オプション | 説明 |
|---|---|
<ref>(位置引数) | プルするリポジトリの参照 |
--from <remote> | 送信元のマシンまたはクラスター |
--from-machine <machine> | 送信元マシン、明示的に指定 |
--force | 既存のローカルバックアップを上書き |
--up | プル後にリポジトリをマウントしてデプロイする |
--bwlimit <limit> | rsync転送の帯域幅制限(例: 10M、500K) |
--delta-base <guid> | この不変ベースGUIDに対して変更されたブロックのみを受信する |
--strategy <strategy> | デルタベースを使う際のブロックデルタ戦略: auto、physical、shared |
--debug | 詳細出力を有効化 |
--skip-router-restart | 操作後のルートサーバー再起動をスキップ |
バックアップの一覧表示
チャンクストレージ内のスナップショットを一覧表示します。
rdc backup manifests my-app
各行は保存された1つの時点です。
| カラム | 意味 |
|---|---|
Repo | ローカル設定から解決されたリポジトリ名(設定にないリポジトリの場合はGUIDにフォールバック) |
Snapshot | スナップショットID。rdc backup restore --atが受け取るのはこれ |
Created | スナップショットを取得したUTC時刻 |
Total | このスナップショットが表すリポジトリイメージのサイズ |
Added | このスナップショットが直前までのものに加えて実際にアップロードしたバイト数 |
Chunks | 追加されたセルの数 |
rdc repo push --to <machine>が宛先に残したものを確認するには、そのマシンが何を保持しているか尋ねます。
rdc repo list --machine server-1
プッシュされたコピーは自分の名前で表示されます。その隣に生のGUIDを持つ2行目があれば、それは保持されているデルタベースであり、そのマシンへの次回のプッシュを全転送ではなく差分転送にするものです。
rdc backup list --machine <machine>はスケジュール実行が書き込むhot/とcold/フォルダを読み取るため、プッシュが置いたコピーには向いていないツールで、何も表示されません。
| カラム | 意味 |
|---|---|
Mode | hotまたはcold。このエントリが属するスケジュールバックアップフォルダ |
Name | ローカル設定から解決されたリポジトリ名(設定にないリポジトリの場合はGUIDにフォールバック) |
GUID | ディスク上のリポジトリGUID |
Size | バックアップファイルの人間可読のサイズ |
Modified | マシン上のファイルのUTCタイムスタンプ |
ストレージバックエンドの一覧表示はrclone側の仕組みとともに廃止されました。コマンドは拒否され、代わりとなるこの2つが示されます。
保持期間
サーバーはチャンクストア全体に対してリポジトリごとの保持ポリシーを強制するため、手で何も削除しなくても古いスナップショットは刈り取られます。ポリシーが宣言されていない場合、すべてのスナップショットが保持されます。
# 現在強制されている内容。
rdc backup retention my-app
# ローリングウィンドウを保持する: 日次7、週次4、月次6。
rdc backup retention set my-app --keep-daily 7 --keep-weekly 4 --keep-monthly 6
# すべてを保持する状態に戻す。
rdc backup retention clear my-app
| オプション | 説明 |
|---|---|
--keep-last <n> | 直近のスナップショットをこの数だけ保持する |
--keep-hourly <n> | この時間数分、各時間の最新スナップショットを保持する |
--keep-daily <n> | この日数分、各日の最新スナップショットを保持する |
--keep-weekly <n> | この週数分、各週の最新スナップショットを保持する |
--keep-monthly <n> | この月数分、各月の最新スナップショットを保持する |
--keep-yearly <n> | この年数分、各年の最新スナップショットを保持する |
少なくとも1つのルールを指定してください。ルールなしでsetを実行すると「何も保持しない」とはみなされず拒否されます。ポリシーを解除するのはclearの役目だからです。
復元
rdc backup restoreはバックアップを稼働中のリポジトリに変えるコマンドで、両方の経路に対して同じ動詞を使います。異なるのは、何を対象に指定するかです。
# チャンクストレージからのある時点。
rdc backup restore my-app --as my-app-yesterday --at <snapshot-id> --up
# プッシュがマシンに残した成果物。
rdc backup restore my-app@server-1 --as my-app --machine server-1 --up
--atはrdc backup manifestsが示すスナップショットIDか、2026-08-14T12:00:00ZのようなRFC 3339形式の時刻を受け取ります。時刻を指定した場合は、その瞬間以前で最も新しいスナップショットに解決されます。それ以前にスナップショットが存在しない時刻を指定すると、繰り上げられるのではなく拒否されます。
--asで新しい名前の下に復元する場合は何も上書きしないため、稼働中のマシンに対する復元ドリルも安全に実行できます。すでに存在する名前への復元は拒否されます。
| オプション | 説明 |
|---|---|
<artifact-ref>(位置引数) | 復元対象。チャンクストアのスナップショットにはrepo、マシン上の成果物にはrepo@place |
--as <name> | 復元されるリポジトリの名前(既定は成果物と同じ名前) |
-m, --machine <machine> | 復元先のマシン |
--datastore <name> | この名前付きデータストアに復元する(接続先マシンがそれをホストする) |
--at <time> | ある時点を復元する: スナップショットIDまたはRFC 3339形式の時刻 |
--up | 転送後に復元されたリポジトリをデプロイする |
--health-window <seconds> | デプロイされたリポジトリの健全性を監視する時間 |
--health-timeout <seconds> | 健全になるまで待機する時間 |
-y, --yes | 確認をスキップ |
--debug | 詳細出力を有効化 |
リポジトリの復元には、設定に含まれるLUKS認証情報が必要です。config storageを有効にしている場合、この認証情報は新しいマシン上でも設定と一緒に戻ってきます。有効にしていない場合は、マシンの故障が道連れにしない場所に設定のコピーを保管しておいてください。
マシンごとに復元を実証する
一度も往復させたことのないマシンは、アップロードがどれほど順調に見えてもバックアップされているとは言えません。アップロードと復元は失敗する理由が異なり、後者の種類の失敗は実際に試したときにしか現れません。
バックアップに頼る前に、マシンごとに一度実施してください。
- スナップショットを取る:
rdc backup snapshot my-app。 - 記録されたことを確認する:
rdc backup manifests my-app。 - 使い捨ての名前で復元する:
rdc backup restore my-app --as my-app-drill --at <snapshot-id>。 - 復元したリポジトリを元のものと比較し、
rdc repo delete my-app-drill --yesでドリルコピーを削除する。
この一連の手順は稼働中のリポジトリにはいっさい触れないため、トラフィックを処理しているマシンでも安全です。古いバックアップの仕組みから移行している最中であれば、そのマシンでこの手順が少なくとも一度成功するまで、古い仕組みも動かし続けてください。2つのバックアップ経路はストレージのコストがかかりますが、1つの未実証の経路はデータそのものを失うコストがかかります。
リポジトリを1つずつ同期する
プッシュとプルは、ref(name、name:tag、name@machineのいずれか)で指定した単一のリポジトリに対して動作します。「すべてのリポジトリを一度に」という形式はありません。リポジトリごとにコマンドを1回ずつ実行してください。
フォークとマシンを指定するrefも、単純な名前と同じように機能します。
rdc repo push shop:nightly@server-1 --to server-2
rdc repo pull shop:nightly@server-1 --from server-2
すべてのオプションは別のマシンへバックアップをプッシュすると別のマシンからバックアップをプルするにまとめられています。
スケジュールバックアップ
Rediaccは名前付きバックアップ戦略を使用します。各戦略はスケジュール、バックアップモード、任意の帯域幅制限、ファイルフィルターを定義します。戦略名をマシンにバインドすることで、どこで何を実行するかを制御します。
バックアップモード
| モード | 動作 | ダウンタイム |
|---|---|---|
hot | サービスが稼働したままリポジトリイメージを凍結する(クラッシュ整合性) | なし |
cold | サービス停止、スナップショット取得、サービス再起動、スナップショットアップロード(アプリケーション整合性) | リポジトリごとの停止+起動ウィンドウ、リポジトリ間で並列化。下記「コールドバックアップのダウンタイム見積もり」を参照。 |
クラッシュ整合性スナップショットが許容されるサービスにはhotを使用します。保証された整合性が必要で短い再起動を受け入れられる場合はcoldを使用します。
コールドバックアップのセマンティクス
コールドバックアップは、対象リポジトリごとに3つのフェーズで実行されます: 停止 → スナップショット → 起動。保証の限界を理解することで、部分的な障害を早期に検出できます。
コールドバックアップが保証すること:
- スナップショット前に、各対象リポジトリで実行中のすべてのコンテナがRediaccfileの
down()フックを通じて正常に停止され、リポジトリごとのDockerデーモンが静止されます。スナップショットはクラッシュ整合性だけでなく、アプリケーション整合性を持ちます。 - スナップショット前に実行されていたコンテナIDのセットが
/var/run/rediacc/cold-backup-<guid>.running.jsonのサイドカーファイルに保持されます。これが「完了時に再び起動すべきもの」の真実の情報源です。 - スナップショット後、リポジトリのRediaccfileの
up()フックが呼び出され、完全なcomposeスタックが復元されます。 - 実行ごとのステータスサイドカーファイル
/var/run/rediacc/cold-backup-<guid>.status.jsonに、各試行のフェーズ、結果、エラーが記録されます。
コールドバックアップが保証しないこと:
up()はベストエフォートです。コールドバックアップの制御外の理由で失敗する可能性があります(depends_on: service_healthy条件の待機中、composeファイルの構文エラー、イメージプル中の一時的なネットワーク障害など)。失敗した場合、コールドバックアップはエラーレベルでログを記録し、ステータスサイドカーを書き込み、次のリポジトリに進みます。up()が失敗した場合、直接フォールバック再起動が実行されます。実行サイドカーが読み込まれ、記録された各コンテナIDがDocker APIを通じて直接再起動されます(composeなし)。composeフローに問題があっても、Rediaccfileフックを再実行せずにサービスを復帰させます。- 一部のコンテナID(Dockerデーモン自体がダウンしているなど)のフォールバックが失敗した場合、サイドカーはそのまま残され、ルーターwatchdogが各ティックで再試行できるようにします。
Watchdog回復: 各ティックで、watchdogは実行サイドカーの存在を確認します。そこにリストされているコンテナIDのうち、現在停止しているものは、コンテナの保存されたrestart_policyに関わらず再起動されます。これにより、restart: on-failure(クリーンな停止後にDockerが再起動しない)のサービスも、コールドバックアップ後に復帰します。リストされたすべてのコンテナが実行中になると、サイドカーは削除されます。
オペレーターが障害を検出する方法:
rdc machine status <machine> --containersで実行状態を確認します。期待されるセットと比較してください。- マシン上の
/var/run/rediacc/cold-backup-<guid>.status.jsonを確認します。rdc term connect <repo> -c "cat /var/run/rediacc/cold-backup-$GUID.status.json"で検査できます。success: falseと古いstartedAtは、最後のバックアップが正常に完了しなかったことを示します。 - renetバックアップ実行のログ(
journalctl -u renet-*または直接のrdc backup schedule呼び出し)は、Cold backup: post-snapshot restart summary total=N compose_ok=N fallback_ok=N failed=N failed_repos=[...]の形式の最終サマリー行を出力します。空でないfailed_reposがgrepのターゲットです。
コールドバックアップのダウンタイム見積もり
各リポジトリは、自身のdown() + up()ウィンドウの間だけダウンします。ウォーム状態のホストでは通常:
| リポジトリの種類 | 典型的な停止+起動 |
|---|---|
| 小規模(コンテナ1-2個、DBなし) | 5-15秒 |
| 中規模(Webアプリ + キャッシュ) | 20-45秒 |
| 大規模(DB + キュー + メール) | 60-120秒 |
凍結ステップは、リポジトリイメージのコピーオンライトreflinkです。メタデータだけなので、リポジトリが1 GBでも100 GBでも所要時間は変わらず、実測ではミリ秒の分解能では現れませんでした。あるリポジトリが、他のリポジトリの凍結のために停止したままになることはありません。アップロードは凍結されたコピーに対して実行され、その間すべてのリポジトリはすでに復帰しています。
実行全体の所要時間(ウォールクロック) は、同時に再起動するリポジトリ数によって決まります。renetはホストからこの値を導出します。
concurrency = min(repoCount, max(2, NumCPU/2), 8)
例:
| ホスト | リポジトリ | 同時実行数 | ウォールクロックの再起動 |
|---|---|---|---|
| 4 CPUのVM | 5リポジトリ、各平均30秒 | 2 | ~75秒 |
| 16 CPUのサーバ | 10リポジトリ、各平均40秒 | 8 | ~80秒 |
| 64 CPUのフリートノード | 50リポジトリ、各平均40秒 | 8 | ~4分 |
環境変数によるオーバーライド: バックアップサービスの環境でREDIACC_COLD_BACKUP_CONCURRENCY=Nを設定(通常はsystemdドロップインを使用)すると、値を固定できます。=1は厳密な直列再起動を強制し、あるリポジトリのup()フックでのクラッシュループをデバッグする際に役立ちます。
レイテンシに敏感なリポジトリ(公開Webアプリ、メール)を運用している場合、そのダウンタイムは自身の停止+起動(通常30-90秒)で制限され、実行全体の長さではありません。リポジトリは発見された順序で同時実行スロットに割り当てられ、優先キューはありません。細かいスケジューリングが必要な場合は、重いリポジトリを--includeで限定した別の戦略に分けてください。
長時間実行されるバックアップとスケジュールの重複
自身のスケジュール間隔より長くかかるコールドバックアップ(例: 500 GBリポジトリの初回シードは適度な回線で正当に24時間以上かかることがあり、その間に夜間タイマーが再度発火する)は、2回目の実行をキューに入れたり起動したりしません。systemdのType=oneshotユニットは単一インスタンスです。タイマーが発火し、サービスがすでにactivatingの場合、systemdは起動を既存のジョブに統合します。新しいプロセスは起動されず、実行は後でのためにキューに入れられません。
具体的に、月曜日の03:00 UTCに開始し、木曜日の正午に終了する実行:
| 曜日 | 03:00 UTCの発火 | 結果 |
|---|---|---|
| 月曜日 | 最初の発火 | 実行開始 |
| 火曜日 | 2回目の発火 | 静かに破棄(前の実行がまだアクティブ) |
| 水曜日 | 3回目の発火 | 静かに破棄(前の実行がまだアクティブ) |
| 木曜日 | 実行が正午に終了 | キャッチアップなし。次の実行は金曜日の03:00 UTC |
タイマーのPersistent=trueディレクティブはこれらの発火を救いません。Persistent=trueは、タイマー自体が非アクティブだった(システムオフ、タイマー無効)ために見逃された発火を再生します。サービスがビジーだったために破棄された発火は失われます。
このデフォルトは意図的です。同じデータストアに対して2つのコールドバックアップを並行実行すると、凍結パス、アップロード、/var/run/rediacc/cold-backup-<guid>.status.jsonのリポジトリごとのサイドカーで競合します。実行中のインスタンスの後ろで待つほうが、同じデータを2方向から叩き合うより優れています。データストアロックがこれを強制します。2つ目のコールド実行はロックが使用中であることを検出し、何も停止しないまま即座に拒否されます。
モニタリングへの影響。 ハングしたバックアップ(例: ネットワークブラックホールで詰まったアップロード)は、その後のすべてのタイマー発火を静かに破棄します。スケジューラはアラームを発しません。systemctl show <unit> -p ActiveEnterTimestampを監視してください。サービスが予想実行時間より長くactivatingになっている場合(例: 夜間タイマーで48時間以上)、調査してください。
各スケジュール発火を実行する必要がある場合、タイマーをOnCalendar=<cron>からOnUnitInactiveSec=<間隔>に切り替えます。これは、固定のウォールクロックスケジュールではなく、前の実行の完了後N時間後に発火するため、長時間実行は破棄を引き起こしません。次の実行を後ろに押すだけです。トレードオフはスケジュールドリフトです。03:00の夜間は「最後の終了から24時間後」になります。
スナップショット、中断、およびプール容量
すべてのプッシュは瞬間的なデータストアスナップショットから動作するため、リポジトリが書き込みを続けている間もアップロードデータの整合性が保たれます。バックアップの実行中は、そのスナップショットがライブリポジトリと共有するすべてのブロックを参照し続けるため、サイクルが完了してスナップショットが削除されるまで、削除やトリムによる空き容量の解放量が減ります。ストレージの健全性レポートでは、バックアップスナップショットが現在確保している容量を確認できます。
中断しても安全です。サービスを停止する(またはマシンを再起動する)と、バックアップは転送を中断してスナップショットを削除してから終了します。すでに保存されているセルは再アップロードされないため、次のスケジュール実行では中断した箇所から再開されます。プロセスがクリーンアップできないほど強制終了された場合(電源断など)、孤立したスナップショットはストレージメンテナーによって数分以内に自動的に検出されて削除されます。
戦略の定義
標準的なデフォルトは2つの戦略の組み合わせです。すべてのリポジトリをキャプチャする高速な毎時ホットストリームと、アプリケーション整合性のあるスナップショットのためにコンテナを静止させる低速な毎週コールドストリームです。どちらも同じチャンクストレージに書き込まれ、共有ブロックはストリームごとではなく1回だけ保存されます。
rdc backup strategy set hourly-hot \
--destination rediacc \
--cron "0 * * * *" \
--mode hot \
--bwlimit 20M \
--enable
rdc backup strategy set weekly-cold \
--destination rediacc \
--cron "15 3 * * 0" \
--mode cold \
--include shop --include mail \
--enable
--destination <name>は戦略内部の宛先に名前を付けます。これは自分で選ぶラベルで、チャンクストアを表します。--includeはバックアップするリポジトリを列挙し、繰り返すことで追加できます。省略すると、その戦略はデータストア上のすべてのリポジトリを対象にします。名前はローカル設定のリポジトリ名(:tagなし)と一致させます。
--excludeはチャンクストア宛先に対しては黙って無視されるのではなく拒否されます。基盤となるbackup snapshotはリポジトリを名前で選択する仕組みであり、独自の除外機能を持たないためです。それを尊重すると、除外したはずのリポジトリをバックアップしてしまうことになります。代わりに--includeで戦略の対象を絞り込んでください。そうすればスケジュール実行が何をカバーするかは、推測ではなく明文化されます。
| オプション | 説明 |
|---|---|
<strategy>(位置引数) | 戦略名(マシンバインディングに使用) |
--destination <name> | 戦略内部の宛先名。既定はチャンクストア |
--storage <name> | 廃止されたrclone宛先の種類をオプトインする。これを使うスケジュールはデプロイできない |
--cron <expression> | cron式(例: "0 2 * * *" で毎日午前2時) |
--mode <hot|cold> | バックアップモード |
--bwlimit <limit> | アップロードの帯域幅制限(例: 10M) |
--include <repos> | この戦略が対象とするリポジトリ(繰り返し指定可能) |
--exclude <repos> | スキップするリポジトリ(繰り返し指定可能)。チャンクストア宛先では拒否される |
--folder <path> | rcloneバケット内のサブフォルダ。チャンクストア宛先では拒否される |
--enable / --disable | 戦略を有効化または無効化 |
戦略の表示
rdc backup strategy list
rdc backup strategy show weekly-cold
戦略の削除
rdc backup strategy remove weekly-cold
マシンへの戦略のバインド
どのマシンにもバインドされていない戦略は、決してデプロイされません。1つ以上の戦略をマシンにバインドします。
rdc backup strategy bind hourly-hot --machine hostinger
rdc backup strategy bind weekly-cold --machine hostinger
rdc backup strategy unbind weekly-cold --machine hostinger
バインディングは設定内にマシン上のリストとして記録され、rdc backup scheduleがどのユニットをデプロイするかを判断する際にこれを読み取ります。
{
"machines": {
"hostinger": {
"backupStrategies": ["hourly-hot", "weekly-cold"]
}
}
}
バインディングはローカル設定のみです。 戦略を定義してマシンにバインドしても、マシン自体には触れません。systemdタイマーをデプロイするには
rdc backup schedule -m <machine>を実行してください(マシンへのスケジュールのデプロイを参照)。戦略やバインディングを変更した後は再度実行してください。
ホットとコールドの選択、およびリポジトリごとのフィルタリング
ホットとコールドの概要
| ホット | コールド | |
|---|---|---|
| 整合性 | クラッシュ整合性(稼働中にイメージを凍結) | アプリケーション整合性(停止 → 凍結 → 起動) |
| ダウンタイム | なし | リポジトリごとの停止+起動ウィンドウ(通常5-120秒) |
| 適切な頻度 | 高頻度(例: 毎時) | 低頻度(例: 毎日または毎週) |
| 典型的な用途 | 高頻度のセーフティネット | スケジュールされた保証整合性バックアップ |
ホットは高頻度実行に適したデフォルトです。スナップショット取得中もサービスは稼働を続けるため、アプリにダウンタイムはまったくありません。スナップショットはクラッシュ整合性です。これは異常終了後に得られる状態と同等で、最新のデータベースやメッセージキューの多くはこれで十分です。
コールドは、保証されたアプリケーション整合性スナップショットが必要で、リポジトリごとの短い再起動を受け入れられる場合に適しています。サービスはスナップショット前に停止され、アップロード開始前に再起動されるため、遅いアップロードや失敗したアップロードによってダウンタイムのウィンドウが延びることはありません。完全な保証モデルについてはコールドバックアップのセマンティクスを参照してください。
どちらのモードも同じチャンクストアに書き込まれます。モードが左右するのは、イメージが凍結されている間にリポジトリをどう扱うかであり、データがどこに置かれるかではありません。毎時のホットスケジュールと毎週のコールドスケジュールの両方でカバーされるリポジトリは、共有するセルを2回ではなく1回だけ保存します。
戦略ごとのリポジトリのスコープ
--includeを指定しない戦略はデータストア上のすべてのリポジトリを対象にします。--includeを繰り返すと、指定した名前のリポジトリだけに絞り込まれ、ローカル設定のリポジトリ名(:tagなし)と一致させます。
# ホット戦略: すべてを毎時バックアップ
rdc backup strategy set hourly-hot \
--destination rediacc \
--cron "0 * * * *" \
--mode hot \
--bwlimit 6M \
--enable
# コールド戦略: 毎週、静止が必要なリポジトリだけを対象に
rdc backup strategy set weekly-cold \
--destination rediacc \
--cron "15 3 * * 0" \
--mode cold \
--include shop --include mail \
--enable
高頻度ホット戦略からリポジトリを除外するタイミング
以下の場合には、すべてを取り込ませる代わりに、高頻度実行に含めるリポジトリを名前で指定してください。
- リポジトリが大きく、ボリューム上に既にあるソースデータから完全に再生成可能で、毎時のバックアップが意味のある回復価値を追加せずに帯域幅を消費する場合。
- バックアップ実行が、利用可能なアップロード速度で自身のスケジュール間隔を超過する場合。
例。 analytics-demoリポジトリには、同じボリューム内に保存された生のCSVダンプから完全に再構築できる約114 GBの派生Postgresテーブルが含まれています。6 MB/sのアップロード制限では、そのリポジトリの初回スナップショットに5時間以上かかります。毎時実行すると、次の実行が発火する時点でまだ実行中であり、その後のすべての発火が静かに破棄されます(長時間実行されるバックアップとスケジュールの重複を参照)。hourly-hotには他のリポジトリだけを列挙し、analytics-demoはweekly-coldに任せることで、まったくバックアップされないのではなく週1回バックアップされるようになります。
データが純粋に再生成可能な場合、そもそもバックアップする必要があるかどうか検討してください。代替手段として、生のソース入力(この例ではCSVダンプ)のみをバックアップし、派生コピーを完全にスキップすることもできます。ソース入力の週次コールドバックアップははるかに小さく、回復には十分です。
両方の戦略がカバーするリポジトリは、毎時のクラッシュ整合性スナップショットと毎週のアプリケーション整合性スナップショットの両方を得ます。rdc backup manifests <repo>はそれらをまとめて表示し、共有されるセルは1回だけ保存されます。
バックアップ操作
マシンへのスケジュールのデプロイ
バインドされた戦略をsystemdタイマーとしてマシンにプッシュします。
rdc backup schedule -m server-1
rdc backup schedule -m server-1 --dry-run
デプロイは状態レコンサイラーです。マシン上の現在のユニットファイルとsystemdの状態を読み取り、設定が生成するであろう内容と比較し(ファイルごとにSHA-256)、内容が実際に変更されたユニットのみに触れます。設定変更なしで再実行してもno-opです。書き込みなし、daemon-reloadなし、タイマーの変動なしです。
--dry-runは、マシンに触れずに、各戦略のプラン(created、updated (service, timer, env)、unchanged、removed)を表示します。--debugと組み合わせると、生成されたユニット本体も認証情報を伏せた状態で表示されます。チャンクストアのユニットはそもそも認証情報を持ちません。マシンは自分自身の署名済みリポジトリライセンスで認証し、サーバーが短命な許可を返すため、ユニットファイルに機微な情報が書き込まれることはありません。
更新または削除しようとしている戦略のバックアップが現在実行中の場合、デプロイは直ちに失敗し、キャンセルするか--forceを渡すヒントが表示されます。--forceを使うと、実行中の呼び出しはメモリ内のユニットを保持し続け、新しい設定は次のタイマーティックで適用されるため、実行中のバックアップは決して強制終了されません。
--reset-failedはオプトインです。渡された場合、デプロイ成功後に変更されたサービスのsystemdの failed 状態をクリアします。既定では無効で、以前の障害シグナルがアラートに表示されたままになります。
今すぐバックアップを実行
タイマーを待たずに即座にバックアップを開始します。タイマーがデプロイされていなくても、systemd-runによるアドホック実行が可能です。
rdc backup run -m server-1
rdc backup run weekly-cold -m server-1
バックアップ状態の表示
バックアップタイマーの現在の状態と最近のジョブ結果を表示します。
rdc backup status -m server-1
rdc backup status hourly-hot -m server-1
実行中のバックアップのキャンセル
rdc backup cancel -m server-1
rdc backup cancel weekly-cold -m server-1
リポジトリの移行
リポジトリをあるマシンから別のマシンに移動します。
rdc repo migrate my-app@server-1 --to server-2
| オプション | 説明 |
|---|---|
<ref>(位置引数) | 移行するリポジトリの参照。@machine部分が移行元を指定する |
--to <place> | 宛先のマシンまたはクラスター |
--provision <provider> | このクラウドプロバイダを通じて、ターゲットマシンを自動プロビジョニングする(例: hetzner、linode) |
--checkpoint | 移行前にCRIUチェックポイントを作成し、プロセスのメモリも一緒に移動する |
--delta-base <guid> | 切り替え時のデルタに使う不変のベースGUID。既定は第一フェーズのベース |
--strategy <strategy> | 切り替え時のブロックデルタ戦略: auto、physical、shared |
--skip-dns | 移行後のDNSレコード更新をスキップ |
--keep-source | 移動成功後もソースイメージを保持する |
--bwlimit <limit> | 転送の帯域幅制限(例: 50M) |
移行はrsyncを介して、2つのフェーズで暗号化されたリポジトリデータを転送します。リポジトリが稼働したままの一括転送と、その後のデルタのための短い停止です。移行はリポジトリを移動させるため、移動が成功するとソースイメージは削除されます。それらを保持したい場合は--keep-sourceを渡してください。これがrepo migrateとrepo pushの違いです。プッシュはソースを稼働させたまま、手を触れずに残します。
廃止前に書かれたアーカイブを読む
rdc storageは、rcloneの仕組みのうち残っているもので、読み取り専用です。もはやバックアップ宛先にはなれませんが、その方法で書かれたアーカイブにはまだアクセスできます。
# すでにrclone用に設定済みのリモートを登録する。
rdc storage import rclone.conf
rdc storage list
# 中身を見る。これは自分のPATH上のrcloneを実行する。
rdc storage browse my-storage
importはrclone設定ファイルを読み取り、リモートを自分の設定に記録します。対応する種類はS3、B2、Google Drive、OneDrive、Mega、Dropbox、Box、Azure Blob、Swiftです。
browseはPATH上にrcloneがあることを必要とします。 これは自分がコマンドを入力しているマシンにインストールされたrcloneを実行します。もう埋め込みコピーはありません。なければそう伝え、それ以上は何もしません。
ストレージバックエンドへのプッシュ、プル、一覧表示、復元は廃止されており、それぞれ拒否された上で代わりのコマンドが示されます。
ベストプラクティス
- 重要なデータのアプリケーション整合性のあるコピーのために、毎日のコールドスナップショットをスケジュールする
- ゼロダウンタイムが必要な高頻度実行にはホットスナップショットを使用する
- 定期的に復元をテストする。
rdc backup restore --as <new-name>は何も上書きしないため、稼働中のマシンでもドリルは安全 - 手で刈り取る代わりに保持ポリシーを設定し、保持するウィンドウを明文化する
- 自分が管理するハードウェア上にコピーを持ちたい場合は、スナップショットに加えてマシン間コピーも保持する
- 認証情報を安全に保管する。バックアップは暗号化されているが、復元にはLUKS認証情報が必要