正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

データレプリケーションのセットアップ

  • プラン: Premium、Ultimate
  • 提供形態: GitLab Self-Managed
  • ステータス: ベータ版

GitLab Self-Managed上のGitLab Orbitは ベータ版です。 この機能はテスト目的で利用可能ですが、本番環境での使用には対応していません。

GitLab OrbitはClickHouse内のGitLabデータベースのコピーからGitLabデータを読み取ります。GitLabデータベース自体からは読み取りません。Siphonがそのコピーを最新の状態に保ちます。

SiphonはKubernetes上で3つのデプロイとして動作します。

デプロイ役割
ProducerPostgreSQLの先行書き込みログを読み取り、変更された各行をNATSにパブリッシュします。
ConsumerNATSを読み取り、行をClickHouseに書き込みます。
Reconcilerネームスペーストラバーサルパスなどの派生列をスケジュールに従って再計算し、影響を受けた行をNATSを通じて再パブリッシュします。

前提条件:

  • GitLab Self-Managed上のGitLab Orbitの前提条件
  • GitLab向けにセットアップされたClickHouseインスタンス(GitLab ClickHouseマイグレーション適用済み)。詳細については、ClickHouseを参照してください。
  • GitLab PostgreSQLサーバーへのスーパーユーザーアクセス。
  • PostgreSQLの再起動1回分のメンテナンスウィンドウ。
  • Helm 3およびクラスターへのkubectlアクセス。

次の順序でレプリケーションをセットアップします。

  1. PostgreSQLで論理レプリケーションを有効にする。
  2. SiphonのPostgreSQLユーザーを作成する。
  3. パブリケーションと権限を作成する。
  4. SiphonのClickHouseユーザーを作成する。
  5. パスワードをSiphonで利用可能にする。
  6. Siphonをインストールする。

PostgreSQLで論理レプリケーションを有効にする

wal_levellogicalでない場合、Siphon producerは起動時に停止します。wal_levelmax_replication_slotsmax_wal_sendersへの変更はすべて、リロードではなくPostgreSQLの完全な再起動が必要です。また、gitlab-ctl reconfigureはPostgreSQLを再起動しません。

  1. /etc/gitlab/gitlab.rbを編集します。

    postgresql['wal_level'] = 'logical'
    postgresql['max_replication_slots'] = 10
    postgresql['max_wal_senders'] = 10
    
    # Accept connections from the cluster. Replace with the address and CIDR for your network.
    postgresql['listen_address'] = '0.0.0.0'
    postgresql['md5_auth_cidr_addresses'] = ['10.0.0.0/8']
    
    # Keep GitLab itself on the local socket. Without this, setting listen_address
    # also repoints GitLab at that address, and GitLab loses its database connection.
    gitlab_rails['db_host'] = '/var/opt/gitlab/postgresql'
  2. ファイルを保存し、GitLabを再設定してからPostgreSQLを再起動します。

    sudo gitlab-ctl reconfigure
    sudo gitlab-ctl restart postgresql
  3. 設定を確認します。

    sudo gitlab-psql -c 'SHOW wal_level'
    sudo gitlab-psql -c "SELECT name, setting, pending_restart FROM pg_settings WHERE name IN ('wal_level','max_wal_senders','max_replication_slots')"

    wal_levellogicalを返し、他の2つはgitlab.rbと一致し、pending_restart = tを報告する行はありません。部分的に適用された組み合わせでは、次回の再起動時にPostgreSQLが起動できなくなります。復旧するには、/etc/gitlab/gitlab.rbを修正し、再設定してサービスが実行中であることを確認してください。

GitLab Helmチャートは本番PostgreSQLを管理しないため、これらの設定は独自のサーバーまたはマネージドデータベースに適用してください。

  1. 次のパラメーターを設定します。

    パラメーター
    wal_levellogical
    max_replication_slots10以上
    max_wal_senders10以上

    マネージドデータベースの場合は、postgresql.confではなくプロバイダーのパラメーターグループを通じて設定します。一部のプロバイダーでは、wal_levelが論理レプリケーションフラグなど別の名前で公開されています。

  2. サーバーを再起動します。

  3. クラスターからポート5432への接続を許可します。

  4. 設定を確認します。

    psql -h <postgresql_host> -U <admin_user> -d gitlabhq_production \
      -c "SELECT name, setting, pending_restart FROM pg_settings WHERE name IN ('wal_level','max_wal_senders','max_replication_slots')"

    wal_levellogicalを返し、他の2つは設定した値と一致し、pending_restart = tを報告する行はありません。

SiphonのPostgreSQLユーザーを作成する

Siphonは3つのロールを使用します。スーパーユーザーとして作成してください。ロールがREPLICATIONを付与できるのは、そのロール自身がすでにREPLICATION属性を持っている場合のみです。GitLabアプリケーションロールはこの属性を持っていません。

スーパーユーザーとしてgitlabhq_productionに接続し、次を実行します。

CREATE USER siphon WITH PASSWORD '<your_password>'
  NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT;
CREATE USER siphon_replicator WITH REPLICATION LOGIN PASSWORD '<your_password>'
  NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT;
CREATE USER siphon_snapshot WITH PASSWORD '<your_password>'
  NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT;

3つのロールは同じパスワードを使用できます。

この手順のvaluesファイルでは、Siphonはすべての接続にsiphon_replicatorとして接続します。他の2つのロールが存在するのは、次のステップのRakeタスクがそれらに読み取りアクセスも付与するためです。スプリットユーザーセットアップでは、後でこれらを使用できます。

パブリケーションと権限を作成する

GitLabにはSiphon向けにPostgreSQLを準備するRakeタスクが同梱されています。このタスクは冪等であり、次を作成します。

  • パブリケーション。
  • Siphonがパブリケーションにテーブルを追加するために呼び出すヘルパー関数。
  • すべてのGitLabスキーマへの読み取りアクセス。

GitLab 19.2.2以降にはこのタスクが含まれています。

  1. タスクが存在することを確認します。

    sudo gitlab-rake -T | grep gitlab:siphon:setup
  2. タスクを実行します。

    sudo gitlab-rake gitlab:siphon:setup
  1. toolboxデプロイを見つけます。

    kubectl -n <gitlab_namespace> get deploy -l app=toolbox
  2. タスクが存在することを確認します。

    kubectl -n <gitlab_namespace> exec -it deploy/<release>-toolbox -- gitlab-rake -T | grep gitlab:siphon:setup
  3. タスクを実行します。

    kubectl -n <gitlab_namespace> exec -it deploy/<release>-toolbox -- gitlab-rake gitlab:siphon:setup

このタスクはsiphon_publication_main_1という名前のパブリケーションを作成し、siphonロールにpublic.siphon_alter_publicationへのEXECUTE権限を付与します。producerはsiphon_replicator接続でこの関数を呼び出すため、siphon_replicatorにも同じEXECUTE権限を付与してください。スーパーユーザーとして次を実行します。

GRANT EXECUTE ON FUNCTION public.siphon_alter_publication(text, text, integer)
  TO siphon_replicator;

パブリケーションはproducerが起動するまで空です。その後、Siphonは同じ関数を通じてパブリケーションにテーブルを追加します。

SiphonのClickHouseユーザーを作成する

SiphonはGitLabがすでに使用しているデータベースに書き込みます。GitLab ClickHouseマイグレーションがターゲットテーブルを作成するため、Siphonにはスキーマ権限は不要です。

管理者としてClickHouseに接続し、次を実行します。

CREATE USER siphon IDENTIFIED WITH sha256_password BY '<your_password>';
CREATE ROLE siphon_app;
GRANT SELECT, INSERT, dictGet ON gitlab_clickhouse_main_production.* TO siphon_app;
GRANT siphon_app TO siphon;

dictGet権限は必須です。これがないと、プローブはメトリクスエンドポイントをスクレイピングするだけなので、ポッドはヘルスチェックを通過します。障害はconsumerログにパーミッションエラーとして現れます。ディクショナリに基づくすべてのテーブルは空のままになります。

systemデータベースを制限するマネージドClickHouseの場合は、次も実行します。

GRANT SELECT ON system.tables, system.columns TO siphon_app;

パスワードをSiphonで利用可能にする

SiphonはKubernetes Secretに基づく環境変数から両方のパスワードを読み取ります。Secretを作成する前にネームスペースが存在している必要があります。次のセクションのvaluesファイルは、Siphonネームスペース内にsiphon-secretsという名前のSecretが1つあり、次のキーを持つことを想定しています。

キー内容
pg-passwordsiphonsiphon_replicatorsiphon_snapshot PostgreSQLロールのパスワード
ch-siphon-passwordClickHouseのsiphonユーザーのパスワード

すでに運用しているシークレットマネージャーに値を保管することをお勧めします。External Secrets Operatorなどのツールを使用してクラスターに同期してください。平文を他の場所に保存しないでください。

Siphonをインストールする

configMode: splitを使用すると、SiphonはGitLabに同梱されているイメージからポッド起動時にテーブルリストを構築します。リストはGitLabのバージョンと一致し、手動での更新は不要です。

global.gitlabVersiongitlab-siphon-tablesイメージのタグであり、レプリケートされるテーブルセットをGitLabのバージョンに固定します。タグはv19.2.0-eeから始まります。タグが存在しないとポッドが起動できなくなるため、インストール前にコンテナレジストリでタグが存在することを確認してください。

  1. 次の内容をsiphon-values.yamlとして保存し、プレースホルダーを置き換えます。

    configMode: split
    
    global:
      # Tag of the gitlab-siphon-tables image.
      # Must match your GitLab version exactly, patch level included.
      gitlabVersion: v19.2.2-ee
    
    image:
      repository: registry.gitlab.com/gitlab-org/analytics-section/siphon
      tag: 0.0.124-beta
    
    siphonConnectionConfigMap:
      create: true
      data:
        prometheus:
          port: 8080
        connection:
          queueing:
            driver: nats
            url: nats://nats.nats.svc.cluster.local:4222
            stream_name: siphon_stream_main_db
            nats_config:
              replicas: 1
              max_age_seconds: 1296000
          clickhouse:
            host: <clickhouse_host>
            # Native protocol, not the HTTP port GitLab uses.
            port: 9000
            ssl: false
            username: siphon
            password: "${CLICKHOUSE_SIPHON_PASSWORD}"
            database: gitlab_clickhouse_main_production
          databases:
            main:
              host: <postgresql_host>
              port: 5432
              database: gitlabhq_production
              user: siphon_replicator
              password: "${SIPHON_DB_PASSWORD}"
              ssl_mode: require
              advisory_lock_id: 1
              application_name: siphon_main_1
              advisory_lock_timeout_ms: 100
              advisory_lock_timeout_fuzziness_ms: 50
              lock_timeout_ms: 500
              lock_timeout_fuzziness_ms: 300
        overrides:
          siphon_main_1:
            database_ref: main
    
    siphonLayoutConfigMap:
      create: true
      data:
        stream_name: siphon_stream_main_db
        refresh_mode: inline
        partitions_monitoring_interval_in_seconds: 3600
        max_column_size_in_bytes: 10485760
        producers:
          main:
            - siphon_main_1
        consumers:
          - siphon_consumer_1
        reconcilers:
          - siphon_reconciler_1
        # Point the producer at the publication the Rake task created. Without this
        # override, the producer derives the name from the application identifier
        # and tries to create its own.
        replication_overrides:
          siphon_main_1:
            publication_name: siphon_publication_main_1
        # GitLab splits its schema three ways even on one database. Map ci and sec onto main.
        database_mapping:
          ci: main
          sec: main
    
    deployments:
      postgres-producer:
        configMode: split
        split:
          role: producer
        envFromSecrets:
          - {name: SIPHON_DB_PASSWORD, secretName: siphon-secrets, secretKey: pg-password}
          - {name: CLICKHOUSE_SIPHON_PASSWORD, secretName: siphon-secrets, secretKey: ch-siphon-password}
      clickhouse-consumer:
        configMode: split
        split:
          role: consumer
        envFromSecrets:
          - {name: SIPHON_DB_PASSWORD, secretName: siphon-secrets, secretKey: pg-password}
          - {name: CLICKHOUSE_SIPHON_PASSWORD, secretName: siphon-secrets, secretKey: ch-siphon-password}
      reconciler:
        configMode: split
        split:
          role: reconciler
        envFromSecrets:
          - {name: SIPHON_DB_PASSWORD, secretName: siphon-secrets, secretKey: pg-password}
          - {name: CLICKHOUSE_SIPHON_PASSWORD, secretName: siphon-secrets, secretKey: ch-siphon-password}
  2. チャートをインストールします。

    helm repo add siphon https://gitlab.com/api/v4/projects/76780115/packages/helm/stable
    helm repo update
    
    helm upgrade --install siphon siphon/siphon \
      --version 1.18.0 \
      --namespace siphon \
      --create-namespace \
      --values siphon-values.yaml

    これらのコマンドは直接Helmインストールのリファレンスです。ネームスペース名とデプロイ方法は独自のツールに合わせて調整してください。

  3. 3つのデプロイがすべて実行中であることを確認します。

    kubectl -n siphon get pods

出力には、Running状態のpostgres-producerclickhouse-consumerreconcilerポッドが一覧表示されます。

Siphonはvaluesファイルを変更してもポッドを再起動しません。変更を適用するには、デプロイを再起動します。

kubectl -n siphon rollout restart deployment

Valuesファイルの設定

設定要件
database_mapping必須。GitLabのスキーマは、インスタンスが個別に保存しているかどうかにかかわらず、3つの論理データベース(maincisec)に分割されています。マッピングがないとジェネレーターが失敗します。cisecを参照するテーブル定義を削除しないでください。削除すると、すべてのCI、脆弱性、依存関係テーブルが暗黙的に削除されます。
stream_nameGitLab Orbitが読み取るストリーム名と一致する必要があります。両側で共有される値の完全なリストについては、共有設定値を参照してください。
advisory_lock_idとロックタイムアウト必須。これらがないとproducerは起動時に停止します。
nats_config.replicasNATSクラスターのサイズと一致する必要があります。単一のNATSサーバーはレプリカを1つしかサポートしません。
ssl_modePostgreSQLサーバーが提供するものと一致する必要があります。例ではrequireを使用しています。これはLinuxパッケージのPostgreSQLがデフォルトでTLSを提供するため機能します。TLSを提供しないサーバーは接続を拒否し、producerはserver refused TLS connectionで起動時に停止します。
connection.replication.use_alter_publication_functionチャートのデフォルトであるtrueのままにする必要があります。public.siphon_alter_publicationへのEXECUTE権限はこの設定のために存在します。パブリケーションはGitLabデータベースユーザーに属しているため、SiphonロールからのダイレクトなALTER PUBLICATIONは失敗します。
max_age_secondsconsumerがどこまで遡って再生できるかを制御します。60以上のテーブルにわたって変更された各行を15日間保持すると、大きなJetStreamファイルストアが生成されます。完全な保持ウィンドウに対応できるようNATSボリュームをサイジングするか、値を下げてください。

大きな行のオブジェクトストレージ

ストリームに収まらない大きな行はオブジェクトストアに送られます。前述のvaluesファイルはオブジェクトストアを設定していないため、SiphonはNATS JetStreamオブジェクトストアを使用し、認証情報は不要です。

外部バケットを使用するには、queueingの下にidentifiertypebucket_nameを含むobject_storage_configを追加し、すべてのSiphonポッドにバケットの認証情報を付与します。type: s3の場合、SiphonはAWS SDKの標準チェーンに従うため、AWS_REGIONを設定し、インスタンスロールをアタッチするか、envenvFromSecretsを通じてAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYを渡します。S3互換サービスの場合は、AWS_ENDPOINT_URL_S3も設定します。Google Cloud Storageの場合は、アプリケーションデフォルト認証情報でtype: gcsを使用します。

レプリケーションを確認する

最初のコピーは一度に1つのテーブルを処理し、各テーブルのマージ中はレプリケーションを一時停止します。そのため、所要時間はデータ量ではなくテーブル数に依存します。GitLab 19.2.2インスタンスは60以上のテーブルをレプリケートします。以下のチェックはレプリケーションが実行中であることを確認するものです。最初のコピーが完了したことを確認するものではありません。

  1. SiphonがPostgreSQLを読み取っていることを確認します。スロットがアクティブであり、GitLabへの書き込み後にconfirmed_flush_lsnが進んでいる必要があります。

    SELECT slot_name, active, wal_status, confirmed_flush_lsn
    FROM pg_replication_slots
    WHERE slot_name = 'siphon_main_1_slot';
  2. ClickHouseに行が届いていることを確認します。

    SELECT count() FROM gitlab_clickhouse_main_production.siphon_namespaces FINAL;
    SELECT count() FROM gitlab_clickhouse_main_production.siphon_projects FINAL;

    PostgreSQLの同じテーブルとカウントを比較してください。テーブルはReplacingMergeTreeであり、バックグラウンドマージが完了するまで更新された行が複数回現れるため、FINALが必要です。テーブルが最初の書き込み時にプレースホルダー行を受け取ることがあるため、ClickHouseのカウントは通常わずかに多くなります。

非アクティブなレプリケーションスロットはGitLab PostgreSQLディスク上に先行書き込みログを保持し、ディスクを満杯にする可能性があります。ディスクの空き容量が許す時間を超えてSiphonを停止する場合は、SELECT pg_drop_replication_slot('siphon_main_1_slot');でスロットを削除し、後で新しいスナップショットを取得してください。

次のステップ