Linux 패키지 설치를 위한 PostgreSQL 복제 및 장애 조치

Tier: Premium, Ultimate Offering: Self-managed

GitLab self-managed의 무료 사용자라면 클라우드 호스팅 솔루션을 사용하는 것을 고려하세요.
이 문서는 자체 컴파일 설치에 대해서는 다루지 않습니다.

복제 및 장애 조치가 필요한 설정이 아닌 경우,
데이터베이스 구성 문서를 참조하세요.

PostgreSQL을 GitLab과 함께 복제 및 장애 조치로 구성하기 전에
이 문서를 완전히 읽는 것이 권장됩니다.

운영 체제 업그레이드

다른 운영 체제를 가진 시스템으로 장애 조치하는 경우,
PostgreSQL을 위한 운영 체제 업그레이드 문서를 읽어보세요.
운영 체제 업그레이드 시 로컬 변경 사항을 고려하지 않으면 데이터 손상이 발생할 수 있습니다.

아키텍처

복제 장애 조치가 있는 PostgreSQL 클러스터를 위한 Linux 패키지 권장 구성은 다음을 요구합니다:

  • 최소 세 개의 PostgreSQL 노드.
  • 최소 세 개의 Consul 서버 노드.
  • 기본 데이터베이스 읽기 및 쓰기를 추적하고 처리하는 최소 세 개의 PgBouncer 노드.
    • PgBouncer 노드 간의 요청을 균형 있게 분배하는 내부 로드 밸런서(TCP).
  • 데이터베이스 로드 밸런싱 활성화.
    • 각 PostgreSQL 노드에 로컬 PgBouncer 서비스가 구성되어 있습니다. 이는 주 PgBouncer 클러스터와는 별개입니다.

또한, 모든 데이터베이스와 GitLab 인스턴스 간에 중복 연결성을 갖추어 네트워크가 단일 실패점이 되지 않도록
기본 네트워크 토폴로지도 고려해야 합니다.

주의:
PostgreSQL 12는 Linux 패키지 설치와 함께 제공됩니다. PostgreSQL 12의 클러스터링은
오직 Patroni와 함께 지원되므로, 복제 및 장애 조치를 위해 Patroni가 필수입니다.
자세한 내용은 Patroni 섹션을 참조하세요.

데이터베이스 노드

각 데이터베이스 노드는 네 개의 서비스를 실행합니다:

  • PostgreSQL: 데이터베이스 자체입니다.
  • Patroni: 클러스터 내 다른 Patroni 서비스와 통신하고 리더 서버 문제 발생 시 페일오버를 처리합니다. 페일오버 절차는 다음으로 구성됩니다:
    • 클러스터의 새로운 리더 선택.
    • 새로운 노드를 리더로 승격.
    • 나머지 서버에 새로운 리더 노드를 따르도록 지시.
  • PgBouncer: 노드에 대한 로컬 풀러입니다. 데이터베이스 로드 밸런싱의 일환으로 읽기 쿼리에 사용됩니다.
  • Consul 에이전트: 현재 Patroni 상태를 저장하는 Consul 클러스터와 통신하기 위해 사용됩니다. 에이전트는 데이터베이스 클러스터 내 각 노드의 상태를 모니터링하고 Consul 클러스터의 서비스 정의에서 그 건강 상태를 추적합니다.

Consul 서버 노드

Consul 서버 노드는 Consul 서버 서비스를 실행합니다. 이러한 노드는 쿼럼에 도달하고 Patroni 클러스터 부트스트랩 _전_에 리더를 선출해야 합니다; 그렇지 않으면 데이터베이스 노드는 해당 Consul 리더가 선출될 때까지 기다립니다.

PgBouncer 노드

각 PgBouncer 노드는 두 개의 서비스를 실행합니다:

  • PgBouncer: 데이터베이스 연결 풀러 자체입니다.
  • Consul 에이전트: Consul 클러스터에서 PostgreSQL 서비스 정의의 상태를 감시합니다. 그 상태가 변경되면, Consul은 PgBouncer 구성을 새로운 PostgreSQL 리더 노드를 가리키도록 업데이트하고 PgBouncer 서비스를 다시 로드하는 스크립트를 실행합니다.

연결 흐름

패키지의 각 서비스는 기본 포트 세트를 제공합니다. 아래 나열된 연결에 대해 특정 방화벽 규칙을 설정해야 할 수 있습니다:

이 설정에는 여러 연결 흐름이 있습니다:

Primary

  • 애플리케이션 서버는 기본 포트에서 PgBouncer에 직접 연결하거나 여러 PgBouncer에 서비스를 제공하는 구성된 내부 로드 밸런서(TCP)를 통해 연결합니다.
  • PgBouncer는 기본 데이터베이스 서버의 PostgreSQL 기본 포트에 연결합니다.

데이터베이스 로드 밸런싱

최근에 변경되지 않고 모든 데이터베이스 노드에서 최신 상태인 데이터에 대한 읽기 쿼리의 경우:

  • 애플리케이션 서버는 각 데이터베이스 노드의 로컬 PgBouncer 서비스에 대해 기본 포트을 통해 라운드 로빈 방식으로 연결합니다.
  • 로컬 PgBouncer는 로컬 데이터베이스 서버의 PostgreSQL 기본 포트에 연결합니다.

복제

  • Patroni는 실행 중인 PostgreSQL 프로세스와 구성을 적극적으로 관리합니다.
  • PostgreSQL 2차 노드는 기본 데이터베이스 서버의 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 정보

기본 설정을 사용할 경우, 최소 구성은 다음을 요구합니다:

  • 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를 데이터베이스 노드 수의 두 배로 설정합니다. Patroni는 복제를 시작할 때 노드당 하나의 추가 슬롯을 사용합니다.
  • max_wal_senders를 클러스터 내에서 할당된 복제 슬롯 수보다 하나 더 많게 설정합니다. 이렇게 하면 복제가 사용 가능한 모든 데이터베이스 연결을 소모하는 것을 방지합니다.

이 문서에서는 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 정보

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: 해시된 상태

리눅스 패키지 설치

먼저, 각 노드에 대해 리눅스 패키지를 다운로드하고 설치해야 합니다.

1단계에서 필요한 종속성을 설치하고, 2단계에서 GitLab 패키지 리포지토리를 추가하세요.

GitLab 패키지를 설치할 때 EXTERNAL_URL 값을 제공하지 마십시오.

데이터베이스 노드 구성

  1. 컨설 노드를 구성해야 합니다.

  2. 다음 단계 실행 전에 CONSUL_SERVER_NODES, PGBOUNCER_PASSWORD_HASH, POSTGRESQL_PASSWORD_HASH, 데이터베이스 노드의 수네트워크 주소를 수집해야 합니다.

파트로니 클러스터 구성

파트로니를 사용하려면 명시적으로 활성화해야 합니다 (patroni['enable'] = true).

복제를 제어하는 모든 PostgreSQL 구성 항목, 예를 들어 wal_level, max_wal_senders 또는 기타 항목은 파트로니에 의해 엄격하게 제어됩니다. 이러한 구성은 postgresql[...] 구성 키로 설정한 원래 설정을 덮어씁니다. 따라서 모두 분리되어 patroni['postgresql'][...] 아래에 배치됩니다. 이 동작은 복제에 한정됩니다.

파트로니는 postgresql[...] 구성 키로 수행된 기타 모든 PostgreSQL 구성을 존중합니다. 예를 들어, 기본적으로 max_wal_senders5로 설정됩니다. 이를 변경하려면 patroni['postgresql']['max_wal_senders'] 구성 키로 설정해야 합니다.

다음은 예시입니다:

# Patroni, PgBouncer 및 Consul을 제외한 모든 구성 요소 비활성화
roles(['patroni_role', 'pgbouncer_role'])

# PostgreSQL 구성
postgresql['listen_address'] = '0.0.0.0'

# 자동 데이터베이스 마이그레이션 비활성화
gitlab_rails['auto_migrate'] = false

# Consul 에이전트 구성
consul['services'] = %w(postgresql)

# START 사용자 구성
# 필수 정보 섹션에 설명된 실제 값을 설정합니다.
#
# PGBOUNCER_PASSWORD_HASH를 생성된 md5 값으로 교체
postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
# POSTGRESQL_REPLICATION_PASSWORD_HASH를 생성된 md5 값으로 교체
postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
# POSTGRESQL_PASSWORD_HASH를 생성된 md5 값으로 교체
postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'

# PATRONI_API_USERNAME을 Patroni Rest API 호출용 사용자 이름으로 교체 (모든 노드에서 동일한 사용자 이름 사용)
patroni['username'] = 'PATRONI_API_USERNAME'
# PATRONI_API_PASSWORD를 Patroni Rest API 호출용 비밀번호로 교체 (모든 노드에서 동일한 비밀번호 사용)
patroni['password'] = 'PATRONI_API_PASSWORD'

# `max_replication_slots`를 데이터베이스 노드 수의 두 배로 설정합니다.
# 파트로니는 복제를 시작할 때 노드당 하나의 추가 슬롯을 사용합니다.
patroni['postgresql']['max_replication_slots'] = X

# `max_wal_senders`를 클러스터의 복제 슬롯 수보다 하나 더 많게 설정합니다.
# 이는 복제가 모든 데이터베이스 연결을 소모하는 것을 방지하는 데 사용됩니다.
patroni['postgresql']['max_wal_senders'] = X+1

# XXX.XXX.XXX.XXX/YY를 다른 파트로니 노드의 네트워크 주소로 교체
patroni['allowlist'] = %w(XXX.XXX.XXX.XXX/YY 127.0.0.1/32)

# XXX.XXX.XXX.XXX/YY를 네트워크 주소로 교체
postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY 127.0.0.1/32)

# 데이터베이스 로드 밸런싱을 위한 로컬 PgBouncer 서비스
pgbouncer['databases'] = {
  gitlabhq_production: {
    host: "127.0.0.1",
    user: "PGBOUNCER_USERNAME",
    password: 'PGBOUNCER_PASSWORD_HASH'
  }
}

# 플레이스홀더를 교체:
#
# Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
# CONSUL_SERVER_NODES에 대해 수집한 주소로 교체
consul['configuration'] = {
  retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
}
#
# END 사용자 구성

모든 데이터베이스 노드는 동일한 구성을 사용합니다. 리더 노드는 구성에서 결정되지 않으며, 리더 또는 복제 노드를 위한 추가 구성은 없습니다.

노드 구성이 완료되면 변경 사항이 적용되도록 각 노드에서 GitLab을 재구성해야 합니다.

일반적으로 Consul 클러스터가 준비되면 첫 번째 노드가 재구성되어 리더가 됩니다. 노드 재구성의 순서를 지정할 필요는 없습니다. 병렬로 또는 순서에 상관없이 실행할 수 있습니다. 임의의 순서를 선택할 경우, 미리 정해진 리더가 없습니다.

모니터링 활성화

모니터링을 활성화하면 모든 데이터베이스 서버에서 활성화해야 합니다.

  1. /etc/gitlab/gitlab.rb를 생성하거나 수정하고 다음 구성을 추가하십시오:

    # Prometheus를 위한 서비스 발견 활성화
    consul['monitoring_service_discovery'] = true
    
    # Exporter가 수신해야 할 네트워크 주소 설정
    node_exporter['listen_address'] = '0.0.0.0:9100'
    postgres_exporter['listen_address'] = '0.0.0.0:9187'
    
  2. sudo gitlab-ctl reconfigure 명령을 실행하여 구성을 컴파일하십시오.

Patroni API의 TLS 지원 활성화

기본적으로 Patroni REST 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' # 이는 평문 비밀번호입니다.

셀프 서명된 인증서 또는 내부 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 노드 구성

  1. 다음 단계 실행 전에 CONSUL_SERVER_NODES, CONSUL_PASSWORD_HASH, 및 PGBOUNCER_PASSWORD_HASH을 수집했는지 확인하세요.

  2. 각 노드에서 /etc/gitlab/gitlab.rb 구성 파일을 편집하고 # START user configuration 섹션에 기록된 값을 아래와 같이 교체하세요:

    # PgBouncer와 Consul 에이전트를 제외한 모든 구성 요소 비활성화
    roles(['pgbouncer_role'])
    
    # PgBouncer 구성
    pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
    
    # Consul 에이전트 구성
    consul['watchers'] = %w(postgresql)
    
    # START user configuration
    # 필수 정보 섹션에서 설명한 실제 값 설정
    # CONSUL_PASSWORD_HASH를 생성된 md5 값으로 교체
    # PGBOUNCER_PASSWORD_HASH를 생성된 md5 값으로 교체
    pgbouncer['users'] = {
      'gitlab-consul': {
        password: 'CONSUL_PASSWORD_HASH'
      },
      'pgbouncer': {
        password: 'PGBOUNCER_PASSWORD_HASH'
      }
    }
    # 플레이스홀더 교체:
    #
    # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
    # CONSUL_SERVER_NODES에 대해 수집된 주소로 교체
    consul['configuration'] = {
      retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
    }
    #
    # END user configuration
    
  3. gitlab-ctl reconfigure 실행

  4. Consul이 PgBouncer를 다시 로드할 수 있도록 .pgpass 파일을 생성하세요. 요청 시 PGBOUNCER_PASSWORD를 두 번 입력하세요:

    gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul
    
  5. 모니터링 활성화

PgBouncer 체크포인트

  1. 각 노드가 현재 노드 리더와 연결되어 있는지 확인하세요:

    gitlab-ctl pgb-console # 요청 시 PGBOUNCER_PASSWORD 입력
    

    비밀번호를 입력한 후 psql: ERROR: Auth failed 오류가 발생하면, 올바른 형식으로 MD5 비밀번호 해시를 이전에 생성했는지 확인하세요. 올바른 형식은 비밀번호와 사용자 이름을 연결하는 것입니다: PASSWORDUSERNAME. 예를 들어, Sup3rS3cr3tpgbouncerpgbouncer 사용자에 대한 MD5 비밀번호 해시를 생성하기 위해 필요한 텍스트입니다.

  2. 콘솔 프롬프트가 활성화되면 다음 쿼리를 실행하세요:

    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 서비스를 실행합니다. 다른 속성을 설정할 수 있지만, 다음 항목은 반드시 설정해야 합니다.

  1. /etc/gitlab/gitlab.rb 파일을 편집합니다:

    # 애플리케이션 노드에서 PostgreSQL 비활성화
    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'] }
    
  2. 변경 사항을 적용하기 위해 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 인스턴스가 정상적으로 실행되고 있어야 합니다. 로그인할 수 있는지 확인하고, 문제 및 병합 요청을 생성하세요. 자세한 내용은 복제 및 장애 조치 문제 해결을 참조하세요.

예제 구성

이 섹션에서는 여러 개의 완전한 예제 구성을 설명합니다.

예제 권장 설정

이 예제는 세 개의 Consul 서버, 세 개의 PgBouncer 서버(관련 내부 로드 밸런서 포함), 세 개의 PostgreSQL 서버 및 하나의 애플리케이션 노드를 사용합니다.

모든 서버를 동일한 10.6.0.0/16 개인 네트워크 범위에서 시작하며, 이 주소들 간에 자유롭게 연결될 수 있습니다.

각 머신과 할당된 IP의 목록 및 설명은 다음과 같습니다:

  • 10.6.0.11: Consul 1
  • 10.6.0.12: Consul 2
  • 10.6.0.13: Consul 3
  • 10.6.0.20: 내부 로드 밸런서
  • 10.6.0.21: PgBouncer 1
  • 10.6.0.22: PgBouncer 2
  • 10.6.0.23: PgBouncer 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_urlhttp://gitlab.example.com입니다.

초기 구성 후 장애 조치가 발생하면 PostgreSQL 리더 노드는 사용할 수 있는 보조 노드 중 하나로 변경되며, 다시 실패가 발생할 때까지 유지됩니다.

Consul 서버에 대한 권장 설정 예시

각 서버에서 /etc/gitlab/gitlab.rb를 편집하세요:

# 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를 편집하세요:

# Pgbouncer 및 Consul 에이전트를 제외한 모든 구성 요소 비활성화
roles(['pgbouncer_role'])

# 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 노드를 제공해야 합니다(이 예시에서는 IP 10.6.0.20에서). 이렇게 하는 방법은 PgBouncer 내부 로드 밸런서 구성 섹션에서 확인할 수 있습니다.

PostgreSQL 서버에 대한 권장 설정 예시

데이터베이스 노드에서 /etc/gitlab/gitlab.rb를 편집하세요:

# Patroni, PgBouncer 및 Consul을 제외한 모든 구성 요소 비활성화
roles(['patroni_role', 'pgbouncer_role'])

# PostgreSQL 구성
postgresql['listen_address'] = '0.0.0.0'
postgresql['hot_standby'] = 'on'
postgresql['wal_level'] = 'replica'

# 자동 데이터베이스 마이그레이션 비활성화
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)

# 데이터베이스 로드 밸런싱을 위한 로컬 PgBouncer 서비스
pgbouncer['databases'] = {
  gitlabhq_production: {
    host: "127.0.0.1",
    user: "pgbouncer",
    password: '771a8625958a529132abe6f1a4acb19c'
  }
}

# Consul 에이전트 구성
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 재구성을 실행하세요.

예제 권장 설정 매뉴얼 단계

구성을 배포한 후 다음 단계를 따르세요:

  1. 기본 데이터베이스 노드를 찾습니다:

    gitlab-ctl get-postgresql-primary
    
  2. 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

Patroni는 PostgreSQL 고가용성을 위한 의견이 반영된 솔루션입니다. PostgreSQL의 제어를 가져오고, 구성 설정을 재정의하며, 생명 주기(시작, 중지, 재시작)를 관리합니다. Patroni는 PostgreSQL 12+ 클러스터링 및 Geo 배포에 대한 cascading replication의 유일한 옵션입니다.

기본 아키텍처 (위에서 언급한)는 Patroni에 대해 변경되지 않습니다.

데이터베이스 노드를 프로비저닝할 때 Patroni에 대한 특별한 고려가 필요하지 않습니다. Patroni는 클러스터의 상태를 저장하고 리더를 선출하기 위해 Consul에 크게 의존합니다. Consul 클러스터의 실패와 그 리더 선출은 Patroni 클러스터에도 전파됩니다.

Patroni는 클러스터를 모니터링하고 모든 장애 조치를 처리합니다. 기본 노드가 실패하면, Patroni는 Consul과 협력하여 PgBouncer에 알립니다. 실패 시 Patroni는 이전 기본을 복제본으로 전환하고 이를 클러스터에 자동으로 재가입시킵니다.

Patroni를 사용하면 연결 흐름이 약간 다릅니다. 각 노드의 Patroni는 클러스터에 가입하기 위해 Consul 에이전트에 연결합니다. 이 시점 이후에 노드가 기본인지 복제본인지 결정합니다. 이 결정에 따라 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

동일한 명령을 모든 세 개의 데이터베이스 서버에서 실행할 수 있습니다. 이는 서버가 수행하는 역할에 따라 복제에 대한 정보를 반환합니다.

리더는 복제본당 하나의 기록을 반환해야 합니다:

-[ 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 필드는 어떤 write-ahead-log 세그먼트가 복제되었는지를 나타냅니다.

리더에서 현재 로그 시퀀스 번호(LSN)를 찾기 위해 다음을 실행합니다:

echo 'SELECT pg_current_wal_lsn();' | gitlab-psql

복제본이 동기화되지 않은 경우, gitlab-ctl patroni members는 누락된 데이터의 양을 나타내고, lag 필드는 경과 시간을 나타냅니다.

리더가 반환한 데이터에 대해 더 알아보려면 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 문서를 주의 깊게 검토하세요 일부 옵션은 완전히 이해하지 못할 경우 데이터 손실의 위험을 동반할 수 있습니다. 구성된 복제 모드는 허용 가능한 데이터 손실의 양을 결정합니다.

경고:
복제는 백업 전략이 아닙니다! 잘 고려되고 테스트된 백업 솔루션을 대체할 수 없습니다.

리눅스 패키지 설치는 기본적으로 synchronous_commiton으로 설정합니다.

postgresql['synchronous_commit'] = 'on'
gitlab['geo-postgresql']['synchronous_commit'] = 'on'

Patroni 페일오버 동작 맞춤화

리눅스 패키지 설치는 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를 사용할 수 없고 이전 리더의 타임라인이 현재와 다르면, 로컬 데이터 디렉터리를 삭제하고 현재 클러스터 리더에서 재복제합니다.

Patroni를 위한 데이터베이스 권한 부여

Patroni는 PostgreSQL 인스턴스를 관리하기 위해 유닉스 소켓을 사용합니다. 따라서 local 소켓의 연결은 신뢰할 수 있어야 합니다.

복제본은 리더와 통신하기 위해 복제 사용자(gitlab_replicator가 기본값)를 사용합니다. 이 사용자에 대해서는 trustmd5 인증 중에서 선택할 수 있습니다. postgresql['sql_replication_password']를 설정하면, Patroni는 md5 인증을 사용하고 그렇지 않을 경우 trust로 돌아갑니다.

선택한 인증 방식에 따라, postgresql['md5_auth_cidr_addresses'] 또는 postgresql['trust_auth_cidr_addresses'] 설정에 클러스터 CIDR을 지정해야 합니다.

Patroni 클러스터와의 상호작용

gitlab-ctl patroni members를 사용하여 클러스터 멤버의 상태를 확인할 수 있습니다. 각 노드의 상태를 확인하려면 gitlab-ctl patroni가 두 개의 추가 하위 명령인 check-leadercheck-replica를 제공하여 노드가 주 노드인지 복제본인지를 나타냅니다.

Patroni가 활성화되면 PostgreSQL의 시작, 종료 및 재시작을 독점적으로 제어합니다. 이는 특정 노드에서 PostgreSQL을 종료하려면 같은 노드에서 Patroni를 종료해야 함을 의미합니다.

sudo gitlab-ctl stop patroni

리더 노드에서 Patroni 서비스를 중지하거나 재시작하면 자동 페일오버가 발생합니다. Patroni가 구성 파일을 다시 로드하거나 페일오버를 트리거하지 않고 PostgreSQL 프로세스를 재시작하도록 하려면, 대신 gitlab-ctl patronireload 또는 restart 하위 명령을 사용해야 합니다. 이 두 하위 명령은 동일한 patronictl 명령의 래퍼입니다.

Patroni의 수동 장애 조치 절차

경고:

GitLab 16.5 및 이전 버전에서는 PgBouncer 노드가 Patroni 노드와 함께 자동으로 장애 조치되지 않습니다.

PgBouncer 서비스는 성공적인 전환을 위해 수동으로 재시작해야 합니다.

Patroni는 자동 장애 조치를 지원하지만, 수동으로 수행할 수도 있으며, 그 경우 두 가지 약간 다른 옵션이 있습니다:

  • Failover: 건강한 노드가 없을 때 수동 장애 조치를 수행할 수 있습니다. 이 작업은 어떤 PostgreSQL 노드에서도 수행할 수 있습니다:

    sudo gitlab-ctl patroni failover
    
  • Switchover: 클러스터가 건강할 때만 작동하며 전환을 예약할 수 있습니다(즉시 발생할 수 있습니다). 이 작업은 어떤 PostgreSQL 노드에서도 수행할 수 있습니다:

    sudo gitlab-ctl patroni switchover
    

이 주제에 대한 더 자세한 내용은 Patroni 문서를 참조하세요.

Geo 보조 사이트 고려 사항

Geo 보조 사이트가 PatroniPgBouncer를 사용하는 기본 사이트에서 복제할 때, PgBouncer를 통한 복제는 지원되지 않습니다. 보조 사이트는 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가 활성화된 상태에서 노드에서 계획된 유지 관리를 실행할 수 있습니다. Patroni 없이 한 노드에서 유지 관리를 수행하려면 다음과 같이 유지 관리 모드로 전환할 수 있습니다:

sudo gitlab-ctl patroni pause

Patroni가 일시 중지 모드에서 실행되면 PostgreSQL의 상태가 변경되지 않습니다. 작업이 끝나면 Patroni를 다시 시작할 수 있습니다:

sudo gitlab-ctl patroni resume

더 자세한 내용은 이 주제에 대한 Patroni 문서를 참조하세요.

Patroni 클러스터에서 PostgreSQL 주요 버전 업그레이드

번들된 PostgreSQL 버전과 각 릴리스에 대한 기본 버전 목록은 Linux 패키지의 PostgreSQL 버전을 참조하십시오.

PostgreSQL을 업그레이드하기 전에 고려해야 할 몇 가지 주요 사실이 있습니다:

  • 가장 중요한 점은 Patroni 클러스터를 안전하게 종료해야 한다는 것입니다. 이는 데이터베이스 업그레이드 기간 동안 GitLab 배포가 중단되며, 적어도 리더 노드가 업그레이드되는 동안 중단됩니다. 이는 데이터베이스 크기에 따라 상당한 다운타임이 될 수 있습니다.

  • PostgreSQL을 업그레이드하면 새로운 제어 데이터로 새로운 데이터 디렉터리가 생성됩니다. Patroni의 관점에서 이는 다시 부트스트랩해야 하는 새로운 클러스터입니다. 따라서 업그레이드 절차의 일환으로 클러스터 상태(Consul에 저장됨)가 지워집니다. 업그레이드가 완료되면 Patroni가 새로운 클러스터를 부트스트랩합니다. 이로 인해 _클러스터 ID_가 변경됩니다.

  • 리더와 복제본의 업그레이드 절차가 동일하지 않습니다. 따라서 각 노드에서 올바른 절차를 사용하는 것이 중요합니다.

  • 복제본 노드를 업그레이드하면 데이터 디렉터리가 삭제되고 리더에서 구성된 복제 방법으로 다시 동기화됩니다(pg_basebackup이 유일한 사용 가능한 옵션임). 데이터베이스 크기에 따라 복제본이 리더와 동기화되기까지 시간이 걸릴 수 있습니다.

  • 업그레이드 절차에 대한 개요는 Patroni 문서에 요약되어 있습니다. 몇 가지 조정을 통해 이 절차를 구현하는 gitlab-ctl pg-upgrade를 여전히 사용할 수 있습니다.

이러한 점을 고려하여 PostgreSQL 업그레이드를 신중하게 계획해야 합니다:

  1. 리더 노드가 어떤 노드인지 및 복제본이 어떤 노드인지 찾아보세요:

    gitlab-ctl patroni members
    

    주의: Geo 보조 사이트에서 Patroni 리더 노드는 standby leader라고 불립니다.

  2. 복제본에서만 Patroni를 중지합니다.

    sudo gitlab-ctl stop patroni
    
  3. 애플리케이션 노드에서 유지 관리 모드를 활성화합니다:

    sudo gitlab-ctl deploy-page up
    
  4. 리더 노드에서 PostgreSQL을 업그레이드하고 업그레이드가 성공적으로 완료되었는지 확인합니다:

    # 기본 명령어 시간 초과는 600초이며 '--timeout'으로 구성할 수 있습니다.
    sudo gitlab-ctl pg-upgrade
    

    주의: gitlab-ctl pg-upgrade는 노드의 역할을 자동으로 감지하려고 합니다. 자동 감지가 작동하지 않거나 역할을 올바르게 감지하지 못했다고 생각되는 경우, --leader 또는 --replica 인수를 사용하여 수동으로 재정의할 수 있습니다. 사용 가능한 옵션에 대한 자세한 정보는 gitlab-ctl pg-upgrade --help를 참조하세요.

  5. 리더와 클러스터의 상태를 확인합니다. 건강한 리더가 있을 때만 진행할 수 있습니다:

    gitlab-ctl patroni check-leader
    
    # 또는
    
    gitlab-ctl patroni members
    
  6. 이제 애플리케이션 노드에서 유지 관리 모드를 비활성화할 수 있습니다:

    sudo gitlab-ctl deploy-page down
    
  7. 복제본에서 PostgreSQL을 업그레이드합니다(모든 복제본에서 병렬로 수행할 수 있습니다):

    sudo gitlab-ctl pg-upgrade
    

복제본 업그레이드 중 문제가 발생할 경우, 문제 해결 섹션을 참고하세요. 해결책이 될 수 있습니다.

주요 사항:

PostgreSQL 업그레이드를 gitlab-ctl revert-pg-upgrade로 되돌리는 것은 gitlab-ctl pg-upgrade와 동일한 고려 사항이 있습니다. 복제본을 먼저 중지한 다음 리더를 되돌리고 마지막으로 복제본을 되돌리는 동일한 절차를 따라야 합니다.

PostgreSQL의 근사 제로 다운타임 업그레이드 in a Patroni 클러스터

Status: Experiment

Patroni는 클러스터를 종료하지 않고 주요 PostgreSQL 업그레이드를 실행할 수 있게 해줍니다. 그러나, 이는 업그레이드된 PostgreSQL을 호스팅하기 위해 새로운 Patroni 노드에 추가 리소스가 필요합니다. 실제로 이 절차를 통해 다음을 수행합니다:

  • 새로운 버전의 PostgreSQL로 새 Patroni 클러스터를 생성합니다.
  • 기존 클러스터에서 데이터를 마이그레이션합니다.

이 절차는 비침투적이며, 클러스터를 종료하기 전에는 기존 클러스터에 영향을 미치지 않습니다. 그러나, 시간과 리소스를 소모할 수 있습니다. 가용성과의 교환 관계를 고려하세요.

절차의 단계는 다음과 같습니다:

  1. 새 클러스터를 위한 리소스 프로비저닝.
  2. 사전 점검.
  3. 새 클러스터의 리더 구성.
  4. 기존 리더에서 퍼블리셔 시작.
  5. 기존 클러스터에서 데이터 복사.
  6. 기존 클러스터에서 데이터 복제.
  7. 새 클러스터 확장.
  8. 응용 프로그램을 새 클러스터로 전환.
  9. 정리.

새 클러스터를 위한 리소스 프로비저닝

Patroni 노드를 위한 새로운 리소스 세트가 필요합니다. 새로운 Patroni 클러스터는 기존 클러스터와 정확히 같은 수의 노드를 요구하지 않습니다. 요구사항에 따라 다른 수의 노드를 선택할 수 있습니다. 새로운 클러스터는 기존 Consul 클러스터를 사용합니다(다른 patroni['scope']와 함께) 그리고 PgBouncer 노드도 포함됩니다.

기존 클러스터의 리더 노드에 새 클러스터의 노드가 접근 가능해야 합니다.

사전 점검

우리는 PostgreSQL 논리 복제에 의존하여 Patroni 클러스터의 근사 제로 다운타임 업그레이드를 지원합니다. 논리 복제 요구사항이 충족되어야 합니다. 특히, wal_levellogical이어야 합니다. wal_level을 확인하려면 기존 클러스터의 어떤 노드에서든 다음 명령을 실행합니다:

SHOW wal_level;

기본적으로 Patroni는 wal_levelreplica로 설정합니다. 이를 logical로 증가시켜야 합니다.

wal_level 변경은 PostgreSQL을 재시작해야 하므로, 이 단계는 짧은 다운타임을 초래합니다(그러므로 근사 제로 다운타임). Patroni 리더 노드에서 이를 수행하려면:

  1. gitlab.rb를 편집하여 다음 내용을 설정합니다:

    patroni['postgresql']['wal_level'] = 'logical'
    
  2. gitlab-ctl reconfigure를 실행합니다. 이는 구성을 작성하지만 PostgreSQL 서비스를 재시작하지는 않습니다.
  3. gitlab-ctl patroni restart를 실행하여 PostgreSQL을 재시작하고 새로운 wal_level을 적용합니다. 이 과정에서 장애 조치를 유발하지 않습니다. 재시작 주기 동안 클러스터 리더는 사용할 수 없습니다.
  4. gitlab-psqlSHOW wal_level을 실행하여 변경사항을 확인합니다.

새 클러스터의 리더 구성

새 클러스터의 첫 번째 노드를 구성합니다. 이 노드는 새 클러스터의 리더가 됩니다. 기존 클러스터의 구성을 사용할 수 있으며, 이는 새로운 PostgreSQL 버전과 호환되는 경우에 가능합니다. Patroni 클러스터 구성 문서를 참조하세요.

공통 구성 외에도, gitlab.rb에서 다음을 적용해야 합니다:

  1. 새로운 Patroni 클러스터가 다른 스코프를 사용하도록 합니다. 스코프는 Consul에서 Patroni 설정을 네임스페이스화하는 데 사용되어, 기존 클러스터와 새로운 클러스터 모두에 같은 Consul 클러스터를 사용할 수 있게 해줍니다.

    patroni['scope'] = 'postgresql_new-ha'
    
  2. Consul 에이전트가 기존 및 새로운 Patroni 클러스터가 제공하는 PostgreSQL 서비스를 혼합하지 않도록 합니다. 이를 위해 내부 속성을 사용해야 합니다:

    consul['internal']['postgresql_service_name'] = 'postgresql_new'
    

기존 리더에서 퍼블리셔 시작

기존 리더에서 gitlab-psql로 다음 SQL 문을 실행하여 논리 복제 퍼블리셔를 시작합니다:

CREATE PUBLICATION patroni_upgrade FOR ALL TABLES;

기존 클러스터에서 데이터 복사

기존 클러스터의 현재 데이터베이스를 덤프하려면, 새 클러스터의 리더에서 다음 명령을 실행합니다:

  1. 선택적. 전역 데이터베이스 객체 복사:

    pg_dumpall -h ${EXISTING_CLUSTER_LEADER} -U gitlab-psql -g | gitlab-psql
    

    기존 데이터베이스 객체(예: 역할)에 대한 오류는 무시할 수 있습니다. 이러한 객체는 노드를 처음 구성할 때 생성됩니다.

  2. 현재 데이터베이스 복사:

    pg_dump -h ${EXISTING_CLUSTER_LEADER} -U gitlab-psql -d gitlabhq_production -s | gitlab-psql
    

    데이터베이스의 크기에 따라 이 명령이 완료되는 데 시간이 걸릴 수 있습니다.

pg_dumppg_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 노드에서 전환을 수행하려면:

  1. gitlab.rb를 편집하여 다음을 설정합니다:

    consul['watchers'] = %w(postgresql_new)
    consul['internal']['postgresql_service_name'] = 'postgresql_new'
    
  2. gitlab-ctl reconfigure를 실행합니다.

정리

이 단계를 완료한 후, 이전 Patroni 클러스터의 리소스를 정리할 수 있습니다.
더 이상 필요하지 않습니다. 그러나 리소스를 제거하기 전에, gitlab-psqlDROP SUBSCRIPTION patroni_upgrade를 실행하여 새로운 리더에서 논리 복제 구독을 제거하세요.