11.1 로그
Patroni 는 데몬으로 상시 동작하므로, 장애가 지나간 뒤 무슨 일이 있었는지 재구성할 1차 자료는 로그다. 어느 시점에 leader lock 을 잃었는지, 왜 demote 를 결정했는지는 DCS 에도 메트릭에도 남지 않고 로그에만 남는다. 로그 동작은 patroni.yml 의 log 섹션에서 제어한다.
출력 형식과 레벨
log.type 은 plain(기본)과 json 중 하나다. json 을 쓰려면 python-json-logger 패키지가 필요하다. plain 형식의 기본 포맷은 "%(asctime)s %(levelname)s: %(message)s" 이고 log.format 으로 바꾼다. json 형식에서는 format 에 문자열 대신 리스트를 주어 어떤 필드를 내보낼지 정의하고, key-value 표기로 필드 이름을 바꿔 붙일 수도 있다.
레벨은 둘로 나뉜다. log.level(기본 INFO)이 일반 로그 레벨이고, 예외 스택 트레이스를 어느 레벨로 기록할지는 log.traceback_level(기본 ERROR)이 따로 정한다. timestamp 형식은 log.dateformat 으로 조정한다.
json 전용 옵션인 log.static_fields 는 모든 레코드에 고정 필드를 추가한다. 여러 노드의 로그를 중앙 수집기로 모을 때 노드 식별자를 넣어 두면 출처 구분이 쉬워진다.
log:
type: json
level: INFO
traceback_level: ERROR
static_fields:
node: patroni-node1
loggers:
patroni.postmaster: WARNINGlog.loggers 는 모듈별 레벨 오버라이드다. 전체 레벨은 그대로 두고 유난히 소란한 모듈만 WARNING 으로 낮추거나, 추적 중인 모듈만 DEBUG 로 올리는 식으로 쓴다.
파일 로깅과 로테이션
log.dir 을 지정하면 stderr 대신 파일로 기록한다. 디렉토리는 미리 존재해야 하고 Patroni 를 실행하는 사용자가 쓸 수 있어야 한다. 파일 로깅의 기본 로테이션은 25MB 파일 4개다. 파일 크기는 log.file_size, 보관 개수는 log.file_num 으로 조정한다. log.mode 는 로그 파일 권한(예: 0644)이고, 지정하지 않으면 umask 를 따른다.
log:
dir: /var/log/patroni
file_num: 8
mode: 0644file_num 을 여유 있게 잡아 두는 편이 안전하다.비동기 로깅 큐
Patroni 의 로깅은 2단계다. 로그 레코드를 먼저 메모리 큐에 넣고, 별도의 로깅 스레드가 큐에서 꺼내 stderr 또는 파일에 쓴다. 로그 저장소의 I/O 가 느려져도 HA 루프를 도는 스레드가 쓰기에 직접 막히지 않도록 한 구조다.
flowchart TD
MAIN["Patroni 스레드"] -->|레코드 추가| Q["메모리 큐<br/>max_queue_size 1000"]
Q -->|꺼내서 기록| LT["로깅 스레드"]
LT --> OUT1["stderr"]
LT --> OUT2["log.dir 파일<br/>25MB x 4 로테이션"]
큐 크기는 log.max_queue_size 로 정하며 기본 1000 레코드다. 기본 설정 기준으로 약 1시간 20분 분량의 로그에 해당한다.
heartbeat 로그와 deduplicate_heartbeat_logs
Patroni 는 매 HA 루프마다 자신의 판단을 로그로 남긴다. 안정 상태에서는 매 loop_wait(기본 10초)마다 “leader lock 을 유지했고 할 일이 없다"는 취지의 같은 내용이 반복되므로, 로그 대부분이 이 heartbeat 로 채워진다. log.deduplicate_heartbeat_logs(기본 false)를 true 로 켜면 내용이 같은 heartbeat 로그의 반복을 억제한다.
deduplicate_heartbeat_logs 를 켜면 저장 공간을 아끼는 대신 이 타이밍 정보를 잃는다.장애 분석에서 보는 로그 패턴
로그 메시지의 정확한 문구는 버전에 따라 달라지므로, 특정 문자열을 외우기보다 패턴 단위로 보는 접근이 오래 간다. 장애 시각 전후로 보통 다음 순서로 검사한다.
- heartbeat 간격이
loop_wait를 크게 벗어난 구간이 있는지. 있다면 그 시각에 Patroni 프로세스나 호스트 자체가 정체된 것이다. - promote 또는 demote 결정이 기록된 지점과 그 직전의 판단 근거. role 전환 로그는 failover 재구성의 축이 된다.
- DCS 통신 오류와 재시도 기록. leader lock 갱신 실패로 이어졌다면 시나리오 A의 전개를 따라간다.
json 로깅을 쓰면 이 검사를 수집기 쿼리로 대신할 수 있다.
정리
- 로그 동작은
log섹션 하나로 제어한다.type(plain/json),level과traceback_level,format, json 전용static_fields, 모듈별loggers오버라이드가 있다. dir을 지정하면 파일 로깅으로 전환되고 기본 25MB x 4 로테이션이 적용된다.file_size,file_num,mode로 조정한다.- 로깅은 메모리 큐(기본 1000 레코드)와 별도 스레드를 거치는 비동기 구조다.
- heartbeat 로그의 timestamp 간격은 HA 루프 타이밍의 진단 자료다.
deduplicate_heartbeat_logs는 이 정보와 저장 공간을 맞바꾸는 설정이다.