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

Tier: Premium, Ultimate Offering: Self-managed

PostgreSQL 복제 및 장애 조치 작업 중 다음과 같은 문제가 발생할 수 있습니다.

Consul 및 PostgreSQL 변경 내용이 적용되지 않음

잠재적인 영향으로 인해 gitlab-ctl reconfigure는 Consul과 PostgreSQL을 다시 로드하지만 서비스를 재시작하지는 않습니다. 그러나 모든 변경 사항을 다시 로드함으로써 활성화할 수 있는 것은 아닙니다.

서비스 중 하나를 재시작하려면 gitlab-ctl restart SERVICE 명령을 실행합니다.

PostgreSQL의 경우 리더 노드를 기본값으로 다시 시작하는 것이 보통 안전합니다. 자동 장애 조치는 1분 타임아웃으로 기본 설정됩니다. 데이터베이스가 그 전에 복귀하는 경우 다른 조치가 필요하지 않습니다.

Consul 서버 노드에서는 제어된 방식으로 Consul 서비스를 다시 시작하는 것이 중요합니다.

PgBouncer 오류 ERROR: pgbouncer cannot connect to server

gitlab-rake gitlab:db:configure 명령을 실행할 때 이 오류가 발생하거나 PgBouncer 로그 파일에서 이 오류를 볼 수 있습니다.

PG::ConnectionBad: ERROR:  pgbouncer cannot connect to server

문제는 PgBouncer 노드의 IP 주소가 데이터베이스 노드의 /etc/gitlab/gitlab.rb에서 trust_auth_cidr_addresses 설정에 포함되어 있지 않을 수 있습니다.

리더 데이터베이스 노드에서 PostgreSQL 로그를 확인하여 이 문제가 발생했는지 확인할 수 있습니다. 만약 아래와 같은 오류를 발견하면 trust_auth_cidr_addresses가 문제입니다.

2018-03-29_13:59:12.11776 FATAL:  no pg_hba.conf entry for host "123.123.123.123", user "pgbouncer", database "gitlabhq_production", SSL off

문제를 해결하려면 IP 주소를 /etc/gitlab/gitlab.rb에 추가합니다.

postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)

변경 사항이 적용되려면 GitLab을 다시 구성합니다.

PgBouncer 오류 Error running command: GitlabCtl::Errors::ExecutionErrorERROR: database gitlabhq_production is not paused

GitLab 16.5.0 이전 버전에 영향을 미치는 알려진 문제로 인해 PgBouncer 노드의 자동 장애 조치가 Patroni switchover 후에 발생하지 않을 수 있습니다. 이 예에서 GitLab은 일시 중지된 데이터베이스를 감지하지 못한 다음 일시 중지되지 않은 데이터베이스를 RESUME하려 시도합니다.

INFO -- : Running: gitlab-ctl pgb-notify --pg-database gitlabhq_production --newhost database7.example.com --user pgbouncer --hostuser gitlab-consul
ERROR -- : STDERR: Error running command: GitlabCtl::Errors::ExecutionError
ERROR -- : STDERR: ERROR: ERROR:  database gitlabhq_production is not paused

Patroni switchover가 성공하려면 모든 PgBouncer 노드에서 다음 명령을 사용하여 PgBouncer 서비스를 매뉴얼으로 다시 시작해야 합니다.

gitlab-ctl restart pgbouncer

복제본 재초기화

복제본이 시작되지 않거나 클러스터에서 뒤처지고 따라잡지 못하는 경우, 복제본을 다시 초기화해야 할 수 있습니다.

  1. 어떤 서버가 다시 초기화해야 하는지 확인하기 위해 복제 상태를 확인합니다. 예를 들어:

    + Cluster: postgresql-ha (6970678148837286213) ------+---------+--------------+----+-----------+
    | Member                              | Host         | Role    | State        | TL | Lag in MB |
    +-------------------------------------+--------------+---------+--------------+----+-----------+
    | gitlab-database-1.example.com       | 172.18.0.111 | 복제본  | 실행 중       | 55 |         0 |
    | gitlab-database-2.example.com       | 172.18.0.112 | 복제본  | 시작 실패     |    |   알 수 없음 |
    | gitlab-database-3.example.com       | 172.18.0.113 | 리더    | 실행 중       | 55 |           |
    +-------------------------------------+--------------+---------+--------------+----+-----------+
    
  2. 손상된 서버에 로그인하여 데이터베이스와 복제를 다시 초기화합니다. Patroni는 해당 서버에서 PostgreSQL을 종료시키고 데이터 디렉터리를 제거한 다음 처음부터 다시 초기화합니다.

    sudo gitlab-ctl patroni reinitialize-replica --member gitlab-database-2.example.com
    

    이 명령은 어느 Patroni 노드에서나 실행할 수 있지만 sudo gitlab-ctl patroni reinitialize-replica --member를 사용하지 않고 실행하면 해당 서버를 다시 시작시킵니다. 의도하지 않은 데이터 손실의 위험을 줄이기 위해 손상된 서버에서 로컬로 실행하는 것이 좋습니다.

  3. 로그를 모니터링합니다.

    sudo gitlab-ctl tail patroni
    

Consul에서 Patroni 상태 재설정

caution
Consul에서 Patroni 상태를 재설정하는 것은 잠재적으로 파괴적인 프로세스입니다. 먼저 건강한 데이터베이스 백업이 있는지 확인하세요.

최후의 수단으로 Consul에서 Patroni 상태를 완전히 재설정할 수 있습니다.

현재 Patroni 클러스터가 알 수 없는 상태이거나 어느 노드도 시작할 수 없는 경우 이 작업이 필요할 수 있습니다.

+ Cluster: postgresql-ha (6970678148837286213) ------+---------+---------+----+-----------+
| Member                              | Host         | Role    | State   | TL | Lag in MB |
+-------------------------------------+--------------+---------+---------+----+-----------+
| gitlab-database-1.example.com       | 172.18.0.111 | 복제본  | 중지됨   |    |   알 수 없음 |
| gitlab-database-2.example.com       | 172.18.0.112 | 복제본  | 중지됨   |    |   알 수 없음 |
| gitlab-database-3.example.com       | 172.18.0.113 | 복제본  | 중지됨   |    |   알 수 없음 |
+-------------------------------------+--------------+---------+---------+----+-----------+

Consul에서 Patroni 상태를 삭제하기 전에 Patroni 노드에서 gitlab-ctl 오류를 해결해보세요.

이 프로세스는 첫 번째 Patroni 노드가 시작될 때 재설정된 Patroni 클러스터를 결과로 낳습니다.

Consul에서 Patroni 상태를 재설정하려면:

  1. 이전 리더로 선출되었거나 응용 프로그램이 현재 리더로 간주하는 노드, 둘 이상이거나 없는 경우:
    • /var/opt/gitlab/consul/databases.ini의 PgBouncer 노드에서 확인하세요. 이 파일에는 현재 리더의 호스트명이 포함되어 있습니다.
    • 모든 데이터베이스 노드의 Patroni 로그 /var/log/gitlab/patroni/current (또는 복구된 이전 로테이션 및 압축된 로그 /var/log/gitlab/patroni/@40000*)를 확인하여 클러스터에 의해 가장 최근에 식별된 서버가 어느 것인지 확인합니다.
    INFO: no action. I am a secondary (database1.local) and following a leader (database2.local)
    
  2. 모든 노드에서 Patroni를 중지합니다.

    sudo gitlab-ctl stop patroni
    
  3. Consul에서 상태를 재설정합니다.

    /opt/gitlab/embedded/bin/consul kv delete -recurse /service/postgresql-ha/
    
  4. Patroni 노드 하나를 시작하여 Patroni 클러스터가 리더로 선출되도록 합니다. 가능하면 첫 번째 단계에서 기록한 이전 리더를 시작하는 것이 좋습니다. 왜냐하면 고장 난 클러스터 상태로 인해 복제되지 못한 기존의 쓰기를 잃지 않기 위함입니다.

    sudo gitlab-ctl start patroni
    
  5. 다른 Patroni 노드를 시작하여 Patroni 클러스터에 복제본으로 합류하도록 합니다.

    sudo gitlab-ctl start patroni
    

문제가 계속되는 경우 다음 단계는 마지막으로 안정적인 백업을 복원하는 것입니다.

pg_hba.conf 엔트리에 대한 Patroni 로그 오류 127.0.0.1

Patroni 로그의 다음 내용은 복제가 작동하지 않고 구성 변경이 필요함을 나타냅니다:

FATAL:  no pg_hba.conf entry for replication connection from host "127.0.0.1", user "gitlab_replicator"

문제를 해결하려면 루프백 인터페이스가 CIDR 주소 디렉터리에 포함되어 있는지 확인하십시오:

  1. /etc/gitlab/gitlab.rb 파일 편집:

    postgresql['trust_auth_cidr_addresses'] = %w(<other_cidrs> 127.0.0.1/32)
    
  2. 변경 사항이 적용되려면 GitLab을 재구성하십시오.
  3. 모든 복제본이 동기화되었는지 확인하십시오.

Patroni 로그의 오류: 요청된 시작 지점이 Write Ahead Log (WAL) 플러시 위치를 앞지른 경우

이 오류는 데이터베이스가 복제되지 않음을 나타냅니다:

FATAL:  could not receive data from WAL stream: ERROR:  requested starting point 0/5000000 is ahead of the WAL flush position of this server 0/4000388

이 예시 오류는 초기에 잘못 구성된 복제본에서 발생하며, 결코 복제되지 않았습니다.

복제본을 초기화하여 문제를 해결하십시오.

Patroni가 MemoryError와 함께 시작하지 못하는 경우

Patroni는 오류와 스택 추적을 기록하면서 시작하지 못할 수 있습니다:

MemoryError
Traceback (most recent call last):
  File "/opt/gitlab/embedded/bin/patroni", line 8, in <module>
    sys.exit(main())
[..]
  File "/opt/gitlab/embedded/lib/python3.7/ctypes/__init__.py", line 273, in _reset_cache
    CFUNCTYPE(c_int)(lambda: None)

스택 추적이 CFUNCTYPE(c_int)(lambda: None)로 끝나면, 이 코드는 Linux 서버가 보안을 위해 강화된 경우 MemoryError를 유발합니다.

이 코드는 Python이 임시 실행 파일을 작성하도록 유도하며, 이를 수행할 파일 시스템을 찾을 수 없는 경우 예를 들어 /tmp 파일 시스템에 noexec가 설정된 경우 MemoryError가 발생합니다 (문제에 대해 자세히 알아보기).

해결 방법:

  • /tmp/var/tmp과 같은 파일 시스템의 마운트 옵션에서 noexec를 제거합니다.
  • 적용되는 경우 SELinux도 이러한 작업을 방지할 수 있습니다. 이 문제가 해결되었는지 확인하기 위해 SELinux를 허용 모드로 설정하십시오.

Patroni는 GitLab 13.1의 Linux 패키지에 처음으로 탑재되었으며, Python 3.7 빌드와 함께 출시되었습니다. 이 문제를 유발하는 코드는 Python 3.8에서 제거되었습니다. 이 문제는 GitLab 14.3의 Linux 패키지에서 수정되어 workaround가 필요 없게 되었습니다.

gitlab-ctl 실행 오류

Patroni 노드가 gitlab-ctl 명령이 실패하며 gitlab-ctl reconfigure가 노드를 수정할 수 없는 상태에 도달할 수 있습니다.

PostgreSQL의 버전 업그레이드와 동시에 발생하는 경우, 다른 절차를 따르십시오

일반적인 증상 중 하나는 데이터베이스 서버가 시작하지 못할 때 gitlab-ctl가 설치에 필요한 정보를 결정할 수 없다는 것입니다:

Malformed configuration JSON file found at /opt/gitlab/embedded/nodes/<HOSTNAME>.json.
This usually happens when your last run of `gitlab-ctl reconfigure` didn't complete successfully.
Error while reinitializing replica on the current node: Attributes not found in /opt/gitlab/embedded/nodes/<HOSTNAME>.json, has reconfigure been run yet?

마찬가지로 노드 파일(/opt/gitlab/embedded/nodes/<HOSTNAME>.json)은 많은 정보를 포함해야 하지만, 아래와 같이 생성될 수 있습니다:

{
  "name": "<HOSTNAME>"
}

이 문제를 해결하기 위한 프로세스에는 현재 PostgreSQL 상태를 폐기하여 이 복제본을 다시 초기화하는 단계가 포함됩니다:

  1. Patroni 및 (있는 경우) PostgreSQL 서비스를 중지하십시오:

    sudo gitlab-ctl status
    sudo gitlab-ctl stop patroni
    sudo gitlab-ctl stop postgresql
    
  2. 경우에 따라 PostgreSQL이 시작되지 못하게 하기 위해 /var/opt/gitlab/postgresql/data를 제거하십시오:

    cd /var/opt/gitlab/postgresql
    sudo rm -rf data
    

    데이터 손실을 방지하기 위해 이 단계를 조심스럽게 수행하십시오. 이 단계는 ‘data/’의 이름을 바꿔 동일한 복제본이 수정되는 데 필요한 새로운 기본 데이터베이스를 위한 충분한 디스크 공간을 확보하고, 복제본이 수정되면 추가 디렉터리를 제거하는 식으로 수행할 수도 있습니다.

  3. PostgreSQL이 실행되지 않는 상태에서 노드 파일이 성공적으로 생성됨:

    sudo gitlab-ctl reconfigure
    
  4. Patroni를 시작하십시오:

    sudo gitlab-ctl start patroni
    
  5. 로그를 모니터링하고 클러스터 상태를 확인하십시오:

    sudo gitlab-ctl tail patroni
    sudo gitlab-ctl patroni members
    
  6. reconfigure를 다시 실행하십시오:

    sudo gitlab-ctl reconfigure
    
  7. 필요한 경우, 복제본을 다시 초기화하십시오. 이는 gitlab-ctl patroni members가 이를 필요로 한다는 것을 나타낼 때 수행하십시오:

    sudo gitlab-ctl patroni reinitialize-replica
    

이 절차가 작동하지 않거나 클러스터가 리더를 선출하지 못하는 경우에는 마지막 수단으로 Patroni 상태를 초기화하기 이전 절차를 사용하십시오.

Patroni 복제본에서 PostgreSQL 주요 버전 업그레이드가 실패하는 경우

Patroni 복제본gitlab-ctl pg-upgrade 중에 루프에 갇히고 업그레이드가 실패할 수 있습니다.

다음은 예시 증상 집합입니다:

  1. Patroni 노드에서 일반적으로 존재해서는 안 되는 postgresql 서비스가 정의됩니다. 새로운 빈 데이터베이스를 만들려고 gitlab-ctl pg-upgrade가 추가하므로 존재할 수 있습니다:

    run: patroni: (pid 1972) 1919s; run: log: (pid 1971) 1919s
    down: postgresql: 1s, normally up, want up; run: log: (pid 1973) 1919s
    
  2. PostgreSQL은 복제본을 다시 초기화하는 부분으로 /var/opt/gitlab/postgresql/data를 제거할 때 PANIC 로그 항목을 생성합니다:

    DETAIL:  Could not open file "pg_xact/0000": No such file or directory.
    WARNING:  terminating connection because of crash of another server process
    LOG:  all server processes terminated; reinitializing
    PANIC:  could not open file "global/pg_control": No such file or directory
    
  3. /var/log/gitlab/patroni/current에서 Patroni는 다음과 같이 로그를 기록합니다. 로컬 PostgreSQL 버전이 클러스터 리더와 다릅니다:

    INFO: trying to bootstrap from leader 'HOSTNAME'
    pg_basebackup: incompatible server version 12.6
    pg_basebackup: removing data directory "/var/opt/gitlab/postgresql/data"
    ERROR: Error when fetching backup: pg_basebackup exited with code=1
    

중요: 이 workaround는 다음과 같은 상태일 때 Patroni 복제본에서 PostgreSQL 업그레이드를 완료합니다:

이 workaround는 Patroni 복제본에서 PostgreSQL 업그레이드를 완료하고, 리더가 업그레이드될 때 생성된 새 클러스터에서 복제본을 다시 초기화합니다:

  1. 모든 노드에서 클러스터 상태를 확인하여 리더와 복제본의 상태를 확인하십시오:

    sudo gitlab-ctl patroni members
    
  2. 복제본: 현재 PostgreSQL 버전을 확인하십시오:

    sudo ls -al /opt/gitlab/embedded/bin | grep postgres
    
  3. 복제본: 노드 파일이 올바르게 작성되었는지 확인하고 gitlab-ctl을 실행할 수 있다는 것을 확인하십시오. 이는 복제본이 이러한 오류 중 하나를 가지고 있는 경우 gitlab-ctl 실행 오류를 해결합니다:

    sudo gitlab-ctl stop patroni
    sudo gitlab-ctl reconfigure
    
  4. 복제본: incompatible server version 오류를 해결하기 위해 PostgreSQL 이진 파일을 필요한 버전으로 다시 연결하십시오:

    1. /etc/gitlab/gitlab.rb 파일을 편집하고 필요한 버전을 지정하십시오:

      postgresql['version'] = 13
      
    2. GitLab을 다시 구성하십시오:

      sudo gitlab-ctl reconfigure
      
    3. 올바른 이진 파일이 연결되어 있는지 확인하십시오. PostgreSQL에 대한 배포된 이진 파일은 주요 릴리스 간에 다를 수 있으며, 일반적으로 일부 잘못된 심볼릭 링크가 있을 수 있습니다:

      sudo ls -al /opt/gitlab/embedded/bin | grep postgres
      
  5. 복제본: 지정된 버전의 PostgreSQL이 완전히 다시 초기화되었는지 확인하십시오:

    cd /var/opt/gitlab/postgresql
    sudo rm -rf data
    sudo gitlab-ctl reconfigure
    
  6. 복제본: 선택적으로 데이터베이스를 두 개의 추가 터미널 세션에서 모니터링합니다:

    • pg_basebackup이 실행될 때 디스크 사용량이 증가합니다. 다음 명령어로 복제본 초기화의 진행 상황을 추적하십시오:

      cd /var/opt/gitlab/postgresql
      watch du -sh data
      
    • 로그에서 프로세스를 모니터링하십시오:

      sudo gitlab-ctl tail patroni
      
  7. 복제본: Patroni를 시작하여 복제본을 다시 초기화하십시오:

    sudo gitlab-ctl start patroni
    
  8. 복제본: 완료된 후 /etc/gitlab/gitlab.rb에서 hardcoded된 버전을 제거하십시오:

    1. /etc/gitlab/gitlab.rb 파일을 편집하고 postgresql['version']를 제거하십시오.
    2. GitLab을 다시 구성하십시오:

      sudo gitlab-ctl reconfigure
      
    3. 올바른 이진 파일이 연결되어 있는지 확인하십시오:

      sudo ls -al /opt/gitlab/embedded/bin | grep postgres
      
  9. 모든 노드에서 클러스터 상태를 확인하십시오:

    sudo gitlab-ctl patroni members
    

필요한 경우 다른 복제본에서 이 절차를 반복하십시오.

다른 컴포넌트의 문제점

만약 여기에 기술되지 않은 컴포넌트에 문제가 발생한다면, 해당 문제에 대한 해결 방법은 아래 컴포넌트의 문서 페이지에서 troubleshooting 섹션을 확인해주세요: