※ PostgreSQL: Managing Parameter Changes in a Patroni Cluster.
안녕하세요. 듀스트림입니다.
요즘은 뭔가 테스트를 하고 싶어도 시간이 없어서 못하는 거 같아요.
7시반 출근 → 21시 퇴근 → 22시 반 집도착 → 씻고 자고 반복~
오늘 주제는 Patroni Cluster 운영 시 꼭 알아야 되는 내용인 Patroni Cluster를 운영 시, DB 파라미터 변경 방법입니다. (Patroni 공식 문서)
PostgreSQL 단독 인스턴스나 다른 HA 도구라면 postgresql.conf 수정 + Reload 또는 Restart로 파라미터를 적용하면 됩니다.
하지만 Patroni로 HA Cluster를 운영 중이라면 이야기가 완전히 달라집니다.
postgresql.conf를 직접 수정하면 Patroni와 설정 소스가 꼬이고, 노드별 설정이 서로 달라지면서 이상 동작이 나올 수 있습니다.
1. Patroni 설정 구조 이해하기
Patroni에서 설정은 크게 세 군데에 흩어져 있습니다.
- Global Dynamic Configuration (DCS)
- etcd / Consul / ZooKeeper / Kubernetes 등 DCS에 저장되는 클러스터 전체 설정입니다.
- bootstrap.dcs 섹션에서 초기값을 넣고, 이후에는 patronictl edit-config 나 REST API로 변경합니다.
- postgresql.parameters 에 들어가는 값이 바로 PostgreSQL GUC 파라미터입니다.
- Local Configuration (patroni.yml)
- 각 노드 로컬에 있는 Patroni 설정 파일입니다.
- 클러스터 ID(scope), DCS 접속 정보, 로그 설정, REST API 포트, PostgreSQL 기본 파라미터 등 노드 로컬 설정을 정의합니다.
- 중요:
- 동일한 키가 DCS와 patroni.yml 양쪽에 존재하면, 로컬 patroni.yml 값이 우선합니다.
- 즉, patroni.yml 에 shared_buffers: 1GB가 있으면, edit-config 로 2GB를 넣어도 실제 적용은 1GB가 될 수 있습니다.
- PostgreSQL 자체 설정 (ALTER SYSTEM, postgresql.conf, 환경변수)
- Patroni가 올려준 Postgres에 대해 DBA가 직접 ALTER SYSTEM을 하거나 postgresql.conf를 건드리는 것.
- 이 설정들은 Patroni 관리 설정(DCS/patroni.yml)과 우선순위 싸움을 할 수 있습니다.
운영 정책상 "Source of Truth"를 DCS로 두고 싶다면, PostgreSQL 파라미터는 patronictl edit-config로만 관리하고 patroni.yml에는 중복되는 GUC를 넣지 않는 것이 깔끔합니다.
2. 파라미터 변경은 "클러스터 단위"가 원칙
"변경은 모든 노드를 다해줘야 할까?" 라는 고민을 할 수도 있습니다. (처음에는 저도 그랬습니다.)
Patroni 구조에서,
- DCS의 Dynamic Configuration은 "Global"입니다.
- patronictl edit-config로 바꾸면 모든 클러스터 노드에 적용됩니다.
아시다시피,
- ALTER SYSTEM, postgresql.conf 직접 수정은 "해당 노드에만 적용"이고, 나머지 노드는 DCS에서 내려준 값 그대로 유지됩니다.
그래서 권장 패턴은,
- 클러스터 전체에 공통으로 적용할 값
→ patronictl edit-config 사용 (DCS에 반영) - 노드별로 달라야 하는 값 (예: 데이터 경로, 로컬 디스크 경로 등)
→ patroni.yml 또는 환경변수로 노드 로컬 설정
3. patronictl edit-config 기본 사용법
공식 문서 기준 patronictl edit-config의 시그니처는 다음과 같습니다.
patronictl -c /path/to/patroni.yml edit-config [CLUSTER_NAME] \
[ -s CONFIG="VALUE" ... ] \
[ -p PG_CONFIG="PG_VALUE" ... ] \
[ --apply CONFIG_FILE | --replace CONFIG_FILE ] \
[ --force ]
여기서 중요한 옵션은 두 가지입니다.
3.1 -p / --pg : PostgreSQL 파라미터 직접 지정
- -p / --pg는 PostgreSQL GUC 파라미터만 편하게 넣는 용도입니다.
- 내부적으로는 postgresql.parameters.<파라미터>=<값> 형태로 DCS에 저장됩니다.
# max_connections 값을 200으로 변경
patronictl -c /postgres/etc/patroni.yml \
edit-config patroni-cluster \
--pg max_connections=200 \
--force
3.2 -s / --set : DCS YAML 경로를 직접 지정
DCS 전체 YAML 트리의 특정 경로를 지정해서 값 설정도 가능합니다.
# loop_wait, ttl 같은 Patroni 운영 파라미터 변경
patronictl -c /postgres/etc/patroni.yml \
edit-config patroni-cluster \
--set loop_wait=5 \
--set ttl=20 \
--force
- PostgreSQL GUC 파라미터도 --set postgresql.parameters.max_connections=200 처럼 DCS 기반 변경이 가능합니다.
(GUC만 바꿀 때는 --pg가 훨씬 간단합니다.)
patronictl edit-config --set 으로 변경되는 항목은 Patroni의 DCS(분산 설정 저장소: etcd/consul/zookeeper)에 저장되는 Patroni 수준의 동적 설정(Dynamic Configuration) 입니다.
즉, PostgreSQL 설정 파일(postgresql.conf)이 아니라, Patroni 클러스터 관리 로직과 작동 주기를 제어하는 파라미터들입니다.
4. 변경 적용 방식: reload vs restart
Patroni 문서 기준 Dynamic Configuration 변경은 다음과 같이 동작합니다.
- patronictl edit-config → DCS에 설정 저장
- 각 Patroni 노드가 loop(Default 10s)마다 DCS를 읽어 차이를 감지
- 변경된 값이
- reload로 적용 가능한 파라미터라면, pg_reload_conf() 호출로 반영
- 재시작 필요한 파라미터라면, 설정은 저장되지만, patronictl list에 Pending restart 컬럼이 *로 표시
- 재시작이 필요한 파라미터는 관리자가 patronictl restart 로 리더/레플리카를 적절한 순서로 재시작
아래 Percona 블로그 예제를 보면 work_mem(reload 가능)과 wal_level(restart 필요) 변경 시 동작을 잘 보여줍니다.
Administering a Patroni Managed PostgreSQL Cluster
Discover how to effectively administer a Patroni managed PostgreSQL cluster, ensuring high availability and robust performance.
www.percona.com
5. patroni.yml 파라미터
- bootstrap.dcs
- 클러스터 초기 부팅 시 DCS에 써 넣을 기본값.
- 이후에는 edit-config로만 변경하는 것을 권장.
- Local patroni.yml (postgresql.parameters 섹션)
- 변경 후 SIGHUP 또는 patronictl reload로 재적용 가능.
- DCS의 동일 키보다 우선순위가 높음.
- 즉, DCS에서 max_connections=300인데, patroni.yml에 max_connections=100이 있으면 실제 적용은 100일 수 있습니다.
그래서 운영 패턴을 보통 이렇게 잡습니다:
- 초기 클러스터 부팅 전
- bootstrap.dcs.postgresql.parameters 에 기본값을 정의.
- 운영 중
- GUC 변경은 무조건 patronictl edit-config 로만 변경.
- patroni.yml에서는 GUC 중복 정의를 최대한 제거.
6. 테스트
초기 클러스터 상태입니다.

6.1 reload-only 파라미터 변경
patronictl -c /postgres/etc/patroni.yml edit-config patroni-cluster --pg log_lock_waits=off --force

6.2 재시작이 필요한 파라미터 변경
patronictl -c /postgres/etc/patroni.yml edit-config patroni-cluster --pg wal_level='logical' --force
아래 처럼 Pending restart reason에 표시됩니다.

이후 rolling으로 재시작을 해주시면 됩니다.
1. Replica부터 재시작
# replica만 재시작
patronictl -c /postgres/etc/patroni.yml restart patroni-cluster --role=replica

2. 트래픽 저감/정지 후 leader 재시작 (또는 스위치오버)
# 스위치오버
patronictl -c /postgres/etc/patroni.yml switchover patroni-cluster
# 특정 노드 재시작
patronictl -c /postgres/etc/patroni.yml restart patroni-cluster node01
# 전체 노드 재시작
patronictl -c /postgres/etc/patroni.yml restart patroni-cluster

6.3 patroni.yml 중복 정의로 인한 미적용 케이스
1. patroni.yml에 아래처럼 정의되어 있다고 가정
postgresql:
parameters:
shared_buffers: 1GB
work_mem: 4MB
2. edit-config 로 shared_buffers 변경
patronictl -c /postgres/etc/patroni.yml edit-config patroni-cluster --pg shared_buffers=2GB --force
3. Patroni 로그를 보면 "Reloading PostgreSQL configuration" 로그가 나오지만, SHOW shared_buffers; 결과는 여전히 1GB
4. 원인
- DCS에는 shared_buffers: 2GB가 들어갔지만,
- patroni.yml에 정의된 shared_buffers: 1GB가 우선순위가 더 높아서 실제 적용은 1GB.
5. 해결 방법
- patroni.yml에서 shared_buffers 항목을 삭제하거나 주석 처리
- Patroni 프로세스에 SIGHUP 또는 patronictl reload 수행 후
patronictl -c /postgres/etc/patroni.yml reload patroni-cluster
- 다시 edit-config로 값을 조정
6. 이후 SHOW shared_buffers; 값이 DCS 값(2GB)으로 반영되는지 확인
7. 정리
Patroni 클러스터에서 PostgreSQL 파라미터를 변경할 때 핵심 포인트는 다음과 같습니다.
- 클러스터 공통 값은 patronictl edit-config로만 관리
- --pg 옵션을 이용해 GUC를 설정하면 DCS에 저장되고, 모든 노드가 loop 주기마다 설정을 받아 적용합니다.
- reload vs restart 구분
- work_mem, log_min_duration_statement 등은 reload로 바로 적용.
- max_connections, shared_buffers, wal_level 등은 재시작이 필요하며, Pending restart 컬럼에서 확인할 수 있습니다.
- patroni.yml
- patroni.yml 의 postgresql.parameters는 DCS보다 우선 적용됩니다.
- DCS를 " Source of Truth"로 쓰려면, GUC는 patroni.yml에서 제거하고 edit-config로만 관리하는 것이 깔끔합니다.
- 테스트는 반드시 별도 환경에서
- 본문에 적은 테스트 시나리오를 테스트/QA 클러스터에서 먼저 검증한 뒤 운영에 적용해야 합니다.
오늘은 여기까지~
'PostgreSQL' 카테고리의 다른 글
| PostgreSQL: pg_mooncake (0) | 2025.12.24 |
|---|---|
| PostgreSQL: PgBouncer (0) | 2025.12.17 |
| PostgreSQL: SELECT 효율 분석 (0) | 2025.11.21 |
| PostgreSQL: DISTINCT ON (0) | 2025.11.19 |
| PostgreSQL: 스트리밍 복제 지연 (0) | 2025.11.12 |