Linux 패키지 설치에서 PostgreSQL 복제 및 장애 조치 문제 해결
Offering: GitLab Self-Managed
PostgreSQL 복제 및 장애 조치 작업 중 다음과 같은 문제가 발생할 수 있습니다. 잠재적인 영향으로 인해 gitlab-ctl reconfigure는 Consul 및 PostgreSQL을 다시 로드만 하고 서비스를 다시 시작하지 않습니다.
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
문제를 해결하려면 /etc/gitlab/gitlab.rb에 IP 주소를 추가합니다.
postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
변경 사항을 적용하려면 GitLab을 재구성합니다.
Patroni 전환 후 PgBouncer 노드가 장애 조치되지 않는 경우#
GitLab 16.5.0 이전 버전에 영향을 미치는 알려진 문제로 인해, Patroni 전환 후 PgBouncer 노드의 자동 장애 조치가 발생하지 않습니다. 이 예시에서 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
복제본 재초기화#
복제본이 시작되거나 클러스터에 재참여할 수 없거나, 뒤처지고 따라잡을 수 없는 경우 복제본을 재초기화해야 할 수 있습니다:
-
복제 상태를 확인하여 어떤 서버를 재초기화해야 하는지 확인합니다. 예를 들어:
+ 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 | | +-------------------------------------+--------------+---------+--------------+----+-----------+ -
손상된 서버에 로그인하고 데이터베이스 및 복제를 재초기화합니다. Patroni는 해당 서버의 PostgreSQL을 종료하고, 데이터 디렉토리를 제거한 후 처음부터 다시 초기화합니다:
sudo gitlab-ctl patroni reinitialize-replica --member gitlab-database-2.example.com이 명령은 모든 Patroni 노드에서 실행할 수 있지만,
--member없이sudo gitlab-ctl patroni reinitialize-replica를 실행하면 실행하는 서버가 다시 시작됩니다. 의도치 않은 데이터 손실의 위험을 줄이기 위해 손상된 서버에서 로컬로 실행해야 합니다. -
로그를 모니터링합니다:
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 상태를 재설정하려면:
-
현재 상태가 둘 이상이나 없는 경우 리더였던 Patroni 노드 또는 애플리케이션이 현재 리더로 생각하는 노드를 메모합니다:
-
PgBouncer 노드의
/var/opt/gitlab/consul/databases.ini를 확인합니다. 이 파일에는 현재 리더의 호스트 이름이 포함되어 있습니다. -
모든 데이터베이스 노드의 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)
-
-
모든 노드에서 Patroni를 중지합니다:
sudo gitlab-ctl stop patroni -
Consul에서 상태를 재설정합니다:
/opt/gitlab/embedded/bin/consul kv delete -recurse /service/postgresql-ha/ -
하나의 Patroni 노드를 시작하여 Patroni 클러스터를 초기화하고 리더로 선출합니다. 손상된 클러스터 상태로 인해 복제되지 않았을 수 있는 기존 쓰기 손실을 방지하기 위해 이전 리더(첫 번째 단계에서 메모)를 시작하는 것이 강력히 권장됩니다:
sudo gitlab-ctl start patroni -
복제본으로 Patroni 클러스터에 참여하는 다른 모든 Patroni 노드를 시작합니다:
sudo gitlab-ctl start patroni
여전히 문제가 발생하면 다음 단계는 마지막 건강한 백업을 복원하는 것입니다.
127.0.0.1에 대한 pg_hba.conf 항목에 관한 Patroni 로그 오류#
Patroni 로그의 다음 로그 항목은 복제가 작동하지 않으며 구성 변경이 필요함을 나타냅니다:
FATAL: no pg_hba.conf entry for replication connection from host "127.0.0.1", user "gitlab_replicator"
문제를 해결하려면 루프백 인터페이스가 CIDR 주소 목록에 포함되어 있는지 확인합니다:
-
/etc/gitlab/gitlab.rb를 편집합니다:postgresql['trust_auth_cidr_addresses'] = %w(<other_cidrs> 127.0.0.1/32) -
변경 사항을 적용하려면 GitLab을 재구성합니다.
재시작 대기 중으로 표시되는 Patroni 멤버#
gitlab-ctl patroni members 출력에서 보조 사이트의 Patroni 멤버가 재시작 대기 중 상태로 표시될 수 있습니다:
secondary-site:postgresql-1> gitlab-ctl patroni members
+ Cluster: postgresql-ha ------------------------------------------------------------------+
| Member | Host | Role | State | TL | Lag in MB | Pending restart |
+----------------+-----------+----------------+---------+----+-----------+-----------------+
| patroni-1 | 10.20.0.1 | Replica | running | 27 | 0 | * |
| patroni-2 | 10.20.0.2 | Replica | running | 27 | 5 | * |
| patroni-3 | 10.20.0.3 | Standby Leader | running | 27 | | * |
+----------------+-----------+----------------+---------+----+-----------+----------
재시작 대기 중 상태는 해당 노드가 일부 구성 변경을 적용하기 위해 재시작을 기다리고 있음을 의미합니다.
재시작 대기 중인 설정이 무엇인지 알려면 확인해야 하는 인스턴스에서 다음을 실행합니다:
sudo gitlab-psql -c "select name, setting, short_desc, sourcefile, sourceline from pg_settings where pending_restart"
대기 중인 구성 변경을 적용하려면 영향을 받은 노드를 재시작합니다:
- 복제본 노드의 경우
sudo gitlab-ctl restart patroni를 실행합니다. - 리더 노드의 경우 다운타임을 방지하기 위해 먼저 장애 조치를 수행하거나
sudo gitlab-ctl reload patroni를 실행합니다.
오류: 요청된 시작 포인트가 WAL(Write Ahead 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
이 예시 오류는 처음에 잘못 구성되어 한 번도 복제하지 않은 복제본에서 발생한 것입니다.
복제본을 재초기화하여 수정합니다.
MemoryError로 Patroni가 시작에 실패하는 경우#
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/.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/.json, has reconfigure been run yet?
마찬가지로, 노드 파일(/opt/gitlab/embedded/nodes/.json)에는 많은 정보가 포함되어야 하지만 다음만 포함되어 있을 수 있습니다:
{
"name": ""
}
이를 수정하는 다음 프로세스에는 이 복제본을 재초기화하는 것이 포함됩니다. 이 노드의 PostgreSQL 현재 상태는 삭제됩니다:
-
Patroni 및 (있는 경우) PostgreSQL 서비스를 종료합니다:
sudo gitlab-ctl status sudo gitlab-ctl stop patroni sudo gitlab-ctl stop postgresql -
PostgreSQL이 시작되지 않도록 상태를 방지하는 경우
/var/opt/gitlab/postgresql/data를 제거합니다:cd /var/opt/gitlab/postgresql sudo rm -rf data[!warning] 데이터 손실을 방지하기 위해 이 단계에 주의합니다. 이 단계는
data/의 이름을 변경하여 달성할 수도 있습니다: 기본 데이터베이스의 새 복사본을 위한 충분한 여유 디스크 공간이 있는지 확인하고, 복제본이 수정되면 추가 디렉토리를 제거합니다. -
PostgreSQL이 실행되지 않으면 노드 파일이 성공적으로 생성됩니다:
sudo gitlab-ctl reconfigure -
Patroni를 시작합니다:
sudo gitlab-ctl start patroni -
로그를 모니터링하고 클러스터 상태를 확인합니다:
sudo gitlab-ctl tail patroni sudo gitlab-ctl patroni members -
reconfigure를 다시 실행합니다:sudo gitlab-ctl reconfigure -
gitlab-ctl patroni members가 필요함을 나타내면 복제본을 재초기화합니다:sudo gitlab-ctl patroni reinitialize-replica
이 절차가 효과가 없고 클러스터가 리더를 선출할 수 없는 경우, 최후의 수단으로만 사용해야 하는 다른 수정 방법이 있습니다.
Patroni 복제본에서 PostgreSQL 주요 버전 업그레이드 실패#
Patroni 복제본이 gitlab-ctl pg-upgrade 중에 루프에 빠져 업그레이드가 실패할 수 있습니다.
다음은 예시 증상 세트입니다:
-
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 -
Patroni가 복제본을 재초기화하는 과정에서
/var/opt/gitlab/postgresql/data를 제거하는 동안 PostgreSQL이/var/log/gitlab/postgresql/current에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 -
/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 클러스터가 다음 상태에 있을 때 적용됩니다:
- 리더가 새 주요 버전으로 성공적으로 업그레이드되었습니다.
- 복제본에서 PostgreSQL을 업그레이드하는 단계가 실패하고 있습니다.
이 해결 방법은 노드를 새 PostgreSQL 버전을 사용하도록 설정한 다음, 리더가 업그레이드될 때 생성된 새 클러스터에서 복제본으로 재초기화하여 Patroni 복제본에서 PostgreSQL 업그레이드를 완료합니다:
-
모든 노드에서 클러스터 상태를 확인하여 어느 것이 리더인지와 복제본이 어떤 상태인지 확인합니다.
sudo gitlab-ctl patroni members -
복제본: 어떤 버전의 PostgreSQL이 활성 상태인지 확인합니다:
sudo ls -al /opt/gitlab/embedded/bin | grep postgres -
복제본: 노드 파일이 올바르고
gitlab-ctl이 실행될 수 있는지 확인합니다. 복제본에 해당 오류가 있는 경우gitlab-ctl실행 오류 문제를 해결합니다:sudo gitlab-ctl stop patroni sudo gitlab-ctl reconfigure -
복제본:
incompatible server version오류를 수정하기 위해 PostgreSQL 바이너리를 필요한 버전으로 다시 링크합니다:-
/etc/gitlab/gitlab.rb를 편집하고 필요한 버전을 지정합니다:postgresql['version'] = 13 -
GitLab을 재구성합니다:
sudo gitlab-ctl reconfigure -
바이너리가 다시 링크되었는지 확인합니다. PostgreSQL에 배포된 바이너리는 주요 릴리스마다 다르며, 적은 수의 잘못된 심볼릭 링크가 있는 것이 일반적입니다:
sudo ls -al /opt/gitlab/embedded/bin | grep postgres
-
-
복제본: 지정된 버전에 대해 PostgreSQL이 완전히 재초기화되었는지 확인합니다:
cd /var/opt/gitlab/postgresql sudo rm -rf data sudo gitlab-ctl reconfigure -
복제본: 선택적으로 두 개의 추가 터미널 세션에서 데이터베이스를 모니터링합니다:
-
pg_basebackup이 실행되면서 디스크 사용량이 증가합니다. 다음으로 복제본 초기화 진행 상황을 추적합니다:cd /var/opt/gitlab/postgresql watch du -sh data -
로그에서 프로세스를 모니터링합니다:
sudo gitlab-ctl tail patroni
-
-
복제본: 복제본을 재초기화하기 위해 Patroni를 시작합니다:
sudo gitlab-ctl start patroni -
복제본: 완료된 후
/etc/gitlab/gitlab.rb에서 하드코딩된 버전을 제거합니다:-
/etc/gitlab/gitlab.rb를 편집하고postgresql['version']을 제거합니다. -
GitLab을 재구성합니다:
sudo gitlab-ctl reconfigure -
올바른 바이너리가 링크되어 있는지 확인합니다:
sudo ls -al /opt/gitlab/embedded/bin | grep postgres
-
-
모든 노드에서 클러스터 상태를 확인합니다:
sudo gitlab-ctl patroni members
필요한 경우 다른 복제본에서도 이 절차를 반복합니다.
생성 중 루프에 갇힌 PostgreSQL 복제본#
PostgreSQL 복제본이 마이그레이션되는 것처럼 보이지만 루프에서 다시 시작되는 경우, 복제본 및 기본 서버의 /opt/gitlab-data/postgresql/ 폴더 권한을 확인합니다.
로그에서 다음 오류 메시지도 볼 수 있습니다:
could not get COPY data stream: ERROR: could not open file "<file>" Permission denied.
다른 구성 요소의 문제#
여기에 설명되지 않은 구성 요소에서 문제가 발생하는 경우 해당 특정 문서 페이지의 문제 해결 섹션을 확인합니다:
