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

Tier: Premium, Ultimate Offering: Self-managed

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

복제 및 장애 조치가 구성된 설정은 여러분이 찾고 있는 것이 아니라면, Linux 패키지를 위한 데이터베이스 구성 문서를 확인하세요.

GitLab에 대한 PostgreSQL의 복제 및 장애 조치를 구성하기 전에 이 문서를 완전히 읽는 것이 권장됩니다.

아키텍처

복제 장애 조치가 구성된 Linux 패키지 권장 구성은 다음과 같은 컴포넌트를 필요로 합니다:

  • 최소 세 개의 PostgreSQL 노드
  • 최소 세 개의 Consul 서버 노드
  • 주 데이터베이스의 읽기 및 쓰기를 추적하고 처리하는 최소 세 개의 PgBouncer 노드
    • PgBouncer 노드 간의 요청을 분산시키기 위한 내부 로드 밸런서(TCP)
  • 데이터베이스 부하 분산이 활성화됨
    • 각 PostgreSQL 노드에 구성된 로컬 PgBouncer 서비스. 이는 주 PgBouncer 클러스터에서 주 데이터베이스를 추적하는 것과 별개입니다.

또한, 모든 데이터베이스 및 GitLab 인스턴스 간의 기초 네트워크 토폴로지를 고려해야 하며, 네트워크가 단일 장애점이 되지 않도록 모든 연결의 중복이 보장되어야 합니다.

note
GitLab 13.3부터 PostgreSQL 12가 Linux 패키지 설치와 함께 제공됩니다. PostgreSQL 12의 클러스터링은 Patroni를 통해서만 지원됩니다. 자세한 내용은 Patroni 섹션을 참조하세요. GitLab 14.0부터 Linux 패키지 설치에는 PostgreSQL 12만 포함되며, 따라서 Patroni는 복제 및 장애 조치를 위해 필수적입니다.

데이터베이스 노드

각 데이터베이스 노드는 다음 네 가지 서비스를 실행합니다:

  • PostgreSQL: 데이터베이스 자체
  • Patroni: 클러스터 내 다른 Patroni 서비스와 통신하고 리더 서버에 문제가 발생할 때 장애 조치를 처리합니다. 장애 조치 절차는 다음과 같습니다:
    • 클러스터를 위한 새로운 리더 선정
    • 새로운 노드를 리더로 승격
    • 나머지 서버에게 새 리더 노드를 따르도록 지시
  • PgBouncer: 노드용 로컬 풀러, 데이터베이스 부하 분산의 일환으로 읽기 쿼리에 사용됨
  • Consul 에이전트: 현재 Patroni 상태를 저장하는 Consul 클러스터와 통신, 데이터베이스 클러스터의 각 노드 상태를 모니터링하여 Consul 클러스터의 서비스 정의에서 해당 노드의 상태를 추적함

Consul 서버 노드

Consul 서버 노드는 Consul 서버 서비스를 실행합니다. 데이터베이스 노드가 부팅되기 전에 정상 작동하고 리더가 선출되어야 합니다.

PgBouncer 노드

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

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

연결 흐름

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

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

주 데이터베이스

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

데이터베이스 부하 분산

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

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

복제

  • Patroni는 실행 중인 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(Classless Inter-Domain Routing)(192.168.0.0/24) 형식일 수 있습니다.

Consul 정보

기본 설정을 사용하는 경우, 최소한의 구성에는 다음이 필요합니다:

  • CONSUL_USERNAME. 리눅스 패키지 설치의 기본 사용자는 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. 리눅스 패키지 설치의 기본 사용자는 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. 리눅스 패키지 설치의 기본 사용자는 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. Consul 노드를 구성하십시오.
  2. 다음 단계를 실행하기 전에 CONSUL_SERVER_NODES, PGBOUNCER_PASSWORD_HASH, POSTGRESQL_PASSWORD_HASH, db 노드 수, 및 네트워크 주소를 모두 수집했는지 확인하십시오.

Patroni 클러스터 구성

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

복제를 제어하는 PostgreSQL 구성 항목 중 wal_level, max_wal_senders 등은 모두 Patroni에 의해 엄격하게 제어됩니다. 이러한 구성은 원래 설정을 덮어쓰며 postgresql[...] 구성 키로 만든 설정을 대체합니다. 따라서 이러한 설정은 모두 복제로 제한됩니다. Patroni는 postgresql[...] 구성 키로 수행한 다른 PostgreSQL 구성을 존중합니다. 예를 들어, max_wal_senders는 기본적으로 5로 설정됩니다. 이를 변경하려면 patroni['postgresql']['max_wal_senders'] 구성 키로 설정해야 합니다.

note
Patroni 노드의 구성은 repmgr과 매우 유사하지만 더 간단합니다. Patroni가 활성화되면 먼저 PostgreSQL의 복제 설정을 무시할 수 있습니다(덮어쓰임). 그런 다음 repmgr[...] 또는 repmgr별 구성을 제거할 수 있습니다. 특히 postgresql['shared_preload_libraries'] = 'repmgr_funcs'를 제거해야 합니다.

다음은 예시입니다:

# 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)

# 사용자 구성 시작
#  필요한 정보 섹션에서 설명된 실제 값 설정
#
# 생성된 md5 값으로 PGBOUNCER_PASSWORD_HASH 교체
postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH'
# 생성된 md5 값으로 POSTGRESQL_REPLICATION_PASSWORD_HASH 교체
postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH'
# 생성된 md5 값으로 POSTGRESQL_PASSWORD_HASH 교체
postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'

# Patroni Rest API 호출에 대한 사용자명(모든 노드에서 동일한 사용자명 사용)
patroni['username'] = 'PATRONI_API_USERNAME'
# Patroni Rest API 호출에 대한 암호(모든 노드에서 동일한 암호 사용)
patroni['password'] = 'PATRONI_API_PASSWORD'

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

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

# 다른 patroni 노드에 대한 네트워크 주소 설정할 수 있습니다
patroni['allowlist'] = %w(XXX.XXX.XXX.XXX/YY 127.0.0.1/32)

# Network Address에 대한 XX.XX.XX.XX/YY 교체
postgresql['trust_auth_cidr_addresses'] = %w(XX.XX.XX.XX/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)
}
#
# 사용자 구성 끝

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

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

일반적으로 Consul 클러스터가 준비되면 먼저 GitLab 재구성을 실행하는 첫 번째 노드가 리더가 됩니다. 노드의 순서를 정하고 싶지 않다면 노드 재구성을 병렬로 실행하거나 임의의 순서대로 실행할 수 있습니다. 임의의 순서를 선택하면 사전에 정해진 리더가 없습니다.

모니터링 활성화

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

  1. /etc/gitlab/gitlab.rb 파일을 만들거나 편집하고 다음 구성을 추가하세요:

    # 서비스 디스커버리를 위해 프로메테우스 활성화
    consul['monitoring_service_discovery'] = true
       
    # 수신 대기해야 하는 네트워크 주소 설정
    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'] = '개인키-암호' # 이것은 일반 텍스트 비밀번호입니다.

자체 서명된 인증서나 내부 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: 각 unsafe 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)
       
    # 사용자 구성 시작
    # 필요한 정보 섹션에 설명된대로 실제 값 설정
    # 생성된 MD5 값을 사용하여 CONSUL_PASSWORD_HASH 대체
    # 생성된 MD5 값을 사용하여 PGBOUNCER_PASSWORD_HASH 대체
    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['configuration'] = {
      retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z)
    }
    #
    # 사용자 구성 끝
    
    note
    pgbouncer_role은 GitLab 10.3에서 도입되었습니다.
  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 Checkpoint

  1. 각 노드가 현재 노드 리더와 통신하는지 확인하세요:

    gitlab-ctl pgb-console # 암호를 물어보면 PGBOUNCER_PASSWORD를 입력하세요
    

    암호를 입력한 후 psql: ERROR: Auth failed라는 오류가 발생하면 이전에 올바른 형식으로 MD5 암호 해시를 생성했는지 확인하세요. 올바른 형식은 암호와 사용자명을 연결하는 것입니다: 암호사용자명. 예를 들어 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'] }
  1. 변경 사항이 적용되려면 GitLab 재구성 하세요.

응용 프로그램 노드의 구성 후 조치

모든 마이그레이션이 실행되었는지 확인하세요:

gitlab-rake gitlab:db:configure

참고: PgBouncer가 PostgreSQL에 연결하는 데 실패하는 rake aborted! 오류가 발생하는 경우, 데이터베이스 노드의 gitlab.rb에서 PgBouncer 노드의 IP 주소가 trust_auth_cidr_addresses에 누락된 경우가 있을 수 있습니다. 계속 진행하기 전에 PgBouncer 에러 ERROR: pgbouncer cannot connect to server를 참조하세요.

백업

PgBouncer 연결을 통한 GitLab의 백업이나 복원은 GitLab 장애를 유발합니다.

자세한 정보 및 백업 재구성 방법을 확인하세요.

GitLab 실행 확인

이 시점에서 GitLab 인스턴스가 실행 중이어야 합니다. 로그인하고 이슈를 생성하고 Merge Request을 만들 수 있는지 확인하세요. 더 많은 정보는 레플리케이션과 장애 조치의 문제 해결를 참조하세요.

구성 예시

이 섹션에서는 여러 예시 구성에 대해 자세히 설명합니다.

권장 설정 예시

이 예시에서는 세 개의 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_url에는 사용하지 마십시오.

초기 구성 이후 장애 조치가 발생하면 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 노드를 서비스하기 위해 설정해야 합니다 (이 예제에서는 10.6.0.20의 IP에 있습니다). 이에 대한 예제는 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

note
PostgreSQL 11에 대한 Repmgr 대신 Patroni를 사용하는 것은 지원됩니다. PostgreSQL 12의 경우 필수입니다. GitLab 14.0부터 PostgreSQL 12만 사용 가능하므로 장애 조치 및 복제를 달성하기 위해 Patroni를 필수로 사용해야 합니다.

Patroni는 PostgreSQL 고가용성에 대한 고정관념적인 솔루션입니다. PostgreSQL의 제어를 맡고 구성을 재정의하며 라이프사이클을 관리합니다 (시작, 중지, 재시작). Patroni는 PostgreSQL 12 클러스터링 및 Geo 배포의 위엔드 리플리케이션을 위한 유일한 옵션입니다.

기본 아키텍처 (위에서 언급함)은 Patroni를 위해 변경되지 않습니다. 데이터베이스 노드를 프로비저닝할 때 Patroni에 대해 특별한 고려 사항이 필요하지 않습니다. Patroni는 클러스터의 상태를 저장하고 리더를 선택하기 위해 Consul에 크게 의존합니다. Consul 클러스터에서 발생하는 장애 및 리더 선택은 Patroni 클러스터에도 전파됩니다.

Patroni는 클러스터를 모니터링하고 장애 조치를 처리합니다. 주 노드가 실패하면 Consul과 함께 PgBouncer에 알립니다. 장애 시 Patroni는 이전 주 노드를 복제본으로 전환하고 자동으로 클러스터에 다시 조인합니다.

Patroni를 사용하면 연결 흐름이 약간 다릅니다. 각 노드의 Patroni는 클러스터에 참여하기 위해 Consul 에이전트에 연결합니다. 이후에 노드가 주 노드인지 복제본인지 결정한 후 직접 Unix 소켓을 통해 통신하는 PostgreSQL을 구성합니다. 즉, Consul 클러스터가 기능하지 않거나 리더가 없으면 Patroni 및 결과적으로 PostgreSQL도 시작되지 않습니다. Patroni는 또한 각 노드의 기본 포트를 통해 액세스할 수 있는 REST API를 노출합니다. 각 노드에서의 default port를 통해 액세스할 수 있는 REST API를 노출합니다.

복제 상태 확인

gitlab-ctl patroni members를 실행하여 클러스터 상태에 대한 요약을 쿼리하세요:

+ 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 필드는 복제된 쓰기 전방 로그 세그먼트를 나타냅니다. 리더에서 현재 Log Sequence Number (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 설문서를 주의 깊게 검토하세요. (Review the Patroni documentation carefully)

Patroni 복제 모드는 허용 가능한 데이터 손실량을 결정합니다.

caution
복제는 백업 전략이 아닙니다! 신중하게 고려되고 테스트된 백업 솔루션이 대체할 수 없습니다.

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

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를 사용할 수 없으며 이전 리더의 타임라인이 현재 타임라인과 달라졌을 때, 로컬 데이터 디렉터리를 삭제하고 현재 클러스터 리더에서 다시 복제합니다.

Patroni의 데이터베이스 인증

Patroni는 PostgreSQL 인스턴스를 관리하기 위해 Unix 소켓을 사용합니다. 따라서 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 patronicheck-leadercheck-replica 두 가지 추가 하위 명령어를 제공하여 해당 노드가 주(primary) 또는 복제본(replica)인지 표시합니다.

Patroni가 활성화된 경우, PostgreSQL의 시작, 종료 및 재시작을 전적으로 제어합니다. 이는 특정 노드에서 PostgreSQL을 종료하려면 해당 노드에서 Patroni를 먼저 중지해야 한다는 것을 의미합니다.

sudo gitlab-ctl stop patroni

리더 노드에서 Patroni 서비스를 중지하거나 다시 시작하면 자동 장애 조치가 트리거됩니다. 만약 장애 조치를 트리거하지 않고 Patroni가 구성을 다시로드하거나 PostgreSQL 프로세스를 재시작해야 하는 경우, 반드시 gitlab-ctl patronireload 또는 restart 하위 명령어를 대신 사용해야 합니다. 이 두 하위 명령어는 동일한 patronictl 명령어의 래퍼입니다.

Patroni의 매뉴얼 장애 조치 절차

caution
GitLab 16.5 이전에서는 PgBouncer 노드가 Patroni 노드와 함께 자동 장애 조치되지 않습니다. PgBouncer 서비스가 매뉴얼으로 다시 시작되어야 합니다.

Patroni는 자동 장애 조치를 지원하지만 매뉴얼 조치를 수행할 수도 있으며, 두 가지 약간 다른 옵션이 있습니다.

  • Failover: 건전한 노드가 없는 상황에서 매뉴얼 장애 조치를 수행할 수 있습니다. 이 작업은 어떤 PostgreSQL 노드에서든 수행할 수 있습니다:

    sudo gitlab-ctl patroni failover
    
  • Switchover: 클러스터가 건전한 상태에서만 작동하며, 스위치오버를 예약할 수 있습니다(즉시 발생할 수도 있음). 이 작업은 어떤 PostgreSQL 노드에서든 수행할 수 있습니다:

    sudo gitlab-ctl patroni switchover
    

이에 대한 자세한 내용은 Patroni documentation을 참조하세요.

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 관련 문서를 참조하십시오.

repmgr에서 Patroni로 전환

caution
repmgr에서 Patroni로 전환하는 것은 간단하지만, 그 반대는 그렇지 않습니다. Patroni에서 repmgr로 되돌아가는 것은 복잡할 수 있으며 데이터 디렉터리 삭제가 필요할 수 있습니다. 이를 수행해야 하는 경우 GitLab 지원팀에 문의하십시오.

다음 단계에 따라 기존 데이터베이스 클러스터를 repmgr 대신 Patroni를 사용하도록 전환할 수 있습니다:

  1. 모든 복제 노드에서 repmgr을 중지하고 마지막으로 기본 노드에서도 중지합니다:

    sudo gitlab-ctl stop repmgrd
    
  2. 모든 복제 노드에서 PostgreSQL을 중지합니다:

    sudo gitlab-ctl stop postgresql
    
    note
    기본 노드에서는 walsender 프로세스가 실행 중이지 않은지 확인하세요. ps aux | grep walsender에 실행 중인 프로세스가 표시되면 안됩니다.
  3. 기본 노드에서 Patroni를 구성합니다. repmgr 및 기타 repmgr 관련 구성을 제거하세요. 또한 PostgreSQL 복제와 관련된 모든 구성도 제거하세요.
  4. 기본 노드에서 GitLab을 다시 구성합니다. 이를 리더로 만듭니다. 다음 명령으로 확인할 수 있습니다.

    sudo gitlab-ctl tail patroni
    
  5. 모든 복제 노드에 대해 마지막 두 단계를 반복합니다. gitlab.rb는 모든 노드에서 동일해야 합니다.
  6. 존재하는 경우 기본 노드에서 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으로 업그레이드하려면 명시적으로 요청해야 합니다.

caution
Patroni 클러스터에서 PostgreSQL을 업그레이드하는 절차는 repmgr을 사용하여 업그레이드하는 것과 다릅니다. 다음은 PostgreSQL을 업그레이드할 때 고려해야 할 주요 차이점 및 중요 사항을 개요로 제공합니다.

다음은 PostgreSQL을 업그레이드하기 전에 고려해야 할 몇 가지 주요 사항입니다:

  • 가장 중요한 점은 Patroni 클러스터를 중지해야 합니다. 이는 데이터베이스 업그레이드 기간 동안이나 적어도 리더 노드가 업그레이드되는 동안 GitLab 배포가 중단됨을 의미합니다. 데이터베이스의 크기에 따라 이는 중요한 다운타임이 될 수 있습니다.

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

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

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

  • 업그레이드 절차에 대한 개요는 Patroni 관련 문서에 기술되어 있습니다. 몇 가지 조정이 있는 절차를 구현하는 gitlab-ctl pg-upgrade도 사용할 수 있습니다.

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

  1. 리더와 복제본을 식별합니다:

    gitlab-ctl patroni members
    
    note
    Geo 보조 사이트에서는 Patroni 리더 노드를 standby leader라고 합니다.
  2. 복제본 노드에서만 Patroni를 중지합니다.

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

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

    sudo gitlab-ctl pg-upgrade -V 13
    
    note
    gitlab-ctl pg-upgrade는 노드의 역할을 감지하려고 노력합니다. 자동 감지 기능이 작동하지 않거나 역할이 올바르게 감지되지 않았다고 생각하는 경우 --leader 또는 --replica 인수를 사용하여 매뉴얼으로 덮어씌울 수 있습니다.
  5. 리더 및 클러스터 상태를 확인합니다. 리더가 정상인 경우에만 계속할 수 있습니다.

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

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

    sudo gitlab-ctl pg-upgrade -V 13
    

복제본을 업그레이드하는 동안 문제가 발생할 경우, 문제 해결 섹션을 참조하시기 바랍니다.

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

Patroni 클러스터에서의 PostgreSQL 거의 제로 다운 타임 업그레이드

Status: Experiment

Patroni를 사용하면 클러스터를 종료하지 않고 주요 PostgreSQL 업그레이드를 실행할 수 있습니다. 그러나 이를 위해 업그레이드된 PostgreSQL을 호스트하기 위한 추가 리소스가 필요합니다. 이 절차를 통해 실제로 수행하는 과정은 다음과 같습니다.

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

이 절차는 비침입적이며 클러스터를 종료하기 전에 기존 클러스터에 영향을 미치지 않습니다. 그러나 이는 시간과 리소스를 소비할 수 있는데, 가용성과의 상충관계를 고려해야 합니다.

순서대로 진행되는 단계는 다음과 같습니다.

  1. 새 클러스터에 대한 리소스를 마련.
  2. 사전 점검.
  3. 새 클러스터의 리더 구성.
  4. 기존 리더에서 publisher 시작.
  5. 기존 클러스터에서 데이터 복사.
  6. 기존 클러스터에서 데이터 복제.
  7. 새 클러스터 확장.
  8. 애플리케이션을 새 클러스터 사용으로 전환.
  9. 정리.

새 클러스터에 대한 리소스를 마련

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

적어도 기존 클러스터의 리더 노드가 새 클러스터의 노드에서 접근 가능한지 확인하세요.

사전 점검

Patroni 클러스터의 거의 제로 다운 타임 업그레이드를 지원하기 위해 PostgreSQL 논리 복제에 의존합니다. 논리 복제 요구 사항을 충족해야 합니다. 특히, 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 클러스터를 사용할 수 있도록 Consul에서 Patroni 설정을 네임스페이스화하기 위해 이 스코프가 사용됩니다.

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

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

기존 리더에서 publisher 시작

기존 리더에서 논리 복제 publisher를 시작하려면 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는 기존 클러스터의 리더 노드의 호스트 주소입니다.

note
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를 실행하여 새 리더의 논리 복제 구독을 제거하세요.