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

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 노드가 Patroni 스위치오버 후 장애 조치되지 않음

알려진 문제로 인해, GitLab 16.5.0 이전 버전에서 PgBouncer 노드의 자동 장애 조치가 Patroni 스위치오버 후에 발생하지 않습니다. 이 예에서, 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 스위치오버가 성공적으로 이루어지도록 하려면, 모든 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 | Replica | running      | 55 |         0 |
    | gitlab-database-2.example.com       | 172.18.0.112 | Replica | start failed |    |   unknown |
    | gitlab-database-3.example.com       | 172.18.0.113 | Leader  | running      | 55 |           |
    +-------------------------------------+--------------+---------+--------------+----+-----------+
    
  2. 문제가 있는 서버에 로그인하여 데이터베이스 및 복제를 재초기화합니다. Patroni는 해당 서버에서 PostgreSQL을 종료하고 데이터 디렉터리를 제거한 후 처음부터 다시 초기화합니다:

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

    이는 모든 Patroni 노드에서 실행할 수 있지만, --member없이 sudo gitlab-ctl patroni reinitialize-replica를 실행하면 해당 서버가 재시작됩니다.

    의도하지 않은 데이터 손실 위험을 줄이기 위해 문제가 있는 서버에서 로컬로 실행해야 합니다.

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

    sudo gitlab-ctl tail patroni
    

Consul에서 Patroni 상태 재설정

경고:
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 | Replica | stopped |    |   unknown |
| gitlab-database-2.example.com       | 172.18.0.112 | Replica | stopped |    |   unknown |
| gitlab-database-3.example.com       | 172.18.0.113 | Replica | stopped |    |   unknown |
+-------------------------------------+--------------+---------+---------+----+-----------+

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

이 과정은 첫 번째 Patroni 노드가 시작될 때 재초기화된 Patroni 클러스터를 생성합니다.

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

  1. 리더였던 Patroni 노드를 기록해 두거나, 현재 상태가 여러 개 또는 없음으로 표시된 경우 애플리케이션이 현재 리더라고 생각하는 노드를 기록합니다:
    • /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. 모든 복제가 동기화되어 있는지 확인합니다

오류: 요청된 시작 지점이 저장소 쓰기 법(log) 플러시 위치보다 앞섭니다.

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

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로 실패합니다 (문제에 대해 자세히 읽기).

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
    

이 절차가 작동하지 않으면 또한 클러스터가 리더를 선출할 수 없는 경우, 마지막 수단으로 사용해야 할 또 다른 수정 방법이 있습니다.

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

Patroni 복제본gitlab-ctl pg-upgrade 동안 루프에 갇힐 수 있으며, 업그레이드가 실패합니다.

증상 예시는 다음과 같습니다:

  1. postgresql 서비스가 정의되어 있으며, 일반적으로 Patroni 노드에는 존재하지 않아야 합니다. 이는 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/log/gitlab/postgresql/current에서 PANIC 로그 항목을 생성합니다. 이는 Patroni가 복제본을 재초기화하는 과정에서 /var/opt/gitlab/postgresql/data를 제거하기 때문입니다:

    DETAIL:  "pg_xact/0000" 파일을 열 수 없습니다: 그런 파일이나 디렉토리가 없습니다.
    WARNING:다른 서버 프로세스의 충돌로 인해 연결을 종료합니다
    LOG:  모든 서버 프로세스가 종료되었습니다; 재초기화 중
    PANIC:  "global/pg_control" 파일을 열 수 없습니다: 그런 파일이나 디렉토리가 없습니다
    
  3. /var/log/gitlab/patroni/current에서 Patroni는 다음과 같이 기록합니다. 로컬 PostgreSQL 버전이 클러스터 리더와 다릅니다:

    INFO: 리더 'HOSTNAME'에서 부팅을 시도합니다
    pg_basebackup: 호환되지 않는 서버 버전 12.6
    pg_basebackup: 데이터 디렉토리 "/var/opt/gitlab/postgresql/data" 제거 중
    ERROR: 백업 가져오는 중 오류 발생: pg_basebackup가 코드=1로 종료되었습니다
    

중요: 이 우회 방법은 Patroni 클러스터가 다음과 같은 상태일 때 적용됩니다:

이 우회 방법은 Patroni 복제본에서 PostgreSQL 업그레이드를 완료하여 새 PostgreSQL 버전을 사용하도록 노드를 설정한 다음, 리더가 업그레이드 되었을 때 생성된 새 클러스터에서 복제본으로 재초기화합니다:

  1. 모든 노드에서 클러스터 상태를 확인하여 리더와 복제본의 상태를 확인합니다.

    sudo gitlab-ctl patroni members
    
  2. 복제본: 활성화된 PostgreSQL 버전을 확인합니다:

    sudo ls -al /opt/gitlab/embedded/bin | grep postgres
    
  3. 복제본: 노드 파일이 올바른지 확인하고 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에서 하드코딩된 버전을 제거합니다:

    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
    

필요한 경우 이 절차를 다른 복제본에서 반복합니다.

다른 구성 요소의 문제

여기에서 설명되지 않은 구성 요소에 문제가 발생하는 경우, 해당 특정 문서 페이지의 문제 해결 섹션을 확인하세요: