Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
proposed |
@proglottis
|
@DylanGriffith
| devops systems | 2023-04-26 |
リポジトリのバックアップ
要約
この提案は、Gitaly特有の最適化を適用する機会を増やす、GitLabにそのまま使えるリポジトリバックアップソリューションを提供しようとするものです。リポジトリのバックアップをbackup.rake
から、リポジトリを列挙し、リポジトリのバックアップをGitalyからオブジェクトストレージに直接ストリーミングするトリガーとなるリポジトリごとの決定を行う調整ワーカーに移行します。
このアプローチの利点は
- バックアップは、物理リポジトリをホストするGitalyからオブジェクトストレージに一度だけ転送されます。
- 特定のリポジトリアクセスパターンを活用することで、よりスマートな意思決定を行うことができます。
- バックアップとリストアの負荷を分散します。
- 全てのプロセスはGitaly内で実行されるため、既存のモニタリングを使用することができます。
- 将来のWALアーカイブやその他の最適化のためのアーキテクチャを提供します。
これにより、既存の2つの戦略の主要なペインポイントが緩和されるはずです:
-
backup.rake
- リポジトリのバックアップは、RPCを使用してGitalyの外部からストリーミングされ、単一の大きなtarファイルに保存されます。転送されるデータ量が多いため、これらのバックアップは小規模なインストールに限られます。 - スナップショット - クラウドプロバイダーは物理ストレージのスナップショットを取ることができます。これらはクラウドプロバイダー特有のものであり、すぐに利用できるソリューションではありません。
動機
目標
- リポジトリバックアップの作成とリストアにかかる時間の改善。
- リポジトリバックアップの監視を改善します。
非ゴール
- ファイルシステムベースのスナップショットの改善。
ファイルシステムベースのスナップショット
スナップショットは、GitalyとPraefectがデータを保存するために使用するディスクの物理的なスナップショットを取ることができるクラウドプラットフォームに依存しています。この戦略は、backup.rake
を使用したバックアップの作成や復元に時間がかかりすぎる場合に使用される傾向があります。
GitalyとGitは、ロックファイルとfsyncを使用して、同時処理によるリポジトリの破損やクラッシュによる部分的な書き込みを防ぎます。これは一般的に、ファイルが書き込まれればそれが有効になることを意味します。しかし、Gitリポジトリは多くのファイルで構成されており、多くの書き込みオペレーションが行われている可能性があるため、ファイルオペレーションが行われていない間にスナップショットをスケジュールすることは不可能です。つまり、スナップショットの一貫性を保証することはできず、スナップショットのバックアップから復元するには手動での操作が必要になります。
WALはクラッシュ耐性を向上させ、スナップショットからの自動リカバリを改善するかもしれませんが、各リポジトリはまだ同期している投票レプリカの大多数を必要とするでしょう。
Gitaly Clusterの各ノードはレプリケーション要因によって均質ではないため、完全なスナップショットバックアップを作成するには、すべてのノードでスナップショットを取得する必要があります。つまり、スナップショット・バックアップはリポジトリ・データの重複が多いということです。
スナップショットはクラウドプロバイダに大きく依存するため、すぐに利用できるものではありません。
ダウンタイム
理想的なリポジトリバックアップソリューションでは、バックアップとリストアの両方のオペレーションをオンラインで行うことができます。具体的には、各ノード/リポジトリが一貫していることを確認するために、書き込みをシャットダウンしたり一時停止したりしたくありません。
一貫性
リポジトリのバックアップの一貫性とは、次のような意味です:
- Git リポジトリがリストア後も有効であること。部分的に適用されるオペレーションがないこと。
- クラスター内のすべてのリポジトリがリストア後にヘルシーであるか、自動的にヘルシーになること。
一貫性のないバックアップは、データ損失の原因になったり、リストア時に手動介入が必要になることがあります。
スナップショットでは、複数のホストのファイルシステムのスナップショットを同期的に、かつ、それらのホストのリポジトリが現在変異していない状態で取得する必要があるため、両方のタイプの一貫性を実現するのは困難です。
作業のディストリビューション
backup.rake
、単一のGitalyノード、または単一のネットワーク接続を実行しているマシン上でボトルネックにならないように、バックアップ/リストア作業を分散したいと思います。
バックアップの際、backup.rake
、すべてのリポジトリバックアップを内部ファイルシステムに集約します。これは、すべてのリポジトリデータをGitalyから(おそらくPraefect経由で)Rakeタスクが実行されている場所にストリーミングする必要があることを意味します。これがCNGの場合、Kubernetes上に大きなボリュームも必要になります。その結果、バックアップtarファイルはオブジェクトストレージに転送されます。同様のプロセスがリストア時にも発生し、リポジトリのサブセットをリストアする場合の部分的なリストアであっても、tarファイル全体をダウンロードしてローカルファイルシステム上で展開する必要があります。事実上、すべてのリポジトリデータは、複数のホスト間で複数回、完全に転送されます。
もし各Gitalyが直接バックアップをアップロードすることができれば、リポジトリデータの転送は1回で済み、ホストの数を減らすことができます。
Gitalyコントロール
Gitalyは自己完結型になることを目指しているので、バックアップを所有する必要があります。
backup.rake
現在、どのリポジトリをバックアップし、そのバックアップをどこに保存するかを決定しています。これはGitalyが適用できる最適化の種類を制限し、開発/テストの複雑さを加えます。
モニタリング
backup.rake
は様々な環境で実行されています。歴史的にGitalyから見たバックアップは、一連の切断されたRPC呼び出しです。そのため、バックアップのモニタリングはほぼゼロでした。理想的なのは、Gitaly内でプロセスが実行され、既存のメトリクスやログスクレイピングを使用してプロセスを監視できることです。
自動バックアップ
backup.rake
がcronで設定されている場合、正常に実行されているかどうか、まだ実行されているかどうか、どれくらいの時間かかったか、どれくらいの容量がかかったかを確認することは困難です。増分バックアップやバックアップの更新が必要かどうかを判断するために、cronが常に前回のバックアップにアクセスできるようにすることは困難です。
継続的に実行される調整プロセスを持つことで、単発バックアップ戦略から、各リポジトリが使用パターンと優先度に基づいて独自のバックアップスケジュールを決定する戦略への移行が可能になります。こうすることで、各リポジトリはGitalyノードに過剰な負荷をかけることなく、適度に最新のバックアップを持つことができるはずです。
更新されたリポジトリのみ
backup.rake
はすべてのリポジトリのバックアップを tar ファイルにパッケージ化し、一般的に以前のバックアップにはアクセスできません。このため、リポジトリが前回のバックアップ以降に変更されたかどうかを判断するのは困難です。
オブジェクトストレージ上で以前のバックアップにアクセスできることは、Gitalyがバックアップを取る必要があるかどうかをより簡単に判断できることを意味します。これにより、もはや変更されていないリポジトリのバックアップに無駄な時間を費やすことがなくなります。
ポイントインタイム・リストア
リポジトリのセットを特定の時点にリストアできるメカニズムが必要です。使用される識別子(バックアップID)は管理者が決定でき、すべてのリポジトリに適用される必要があります。
WAL(先行ログ書き込み)
私たちは、WALの継続的なアーカイブを可能にするインフラを提供したいと考えています。これは、アーカイブをストリーミングする中心的な場所を提供し、リポジトリがフルバックアップからリストアされ、WALが特定の時点まで適用されるように、ログの場所とフルバックアップを一致させることができることを意味します。
WORM
Gitalyのアクセス可能なストレージは、攻撃者がノードのオブジェクトストレージの認証情報にアクセスした場合に、既存のバックアップが変更されるのを防ぐために、WORM(write once, read many)である必要があります。
リポジトリのバックアップで現在使用されているポインタレイアウトは、ポインタファイルを上書きできることに依存しています。
WORMはオブジェクトストレージプロバイダー特有のものでしょう:
bundle-uri
バックアップデータに直接アクセスすることで、bundle-uriを使ったクローン/フェッチ転送の最適化の道が開けるかもしれません。これにより、リポジトリ自体からパックを転送する代わりに、Gitクライアントを直接バンドルファイルに向けることができます。リポジトリの一括転送はより高速になり、Gitalyサーバーではなく、普通のhttpサーバーにオフロードされます。
提案
提案は初期MVPとリポジトリごとのコーディネーターに分かれています。
MVP
MVPの目標は、バックアップ処理をサーバーサイドに移行することで、最悪のケース、つまり全損シナリオが改善されることを検証することです。つまり、フルバックアップの作成と復元にかかる総時間を短縮することです。
MVP では、バックアップとリストアのリポジトリ RPC を導入します。調整ワーカーは存在しません。RPCは、呼び出されたGitalyノードからオブジェクトストレージに直接バックアップをストリーミングします。これらのRPCは、backup.rake
からgitaly-backup
ツールを介して呼び出されます。backup.rake
、リポジトリのバックアップはバックアップアーカイブにパッケージされなくなります。
この作業はすでに進行中で、サーバーサイドバックアップMVPエピックによって追跡されています。
リポジトリ単位のコーディネータ
backup.rake
経由ですべてのリポジトリのバックアップを一度に取る代わりに、バックアップ調整ワーカーが作成されます。このワーカーは定期的にすべてのリポジトリを列挙し、バックアップを取る必要があるかどうかを決定します。これらの決定は、使用パターンやリポジトリの優先順位によって決定されます。
リストアの際、リポジトリごとにバックアップの状態が異なるため、タイムスタンプがユーザーから提供されます。このタイムスタンプは、リポジトリごとにどのバックアップをリストアするかを決定するために使用されます。WALアーカイブが実装されると、指定されたタイムスタンプまでWALを再生することができます。
この幅広い取り組みはサーバーサイドバックアップエピックで追跡されます。
デザインおよび実施内容
MVP
BackupRepository
とRestoreRepository
の 2 つの RPC があります。これらの RPC は、同期的にオブジェクト・ストレージに直接バックアップを作成/リストアします。backup.rake
は、新しい--server-side
フラグでgitaly-backup
を引き続き使用します。各 Gitaly には、使用するオブジェクトストレージサービスを指定するバックアップ設定が必要です。
当初、オブジェクトストレージ内のバックアップの構造は、既存のポインタレイアウトと同じになります。
MVPの場合、バックアップIDはオブジェクトストレージ上のバックアップIDと完全に一致する必要があります。
オブジェクト ストレージの設定は、新しい configconfig.backup.go_cloud_url
によって制御されます。Goクラウド開発キットは、認証の設定にプロバイダ固有の方法を使用しようとします。これは、VMまたは環境変数から推測できます。サポートされるストレージサービスを参照してください。