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

Tier: Premium, Ultimate Offering: Self-Managed

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

복제 및 장애 조치가 설정이 필요한 것이 아니라면, 리눅스 패키지에 대한 데이터베이스 구성 문서를 참조하십시오.

GitLab을 위한 PostgreSQL을 구성하기 전에 본 문서를 완전히 읽는 것이 좋습니다.

운영 체제 업그레이드

다른 운영 체제로 장애 조치를 수행하는 경우, PostgreSQL 운영 체제 업그레이드 문서를 참조하십시오. 운영 체제 업그레이드에 대한 로컬 변경 사항을 고려하지 않으면 데이터 손상이 발생할 수 있습니다.

아키텍처

PostgreSQL 클러스터를 복제 장애 조치가 가능하도록하는 리눅스 패키지 권장 구성은 다음과 같습니다:

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

또한, 데이터베이스 및 GitLab 인스턴스간에 중복 연결을 보장하기 위해 기본 네트워크 토폴로지를 고려해야 합니다. 네트워크가 단일 장애 지점이 되는 것을 피하기 위함입니다.

note
PostgreSQL 12는 리눅스 패키지 설치와 함께 제공됩니다. PostgreSQL 12의 클러스터링은 Patroni와만 호환되며, 따라서 복제 및 장애 조치를 위해 Patroni가 필수적입니다. 자세한 내용은 Patroni 섹션을 참조하십시오.

데이터베이스 노드

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

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

Consul 서버 노드

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

PgBouncer 노드

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

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

연결 흐름

패키지의 각 서비스는 기본 포트의 세트로 제공됩니다. 다음에 나열된 연결에 대한 특정 방화벽 규칙을 만들어야 할 수 있습니다.

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

주 서버

  • 애플리케이션 서버는 기본 포트를 통해 PgBouncer에 직접 연결하거나 여러 PgBouncer를 제공하는 구성된 내부 로드 밸런서 (TCP)를 통해 연결합니다.
  • 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 정보

기본 설정을 사용하는 경우, 최소한의 구성은 다음과 같습니다:

  • 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. 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: 해시 처리되어 있음

Linux 패키지 설치

먼저 Linux 패키지를 다운로드하고 설치하십시오. 모든 노드에 Linux 패키지를 설치해야 합니다.

1단계에서 필요한 의존성을 설치하고, 2단계에서 GitLab 패키지 리포지터리를 추가하십시오. GitLab 패키지를 설치할 때 EXTERNAL_URL 값을 제공하지 마십시오.

데이터베이스 노드 구성

  1. Consul 노드를 구성하는 것을 확인하십시오.
  2. 다음 단계를 실행하기 전에 CONSUL_SERVER_NODES, PGBOUNCER_PASSWORD_HASH, POSTGRESQL_PASSWORD_HASH, 데이터베이스 노드의 숫자네트워크 주소를 수집하는 것을 확인하십시오.

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'] 구성 키로 설정해야합니다.

다음은 예시입니다:

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

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

# 다른 Patroni 노드의 네트워크 주소에 대한 XXX.XXX.XXX.XXX/YY 플레이스홀더를 교체합니다
patroni['allowlist'] = %w(XXX.XXX.XXX.XXX/YY 127.0.0.1/32)

# 네트워크 주소를 교체합니다
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)
}
#
# 사용자 구성 끝

모든 데이터베이스 노드는 동일한 구성을 사용합니다. 리더 노드는 구성으로 결정되지 않으며, 리더 노드나 레플리카 노드에 대한 추가 또는 다른 구성이 없습니다.

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

일반적으로 Consul 클러스터가 준비되면 GitLab을 다시 구성하는 첫 번째 노드가 리더가 됩니다. 노드를 순차적으로 구성해야 하는 것은 없습니다. 병렬로 실행하거나 임의로 실행할 수 있습니다. 임의의 순서를 선택하는 경우 사전 지정된 리더가 없습니다.

모니터링 활성화

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

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

    # Prometheus를 위한 서비스 디스커버리 활성화
    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)
       
    # 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. .pgpass 파일을 생성하여 Consul이 PgBouncer를 다시로드할 수 있도록 만드세요. 두 번 물어보면 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' 또는 '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

참고: PostgreSQL의 trust_auth_cidr_addresses에 PgBouncer 노드의 IP 주소가 데이터베이스 노드의 gitlab.rb에 누락된다는 rake aborted! 오류가 발생하는 경우, 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_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입니다). 이를 수행하는 예시는 내부 로드 밸런서 구성 섹션에서 찾을 수 있습니다.

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 배포를 위한 캐스케이딩 복제를 위한 유일한 옵션입니다.

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

Patroni는 클러스터를 모니터하고 장애 조치를 다룹니다. 주 노드에 장애가 발생할 때 Patroni는 PgBouncer에 통지하는 데 사용됩니다. 장애 시, Patroni는 이전 주 노드를 복제본으로 전환하고 자동으로 클러스터에 다시 연결합니다.

Patroni를 사용하면 연결 흐름이 약간 다릅니다. 각 노드의 Patroni는 클러스터에 참여하기 위해 Consul 에이전트에 연결합니다. 이 포인트 이후에 노드가 주 도메인 또는 복제본인지 결정합니다. 이 결정에 따라 Patroni는 직접 Unix 소켓을 통해 통신하는 PostgreSQL 구성 및 시작합니다. 이는 Consul 클러스터가 작동하지 않거나 리더가 없는 경우, Patroni 및 확장하여 PostgreSQL이 시작하지 않음을 의미합니다. Patroni는 또한 각 노드에서 기본 포트를 통해 액세스할 수 있는 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 필드는 현재 전진 로그 세그먼트를 복제한 정도와 관련이 있습니다. 현재 WAL(Write-Ahead Log) 시퀀스 번호(LSN)을 확인하려면 리더에서 다음을 실행하세요:

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

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

리더가 반환해야할 것들:

-[ 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 문서를 주의 깊게 검토하세요. 완전히 이해하지 않은 경우 잠재적 데이터 손실 위험이 있는 일부 옵션이 있습니다. 구성된 복제 모드는 허용 가능한 데이터 손실량을 결정합니다.

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

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

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 인스턴스를 관리하기 위해 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 문서를 참조하십시오.

Geo 보조 사이트 고려 사항

기본 사이트가 PatroniPgBouncer를 사용하는 보조 사이트가 복제할 때 반드시 PgBouncer를 통해 복제되지 않습니다. 보조가 Patroni 클러스터에서 자동 또는 매뉴얼으로 장애 조치되면 새 리더에서 복제할 수 있도록 보조 사이트를 매뉴얼으로 다시 지정할 수 있습니다. 이는 다음과 같이 수행합니다:

sudo gitlab-ctl replicate-geo-database --host=<new_leader_ip> --replication-slot=<slot_name>

그렇지 않으면, 복제가 발생하지 않으며 원래 노드가 다시 팔로워 노드로 다시 추가되더라도 복제가 발생하지 않습니다. 이렇게 하면 보조 사이트 데이터베이스가 동기화되며 동기화에 필요한 데이터 양에 따라 시간이 오래 걸릴 수 있습니다. 복제가 동기화된 후에도 동작하지 않으면 gitlab-ctl reconfigure를 실행해야 할 수도 있습니다.

Patroni 클러스터 복구

이전 주(primary)를 복구하고 복제본으로 클러스터에 다시 참여시키려면 다음과 같이 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
    
    note
    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
    
    note
    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
    

복제본을 업그레이드하는 중에 문제가 발생하는 경우, 이에 대한 해결 방법을 찾을 수 있는 문제 해결 섹션이 있습니다.

note
gitlab-ctl revert-pg-upgrade로 PostgreSQL 업그레이드를 되돌리는 것은 gitlab-ctl pg-upgrade와 동일한 주의를 요구합니다. 먼저 복제본을 중지한 후, 리더 노드를 되돌리고, 마지막으로 복제본을 되돌려야 합니다.

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

Status: Experiment

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

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

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

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

  1. 새 클러스터에 대한 리소스 확보.
  2. 필수 사전 점검.
  3. 새 클러스터의 리더 구성.
  4. 기존 리더에서 발행자 시작.
  5. 기존 클러스터에서 데이터 복사.
  6. 기존 클러스터에서 데이터 복제.
  7. 새 클러스터 확장.
  8. 응용 프로그램을 새 클러스터 사용으로 전환.
  9. 정리.

새 클러스터에 대한 리소스 확보

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

기존 클러스터의 리더 노드가 새 클러스터의 노드에서 액세스할 수 있는지 확인하세요.

필수 사전 점검

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

SHOW wal_level;

기본적으로 Patroni는 wal_levelreplica로 설정합니다. 이를 logical로 증가시켜야 합니다. wal_level을 변경하려면 PostgreSQL을 다시 시작해야 하므로(short downtime으로 인해), 이 단계는 PostgreSQL을 잠시 재시작하는 것입니다. 이를 위해 Patroni 리더 노드에서 다음을 수행합니다.

  1. 다음과 같이 gitlab.rb을 편집합니다.

    patroni['postgresql']['wal_level'] = 'logical'
    
  2. gitlab-ctl reconfigure를 실행합니다. 이는 구성을 작성하지만 PostgreSQL 서비스를 다시 시작하지는 않습니다.
  3. 새로운 wal_level을 적용하도록 PostgreSQL을 다시 시작하려면 gitlab-ctl patroni restart를 실행합니다. 재시작 주기 동안 클러스터 리더는 사용할 수 없습니다.
  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는 기존 클러스터의 리더 노드의 호스트 주소입니다.

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-psql을 사용하여 새 리더의 논리 복제 구독을 제거하려면 DROP SUBSCRIPTION patroni_upgrade를 실행하세요.