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

Tier: Premium, Ultimate Offering: Self-Managed

만약 GitLab Self-Managed의 무료 사용자라면 클라우드 호스팅 솔루션을 고려해보세요. 본 문서는 직접 컴파일한 설치에 관한 내용을 다루지 않습니다.

복제 및 장애 조치를 위한 설정이 여러분이 찾던 것이 아니라면, Linux 패키지용 데이터베이스 구성 문서를 참조하세요.

PostgreSQL을 GitLab을 위해 복제 및 장애 조치를 구성하기 전에 본 문서를 꼭 전체로 읽는 것을 권장합니다.

아키텍처

  • PostgreSQL 클러스터를 위한 Linux 패키지 권장 구성은 다음과 같습니다:
    • 최소 3개의 PostgreSQL 노드.
    • 최소 3개의 Consul 서버 노드.
    • 주/쓰기 요청을 추적하고 다루는 최소 3개의 PgBouncer 노드.
      • PgBouncer 노드 간 요청을 균형잡기 위한 내부 로드 밸런서(TCP).
    • 데이터베이스 부하 분산 활성화.
    • 각 PostgreSQL 노드에 구성된 로컬 PgBouncer 서비스. 이는 주(PG) 추적과 분리된 본 채우서터 클러스터에서 따로 설정됩니다.

아키텍처

또한 네트워크 탑로지를 고려하여, 데이터베이스 및 GitLab 인스턴스 간에 중복 연결이 있는지 확인하여 네트워크가 단일 장애점이 되는 것을 피해야 합니다.

참고: 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 서버 서비스를 실행합니다. 이러한 노드들은 Patroni 클러스터 부트스트랩 전에 퀄러럼에 도달하고 리더를 선출해야 합니다; 그렇지 않으면 데이터베이스 노드는 이러한 Consul 리더가 선출될 때까지 기다립니다.

PgBouncer 노드

각 PgBouncer 노드는 두 가지 서비스를 실행합니다: - PgBouncer: 데이터베이스 연결 풀러 자체. - Consul 에이전트: Consul 클러스터의 PostgreSQL 서비스 정의 상태를 관찰합니다. 그 상태가 바뀌면 Consul이 PgBouncer 구성을 새 PostgreSQL 리더 노드를 가리키도록 변경하고 PgBouncer 서비스를 다시로드합니다.

연결 흐름

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

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

Primary

  • 응용 프로그램 서버는 PgBouncer로의 기본 포트(../package_information/defaults.md) 또는 여러 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. 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: 해시된

Linux 패키지 설치

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

스텝 1에서 필요한 종속성을 설치하고, 스텝 2에서 GitLab 패키지 저장소를 추가해야 합니다. GitLab 패키지를 설치할 때는 EXTERNAL_URL 값을 제공하지 마십시오.

데이터베이스 노드 구성

  1. Consul 노드를 구성했는지 확인하세요.
  2. 다음 단계를 실행하기 전에 CONSUL_SERVER_NODES, PGBOUNCER_PASSWORD_HASH, POSTGRESQL_PASSWORD_HASH, 데이터베이스 노드 수(#postgresql-information), 그리고 네트워크 주소(#network-information)를 수집해야 합니다.

Patroni 클러스터 구성

patroni['enable'] = true로 명시적으로 Patroni를 활성화해야 합니다.

Patroni에 의해 제어되는 복제를 제어하는 PostgreSQL 구성 항목(예: wal_level, max_wal_senders 등)은 모두 patroni['postgresql'][...] 아래에 분리되어 있습니다. 이 동작은 복제에만 해당됩니다. Patroni는 postgresql[...] 구성 키로 수행한 다른 PostgreSQL 구성을 존중합니다. 예를 들어, max_wal_senders는 기본적으로 5로 설정됩니다. 이를 변경하려면 patroni['postgresql']['max_wal_senders'] 구성 키로 설정해야 합니다.

참고: 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는 복제당 하나의 추가 슬롯을 사용하므로 `max_replication_slots`를 데이터베이스 노드 수의 두 배로 설정
patroni['postgresql']['max_replication_slots'] = X

# `max_wal_senders`를 클러스터의 복제 슬롯 수에 1을 더하여 설정
# 이는 복제가 모든 가능한 데이터베이스 연결을 사용하는 것을 방지하는 데 사용됨
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)

# 네트워크 주소로 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)
}
#
# 사용자 구성 끝

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

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

일반적으로 Consul 클러스터가 준비되면 처음으로 다시 구성하는 노드가 리더가 됩니다. 노드의 순서를 정해놓지 않아도 됩니다. 병렬로 실행하든 임의의 순서로 실행하든 상관없이 초기 리더를 결정하지 않습니다.

모니터링 활성화

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

  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'] = '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: 모든 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 노드 각각에서 서로 다른 인증서 및 키를 사용할 수 있지만 검증할 수 있는 경우에만 가능합니다. 그러나 내부 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
    

    참고: 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 암호 해시를 생성했는지 확인하십시오. 올바른 형식은 암호와 사용자 이름을 연결하는 것입니다: 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' 또는 '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로의 PgBouncer 연결이 실패한다는 rake aborted! 오류가 발생한다면, 데이터베이스 노드의 gitlab.rb에서 PgBouncer 노드의 IP 주소가 trust_auth_cidr_addresses에 포함되어 있는지 확인해야 할 수도 있습니다. 계속 진행하기 전에 PgBouncer error 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

참고: PostgreSQL 11에서 Repmgr 대신 Patroni를 사용하는 것이 지원되며 PostgreSQL 12에서 필수입니다. GitLab 14.0부터는 PostgreSQL 12만 사용 가능하므로 Patroni는 장애 조치 및 복제를 달성하기 위해 필수적입니다.

Patroni는 PostgreSQL 고가용성을 위한 주관적인 솔루션입니다. PostgreSQL을 제어하고 구성을 무시하며 수명주기(시작, 중지, 다시 시작)를 관리합니다. Patroni는 PostgreSQL 12 클러스터링 및 Geo 배포의 단계적 복제에 대한 유일한 옵션입니다.

기본 아키텍처 (위에서 언급됨)는 Patroni에 대해 변경되지 않습니다. 데이터베이스 노드를 프로비저닝하는 동안 Patroni에 대해 특별한 고려사항이 필요하지 않습니다. Patroni는 콘술을 사용하여 클러스터의 상태를 저장하고 리더를 선출하는 데 매우 의존합니다. 콘술 클러스터에서의 장애 및 리더 선출은 Patroni 클러스터로 전파됩니다.

Patroni는 클러스터를 모니터링하고 장애 조치를 처리합니다. 기본 노드에 장애가 발생하면 콘술과 협력하여 PgBouncer에 알립니다. 장애 발생시 Patroni는 이전 기본 노드의 변이를 처리하고 자동으로 클러스터에 다시 연결합니다.

Patroni를 사용하면 연결 흐름이 약간 다릅니다. 각 노드의 Patroni는 클러스터에 참여하기 위해 콘술 에이전트에 연결합니다. 이후에 노드가 기본 또는 복제인지를 결정합니다. 이 결정에 따라 직접 Unix 소켓을 통해 통신하는 PostgreSQL을 구성하고 시작합니다. 이는 콘술 클러스터가 기능하지 않거나 리더가 없는 경우 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 | 복제본  | 실행 중 |  5 |         0 |
| gitlab-database-2.example.com       | 172.18.0.112 | 복제본  | 실행 중 |  5 |       100 |
| gitlab-database-3.example.com       | 172.18.0.113 | 리더    | 실행 중 |  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 설명서에서 자세히 읽어보세요. 이 정보는 state 필드에 대한 다른 값과 함께 반환됩니다.

복제본은 다음을 반환해야 합니다:

-[ 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 장애 조치 동작 사용자 정의

리눅스 패키지 설치는 /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는 Unix 소켓을 사용하여 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 patronicheck-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 문서의 해당 부분을 참조하십시오.

repmgr에서 Patroni로 전환

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

다음 단계를 수행하여 기존 데이터베이스 클러스터를 repmgr 대신 Patroni를 사용하도록 변경할 수 있습니다.

  1. 모든 레플리카 노드에서 repmgr을 중지하고 마지막으로 기본 노드에서도 중지합니다.

    sudo gitlab-ctl stop repmgrd
    
  2. 모든 레플리카 노드에서 PostgreSQL을 중지합니다.

    sudo gitlab-ctl stop postgresql
    

    참고: 기본 노드에서 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로 업그레이드할 수 없습니다. 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부터 Linux 패키지에는 기본적으로 PostgreSQL 12.6과 13.3이 함께 제공됩니다. GitLab 15.0부터는 PostgreSQL 13가 기본값입니다. GitLab 15.0 이전 버전에서 PostgreSQL 13으로 업그레이드하려면 명시적으로 요청해야 합니다.

경고: Patroni 클러스터에서 PostgreSQL을 업그레이드하는 절차는 repmgr을 사용하여 업그레이드하는 것과 다릅니다. 다음은 업그레이드할 때 고려해야 할 주요 차이점과 중요한 사항을 개요화한 것입니다.

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을 리더 노드에서 업그레이드하고 업그레이드가 성공적으로 완료되었는지 확인합니다.

    sudo gitlab-ctl pg-upgrade -V 13
    

    참고: gitlab-ctl pg-upgrade는 노드의 역할을 감지하려고 시도합니다. 자동 감지가 작동하지 않거나 역할이 올바르게 감지되지 않은 것으로 판단되는 경우 --leader 또는 --replica 옵션을 사용하여 수동으로 무시할 수 있습니다.

  5. 리더와 클러스터 상태를 확인하고 리더가 정상적인 경우에만 진행할 수 있습니다.

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

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

    sudo gitlab-ctl pg-upgrade -V 13
    

레플리카 업그레이드 시 문제가 발생하는 경우 해결 방법을 참조할 수 있습니다.

참고: gitlab-ctl revert-pg-upgrade로 PostgreSQL 업그레이드를 되돌리는 경우 gitlab-ctl pg-upgrade와 동일한 고려사항이 적용됩니다. 먼저 레플리카를 중지한 후 리더를 되돌리고 마지막으로 레플리카를 되돌려야 합니다.

Patroni 클러스터의 PostgreSQL을 거의 중지하지 않고 업그레이드하는 방법

상태: EXPERIMENT

Patroni를 사용하면 클러스터를 중지하지 않고 주요 PostgreSQL 업그레이드를 실행할 수 있습니다. 그러나 새로운 Patroni 노드에 업그레이드된 PostgreSQL을 호스팅하기 위해 추가 자원이 필요합니다. 이 절차를 통해 실제로 다음을 수행합니다.

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

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

순서대로 진행되는 단계:

  1. 새 클러스터에 대한 리소스 할당.
  2. Preflight 체크.
  3. 새 클러스터의 리더 구성.
  4. 기존 리더에서 퍼블리셔 시작.
  5. 기존 클러스터에서 데이터 복사.
  6. 기존 클러스터에서 데이터 복제.
  7. 새 클러스터 확장.
  8. 응용 프로그램을 새 클러스터에 사용하도록 전환.
  9. 정리.

새 클러스터에 대한 리소스 할당

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

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

Preflight 체크

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

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을 적용하되 failover를 유발하지 않습니다. 재시작 주기 동안 클러스터 리더가 사용할 수 없습니다.
  4. gitlab-psqlSHOW wal_level을 실행하여 변경을 확인합니다.

새 클러스터의 리더 구성

새 클러스터의 첫 번째 노드를 구성하십시오. 이 노드가 새 클러스터의 리더가 됩니다. 기존 클러스터의 설정이 새 PostgreSQL 버전과 호환되는 경우 기존 클러스터의 구성을 사용할 수 있습니다. Patroni 클러스터 구성 문서를 참조하세요.

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

  1. 새 Patroni 클러스터가 다른 스코프를 사용하도록 확인하세요. 스코프는 Consul에서 Patroni 설정을 네임스페이스로 사용하여 기존 및 새 클러스터에 동일한 Consul 클러스터를 사용할 수 있게 합니다.

    patroni['scope'] = 'postgresql_new-ha'
    
  2. Consul 에이전트가 기존 Patroni 클러스터와 새 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 사용자는 새 리더 노드에서 기존 리더를 인증할 수 있어야 합니다.

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

초기 데이터 덤프를 수행한 후에는 새 리더를 기존 클러스터의 최신 변경 사항과 동기화해야 합니다. 새 리더에서 다음 SQL 문을 실행하여 기존 리더의 게시를 구독하도록 gitlab-psql을 사용합니다.

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를 실행합니다.