홈 서버에 Prometheus + Grafana 모니터링 스택 올리기
집에 미니PC 한 대를 굴리고 있다. 근데 이게 지금 잘 돌고 있는건지 아닌지 알 방법이 없었다. CPU가 언제 튀는지, 디스크가 언제 차는지, 컨테이너가 죽었는지 살았는지... 다 터지고 나서야 아는 식이었음 감으로 서버 굴리는게 영 찝찝해서 일단 눈으로 볼 수 있게 만들기로 햇다.
전부 Docker Compose로 묶었다. 설정을 파일로 남겨둬야 나중에 서버 다시 세울 일이 생겨도 그대로 복구가 된다.
뭘 올렸나
- Prometheus -> 지표 수집, 저장. 보존기간은 30일로 잡았음
- Grafana -> 그 지표를 대시보드로 본다
- Alertmanager -> 알림 라우팅. 나는 Discord로 받게 했음
- node_exporter -> 호스트 하드웨어랑 OS 지표
- cAdvisor -> 컨테이너별 리소스
- 서비스 몇 개는 헬스체크용 exporter를 따로 붙였음
일단 밖에서 안 보이게
홈 서버는 인터넷에 노출되는 순간부터 골치 아파진다. 그래서 Grafana나 Prometheus를 0.0.0.0에 안 열고 WireGuard VPN 인터페이스에만 바인딩했다.
grafana:
ports:
- "10.100.0.1:3000:3000" # VPN IP에만
이러면 VPN에 붙어야만 대시보드가 열린다. 방화벽(UFW)도 VPN 인터페이스에서 오는 트래픽만 허용하게 해뒀다. 서버 지켜보려고 올린 도구 때문에 서버가 더 노출되면 그건 좀 웃기니까...
문서만 봐선 모르는 것들
세팅하면서 몇 번 막혔다.
Alertmanager가 자꾸 재시작을 반복했다. 로그를 보니 no private IP address found. 노드가 하나뿐인데 gossip 클러스터를 켜려다 IP를 못 찾고 죽는 거였음 --cluster.listen-address= 를 빈 값으로 줘서 클러스터 기능을 꺼버리니 해결됏다. 어차피 단일 노드라 필요 없다.
Discord webhook도 한참 헤맸다. 알림이 안 오길래 봤더니 Alertmanager 컨테이너 uid가 webhook 파일을 못 읽고 있었다. 근데 에러도 안 뱉고 조용히 실패해서 원인 찾는데 시간 좀 걸렸다... 파일 644, 디렉토리 755로 맞춰주니 됐음
Grafana는 데이터소스 UID 때문에 크래시가 났다. 기존 볼륨에 자동생성된 UID가 남아있는데 uid: prometheus 로 고정 프로비저닝을 하니 충돌한 거였다. 볼륨 새로 초기화해서 넘어갔다.
그래서
이제 서버가 이상해지면 Discord로 먼저 알림이 온다. 대시보드 하나에 하드웨어, 컨테이너, 서비스 상태가 다 모여있어서 뭔가 싸하면 바로 볼 수 있음
다음엔 이 서버가 실제로 털렸던 얘기를 정리해보려고 한다.