大規模リファレンスアーキテクチャをバックアップおよび復元する
- プラン: Free、Premium、Ultimate
- 提供形態: GitLab Self-Managed
GitLabのバックアップは、大規模なGitLabのデプロイにおけるデータの一貫性を保ち、ディザスターリカバリーを可能にします。このプロセス:
- 分散ストレージコンポーネント全体でデータバックアップを調整します。
- 数テラバイトまでのPostgreSQLデータベースを保持します。
- 外部サービスでオブジェクトストレージデータを保護します。
- 大規模なGitリポジトリコレクションのバックアップの整合性を維持します。
- 設定ファイルとシークレットファイルの復元可能なコピーを作成します。
- システムデータを最小限のダウンタイムで復元できるようにします。
3,000人以上のユーザーをサポートするリファレンスアーキテクチャを実行しているGitLab環境向けの以下の手順に従ってください。クラウドベースのデータベースとオブジェクトストレージに関する特別な考慮事項を含みます。
このドキュメントは、以下の環境で使用することを想定しています:
- Linuxパッケージ(Omnibus)とクラウドネイティブハイブリッドリファレンスアーキテクチャ(60 RPS / 3,000ユーザー以上)
- RDS(PostgreSQLデータベース用)
- S3(オブジェクトストレージ用)
- オブジェクトストレージ (blobやコンテナレジストリを含む、可能な限りのすべてを保存するため)
毎日のバックアップを設定する
PostgreSQLデータベースのバックアップを設定する
The バックアップコマンドはpg_dumpを使用しますが、これは100 GBを超えるデータベースには適していません。ネイティブで堅牢なバックアップ機能を備えたPostgreSQLソリューションを選択する必要があります。
- AWS Backupを設定して、RDS(およびS3)データをバックアップします。保護を最大限にするため、継続的なバックアップとスナップショットのバックアップを設定します。
- AWS Backupを設定して、バックアップを別のリージョンにコピーします。AWSがバックアップを取得すると、そのバックアップは保存されたリージョンでのみ復元することができます。
- AWS Backupが少なくとも1回スケジュールされたバックアップを実行した後、必要に応じてオンデマンドバックアップを作成できます。
Schedule Google Cloud SQLデータの自動デイリーバックアップをスケジュールします。毎日のバックアップは最長1年間保持でき、トランザクションログは、ポイントインタイムリカバリーのためにデフォルトで7日間保持できます。
オブジェクトストレージデータのバックアップを設定する
オブジェクトストレージ (NFSではない )は、blobやコンテナレジストリを含むGitLabデータの保存に推奨されます。
AWS Backupを設定して、S3データをバックアップします。これは、PostgreSQLデータベースのバックアップを設定するときと同時に行うことができます。
各GitLabオブジェクトストレージバケットをバックアップバケットにコピーするStorage Transfer Serviceジョブを作成します。これらのジョブは一度作成すれば、毎日実行するようにスケジュールできます。ただし、これでは新しいオブジェクトストレージデータと古いデータが混ざり合い、GitLabで削除されたファイルもバックアップに残ることになります。これは復元する後にストレージを無駄にしますが、それ以外は問題ありません。これらのファイルはGitLabデータベースに存在しないため、GitLabユーザーにはアクセスできません。復元する後にこれらの孤立したファイルの一部を削除できますが、このクリーンアップRakeタスクはファイルの一部のみを操作します。
When to overwriteにはNeverを選択します。GitLabのオブジェクトストレージに保存されたファイルは、イミュータブルであるように設計されています。この選択は、悪意のあるアクターがGitLabファイルの改ざんに成功した場合に役立つ可能性があります。When to deleteにはNeverを選択します。バックアップバケットをソースに同期すると、ファイルが誤ってまたは悪意を持ってソースから削除された場合にリカバリーできません。
あるいは、オブジェクトストレージを日ごとに分離されたバケットまたはサブディレクトリにバックアップすることも可能です。これにより、復元する後の孤立したファイルの問題を回避し、必要に応じてファイルバージョンのバックアップをサポートします。しかし、バックアップストレージのコストが大幅に増加します。これは、Cloud SchedulerによってトリガーされるCloud Functionを使用するか、cronjobによって実行されるスクリプトを使用することで実現できます。部分的な例:
# Set GCP project so you don't have to specify it in every command gcloud config set project example-gcp-project-name # Grant the Storage Transfer Service's hidden service account permission to write to the backup bucket. The integer 123456789012 is the GCP project's ID. gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.objectAdmin gs://backup-bucket # Grant the Storage Transfer Service's hidden service account permission to list and read objects in the source buckets. The integer 123456789012 is the GCP project's ID. gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-artifacts gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-ci-secure-files gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-dependency-proxy gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-lfs gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-mr-diffs gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-packages gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-pages gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-registry gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-terraform-state gsutil iam ch serviceAccount:project-123456789012@storage-transfer-service.iam.gserviceaccount.com:roles/storage.legacyBucketReader,roles/storage.objectViewer gs://gitlab-bucket-uploads # Create transfer jobs for each bucket, targeting a subdirectory in the backup bucket. today=$(date +%F) gcloud transfer jobs create gs://gitlab-bucket-artifacts/ gs://backup-bucket/$today/artifacts/ --name "$today-backup-artifacts" gcloud transfer jobs create gs://gitlab-bucket-ci-secure-files/ gs://backup-bucket/$today/ci-secure-files/ --name "$today-backup-ci-secure-files" gcloud transfer jobs create gs://gitlab-bucket-dependency-proxy/ gs://backup-bucket/$today/dependency-proxy/ --name "$today-backup-dependency-proxy" gcloud transfer jobs create gs://gitlab-bucket-lfs/ gs://backup-bucket/$today/lfs/ --name "$today-backup-lfs" gcloud transfer jobs create gs://gitlab-bucket-mr-diffs/ gs://backup-bucket/$today/mr-diffs/ --name "$today-backup-mr-diffs" gcloud transfer jobs create gs://gitlab-bucket-packages/ gs://backup-bucket/$today/packages/ --name "$today-backup-packages" gcloud transfer jobs create gs://gitlab-bucket-pages/ gs://backup-bucket/$today/pages/ --name "$today-backup-pages" gcloud transfer jobs create gs://gitlab-bucket-registry/ gs://backup-bucket/$today/registry/ --name "$today-backup-registry" gcloud transfer jobs create gs://gitlab-bucket-terraform-state/ gs://backup-bucket/$today/terraform-state/ --name "$today-backup-terraform-state" gcloud transfer jobs create gs://gitlab-bucket-uploads/ gs://backup-bucket/$today/uploads/ --name "$today-backup-uploads"- これらのTransferジョブは、実行後に自動的に削除されません。スクリプトで古いジョブのクリーンアップを実装できます。
- サンプルスクリプトは古いバックアップを削除しません。必要に応じて、目的の保持ポリシーに従って古いバックアップのクリーンアップを実装できます。
データの一貫性の低下を避けるため、バックアップがCloud SQLバックアップと同時またはそれ以降に実行されるようにしてください。
Gitリポジトリのバックアップを設定する
Gitalyサーバーサイドバックアップを実行するようにcronjobを設定します:
サーバーサイドバックアップを設定する手順に従い、すべてのGitalyノードでGitalyサーバーサイドバックアップの保存先を設定します。このバケットは、Gitalyがリポジトリデータを保存するために排他的に使用されます。
Gitalyが、以前に設定された指定のオブジェクトストレージバケット内のすべてのGitリポジトリデータをバックアップする一方で、バックアップユーティリティツール(
gitlab-backup)は追加のバックアップデータをアップロードします。このデータには、復元するための重要なメタデータを含むtarファイルが含まれます。他のバックアップと同じバケットを使用することも、別のバケットを使用することもできます。このバックアップデータが適切にリモートストレージ(クラウド)にアップロードされるようにするには、バックアップをリモートストレージ(クラウド)にアップロードの手順に従ってアップロードバケットを設定してください。(オプション)このバックアップデータの耐久性を強化するには、以前に設定したすべてのバケットを、それぞれのオブジェクトストレージプロバイダで、オブジェクトストレージデータのバックアップに追加してバックアップします。
PumaまたはSidekiqを実行しているGitLab RailsノードにSSH接続します。
Gitデータの完全なバックアップを作成します。
REPOSITORIES_SERVER_SIDE変数を使用し、PostgreSQLデータをスキップします:sudo gitlab-backup create REPOSITORIES_SERVER_SIDE=true SKIP=dbこれにより、GitalyノードはGitデータと一部のメタデータをリモートストレージにアップロードします。アップロード、アーティファクト、LFSなどのblobは明示的にスキップする必要はありません。
gitlab-backupコマンドはデフォルトでオブジェクトストレージをバックアップしないためです。次のステップで必要となるバックアップのバックアップIDをメモしてください。例えば、バックアップコマンドが
2024-02-22 02:17:47 UTC -- Backup 1708568263_2024_02_22_16.9.0-ce is done.と出力した場合、バックアップIDは1708568263_2024_02_22_16.9.0-ceです。完全なバックアップが、Gitalyバックアップバケットと通常のバックアップバケットの両方にデータを作成したことを確認します。
再度バックアップコマンドを実行し、今回はGitリポジトリの増分バックアップとバックアップIDを指定します。前のステップの例のIDを使用すると、コマンドは次のようになります:
sudo gitlab-backup create REPOSITORIES_SERVER_SIDE=true SKIP=db INCREMENTAL=yes PREVIOUS_BACKUP=1708568263_2024_02_22_16.9.0-cePREVIOUS_BACKUPの値はこのコマンドでは使用されませんが、コマンドで必須です。この不要な要件を削除するためのイシュー429141があります。増分バックアップが成功し、オブジェクトストレージにデータが追加されたことを確認します。
cronを設定して毎日バックアップを作成します。
rootユーザーのcrontabを編集します。sudo su - crontab -eそこで、毎月毎日午前2時にバックアップをスケジュールするために、以下の行を追加します。バックアップを復元するのに必要な増分数を制限するため、毎月1日にGitリポジトリの完全なバックアップが取得され、残りの日は増分バックアップが取得されます:
0 2 1 * * /opt/gitlab/bin/gitlab-backup create REPOSITORIES_SERVER_SIDE=true SKIP=db CRON=1 0 2 2-31 * * /opt/gitlab/bin/gitlab-backup create REPOSITORIES_SERVER_SIDE=true SKIP=db INCREMENTAL=yes PREVIOUS_BACKUP=1708568263_2024_02_22_16.9.0-ce CRON=1
サーバーサイドバックアップを設定する手順に従い、すべてのGitalyノードでGitalyサーバーサイドバックアップの保存先を設定します。このバケットは、Gitalyがリポジトリデータを保存するために排他的に使用されます。
Gitalyが、以前に設定された指定のオブジェクトストレージバケット内のすべてのGitリポジトリデータをバックアップする一方で、バックアップユーティリティツール(
gitlab-backup)は追加のバックアップデータをアップロードします。このデータには、復元するための重要なメタデータを含むtarファイルが含まれます。他のバックアップと同じバケットを使用することも、別のバケットを使用することもできます。このバックアップデータが適切にリモートストレージ(クラウド)にアップロードされるようにするには、バックアップをリモートストレージ(クラウド)にアップロードの手順に従ってアップロードバケットを設定してください。(オプション)このバックアップデータの耐久性を強化するには、以前に設定したすべてのバケットを、それぞれのオブジェクトストレージプロバイダで、オブジェクトストレージデータのバックアップに追加してバックアップします。
PumaまたはSidekiqを実行しているGitLab RailsノードにSSH接続します。
Gitデータの完全なバックアップを作成します。
REPOSITORIES_SERVER_SIDE変数を使用し、他のすべてのデータをスキップします:kubectl exec <Toolbox pod name> -it -- backup-utility --repositories-server-side --skip db,builds,pages,registry,uploads,artifacts,lfs,packages,external_diffs,terraform_state,pages,ci_secure_filesこれにより、GitalyノードはGitデータと一部のメタデータをリモートストレージにアップロードします。Toolboxに含まれるツールを参照してください。
完全なバックアップが、Gitalyバックアップバケットと通常のバックアップバケットの両方にデータを作成したことを確認します。サーバーサイドリポジトリバックアップでは
backup-utilityによる増分リポジトリバックアップはサポートされていません。チャートイシュー3421を参照してください。cronを設定して毎日バックアップを作成します。具体的には、
gitlab.toolbox.backups.cron.extraArgsを次のように設定します:--repositories-server-side --skip db --skip repositories --skip uploads --skip builds --skip artifacts --skip pages --skip lfs --skip terraform_state --skip registry --skip packages --skip ci_secure_files
設定ファイルのバックアップを設定する
設定とシークレットがデプロイメントの外部で定義され、その後デプロイされる場合、バックアップ戦略の実装は特定のセットアップと要件に依存します。例として、AWS Secret Managerにシークレットを保存し、複数リージョンへのレプリケーションを設定して、スクリプトでシークレットを自動的にバックアップできます。
設定とシークレットがデプロイ内部でのみ定義されている場合:
- 設定ファイルの保存では、設定ファイルとシークレットファイルを抽出する方法について説明します。
- これらのファイルは、より制限の厳しい別のオブジェクトストレージアカウントにアップロードする必要があります。
バックアップを復元する
GitLabインスタンスのバックアップを復元する。
前提条件
バックアップを復元する前に:
動作するターゲットGitLabインスタンスを選択します。
ターゲットGitLabインスタンスが、AWSバックアップが保存されているリージョンにあることを確認してください。
バックアップデータが作成されたターゲットGitLabインスタンスが、まったく同じバージョンとタイプ(CEまたはEE)のGitLabを使用していることを確認してください。たとえば、CE 15.1.4などです。
ターゲットGitLabインスタンスに同じリポジトリストレージが設定されていることを確認してください。追加のストレージがあっても問題ありません。
オブジェクトストレージが設定されていることを確認してください。
新しいシークレットや設定を使用し、復元する中の予期せぬ設定変更を回避するには:
すべてのノードでのLinuxパッケージインストール:
Helmチャート(Kubernetes)インストール:
すべてのGitLab Linuxパッケージノードで、以下を実行します:
sudo gitlab-ctl reconfigure sudo gitlab-ctl startチャートをデプロイして、GitLabインスタンスが稼働していることを確認してください。以下のコマンドを実行して、Toolboxポッドが有効かつ稼働していることを確認してください:
kubectl get pods -lrelease=RELEASE_NAME,app=toolboxWebservice、Sidekiq、およびToolboxポッドは再起動する必要があります。これらのポッドを再起動する最も安全な方法は、以下を実行することです:
kubectl delete pods -lapp=sidekiq,release=<helm release name> kubectl delete pods -lapp=webservice,release=<helm release name> kubectl delete pods -lapp=toolbox,release=<helm release name>
ターゲットGitLabインスタンスがまだ動作していることを確認します。例:
- ヘルスチェックエンドポイントへのリクエストを行います。
- GitLabチェックRakeタスクを実行します。
PostgreSQLデータベースに接続するGitLabサービスを停止します。
PumaまたはSidekiqを実行しているすべてのノードでのLinuxパッケージインストールで、以下を実行します:
sudo gitlab-ctl stopHelmチャート(Kubernetes)インストール:
以降の再起動のために、データベースクライアントの現在のレプリカ数をメモします:
kubectl get deploy -n <namespace> -lapp=sidekiq,release=<helm release name> -o jsonpath='{.items[].spec.replicas}{"\n"}' kubectl get deploy -n <namespace> -lapp=webservice,release=<helm release name> -o jsonpath='{.items[].spec.replicas}{"\n"}' kubectl get deploy -n <namespace> -lapp=prometheus,release=<helm release name> -o jsonpath='{.items[].spec.replicas}{"\n"}'復元するプロセスにロックが干渉するのを防ぐため、データベースのクライアントを停止します:
kubectl scale deploy -lapp=sidekiq,release=<helm release name> -n <namespace> --replicas=0 kubectl scale deploy -lapp=webservice,release=<helm release name> -n <namespace> --replicas=0 kubectl scale deploy -lapp=prometheus,release=<helm release name> -n <namespace> --replicas=0
オブジェクトストレージデータを復元する
各バケットはAWS内で個別のバックアップとして存在し、各バックアップは既存または新しいバケットに復元することができます。
バケットを復元するには、正しい権限を持つIAMロールが必要です:
AWSBackupServiceRolePolicyForBackupAWSBackupServiceRolePolicyForRestoresAWSBackupServiceRolePolicyForS3RestoreAWSBackupServiceRolePolicyForS3Backup
既存のバケットを使用している場合、それらにはアクセス制御リストが有効になっている必要があります。
復元するジョブが実行されている間に、PostgreSQLデータベースデータの復元するに進むことができます。
- Storage Transfer Serviceジョブを作成し、バックアップされたデータをGitLabバケットに転送します。
- 転送ジョブが実行されている間に、PostgreSQLデータベースデータの復元するに進むことができます。
PostgreSQLデータベースデータを復元する
組み込みのツールを使用してAWSRDSデータベースを復元すると、新しいRDSインスタンスが作成されます。
新しいRDSインスタンスは異なるエンドポイントを持つため、ターゲットGitLabインスタンスを再設定して新しいデータベースを指すようにする必要があります:
Linuxパッケージインストールの場合は、パッケージ化されていないPostgreSQLデータベース管理サーバーの使用に従ってください。
Helmチャート(Kubernetes)インストールの場合は、外部データベースでのGitLabチャートの設定に従ってください。
次に進む前に、新しいRDSインスタンスが作成され、使用可能になるまで待機します。
新しいデータベースインスタンスに復元する場合、GitLabを再設定して新しいデータベースを指すようにします:
Linuxパッケージインストールの場合は、パッケージ化されていないPostgreSQLデータベース管理サーバーの使用に従ってください。
Helmチャート(Kubernetes)インストールの場合は、外部データベースでのGitLabチャートの設定に従ってください。
次に進む前に、Cloud SQLインスタンスが使用可能になるまで待機します。
Gitリポジトリを復元する
まず、オブジェクトストレージデータの復元するの一部として、すでに以下を完了している必要があります:
- GitalyサーバーサイドバックアップのGitリポジトリを含むバケットを復元する。
*_gitlab_backup.tarファイルを含むバケットを復元する。
PumaまたはSidekiqを実行しているGitLab RailsノードにSSH接続します。
バックアップバケット内で、復元するしたPostgreSQLおよびオブジェクトストレージデータと整合するタイムスタンプに基づいて
*_gitlab_backup.tarファイルを選択します。/var/opt/gitlab/backups/にtarファイルをダウンロードします。復元するするバックアップのIDを指定し、名前から
_gitlab_backup.tarを省略してバックアップを復元するします:# This command will overwrite the contents of your GitLab database! sudo gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce SKIP=dbバックアップtarファイルとインストールされているGitLabのバージョンとの間に不一致がある場合、復元するコマンドはエラーメッセージを出して中断します。正しいバージョンのGitLabをインストールしてから、再度試してください。
GitLabを再設定し、開始して確認します:
すべてのPostgreSQLノードで、以下を実行します:
sudo gitlab-ctl reconfigureすべてのPumaまたはSidekiqノードで、以下を実行します:
sudo gitlab-ctl start1つのPumaまたはSidekiqノードで、以下を実行します:
sudo gitlab-rake gitlab:check SANITIZE=true
特に
/etc/gitlab/gitlab-secrets.jsonが復元するされた場合、または異なるサーバーが復元するのターゲットである場合に、データベース値が復号化するできることを確認します:PumaまたはSidekiqノードで、以下を実行します:
sudo gitlab-rake gitlab:doctor:secretsさらに確実性を高めるため、アップロードされたファイルの整合性チェックを実行できます。
PumaまたはSidekiqノードで、以下を実行します:
sudo gitlab-rake gitlab:artifacts:check sudo gitlab-rake gitlab:lfs:check sudo gitlab-rake gitlab:uploads:check不足または破損したファイルが見つかっても、必ずしもバックアップと復元するプロセスが失敗したことを意味するわけではありません。例えば、ソースのGitLabインスタンスでファイルが見つからないか破損している可能性があります。以前のバックアップと相互参照する必要があるかもしれません。GitLabを新しい環境に移行する場合、ソースのGitLabインスタンスで同じチェックを実行して、整合性チェックの結果が以前から存在するものなのか、それともバックアップと復元するプロセスに関連するものなのかを判断できます。
ToolboxポッドにSSH接続します。
バックアップバケット内で、復元するしたPostgreSQLおよびオブジェクトストレージデータと整合するタイムスタンプに基づいて
*_gitlab_backup.tarファイルを選択します。/var/opt/gitlab/backups/にtarファイルをダウンロードします。復元するするバックアップのIDを指定し、名前から
_gitlab_backup.tarを省略してバックアップを復元するします:# This command will overwrite the contents of Gitaly! kubectl exec <Toolbox pod name> -it -- backup-utility --restore -t 11493107454_2018_04_25_10.6.4-ce --skip db,builds,pages,registry,uploads,artifacts,lfs,packages,external_diffs,terraform_state,pages,ci_secure_filesバックアップtarファイルとインストールされているGitLabのバージョンとの間に不一致がある場合、復元するコマンドはエラーメッセージを出して中断します。正しいバージョンのGitLabをインストールしてから、再度試してください。
GitLabを再起動して確認します:
前提条件に記載されているレプリカ数を使用して、停止しているデプロイを開始します:
kubectl scale deploy -lapp=sidekiq,release=<helm release name> -n <namespace> --replicas=<original value> kubectl scale deploy -lapp=webservice,release=<helm release name> -n <namespace> --replicas=<original value> kubectl scale deploy -lapp=prometheus,release=<helm release name> -n <namespace> --replicas=<original value>Toolboxポッドで、以下を実行します:
sudo gitlab-rake gitlab:check SANITIZE=true
特に
/etc/gitlab/gitlab-secrets.jsonが復元するされた場合、または異なるサーバーが復元するのターゲットである場合に、データベース値が復号化するできることを確認します:Toolboxポッドで、以下を実行します:
sudo gitlab-rake gitlab:doctor:secretsさらに確実性を高めるため、アップロードされたファイルの整合性チェックを実行できます。
これらのコマンドはすべての行をイテレーションするため、時間がかかることがあります。したがって、Toolboxポッドではなく、GitLab Railsノードで以下のコマンドを実行します:
sudo gitlab-rake gitlab:artifacts:check sudo gitlab-rake gitlab:lfs:check sudo gitlab-rake gitlab:uploads:check不足または破損したファイルが見つかっても、必ずしもバックアップと復元するプロセスが失敗したことを意味するわけではありません。例えば、ソースのGitLabインスタンスでファイルが見つからないか破損している可能性があります。以前のバックアップと相互参照する必要があるかもしれません。GitLabを新しい環境に移行する場合、ソースのGitLabインスタンスで同じチェックを実行して、整合性チェックの結果が以前から存在するものなのか、それともバックアップと復元するプロセスに関連するものなのかを判断できます。
復元が完了しました。