- アーキテクチャ
- セットアップ
- 設定例
- パトロニ
-
トラブルシューティング
- ConsulとPostgreSQLの変更が反映されない
- PgBouncerエラー
ERROR: pgbouncer cannot connect to server
- レプリカの再初期化
- コンシュルでのパトロニ状態のリセット
- Patroniログに
pg_hba.conf
のエントリに関するエラーが表示されます。127.0.0.1
- Patroniログのエラー:要求された開始ポイントがWrite Ahead Log(WAL) のフラッシュ位置より前にあります。
- Patroniが
MemoryError
- 実行中のエラー
gitlab-ctl
- PostgreSQLのメジャーバージョンアップがPatroniレプリカで失敗します。
- 他のコンポーネントのイシュー
LinuxパッケージインストールにおけるPostgreSQLのレプリケーションとフェイルオーバー
GitLab セルフマネジメントのフリーユーザーであれば、クラウドホストソリューションを使うことを検討してください。この文書では、セルフコンパイルによるインストールはカバーしていません。
レプリケーションやフェイルオーバーの設定が求めていたものでない場合は、Linux パッケージのデータベース設定ドキュメントをご覧ください。
PostgreSQLをGitLab用にレプリケーションとフェイルオーバーで設定しようとする前に、このドキュメントを十分に読むことをお勧めします。
アーキテクチャ
Linux pacakageが推奨するレプリケーションフェイルオーバーを持つPostgreSQLクラスタの設定には、以下のものが必要です:
- 最低3つのPostgreSQLノード。
- 最低3台のConsulサーバーノード
- プライマリデータベースの読み取りと書き込みを追跡し、処理する最低3台のPgBouncerノード。
- 内部ロードバランサー(TCP) 、PgBouncerノード間のリクエストのバランスを取ります。
-
データベースのロードバランシングが有効です。
- 各PostgreSQLノードに設定されたローカルPgBouncerサービス。これはプライマリを追跡するメインのPgBouncerクラスターとは別です。
また、ネットワークが単一障害点にならないように、すべてのデータベースとGitLabインスタンス間の冗長接続を確認し、基盤となるネットワークトポロジーを考慮する必要があります。
データベースノード
各データベースノードは4つのサービスを実行します:
-
PostgreSQL
:データベース自体 -
Patroni
:クラスター内の他のPatroniサービスと通信を行い、リーダーサーバにイシューが発生した場合のフェイルオーバーを行います。フェイルオーバーの手順は以下の通りです:- クラスターの新しいリーダーを選択します。
- 新しいノードをリーダーに昇格させます。
- 残りのサーバーに新しいリーダーノードに従うように指示します。
-
PgBouncer
:ノードのローカル・プーラ。データベースのロードバランシングの一部として_読み取り_クエリに使用されます。 -
Consul
エージェント:現在のPatroniの状態を保存するConsulクラスタと通信します。エージェントはデータベースクラスタの各ノードの状態を監視し、Consulクラスタ上のサービス定義でその状態を追跡します。
Consulサーバノード
ConsulサーバノードはConsulサーバサービスを実行します。これらのノードはPatroniクラスタが起動する_前に_クォーラムに達し、リーダーを選出する必要があります。
PgBouncerノード
各PgBouncerノードは2つのサービスを実行します:
-
PgBouncer
:データベース接続プーラー -
Consul
エージェント:Consulクラスタ上のPostgreSQLサービス定義の状態を監視します。ステータスが変更された場合、ConsulはPgBouncerの設定を更新して新しいPostgreSQLリーダーノードを指すようにし、PgBouncerサービスをリロードするスクリプトを実行します。
接続フロー
パッケージ内の各サービスには、デフォルトのポートセットが付属しています。以下に挙げる接続については、特定のファイアウォールルールを作成する必要があるかもしれません:
このセットアップにはいくつかの接続フローがあります:
プライマリー
- アプリケーションサーバーはデフォルトのポートを経由して直接PgBouncerに接続するか、設定された内部ロードバランサー((TCP) )を経由して複数のPgBouncerに接続します。
- PgBouncerはプライマリデータベースサーバのPostgreSQLデフォルトポートに接続します。
データベースの負荷分散
最近変更されておらず、すべてのデータベースノードで最新のデータに対する読み取りクエリ:
- アプリケーションサーバは、ラウンドロビン方式で各データベースノードのデフォルトポートを経由してローカルのPgBouncerサービスに接続します。
- ローカルのPgBouncerはローカルのデータベースサーバーのPostgreSQLのデフォルトポートに接続します。
レプリケーション
- Patroniは実行中のPostgreSQLプロセスと設定をアクティブに管理します。
- PostgreSQLセカンダリはプライマリデータベースサーバに接続しますPostgreSQLデフォルトポート
- Consul サーバとエージェントは互いに接続Consul デフォルトポート
セットアップ
必要な情報
設定を進める前に、必要な情報をすべて収集する必要があります。
ネットワーク情報
PostgreSQLはデフォルトではどのネットワークインターフェースも待ち受けません。他のサービスからアクセスするためには、どのIPアドレスをリッスンするかを知る必要があります。同様に、PostgreSQLへのアクセスはネットワーク接続元に基づいて制御されます。
これが必要な理由です:
- 各ノードのネットワーク・インターフェースのIPアドレス。これは、すべてのインターフェイスでリッスンするために
0.0.0.0
に設定できます。ループバックアドレス127.0.0.1
には設定できません。 - ネットワーク・アドレス。これは、サブネット(つまり、
192.168.0.0/255.255.255.0
)またはクラスレス・ドメイン間ルーティング(CIDR) (192.168.0.0/24
) 形式にすることができます。
領事情報
デフォルト設定を使用する場合、最小限の設定が必要です:
-
CONSUL_USERNAME
.Linuxパッケージ・インストールのデフォルト・ユーザーは次のとおりです。gitlab-consul
-
CONSUL_DATABASE_PASSWORD
.データベース・ユーザーのパスワード。 -
CONSUL_PASSWORD_HASH
.これはConsulのユーザー名とパスワードのペアから生成されたハッシュです。これはsudo gitlab-ctl pg-password-md5 CONSUL_USERNAME
-
CONSUL_SERVER_NODES
.ConsulサーバーノードのIPアドレスまたはDNSレコード。
サービスに関する注意事項
- デフォルトでは
gitlab-consul
です。 - 別のユーザー名を使用する場合は、
CONSUL_USERNAME
変数で指定する必要があります。 - パスワードは以下の場所に保存されます:
-
/etc/gitlab/gitlab.rb
ハッシュ -
/var/opt/gitlab/pgbouncer/pg_auth
ハッシュ -
/var/opt/gitlab/consul/.pgpass
: 平文
-
PostgreSQL 情報
PostgreSQLを設定する際には、以下のようにします:
-
max_replication_slots
をデータベースノード数の2倍に設定します。Patroniはレプリケーションを開始する際に、1ノードあたり1スロット余分に使用します。 -
max_wal_senders
、クラスターに割り当てられたレプリケーション・スロット数より1つ多く設定してください。これにより、レプリケーションが利用可能なデータベース接続をすべて使い切ってしまうことを防ぎます。
このドキュメントでは、3つのデータベース・ノードを想定しています:
patroni['postgresql']['max_replication_slots'] = 6
patroni['postgresql']['max_wal_senders'] = 7
前述のように、データベースとの認証権限が必要なネットワークサブネットを準備します。また、ConsulサーバーノードのIPアドレスまたはDNSレコードを用意しておく必要があります。
アプリケーションのデータベースユーザーには以下のパスワード情報が必要です:
-
POSTGRESQL_USERNAME
.Linuxパッケージ・インストールのデフォルト・ユーザーは次のとおりです。gitlab
-
POSTGRESQL_USER_PASSWORD
.データベース・ユーザーのパスワードは -
POSTGRESQL_PASSWORD_HASH
.これはユーザ名とパスワードのペアから生成されるハッシュです。これはsudo gitlab-ctl pg-password-md5 POSTGRESQL_USERNAME
パトロニ情報
Patroni APIを利用するためには、以下のパスワード情報が必要です:
-
PATRONI_API_USERNAME
.APIへの基本認証のためのユーザー名 -
PATRONI_API_PASSWORD
.APIへの基本認証用パスワード
PgBouncer情報
デフォルトの設定を使用する場合、最小設定に必要なのは
-
PGBOUNCER_USERNAME
.Linuxパッケージ・インストールのデフォルト・ユーザーは次のとおりです。pgbouncer
-
PGBOUNCER_PASSWORD
.これはPgBouncerサービスのパスワードです。 -
PGBOUNCER_PASSWORD_HASH
.これはPgBouncerのユーザー名/パスワードのペアから生成されたハッシュです。これはsudo gitlab-ctl pg-password-md5 PGBOUNCER_USERNAME
-
PGBOUNCER_NODE
はPgBouncerが動作しているノードのIPアドレスまたはFQDNです。
サービス自体について覚えておくべきことがいくつかあります:
- サービスはデータベースと同じシステムアカウントで実行されます。パッケージではデフォルトで
gitlab-psql
- PgBouncerサービスにデフォルト以外のユーザーアカウント(デフォルトは
pgbouncer
)を使用する場合、このユーザー名を指定する必要があります。 - パスワードは以下の場所に保存されます:
-
/etc/gitlab/gitlab.rb
ハッシュ化されたプレーンテキスト -
/var/opt/gitlab/pgbouncer/pg_auth
ハッシュ
-
Linux パッケージのインストール
まず、各ノードにLinuxパッケージをダウンロードしてインストールしてください。
ステップ1から必要な依存関係をインストールし、ステップ2からGitLabパッケージリポジトリを追加してください。GitLabパッケージをインストールする時、EXTERNAL_URL
。
データベースノードの設定
- Consulノードの設定を確認してください。
- 次のステップを実行する前に、
CONSUL_SERVER_NODES
,PGBOUNCER_PASSWORD_HASH
,POSTGRESQL_PASSWORD_HASH
,dbノードの数、ネットワークアドレスを必ず収集してください。
Patroniクラスターの設定
Patroniを使うには明示的に有効にする必要があります(patroni['enable'] = true
)。
レプリケーションを制御するPostgreSQLの設定項目、例えばwal_level
、max_wal_senders
、その他はPatroniによって厳密に制御されます。これらの設定は、postgresql[...]
コンフィギュレーションキーで行った元の設定を上書きします。したがって、これらはすべて分離され、patroni['postgresql'][...]
の下に置かれます。この動作はレプリケーションに限定されます。Patroniはpostgresql[...]
設定キーで行った他のPostgreSQL設定を尊重します。例えば、デフォルトではmax_wal_senders
は5
に設定されています。 これを変更したい場合はpatroni['postgresql']['max_wal_senders']
設定キーで設定しなければなりません。
repmgr[...]
、repmgr固有の設定も削除してください。特に、postgresql['shared_preload_libraries'] = 'repmgr_funcs'
を削除してください。以下に例を示します:
# Disable all components except Patroni, PgBouncer and Consul
roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
# Configure the Consul agent
consul['services'] = %w(postgresql)
# START user configuration
# Please set the real values as explained in Required Information section
#
# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value
postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
# Replace POSTGRESQL_REPLICATION_PASSWORD_HASH with a generated md5 value
postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
# Replace PATRONI_API_USERNAME with a username for Patroni Rest API calls (use the same username in all nodes)
patroni['username'] = 'PATRONI_API_USERNAME'
# Replace PATRONI_API_PASSWORD with a password for Patroni Rest API calls (use the same password in all nodes)
patroni['password'] = 'PATRONI_API_PASSWORD'
# Sets `max_replication_slots` to double the number of database nodes.
# Patroni uses one extra slot per node when initiating the replication.
patroni['postgresql']['max_replication_slots'] = X
# Set `max_wal_senders` to one more than the number of replication slots in the cluster.
# This is used to prevent replication from using up all of the
# available database connections.
patroni['postgresql']['max_wal_senders'] = X+1
# Replace XXX.XXX.XXX.XXX/YY with Network Addresses for your other patroni nodes
patroni['allowlist'] = %w(XXX.XXX.XXX.XXX/YY 127.0.0.1/32)
# Replace XXX.XXX.XXX.XXX/YY with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY 127.0.0.1/32)
# Local PgBouncer service for Database Load Balancing
pgbouncer['databases'] = {
gitlabhq_production: {
host: "127.0.0.1",
user: "PGBOUNCER_USERNAME",
password: 'PGBOUNCER_PASSWORD_HASH'
}
}
# Replace placeholders:
#
# Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
# with the addresses gathered for CONSUL_SERVER_NODES
consul['configuration'] = {
retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
}
#
# END user configuration
すべてのデータベースノードが同じ設定を使用します。リーダノードは設定で決定されず、リーダノードとレプリカノードのどちらにも追加設定や異なる設定はありません。
ノードの設定が完了したら、変更を有効にするために各ノードでGitLabを再設定する必要があります。
通常、Consulクラスターの準備ができたら、最初に再設定を行ったノードがリーダーになります。ノードの再設定を順番に行う必要はありません。並列に実行しても、任意の順番で実行してもかまいません。任意の順序を選択した場合、あらかじめ決められたリーダーは存在しません。
モニタリングの有効化
GitLab 12.0から導入されました。
モニタリングを有効にする場合、全てのデータベースサーバーで有効にする必要があります。
-
/etc/gitlab/gitlab.rb
を作成/編集し、以下の設定を追加します:# Enable service discovery for Prometheus consul['monitoring_service_discovery'] = true # Set the network addresses that the exporters must listen on node_exporter['listen_address'] = '0.0.0.0:9100' postgres_exporter['listen_address'] = '0.0.0.0:9187'
-
sudo gitlab-ctl reconfigure
を実行して設定をコンパイルします。
Patroni APIのTLSサポートを有効にします。
デフォルトではPatroniREST APIはHTTPで提供されます。TLSを有効にして、同じポートでHTTPSを使用するオプションがあります。
TLSを有効にするには、PEM形式の証明書と秘密鍵ファイルが必要です。どちらのファイルもPostgreSQLユーザー(gitlab-psql
がデフォルト、もしくはpostgresql['username']
で設定されたユーザー)が読めるものでなければなりません:
patroni['tls_certificate_file'] = '/path/to/server/certificate.pem'
patroni['tls_key_file'] = '/path/to/server/key.pem'
サーバの秘密鍵が暗号化されている場合、それを復号するためのパスワードを指定してください:
patroni['tls_key_password'] = 'private-key-password' # This is the plain-text password.
自己署名証明書や内部CAを使用している場合は、TLS検証を無効にするか、内部CAの証明書を渡す必要があります。そうしないとgitlab-ctl patroni ....
コマンドを使うときに予期せぬエラーに遭遇する可能性があります。LinuxパッケージはPatroni APIクライアントがこの設定に従うことを保証します。
TLS証明書検証はデフォルトで有効になっています。無効にするには
patroni['tls_verify'] = false
あるいは、内部CAのPEM形式の証明書を渡すこともできます。この場合も、ファイルはPostgreSQLユーザが読めるものでなければなりません:
patroni['tls_ca_file'] = '/path/to/ca.pem'
TLSが有効な場合、全てのエンドポイントにおいてAPIサーバとクライアントの相互認証が可能で、その範囲はpatroni['tls_client_mode']
属性に依存します:
-
none
(デフォルト):APIはクライアントの証明書をチェックしません。 -
optional
:クライアント証明書は、すべての安全でないAPI 呼び出しに必要です。 -
required
:すべてのAPIコールにクライアント証明書が必要です。
クライアント証明書は、patroni['tls_ca_file']
属性で指定された CA 証明書と照合して検証されます。したがって、この属性は相互TLS認証に必要です。また、PEM 形式のクライアント証明書ファイルと秘密鍵ファイルを指定する必要があります。どちらのファイルもPostgreSQLユーザが読めるものでなければなりません:
patroni['tls_client_mode'] = 'required'
patroni['tls_ca_file'] = '/path/to/ca.pem'
patroni['tls_client_certificate_file'] = '/path/to/client/certificate.pem'
patroni['tls_client_key_file'] = '/path/to/client/key.pem'
異なるPatroniノード上のAPIサーバとクライアントで、検証可能であれば異なる証明書と鍵を使用することができます。ただし、CA証明書(patroni['tls_ca_file']
)、TLS証明書検証(patroni['tls_verify']
)、クライアントTLS認証モード(patroni['tls_client_mode']
)は全ノードで同じ値である必要があります。
PgBouncerノードの設定
-
次のステップを実行する前に、
CONSUL_SERVER_NODES
、CONSUL_PASSWORD_HASH
、PGBOUNCER_PASSWORD_HASH
。 -
各ノードで、
/etc/gitlab/gitlab.rb
設定ファイルを編集し、# START user configuration
セクションに記載されている値を以下のように置き換えます:# Disable all components except PgBouncer and Consul agent roles(['pgbouncer_role']) # Configure PgBouncer pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) # Configure Consul agent consul['watchers'] = %w(postgresql) # START user configuration # Please set the real values as explained in Required Information section # Replace CONSUL_PASSWORD_HASH with with a generated md5 value # Replace PGBOUNCER_PASSWORD_HASH with with a generated md5 value pgbouncer['users'] = { 'gitlab-consul': { password: 'CONSUL_PASSWORD_HASH' }, 'pgbouncer': { password: 'PGBOUNCER_PASSWORD_HASH' } } # Replace placeholders: # # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z # with the addresses gathered for CONSUL_SERVER_NODES consul['configuration'] = { retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z) } # # END user configuration
pgbouncer_role
はGitLab 10.3で導入されました。 -
走る
gitlab-ctl reconfigure
-
ConsulがPgBouncerをリロードできるように
.pgpass
。と聞かれたら、PGBOUNCER_PASSWORD
を2回入力してください:gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul
PgBouncerチェックポイント
-
各ノードが現在のノードリーダーと話していることを確認します:
gitlab-ctl pgb-console # Supply PGBOUNCER_PASSWORD when prompted
パスワードを入力した後にエラー(
psql: ERROR: Auth failed
)が発生した場合は、以前に正しいフォーマットでMD5パスワード・ハッシュを生成していることを確認してください。正しいフォーマットは、パスワードとユーザー名を連結したものです:PASSWORDUSERNAME
。たとえば、Sup3rS3cr3tpgbouncer
は、pgbouncer
ユーザーの MD5 パスワードハッシュを生成するために必要なテキストです。 -
コンソールプロンプトが使用可能になったら、以下のクエリを実行します:
show databases ; show clients ;
出力は以下のようになるはずです:
name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0 pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 (2 rows) type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+----- C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 | (2 rows)
内部ロードバランサーの設定
推奨されているように複数のPgBouncerノードを実行している場合、TCP内部ロードバランサーを設定する必要があります。これは評判の良いTCPロードバランサーで実現できます。
例として、HAProxyを使った方法を紹介します:
global
log /dev/log local0
log localhost local1 notice
log stdout format raw local0
defaults
log global
default-server inter 10s fall 3 rise 2
balance leastconn
frontend internal-pgbouncer-tcp-in
bind *:6432
mode tcp
option tcplog
default_backend pgbouncer
backend pgbouncer
mode tcp
option tcp-check
server pgbouncer1 <ip>:6432 check
server pgbouncer2 <ip>:6432 check
server pgbouncer3 <ip>:6432 check
ロードバランサのドキュメントを参照してください。
アプリケーションノードの設定
アプリケーションノードはgitlab-rails
サービスを実行します。他の属性を設定することもできますが、以下の属性を設定する必要があります。
-
/etc/gitlab/gitlab.rb
を編集します:# Disable PostgreSQL on the application node postgresql['enable'] = false gitlab_rails['db_host'] = 'PGBOUNCER_NODE' or 'INTERNAL_LOAD_BALANCER' gitlab_rails['db_port'] = 6432 gitlab_rails['db_password'] = 'POSTGRESQL_USER_PASSWORD' gitlab_rails['auto_migrate'] = false gitlab_rails['db_load_balancing'] = { 'hosts' => ['POSTGRESQL_NODE_1', 'POSTGRESQL_NODE_2', 'POSTGRESQL_NODE_3'] }
-
変更を有効にするには、GitLabを再設定してください。
アプリケーションノードの設定後
すべてのマイグレーションが実行されたことを確認します:
gitlab-rake gitlab:db:configure
注意: PgBouncerがPostgreSQLに接続できないという
rake aborted!
エラーが発生した場合、PgBouncerノードのIPアドレスがデータベースノードのgitlab.rb
、PostgreSQLのtrust_auth_cidr_addresses
。PgBouncerエラーERROR: pgbouncer cannot connect to server
トラブルシューティングを参照ください。
バックアップ
PgBouncer接続を通してGitLabのバックアップやリストアをしないでください:GitLabが停止してしまいます。
バックアップの再設定方法についてはこちらをご覧ください。
GitLabが稼働していることを確認します。
この時点で、GitLab インスタンスが稼働しているはずです。サインインし、イシューやマージリクエストを作成できることを確認しましょう。問題が発生した場合は、トラブルシューティングのセクションを参照してください。
設定例
このセクションでは、完全に拡張されたいくつかの設定例について説明します。
推奨セットアップ例
この例では、3台のConsulサーバ、3台のPgBouncerサーバ(関連する内部ロードバランサ付き)、3台のPostgreSQLサーバ、1台のアプリケーションノードを使用しています。
全てのサーバは同じ10.6.0.0/16の非公開ネットワークにあり、これらのアドレスで自由に接続できます。
各マシンと割り当てられたIPのリストと説明は以下の通りです:
-
10.6.0.11
:領事1 -
10.6.0.12
:領事2 -
10.6.0.13
:領事3 -
10.6.0.20
:内部ロードバランサー -
10.6.0.21
:PgBouncer 1 -
10.6.0.22
:用心棒2 -
10.6.0.23
:用心棒3 -
10.6.0.31
:PostgreSQL 1 -
10.6.0.32
:PostgreSQL 2 -
10.6.0.33
:PostgreSQL 3 -
10.6.0.41
:GitLabアプリケーション
すべてのパスワードはtoomanysecrets
に設定されています。このパスワードや派生ハッシュは使用しないでください。GitLabのexternal_url
はhttp://gitlab.example.com
。
初期設定の後、フェイルオーバーが発生すると、PostgreSQLリーダーノードはフェイルバックされるまで利用可能なセカンダリノードの1つに変更されます。
Consulサーバの推奨設定例
各サーバーで/etc/gitlab/gitlab.rb
を編集します:
# Disable all components except Consul
roles(['consul_role'])
consul['configuration'] = {
server: true,
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
consul['monitoring_service_discovery'] = true
変更を有効にするには、GitLabを再設定してください。
PgBouncerサーバーの推奨セットアップ例
各サーバで/etc/gitlab/gitlab.rb
を編集します:
# Disable all components except Pgbouncer and Consul agent
roles(['pgbouncer_role'])
# Configure PgBouncer
pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
pgbouncer['users'] = {
'gitlab-consul': {
password: '5e0e3263571e3704ad655076301d6ebe'
},
'pgbouncer': {
password: '771a8625958a529132abe6f1a4acb19c'
}
}
consul['watchers'] = %w(postgresql)
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
consul['monitoring_service_discovery'] = true
変更を有効にするには、GitLabを再設定してください。
内部ロードバランサーの設定
内部ロードバランサー(TCP) は各PgBouncerノード(この例では10.6.0.20
のIP)に提供するために設定する必要があります。設定方法はPgBouncer Configure Internal Load Balancerを参照してください。
PostgreSQLサーバの推奨設定例
データベースノードで/etc/gitlab/gitlab.rb
を編集します:
# Disable all components except Patroni, PgBouncer and Consul
roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
postgresql['hot_standby'] = 'on'
postgresql['wal_level'] = 'replica'
# Disable automatic database migrations
gitlab_rails['auto_migrate'] = false
postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c'
postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f'
patroni['username'] = 'PATRONI_API_USERNAME'
patroni['password'] = 'PATRONI_API_PASSWORD'
patroni['postgresql']['max_replication_slots'] = 6
patroni['postgresql']['max_wal_senders'] = 7
patroni['allowlist'] = = %w(10.6.0.0/16 127.0.0.1/32)
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16 127.0.0.1/32)
# Local PgBouncer service for Database Load Balancing
pgbouncer['databases'] = {
gitlabhq_production: {
host: "127.0.0.1",
user: "pgbouncer",
password: '771a8625958a529132abe6f1a4acb19c'
}
}
# Configure the Consul agent
consul['services'] = %w(postgresql)
consul['configuration'] = {
retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13)
}
consul['monitoring_service_discovery'] = true
変更を有効にするには、GitLabを再設定してください。
推奨セットアップ手動手順例
設定をデプロイしたら、以下の手順に従ってください:
-
プライマリデータベースノードを見つけます:
gitlab-ctl get-postgresql-primary
-
アプリケーション・サーバーの
10.6.0.41
:gitlab-consul
ユーザーの PgBouncer パスワードをtoomanysecrets
に設定します:gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul
データベースのマイグレーションを実行します:
gitlab-rake gitlab:db:configure
パトロニ
PatroniはPostgreSQLの高可用性を実現するソリューションです。PostgreSQLを制御し、設定を上書きし、ライフサイクル(起動、停止、再起動)を管理します。PatroniはPostgreSQL 12のクラスタリングとデプロイ用のカスケードレプリケーションのための唯一のオプションです。
基本的なアーキテクチャ(上記)はPatroniでも変わりません。データベースノードをプロビジョニングする際に、Patroniを特別に考慮する必要はありません。Patroniはクラスターの状態を保存し、リーダーを選出するためにConsulに大きく依存しています。Consulクラスタとそのリーダー選出に障害が発生すると、Patroniクラスタにも同様に伝搬します。
Patroniはクラスターを監視し、フェイルオーバーを処理します。プライマリノードに障害が発生すると、Consulと連携してPgBouncerに通知します。障害が発生すると、Patroniは古いプライマリのレプリカへの移行を処理し、自動的にクラスタに再参加させます。
Patroniの場合、接続フローは少し異なります。各ノードのPatroniはConsulエージェントに接続してクラスターに参加します。この時点で初めて、そのノードがプライマリかレプリカかを判断します。この決定に基づいて、PostgreSQLを設定し、起動します。PostgreSQLはUnixソケットで直接通信します。つまり、Consulクラスタが機能していなかったり、リーダがいなかったりすると、Patroni、ひいてはPostgreSQLは起動しません。PatroniはREST APIも公開しており、各ノードのデフォルトポートからアクセスすることができます。
レプリケーション状況の確認
gitlab-ctl patroni members
を実行して Patroni にクラスタステータスの概要をクエリします:
+ Cluster: postgresql-ha (6970678148837286213) ------+---------+---------+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+-------------------------------------+--------------+---------+---------+----+-----------+
| gitlab-database-1.example.com | 172.18.0.111 | Replica | running | 5 | 0 |
| gitlab-database-2.example.com | 172.18.0.112 | Replica | running | 5 | 100 |
| gitlab-database-3.example.com | 172.18.0.113 | Leader | running | 5 | |
+-------------------------------------+--------------+---------+---------+----+-----------+
レプリケーションの状態を確認するには
echo -e 'select * from pg_stat_wal_receiver\x\g\x \n select * from pg_stat_replication\x\g\x' | gitlab-psql
同じコマンドを3台すべてのデータベースサーバで実行できます。サーバーが実行しているロールに応じて、レプリケーションに関するあらゆる情報が返されます。
リーダーはレプリカ1つにつき1つのレコードを返す必要があります:
-[ RECORD 1 ]----+------------------------------
pid | 371
usesysid | 16384
usename | gitlab_replicator
application_name | gitlab-database-1.example.com
client_addr | 172.18.0.111
client_hostname |
client_port | 42900
backend_start | 2021-06-14 08:01:59.580341+00
backend_xmin |
state | streaming
sent_lsn | 0/EA13220
write_lsn | 0/EA13220
flush_lsn | 0/EA13220
replay_lsn | 0/EA13220
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | 2021-06-18 19:17:14.915419+00
もしそうなら、さらに調査してください:
- 記録漏れや余分な記録がある場合
-
reply_time
は最新ではありません。
lsn
フィールドは、どのライトアヘッドログセグメントがレプリケートされたかに関連します。現在のログシーケンス番号(LSN)を調べるには、リーダー上で以下を実行してください:
echo 'SELECT pg_current_wal_lsn();' | gitlab-psql
レプリカが同期していない場合、gitlab-ctl patroni members
は欠落しているデータ量を示し、lag
フィールドは経過時間を示します。
leaderが返すデータについては、state
フィールドの他の値を含め、PostgreSQLのドキュメントを参照してください。
レプリカは
-[ RECORD 1 ]---------+-------------------------------------------------------------------------------------------------
pid | 391
status | streaming
receive_start_lsn | 0/D000000
receive_start_tli | 5
received_lsn | 0/EA13220
received_tli | 5
last_msg_send_time | 2021-06-18 19:16:54.807375+00
last_msg_receipt_time | 2021-06-18 19:16:54.807512+00
latest_end_lsn | 0/EA13220
latest_end_time | 2021-06-18 19:07:23.844879+00
slot_name | gitlab-database-1.example.com
sender_host | 172.18.0.113
sender_port | 5432
conninfo | user=gitlab_replicator host=172.18.0.113 port=5432 application_name=gitlab-database-1.example.com
レプリカが返すデータについての詳細はPostgreSQLのドキュメントを参照してください。
適切なPatroniレプリケーションメソッドの選択
変更する前にPatroniのドキュメントをよくレビューしてください。 いくつかのオプションは完全に理解されていない場合、潜在的なデータ損失のリスクを伴います。.設定されたレプリケーションモードにより、許容されるデータ損失の量が決まります。
Linuxパッケージのインストールはデフォルトでsynchronous_commit
、on
。
postgresql['synchronous_commit'] = 'on'
gitlab['geo-postgresql']['synchronous_commit'] = 'on'
Patroni フェイルオーバー動作のカスタマイズ
Linuxパッケージのインストールでは、Patroniのリストアプロセスをコントロールするためのいくつかのオプションが用意されています。
各オプションのデフォルト値を/etc/gitlab/gitlab.rb
に示します。
patroni['use_pg_rewind'] = true
patroni['remove_data_directory_on_rewind_failure'] = false
patroni['remove_data_directory_on_diverged_timelines'] = false
アップストリームのドキュメントは常に最新ですが、以下の表は機能の最低限の概要を提供するものです。
設定 | 概要 | - | - | |use_pg_rewind |データベースクラスタに再参加する前に、以前のクラスタリーダ上でpg_rewind 。|remove_data_directory_on_rewind_failure |pg_rewind |失敗した場合、ローカルのPostgreSQLデータディレクトリを削除し、現在のクラスタリーダから再複製してください。|remove_data_directory_on_diverged_timelines |pg_rewind |使用できず、以前のリーダのタイムラインが現在のタイムラインから乖離している場合、ローカルのデータディレクトリを削除し、現在のクラスタリーダから再複製してください。| |失敗した場合、ローカルのPostgreSQLデータディレクトリを削除し、現在のクラスタリーダから再複製してください。 |
Patroniのデータベース作成者
PatroniはPostgreSQLインスタンスを管理するためにUnixソケットを使用します。そのため、local
ソケットからの接続は信頼されなければなりません。
また、レプリカはリーダーとの通信にレプリケーションユーザー( デフォルトではgitlab_replicator
)を使用します。このユーザーには、trust
とmd5
のどちらかの認証を選択できます。postgresql['sql_replication_password']
を設定した場合、Patroniはmd5
認証を使用し、それ以外の場合はtrust
にフォールバックします。 クラスタのCIDRはそれぞれpostgresql['md5_auth_cidr_addresses']
またはpostgresql['trust_auth_cidr_addresses']
で指定する必要があります。
クラスターとのやりとり
gitlab-ctl patroni members
を使ってクラスタメンバーの状態を確認することができます。各ノードのステータスを確認するためにgitlab-ctl patroni
にはcheck-leader
とcheck-replica
という2つのサブコマンドがあり、ノードがプライマリかレプリカかを示します。
Patroniが有効な場合、PostgreSQLの起動、シャットダウン、再起動を排他的に制御します。つまり、あるノードのPostgreSQLをシャットダウンするには、同じノードのPatroniをシャットダウンしなければなりません:
sudo gitlab-ctl stop patroni
リーダーノードでPatroniサービスを停止または再起動すると、自動的にフェイルオーバーが発生します。フェイルオーバーを発生させずにPatroniの設定をリロードしたり、PostgreSQLプロセスを再起動する必要がある場合は、gitlab-ctl patroni
のサブコマンドreload
またはrestart
を使用してください。これら2つのサブコマンドは同じpatronictl
コマンドのラッパーです。
Patroniの手動フェイルオーバー手順
Patroniは自動フェイルオーバーをサポートしていますが、手動フェイルオーバーも可能です:
-
フェイルオーバー: 健全なノードがない場合に手動でフェイルオーバーを行うことができます。このアクションはどのPostgreSQLノードでも実行できます:
sudo gitlab-ctl patroni failover
-
Switchover:クラスターが健全な時にのみ動作し、切り替えをスケジュールすることができます(すぐに実行することもできます)。どのPostgreSQLノードでもこのアクションを実行できます:
sudo gitlab-ctl patroni switchover
この件に関する詳細はPatroniのドキュメントを参照してください。
Geoセカンダリーサイトの考察
GeoセカンダリサイトがPatroni
、PgBouncer
を使用するプライマリサイトからレプリケートする場合、PgBouncerを介したレプリケーションはサポートされません。セカンダリノードはクラスターのリーダーノードから直接レプリケートする必要がありますPatroni
。 Patroni
クラスターPatroni
内で自動または手動でフェイルオーバーが Patroni
発生した場合、セカンダリサイトを手動で再指定して、新しいリーダーノードからレプリケートすることができます:
sudo gitlab-ctl replicate-geo-database --host=<new_leader_ip> --replication-slot=<slot_name>
そうしないと、元のノードがフォロワーノードとして再追加されても、レプリケーションは行われません。これはセカンダリ・サイトのデータベースを再同期するもので、同期するデータ量によっては長い時間がかかる場合があります。再同期後もレプリケーションが機能しない場合は、gitlab-ctl reconfigure
。
Patroniクラスターのリカバリ
古いプライマリをリカバリしてレプリカとしてクラスターに再参加させるには、Patroniを起動します:
sudo gitlab-ctl start patroni
これ以上の設定や介入は必要ありません。
パトロニのメンテナンス手順
Patroniを有効にすると、ノードに対して計画的なメンテナンスを実行することができます。Patroniを使用していないノードのメンテナンスを行うには、以下の手順でメンテナンスモードにします:
sudo gitlab-ctl patroni pause
Patroniが一時停止モードで動作している場合、PostgreSQLの状態は変化しません。終了後、Patroniを再開することができます:
sudo gitlab-ctl patroni resume
詳細はPatroniのドキュメントを参照してください。
repmgrからPatroniへの切り替え
以下の手順で、終了したデータベースクラスタをrepmgrの代わりにPatroniを使うように切り替えることができます:
-
すべてのレプリカノードでrepmgrを停止し、最後にプライマリノードで停止します:
sudo gitlab-ctl stop repmgrd
-
すべてのレプリカノードでPostgreSQLを停止します:
sudo gitlab-ctl stop postgresql
プライマリノードでwalsender
プロセスが実行されていないことを確認してください。ps aux | grep walsender
に実行中のプロセスが表示されていないことを確認してください。 - プライマリノードでPatroniを設定します。
repmgr
、その他のrepmgr固有の設定を削除します。PostgreSQLレプリケーションに関連する設定もすべて削除してください。 -
プライマリノードでGitLabを再設定します。これでリーダーノードになります。これで確認できます:
sudo gitlab-ctl tail patroni
- 最後の二つのステップをすべてのレプリカノードで繰り返します。
gitlab.rb
はすべてのノードで同じように見えるはずです。 -
存在する場合は、
gitlab_repmgr
プライマリ上のデータベースとロールをgitlab_repmgr
削除してください。データベースをgitlab_repmgr
削除gitlab_repmgr
しないと、PostgreSQL 11から12へのアップグレードは失敗します:could not load library "$libdir/repmgr_funcs": ERROR: could not access file "$libdir/repmgr_funcs": No such file or directory
PatroniクラスタでのPostgreSQLメジャーバージョンのアップグレード
GitLab 14.1では、PostgreSQL 12.6と13.3はデフォルトでLinuxパッケージに同梱されています。GitLab 15.0ではPostgreSQL 13がデフォルトです。GitLab 15.0より前のバージョンでPostgreSQL 13にアップグレードしたい場合は、明示的にリクエストする必要があります。
PostgreSQLをアップグレードする前に考慮しなければならないいくつかの重要な事実を示します:
-
最大のポイントは、Patroniクラスターをシャットダウンしなければならないということです。これは、データベースのアップグレードの間、あるいは少なくともリーダーノードがアップグレードされる間、GitLabのデプロイが停止することを意味します。これは、データベースのサイズによってはかなりのダウンタイムになる可能性があります。
-
PostgreSQL をアップグレードすると、新しい制御データを持つ新しいデータディレクトリが作成されます。Petroniから見ると、これは新しいクラスターであり、再度ブートストラップする必要があります。したがって、アップグレード手順の一環として、クラスターの状態(Consulに保存されている)は消去されます。アップグレードが完了すると、Patroniは新しいクラスターをブートストラップします。これにより_クラスターIDが_変更されます。
-
リーダーとレプリカのアップグレード手順は同じではありません。そのため、各ノードで正しい手順を使用することが重要です。
-
レプリカノードをアップグレードすると、データディレクトリが削除され、設定されたレプリケーション方法を使用してリーダーから再同期されます(
pg_basebackup
が唯一の利用可能なオプションです)。データベースのサイズによっては、レプリカがリーダーに追いつくのに時間がかかる場合があります。 -
アップグレード手順の概要はPatroni のドキュメントにあります。この手順を実装している
gitlab-ctl pg-upgrade
を、少し調整して使うこともできます。
これらを考慮した上で、PostgreSQLのアップグレードを慎重に計画してください:
-
どのノードがリーダで、どのノードがレプリカかを調べてください:
gitlab-ctl patroni members
Geoセカンダリノードでは、Patroniリーダーノードはstandby leader
と呼ばれます。 -
レプリカ上でのみPatroniを停止します。
sudo gitlab-ctl stop patroni
-
アプリケーションノードでメンテナンスモードを有効にします:
sudo gitlab-ctl deploy-page up
-
リーダーノードで PostgreSQL をアップグレードし、アップグレードが正常に完了したことを確認します:
sudo gitlab-ctl pg-upgrade -V 13
gitlab-ctl pg-upgrade
はノードのロールを検出しようとします。何らかの理由で自動検出がうまくいかなかったり、正しくロールを検出できなかったと思われる場合は、--leader
や--replica
引数を使用して手動で上書きすることができます。 -
リーダーとクラスターの状態を確認します。リーダが正常である場合にのみ続行できます:
gitlab-ctl patroni check-leader # OR gitlab-ctl patroni members
-
アプリケーションノードのメンテナンスモードを無効にできます:
sudo gitlab-ctl deploy-page down
-
レプリカのPostgreSQLをアップグレードします(すべてのレプリカで並行して行うことができます):
sudo gitlab-ctl pg-upgrade -V 13
レプリカのアップグレードでイシューが発生した場合、解決策となる可能性のあるトラブルシューティングセクションがあります。
gitlab-ctl revert-pg-upgrade
、PostgreSQLのアップグレードを元に戻すには、gitlab-ctl pg-upgrade
と同じ考慮事項があります。まずレプリカを停止し、次にリーダを元に戻し、最後にレプリカを元に戻すという同じ手順を踏む必要があります。PatroniクラスタにおけるPostgreSQLのほぼゼロダウンタイムのアップグレード
PatroniではPostgreSQLのメジャーアップグレードをクラスターをシャットダウンすることなく実行することができます。しかし、アップグレードされたPostgreSQLを持つ新しいPatroniノードをホストするための追加リソースが必要です。実際には、この手順では
- 新しいバージョンのPostgreSQLで新しいPatroniクラスタを作成します。
- 既存のクラスターからデータをマイグレーションします。
この手順は非侵襲的で、既存のクラスターをオフにする前に影響を与えることはありません。ただし、時間とリソースの両方がかかります。可用性とのトレードオフを考慮してください。
手順を順に説明します:
- 新しいクラスターのリソースをプロビジョニングします。
- プリフライトチェック。
- 新しいクラスターのリーダーを設定します。
- 既存のリーダでパブリッシャーを開始します。
- 既存のクラスターからデータをコピーします。
- 既存のクラスターからデータを複製します。
- 新しいクラスターを成長させます。
- 新しいクラスターを使用するようにアプリケーションを切り替えます。
- クリーンアップします。
新しいクラスターにリソースを提供します。
Patroniノード用の新しいリソースが必要です。新しいPatroniクラスタは既存のクラスタと全く同じ数のノードを必要としません。要件に応じて異なるノード数を選択できます。新しいクラスターは既存のConsulクラスター(異なるpatroni['scope']
)とPgBouncerノードを使用します。
少なくとも既存のクラスターのリーダーノードが新しいクラスターのノードからアクセス可能であることを確認してください。
プリフライトチェック
PostgreSQLの論理レプリケーションは、クラスターのダウンタイムがほぼゼロになるようなアップグレードをサポートします。論理レプリケーションの要件を満たす必要があります。特に、wal_level
はlogical
でなければなりません。wal_level
を確認するには、既存のクラスターの任意のノードでgitlab-psql
を指定して以下のコマンドを実行してください:
SHOW wal_level;
デフォルトでは、Patroniはwal_level
をreplica
に設定します。 これをlogical
に増やす必要があります。wal_level
を変更するにはPostgreSQLを再起動する必要があるため、この手順を実行するとダウンタイムが短くなります(つまりダウンタイムはほぼゼロになります)。Patroniリーダーノードでこれを行うには、以下の手順に従います:
-
gitlab.rb
:patroni['postgresql']['wal_level'] = 'logical'
- Run
gitlab-ctl reconfigure
.これで設定が書き込まれますが、PostgreSQLサービスは再起動されません。 -
gitlab-ctl patroni restart
を実行して PostgreSQL を再起動し、フェイルオーバーをトリガせずに新しいwal_level
を適用します。再起動サイクルの間、クラスター・リーダーは利用できません。 -
gitlab-psql
でSHOW wal_level
を実行して変更を確認してください。
新しいクラスターのリーダーを設定します。
新しいクラスターの最初のノードを設定します。このノードが新しいクラスタのリーダになります。新しいPostgreSQLのバージョンと互換性があれば、既存のクラスターの設定を使用することができます。Patroniクラスタの設定に関するドキュメントを参照してください。
共通の設定に加えて、gitlab.rb
:
-
新しいPatroniクラスタが異なるスコープを使用していることを確認してください。スコープはConsulのPatroni設定の名前空間として使用され、既存のクラスタと新しいクラスタで同じConsulクラスタを使用することができます。
patroni['scope'] = 'postgresql_new-ha'
-
Consulエージェントが既存のPatroniクラスタと新しいPatroniクラスタで提供されるPostgreSQLサービスを混在させないようにしてください。このためには、内部属性を使用する必要があります:
consul['internal']['postgresql_service_name'] = 'postgresql_new'
既存のリーダーでパブリッシャーを開始
既存のリーダー上で、論理レプリケーションパブリッシャーを開始するために、gitlab-psql
を指定して、この SQL 文を実行してください:
CREATE PUBLICATION patroni_upgrade FOR ALL TABLES;
既存のクラスターからデータをコピーします。
既存のクラスターから現在のデータベースをダンプするには、新しいクラスターのリーダー上で以下のコマンドを実行します:
-
オプション。グローバル・データベース・オブジェクトをコピーします:
pg_dumpall -h ${EXISTING_CLUSTER_LEADER} -U gitlab-psql -g | gitlab-psql
ロールなどの既存のデータベース・オブジェクトに関するエラーは無視できます。これらのオブジェクトは、ノードの初回設定時に作成されます。
-
現在のデータベースをコピーします:
pg_dump -h ${EXISTING_CLUSTER_LEADER} -U gitlab-psql -d gitlabhq_production -s | gitlab-psql
データベースのサイズによっては、このコマンドの完了に時間がかかる場合があります。
pg_dump
およびpg_dumpall
コマンドは/opt/gitlab/embedded/bin
にあります。 これらのコマンドでは、EXISTING_CLUSTER_LEADER
は既存のクラスターのリーダー・ノードのホスト・アドレスです。
gitlab-psql
ユーザーは、新しいリーダーノードから既存のリーダーを認証できる必要があります。既存のクラスターからのデータの複製
最初のデータダンプを取った後、新しいリーダーを既存のクラスターの最新の変更と同期させておく必要があります。新しいリーダー上で、gitlab-psql
を指定してこのSQL文を実行し、既存のリーダーの公開を購読します:
CREATE SUBSCRIPTION patroni_upgrade
CONNECTION 'host=EXISTING_CLUSTER_LEADER dbname=gitlabhq_production user=gitlab-psql'
PUBLICATION patroni_upgrade;
この文では、EXISTING_CLUSTER_LEADER
は既存のクラスターのリーダーノードのホストアドレスです。他のパラメータを使用して接続文字列を変更することもできます。たとえば、認証パスワードを渡すことができます。
レプリケーションの状態を確認するには、以下のクエリを実行します:
-
SELECT * FROM pg_replication_slots WHERE slot_name = 'patroni_upgrade'
既存のリーダー(パブリッシャー)に対して -
SELECT * FROM pg_stat_subscription
新しいリーダー(購読者)の上で。
新しいクラスターの成長
新しいクラスターの他のノードを、リーダーを設定した方法で設定します。同じpatroni['scope']
とconsul['internal']['postgresql_service_name']
を使用していることを確認してください。
ここで起こること
- アプリケーションはデータベースのバックエンドとして既存のリーダーを使用します。
- 論理レプリケーションは、新しいリーダーの同期を保証します。
- 他のノードが新しいクラスターに追加されると、Patroniはこれらのノードへのレプリケーションを処理します。
新しいクラスターのレプリカノードが初期化され、レプリケーションラグに追いつくまで待つのがよいでしょう。
新しいクラスターを使用するようにアプリケーションを切り替えます。
この時点までは、既存のクラスターのデータを失うことなくアップグレード手順を停止できます。アプリケーションのデータベースバックエンドを切り替えて新しいクラスターに向けると、古いクラスターは新しい更新を受け取りません。新しいクラスターに遅れをとります。この時点以降、リカバリはすべて新しいクラスターのノードから行う必要があります。
すべてのPgBouncerノードで切り替えを行うには:
-
gitlab.rb
:consul['watchers'] = %w(postgresql_new) consul['internal']['postgresql_service_name'] = 'postgresql_new'
-
gitlab-ctl reconfigure
を実行してください。
クリーンアップ
以上の手順が完了したら、古いPatroniクラスタのリソースをクリーンアップします。これらはもはや必要ありません。しかし、リソースを削除する前に、DROP SUBSCRIPTION patroni_upgrade
を実行して新しいリーダーの論理レプリケーションサブスクリプションを削除してください。gitlab-psql
.
トラブルシューティング
ConsulとPostgreSQLの変更が反映されない
潜在的な影響のため、gitlab-ctl reconfigure
、ConsulとPostgreSQLをリロードするだけで、サービスは再起動しません。しかし、すべての変更がリロードによって有効になるわけではありません。
どちらかのサービスを再起動するにはgitlab-ctl restart SERVICE
PostgreSQLの場合、通常はデフォルトでリーダーノードを再起動するのが安全です。自動フェイルオーバーのデフォルトは1分間のタイムアウトです。それまでにデータベースが復帰していれば、他に何もする必要はありません。
Consulサーバーノードでは、Consulサービスを制御された方法で再起動することが重要です。
PgBouncerエラーERROR: pgbouncer cannot connect to server
gitlab-rake gitlab:db:configure
、PgBouncerのログファイルにエラーが表示されます。
PG::ConnectionBad: ERROR: pgbouncer cannot connect to server
問題はPgBouncerノードのIPアドレスがデータベースノードの/etc/gitlab/gitlab.rb
のtrust_auth_cidr_addresses
の設定に含まれていないことです。
リーダーデータベースノードのPostgreSQLログを確認することでイシューを確認できます。以下のエラーが表示された場合、trust_auth_cidr_addresses
が問題です。
2018-03-29_13:59:12.11776 FATAL: no pg_hba.conf entry for host "123.123.123.123", user "pgbouncer", database "gitlabhq_production", SSL off
この問題を解決するには、IPアドレスを/etc/gitlab/gitlab.rb
に追加してください。
postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
変更を有効にするには、GitLabを再設定してください。
レプリカの再初期化
レプリカがクラスターを開始できない、あるいは再参加できない場合、あるいは遅れて追いつけない場合、レプリカを再初期化する必要があるかもしれません:
-
レプリケーション・ステータスを確認して、再初期化が必要なサーバを確認します。たとえば
+ Cluster: postgresql-ha (6970678148837286213) ------+---------+--------------+----+-----------+ | Member | Host | Role | State | TL | Lag in MB | +-------------------------------------+--------------+---------+--------------+----+-----------+ | gitlab-database-1.example.com | 172.18.0.111 | Replica | running | 55 | 0 | | gitlab-database-2.example.com | 172.18.0.112 | Replica | start failed | | unknown | | gitlab-database-3.example.com | 172.18.0.113 | Leader | running | 55 | | +-------------------------------------+--------------+---------+--------------+----+-----------+
-
壊れたサーバにサインインし、データベースとレプリケーションを再初期化します。PatroniはそのサーバのPostgreSQLをシャットダウンし、データディレクトリを削除し、ゼロから再初期化します:
sudo gitlab-ctl patroni reinitialize-replica --member gitlab-database-2.example.com
This can be run on any Patroni node, but be aware that
sudo gitlab-ctl patroni reinitialize-replica
without--member
restarts the server it is run on.これはどのPatroniノードでも実行できますが、、 を実行しない場合、実行されたサーバが再起動されることに注意してください。意図しないデータ損失のリスクを減らすために、壊れたサーバ上でローカルに実行してください。 -
ログを監視してください:
sudo gitlab-ctl tail patroni
コンシュルでのパトロニ状態のリセット
最後の手段として、ConsulのPatroniの状態を完全にリセットすることができます。
これはPatroniクラスタが未知の状態、もしくは悪い状態にあり、どのノードも起動できない場合に必要となります:
+ Cluster: postgresql-ha (6970678148837286213) ------+---------+---------+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+-------------------------------------+--------------+---------+---------+----+-----------+
| gitlab-database-1.example.com | 172.18.0.111 | Replica | stopped | | unknown |
| gitlab-database-2.example.com | 172.18.0.112 | Replica | stopped | | unknown |
| gitlab-database-3.example.com | 172.18.0.113 | Replica | stopped | | unknown |
+-------------------------------------+--------------+---------+---------+----+-----------+
ConsulでPatroniの状態を削除する前に、Patroniノードでgitlab-ctl
エラー を解決してみてください。
このプロセスにより、最初のPatroniノードが起動したときにPatroniクラスタが再初期化されます。
ConsulでPatroniの状態をリセットするには:
- ConsulでPatroniの状態をリセットするには:リーダーだったPatroniノード、またはアプリケーションが現在のリーダーだと思っているPatroniノードをメモしてください:
-
/var/opt/gitlab/consul/databases.ini
、現在のリーダーのホスト名を含むPgBouncerノードを探します。 -
すべてのデータベースノードのPatroniログ
/var/log/gitlab/patroni/current
(または、より古いローテートされ圧縮されたログ/var/log/gitlab/patroni/@40000*
)を見て、クラスターによって最も最近リーダーとして認識されたサーバを確認します:INFO: no action. I am a secondary (database1.local) and following a leader (database2.local)
-
-
全てのノードでPatroniを停止します:
sudo gitlab-ctl stop patroni
-
Consulの状態をリセットします:
/opt/gitlab/embedded/bin/consul kv delete -recurse /service/postgresql-ha/
-
Patroniクラスタを初期化し、リーダーとして選出します。クラスターの状態が壊れたためにレプリケートされなかったかもしれない既存の書き込みを失わないために、(最初のステップで述べた)前のリーダーを起動することを強く推奨します:
sudo gitlab-ctl start patroni
-
Patroniクラスターに参加する他のすべてのPatroniノードをレプリカとして起動します:
sudo gitlab-ctl start patroni
それでもイシューが表示される場合は、次のステップとして最後に健全なバックアップをリストアします。
Patroniログにpg_hba.conf
のエントリに関するエラーが表示されます。127.0.0.1
Patroniログの以下のログエントリはレプリケーションが機能しておらず、設定変更が必要であることを示しています:
FATAL: no pg_hba.conf entry for replication connection from host "127.0.0.1", user "gitlab_replicator"
この問題を解決するには、ループバックインターフェースがCIDRアドレスリストに含まれていることを確認してください:
-
/etc/gitlab/gitlab.rb
を編集します:postgresql['trust_auth_cidr_addresses'] = %w(<other_cidrs> 127.0.0.1/32)
- 変更を有効にするには、GitLabを再設定してください。
- 全てのレプリカが同期されていることを確認します。
Patroniログのエラー:要求された開始ポイントがWrite Ahead Log(WAL) のフラッシュ位置より前にあります。
このエラーはデータベースがレプリケートされていないことを示します:
FATAL: could not receive data from WAL stream: ERROR: requested starting point 0/5000000 is ahead of the WAL flush position of this server 0/4000388
このエラーの例は、初期設定に誤りがあり、一度もレプリケートされていないレプリカのものです。
レプリカを再初期化することで修正してください。
PatroniがMemoryError
Patroni は起動に失敗し、エラーとスタックトレースを記録します:
MemoryError
Traceback (most recent call last):
File "/opt/gitlab/embedded/bin/patroni", line 8, in <module>
sys.exit(main())
[..]
File "/opt/gitlab/embedded/lib/python3.7/ctypes/__init__.py", line 273, in _reset_cache
CFUNCTYPE(c_int)(lambda: None)
スタックトレースの末尾がCFUNCTYPE(c_int)(lambda: None)
である場合、Linux サーバーがセキュリティのためにハード化されていれば、このコードはMemoryError
をトリガーします。
このコードは Python に一時的な実行可能ファイルを書かせます。例えば、noexec
が/tmp
ファイルシステムに設定されている場合、MemoryError
で失敗します(詳しくはイシューを読んでください)。
回避策
-
/tmp
や/var/tmp
のようなファイルシステムのマウントオプションからnoexec
を削除します。 - enforcingに設定すると、SELinuxがこれらのオペレーションを阻止することもあります。SELinux を permissive に設定して、イシューが修正されていることを確認してください。
PatroniはPython 3.7のビルドとともにGitLab 13.1のLinuxパッケージで最初に出荷されました。この問題を引き起こすコードは Python 3.8 で削除されました。この修正はGitLab 14.3以降の Linux パッケージで出荷され、回避策の必要性はなくなりました。
実行中のエラーgitlab-ctl
Patroniノードはgitlab-ctl
コマンドが失敗し、gitlab-ctl reconfigure
ノードを修正できない状態になることがあります。
PostgreSQLのバージョンアップと重なる場合は、別の手順に従ってください。
よくある症状として、データベースサーバが起動に失敗している場合、gitlab-ctl
がインストールに必要な情報を判断できないというものがあります:
Malformed configuration JSON file found at /opt/gitlab/embedded/nodes/<HOSTNAME>.json.
This usually happens when your last run of `gitlab-ctl reconfigure` didn't complete successfully.
Error while reinitializing replica on the current node: Attributes not found in
/opt/gitlab/embedded/nodes/<HOSTNAME>.json, has reconfigure been run yet?
同様に、ノードファイル(/opt/gitlab/embedded/nodes/<HOSTNAME>.json
)には多くの情報が含まれているはずですが、作成される情報はわずかです:
{
"name": "<HOSTNAME>"
}
これを修正するための以下のプロセスには、このレプリカの再初期化が含まれます:
-
Patroniと(存在すれば)PostgreSQLのサービスを停止します:
sudo gitlab-ctl status sudo gitlab-ctl stop patroni sudo gitlab-ctl stop postgresql
-
その状態がPostgreSQLの起動を妨げている場合に備えて、
/var/opt/gitlab/postgresql/data
:cd /var/opt/gitlab/postgresql sudo rm -rf data
データの損失を避けるため、この手順には注意してください。
data/
プライマリデータベースの新しいコピーのために十分な空きディスクがあることを確認し、レプリカが修正されたら余分なディレクトリを削除してください。 -
PostgreSQLが稼働していない状態で、ノードファイルが正常に作成されました:
sudo gitlab-ctl reconfigure
-
Patroniを起動します:
sudo gitlab-ctl start patroni
-
ログを監視し、クラスターの状態を確認します:
sudo gitlab-ctl tail patroni sudo gitlab-ctl patroni members
-
再度
reconfigure
:sudo gitlab-ctl reconfigure
-
gitlab-ctl patroni members
が必要であると示した場合は、レプリカを再初期化します:sudo gitlab-ctl patroni reinitialize-replica
この手順がうまくいかず、クラスターがリーダーを選出できない場合、最後の手段としてのみ使用すべきもう1つの修正があります。
PostgreSQLのメジャーバージョンアップがPatroniレプリカで失敗します。
Patroniレプリカが gitlab-ctl pg-upgrade
、ループにはまり、アップグレードに失敗することがあります。
症状の例を以下に示します:
-
通常Patroniノードには存在しないはずの
postgresql
サービスが定義されています。これはgitlab-ctl pg-upgrade
、新しい空のデータベースを作成するために追加されるためです:run: patroni: (pid 1972) 1919s; run: log: (pid 1971) 1919s down: postgresql: 1s, normally up, want up; run: log: (pid 1973) 1919s
-
PostgreSQLはレプリカの再初期化の一環としてPatroniが
/var/opt/gitlab/postgresql/data
を削除する際に、/var/log/gitlab/postgresql/current
にPANIC
ログエントリを生成します:DETAIL: Could not open file "pg_xact/0000": No such file or directory. WARNING: terminating connection because of crash of another server process LOG: all server processes terminated; reinitializing PANIC: could not open file "global/pg_control": No such file or directory
-
/var/log/gitlab/patroni/current
で、Patroniは以下のログを記録します。ローカルのPostgreSQLのバージョンがクラスター・リーダーと異なります:INFO: trying to bootstrap from leader 'HOSTNAME' pg_basebackup: incompatible server version 12.6 pg_basebackup: removing data directory "/var/opt/gitlab/postgresql/data" ERROR: Error when fetching backup: pg_basebackup exited with code=1
重要: この回避策はPatroniクラスタが以下の状態のときに適用されます:
- リーダーが新しいメジャーバージョンに正常にアップグレードされました。
- レプリカのPostgreSQLをアップグレードするステップが失敗しています。
この回避策では、PatroniレプリカのPostgreSQLのアップグレードを完了させるために、新しいバージョンのPostgreSQLを使用するようにノードを設定し、リーダーのアップグレード時に作成された新しいクラスターのレプリカとして再初期化します:
-
すべてのノードでクラスターの状態を確認し、どのノードがリーダーで、レプリカがどのような状態にあるかを確認します。
sudo gitlab-ctl patroni members
-
レプリカ: どのバージョンのPostgreSQLがアクティブかを確認します:
sudo ls -al /opt/gitlab/embedded/bin | grep postgres
-
Replica: ノードファイルが正しく、
gitlab-ctl
が実行できることを確認してください。レプリカにこれらのエラーがある場合、gitlab-ctl
](#errors-running-gitlab-ctl) を実行する[のエラーも解決されます:sudo gitlab-ctl stop patroni sudo gitlab-ctl reconfigure
-
Replica: PostgreSQLバイナリを必要なバージョンに再リンクして、
incompatible server version
のエラーを修正してください:-
/etc/gitlab/gitlab.rb
を編集して必要なバージョンを指定してください:postgresql['version'] = 13
-
GitLab を再設定します:
sudo gitlab-ctl reconfigure
-
バイナリが再リンクされているか確認してください。PostgreSQL用に配布されているバイナリはメジャーリリースによって異なるため、誤ったシンボリックリンクが少なからず存在するのが普通です:
sudo ls -al /opt/gitlab/embedded/bin | grep postgres
-
-
Replica: PostgreSQLが指定されたバージョンで完全に再初期化されていることを確認してください:
cd /var/opt/gitlab/postgresql sudo rm -rf data sudo gitlab-ctl reconfigure
-
Replica: オプションで、さらに2つのターミナルセッションでデータベースを監視します:
-
pg_basebackup
を実行するとディスク使用量が増加します。でレプリカの初期化の進捗を追跡します:cd /var/opt/gitlab/postgresql watch du -sh data
-
ログでプロセスを監視します:
sudo gitlab-ctl tail patroni
-
-
レプリカPatroni を起動してレプリカを再初期化します:
sudo gitlab-ctl start patroni
-
レプリカを再初期化します:完了後、
/etc/gitlab/gitlab.rb
からハードコードされたバージョンを削除します:-
/etc/gitlab/gitlab.rb
を編集し、postgresql['version']
を削除してください。 -
GitLab を再設定します:
sudo gitlab-ctl reconfigure
-
正しいバイナリがリンクされているか確認してください:
sudo ls -al /opt/gitlab/embedded/bin | grep postgres
-
-
すべてのノードでクラスターの状態を確認します:
sudo gitlab-ctl patroni members
必要に応じて、もう一方のレプリカでこの手順を繰り返します。
他のコンポーネントのイシュー
ここに記載されていないコンポーネントでイシューが発生した場合は、そのコンポーネントのドキュメントページのトラブルシューティングセクションを確認してください: