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

16.5.0 이전 버전의 GitLab에 영향을 주는 알려진 문제로 인해, 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 노드의 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을 종료하고 데이터 디렉터리를 제거한 후 scratch부터 다시 초기화합니다:

    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 상태 재설정

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

마지막 수단으로 판단할 수 있는 상태에서 Patroni 상태를 Consul에서 완전히 재설정할 수 있습니다.

이를 수행해야 하는 이유는 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. 이전 리더인지 또는 애플리케이션이 현재 리더로 생각하는 노드를 확인하세요:
    • /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 클러스터가 리더로 선출하도록 한 노드를 시작하세요. 존재하는 쓰기가 클러스터 상태가 꺠진 상태 때문에 복제되지 못한 쓰기들을 잃지 않도록 하는 것이 매우 권장됩니다:

    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이 임시 실행 파일을 작성하도록 하는데, 이를 할 파일 시스템을 찾을 수 없는 경우(ex, /tmp 파일 시스템에 noexec이 설정된 경우) MemoryError가 발생합니다 (이슈에서 자세히 읽기).

gitlab-ctl 실행 중 오류가 발생하는 경우

Patroni 노드는 gitlab-ctl 명령이 실패하며 gitlab-ctl reconfigure가 노드를 수정하지 못하는 상태에 빠질 수 있습니다.

만약 데이터베이스 서버가 시작하지 못하는 경우, gitlab-ctl은 설치에 필요한 정보를 결정하지 못할 수 있습니다.

/opt/gitlab/embedded/nodes/<HOSTNAME>.json에 구성이 잘못된 JSON 파일이 있습니다.
이는 일반적으로 `gitlab-ctl reconfigure`의 마지막 실행이 성공적으로 완료되지 않았을 때 발생합니다.
현재 노드에서 복제본을 다시 초기화하는 중 오류가 발생하였습니다: /opt/gitlab/embedded/nodes/<HOSTNAME>.json에서 속성을 찾을 수 없습니다. reconfigure가 이미 실행되었습니까?

또한 노드 파일(/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 복제본에서 PostgreSQL 주요 버전 업그레이드가 실패하는 경우

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

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

  1. 보통 Patroni 노드에는 존재해서는 안 될 postgresql 서비스가 정의되어 있습니다. 이는 gitlab-ctl pg-upgrade가 새로운 빈 데이터베이스를 만들기 위해 postgresql을 추가하기 때문에 존재할 수 있습니다:

    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를 제거할 때 /var/log/gitlab/postgresql/currentPANIC 로그 항목을 생성합니다:

    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
    

중요: 이 해결책은 다음 상태에 대한 Patroni 클러스터에서 적용됩니다:

이 해결책은 Patroni 복제본에서 PostgreSQL 업그레이드를 완료하여 새 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
    

필요하다면 이 절차를 다른 복제본에서 반복하세요.

다른 컴포넌트의 문제점

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