3.2 설치와 최소 권한
Exporter는 database 내부 상태를 읽고 network에 노출합니다. 설치보다 먼저 권한, secret, network 경계를 정해야 합니다.
Monitoring role
PostgreSQL 10 이상에서는 전용 login role에 pg_monitor를 부여하는 구성이 출발점입니다.
CREATE ROLE postgres_exporter
LOGIN
PASSWORD 'replace-with-secret'
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
INHERIT;
GRANT CONNECT ON DATABASE postgres TO postgres_exporter;
GRANT pg_monitor TO postgres_exporter;
pg_monitor는 pg_read_all_settings, pg_read_all_stats, pg_stat_scan_tables 권한을 포함합니다. 통계 view를 읽기 위해 superuser를 주는 방식은 피합니다.
Role에 search path도 명시합니다.
ALTER ROLE postgres_exporter
SET search_path = pg_catalog, public;
public은 pg_stat_statements를 설치한 schema의 예시입니다. 다른 schema에 설치했다면 그 신뢰된 schema로 바꾸고 USAGE 권한을 부여합니다. stat_statements collector가 pg_stat_statements를 schema 없이 조회하므로 extension schema가 search_path에 있어야 합니다. Custom function을 SECURITY DEFINER로 만들어 metric을 노출한다면 고정된 search_path, 함수 owner, 실행 권한을 별도로 검토해야 합니다. 이 노트에서는 built-in collector를 우선 사용합니다.
Connection 정보 분리
Exporter는 URI, user, password를 별도 환경변수나 file로 받도록 지원합니다.
export DATA_SOURCE_URI='db.internal:5432/postgres?sslmode=require'
export DATA_SOURCE_USER='postgres_exporter'
export DATA_SOURCE_PASS_FILE='/run/secrets/postgres_exporter_password'
exec postgres_exporter
Password를 process argument나 URI에 직접 넣으면 process 목록, shell history, deployment manifest에 남을 수 있습니다. Container에서는 secret volume과 DATA_SOURCE_PASS_FILE을 사용합니다.
PostgreSQL TLS
Network를 건너 database에 접속한다면 sslmode=verify-full과 신뢰할 CA를 사용합니다.
db.internal:5432/postgres?sslmode=verify-full&sslrootcert=/etc/ssl/db-ca.crt
require는 암호화는 요구하지만 server 인증을 완전히 검증하지 않습니다. 운영에서 가능한 경우 hostname 검증까지 포함합니다.
Metrics endpoint 보호
기본 endpoint는 :9187/metrics입니다. Metric에는 database 이름, role, 설정값, workload 패턴처럼 공격자에게 유용한 정보가 포함될 수 있습니다.
- 9187은 Prometheus network에서만 접근하도록 firewall이나 NetworkPolicy를 적용합니다.
- exporter-toolkit의 web config는 TLS와 basic authentication 설정을 지원합니다.
- 인터넷이나 사용자 VLAN에 직접 노출하지 않습니다.
- Prometheus에서 exporter 방향의 연결만 허용합니다.
Kubernetes NetworkPolicy 예시는 다음과 같습니다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-prometheus-to-postgres-exporter
spec:
podSelector:
matchLabels:
app: postgres-exporter
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
ports:
- protocol: TCP
port: 9187
배포 위치 선택
| 방식 | 장점 | 주의점 |
|---|---|---|
| DB host의 systemd service | network 경로가 짧음 | host lifecycle과 함께 관리 |
| PostgreSQL Pod sidecar | instance와 함께 배포 | Pod 자원/upgrade 결합 |
| 중앙 exporter | managed DB에 편리 | multi-target beta/장애 집중 |
Exporter를 database마다 둘 때도 Prometheus의 instance label이 실제 DB 정체성을 일관되게 표현하도록 relabeling합니다.
설치 후 security check
SELECT rolname, rolsuper, rolcreaterole, rolcreatedb
FROM pg_roles
WHERE rolname = 'postgres_exporter';
ss -lntp | grep 9187
curl -fsS http://127.0.0.1:9187/metrics | grep '^pg_up'
운영 전에는 credential rotation 절차와 exporter 장애 시 영향도 함께 문서화합니다. Exporter 장애가 PostgreSQL 장애로 잘못 page되지 않도록 up과 pg_up을 분리해 봅니다.
참고: PostgreSQL predefined roles, Exporter non-superuser configuration