pgcat+Patroni TCP keepalive 적용: 좀비 소켓 방지 (Step 1 옵션 B)
This commit is contained in:
93
history/2026-04-16-pgcat-patroni-tcp-keepalive.md
Normal file
93
history/2026-04-16-pgcat-patroni-tcp-keepalive.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
---
|
||||||
|
date: 2026-04-16
|
||||||
|
topic: pgcat + Patroni TCP keepalive 적용 (Step 1 옵션 B)
|
||||||
|
areas:
|
||||||
|
- infra/postgresql-ha.md
|
||||||
|
tags: [history, pgcat, patroni, postgresql, tcp-keepalive]
|
||||||
|
---
|
||||||
|
|
||||||
|
Patroni multi-host 마이그레이션 원래 Step 1 계획(pgcat Patroni REST API 연동)이 소스 재조사 결과 **pgcat 1.2.0 에 해당 기능 미존재** 판정 → kappa 결정에 따라 옵션 B(HAProxy 구조 유지 + TCP keepalive 추가)로 선회.
|
||||||
|
|
||||||
|
## 배경
|
||||||
|
|
||||||
|
2026-04-15 19:53 UTC Patroni TL5→6 재선출 후 n8n 이 24h 동안 1038건 "Database connection timed out" 에러. 조사 결과 n8n TypeORM 풀의 단일 소켓이 failover 2분 전 열린 채 7588초간 idle 유지 → pgcat 까지 요청 도달조차 못하는 좀비 상태 (`230ec530-b8a6-406c-9165-35c9eb2d8282` 조사 문서).
|
||||||
|
|
||||||
|
n8n rollout restart 로 즉시 정상화. 재발 방지를 위해 **pgcat 와 Patroni 양쪽에 TCP keepalive 명시 활성화**.
|
||||||
|
|
||||||
|
## 변경 내용
|
||||||
|
|
||||||
|
### helm-charts (commit `7ebd7e3`)
|
||||||
|
|
||||||
|
`values/pgcat.yaml` `configMaps.pgcat-config.pgcat.toml` `[general]` 섹션:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
tcp_keepalives_idle = 60
|
||||||
|
tcp_keepalives_interval = 10
|
||||||
|
tcp_keepalives_count = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
pgcat 1.2.0 에서 실제로 지원하는 정확한 키명 (`pgcat.toml` 예제 파일 및 `src/config.rs` 확인). 서버 소켓에 적용.
|
||||||
|
|
||||||
|
### Patroni (DCS)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
patronictl -c /etc/patroni.yml edit-config \
|
||||||
|
-p tcp_keepalives_idle=60 \
|
||||||
|
-p tcp_keepalives_interval=10 \
|
||||||
|
-p tcp_keepalives_count=3 --force
|
||||||
|
patronictl reload nocodb-cluster --force
|
||||||
|
```
|
||||||
|
|
||||||
|
3노드 전체 postgresql.conf 에 반영, SIGHUP 으로 적용 (재시작 불필요). 새 TCP 연결부터 keepalive 옵션 적용.
|
||||||
|
|
||||||
|
**주의**: `SHOW tcp_keepalives_idle` 을 unix socket (psql local) 에서 실행하면 0으로 출력. TCP 세션 확인 필수:
|
||||||
|
```bash
|
||||||
|
PGPASSWORD=... psql -h 192.168.9.1 -p 5432 -U n8n -d n8n -c "SHOW tcp_keepalives_idle"
|
||||||
|
# → 60
|
||||||
|
```
|
||||||
|
|
||||||
|
## 검증 — Patroni switchover 재현 테스트
|
||||||
|
|
||||||
|
**before**: TL6 leader postgres-3 (10.100.1.83)
|
||||||
|
**action**: `patronictl switchover --leader postgres-3 --candidate postgres-2 --force`
|
||||||
|
**after**: TL7 leader postgres-2 (10.100.3.185)
|
||||||
|
|
||||||
|
### pgcat → 새 leader 도달 시간
|
||||||
|
|
||||||
|
```
|
||||||
|
T1=22:24:37.696 UTC switchover 커맨드 반환
|
||||||
|
t+0002ms pgcat 경유 SELECT → "connection lost" (HAProxy 아직 구 leader 마크)
|
||||||
|
t+5175ms 여전히 connection lost
|
||||||
|
t+7331ms 10.100.1.83 응답 (구 leader, 이제 replica — SELECT 는 성공)
|
||||||
|
t+8461ms 10.100.3.185 응답 (새 leader)
|
||||||
|
```
|
||||||
|
|
||||||
|
**write 가능 복구 시간: ~8.5초.** HAProxy `inter 3s fall 3` (9초 감지) 이론치와 일치. keepalive 와 독립 — HAProxy 헬스체크 파라미터가 결정.
|
||||||
|
|
||||||
|
### 애플리케이션 영향 (switchover 전후 ~150초 창)
|
||||||
|
|
||||||
|
| 서비스 | 에러 수 | 타입 |
|
||||||
|
|---|---|---|
|
||||||
|
| NocoDB | 1 | "unexpected EOF" 1회 |
|
||||||
|
| n8n | 9 건 (7초 윈도우) | SocketError/UnexpectedEof, Connection terminated, AllServersDown, Database connection timed out |
|
||||||
|
|
||||||
|
**이전 2026-04-15 failover (1038건, 2시간 지속) 대비 극적 대비.** 좀비 소켓 없음.
|
||||||
|
|
||||||
|
## 롤백
|
||||||
|
|
||||||
|
- `values/pgcat.yaml` 에서 `tcp_keepalives_*` 3줄 제거 → ArgoCD sync → pgcat rolling restart
|
||||||
|
- Patroni: `patronictl edit-config` 에서 동일 3개 파라미터 제거 → reload
|
||||||
|
|
||||||
|
## 관측 기간
|
||||||
|
|
||||||
|
7일 (2026-04-23까지). 다음 Patroni failover 발생 시 app 에러 윈도우 < 10초 지속 여부 확인. 지속 시 원인 재조사.
|
||||||
|
|
||||||
|
## 관련 문서
|
||||||
|
|
||||||
|
- `infra/postgresql-ha.md` — 「좀비 소켓 방지 — TCP keepalive」 섹션 신설
|
||||||
|
- `history/2026-04-16-pgcat-patroni-api-audit-correction.md` — (별도 예정) pgcat Patroni API 미지원 정정, 원 감사 07497dd8 의 PR #944 cite 오류
|
||||||
|
- helm-charts commit: https://gitea.inouter.com/kaffa/helm-charts/commit/7ebd7e3
|
||||||
|
|
||||||
|
## 후속
|
||||||
|
|
||||||
|
- kappa 지시: **PgPool-II PoC** (이 작업 안정화 후 별도 지시 예정)
|
||||||
@@ -149,7 +149,29 @@ servers = [["192.168.9.1", 5432, "primary"]]
|
|||||||
|
|
||||||
pgcat는 풀링 전용으로만 쓰고, leader 탐지는 OpenWrt HAProxy에 위임. `query_parser_enabled = false` 설정 (read/write splitting 비활성).
|
pgcat는 풀링 전용으로만 쓰고, leader 탐지는 OpenWrt HAProxy에 위임. `query_parser_enabled = false` 설정 (read/write splitting 비활성).
|
||||||
|
|
||||||
Patroni failover 인시던트 이력: [[../history/2026-04-08-patroni-failover-incident|2026-04-08 pgcat/nocodb/outline read-only 사고]]
|
### 좀비 소켓 방지 — TCP keepalive
|
||||||
|
|
||||||
|
Patroni failover 시 pgcat↔backend 및 client↔pgcat TCP 소켓이 반쪽만 끊어진 채 애플리케이션 풀이 계속 붙잡는 현상을 방지하기 위해 양쪽 모두 TCP keepalive 활성화.
|
||||||
|
|
||||||
|
**pgcat (`db/pgcat-config` `[general]`)**:
|
||||||
|
```toml
|
||||||
|
tcp_keepalives_idle = 60
|
||||||
|
tcp_keepalives_interval = 10
|
||||||
|
tcp_keepalives_count = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
**Patroni (`postgresql.parameters` via `patronictl edit-config -p`)**:
|
||||||
|
```
|
||||||
|
tcp_keepalives_idle = 60
|
||||||
|
tcp_keepalives_interval = 10
|
||||||
|
tcp_keepalives_count = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
동작: 60s idle 후 keepalive probe 전송, 10s 간격으로 3회 재전송 실패 시 커넥션 종료. 최대 감지 시간 **90초**. pgcat 는 서버 측에, Patroni 는 클라이언트(= pgcat 소켓) 측에 각각 설정 — 어느 쪽에서 먼저 죽음을 감지해도 소켓이 정리됨.
|
||||||
|
|
||||||
|
검증: 2026-04-16 switchover 테스트(postgres-3→postgres-2, TL6→7) 기준 n8n 에러 윈도우 7초·9건으로 한정 ([[../history/2026-04-16-pgcat-patroni-tcp-keepalive|history]]). 이전 2026-04-15 19:53 UTC failover 시 1038건과 극적 대비.
|
||||||
|
|
||||||
|
Patroni failover 인시던트 이력: [[../history/2026-04-08-patroni-failover-incident|2026-04-08 pgcat/nocodb/outline read-only 사고]] · [[../history/2026-04-15-pgcat-ha-promotion|2026-04-15 pgcat HA 승격 Step 0]]
|
||||||
|
|
||||||
## APISIX etcd 사용 현황
|
## APISIX etcd 사용 현황
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user