구성 개요
모니터링 스택은 세 가지로 구성된다.
- Prometheus — 메트릭 수집 및 저장
- Grafana — 대시보드 시각화
- Node Exporter — 서버 시스템 메트릭 노출 (CPU, RAM, 디스크, 네트워크 등)
Prometheus와 Grafana는 홈서버에서 Docker로 실행하고, Node Exporter는 홈서버와 OCI 서버 양쪽에 systemd로 설치했다. 두 서버가 Tailscale VPN으로 연결돼 있으니 Prometheus가 VPN을 통해 OCI 메트릭도 수집할 수 있다.

| 서비스 | 포트 |
|---|---|
| Prometheus | 19090 |
| Grafana | 13000 |
| Node Exporter | 19100 |
1. 디렉토리 생성
mkdir ~/monitoring && cd ~/monitoring
2. docker-compose.yml 작성
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
ports:
- "19090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
ports:
- "13000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=your_password_here
- GF_SERVER_ROOT_URL=http://100.109.108.36:13000
volumes:
prometheus_data:
grafana_data:
version: "3.8"은 Docker Compose v2부터 obsolete라 생략했다. 넣어도 동작하지만 경고가 뜬다.
3. prometheus.yml 작성
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'thinkpad'
static_configs:
- targets: ['100.109.108.36:19100']
labels:
instance: 'thinkpad-homeserver'
- job_name: 'oci'
static_configs:
- targets: ['<OCI_Tailscale_IP>:19100']
labels:
instance: 'oci-server'
OCI 서버의 Tailscale IP는 OCI에서 아래 명령으로 확인한다.
tailscale ip -4
4. Node Exporter 설치 (홈서버 + OCI 공통)
두 서버 모두 동일하게 진행한다.
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
tar xf node_exporter-1.8.2.linux-amd64.tar.gz
sudo cp node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/
sudo chmod +x /usr/local/bin/node_exporter
systemd 서비스로 등록한다.
sudo tee /etc/systemd/system/node_exporter.service << 'EOF'
[Unit]
Description=Node Exporter
After=network.target
[Service]
Type=simple
User=nobody
ExecStart=/usr/local/bin/node_exporter --web.listen-address=":19100"
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporter
정상 동작 확인:
sudo systemctl status node_exporter
# active (running) 이 뜨면 성공
status=203/EXEC에러가 나는 경우 바이너리 복사가 안 된 것이므로 설치 단계부터 다시 진행한다.
5. OCI 방화벽 설정
OCI 서버에서 Node Exporter 포트를 Tailscale 인터페이스에서만 허용한다. 외부에 열면 안 된다.
sudo ufw allow in on tailscale0 to any port 19100
sudo ufw deny 19100
6. 컨테이너 시작
cd ~/monitoring
docker compose up -d
docker compose ps
7. Grafana 초기 설정
브라우저에서 http://100.109.108.36:13000 접속.
초기 계정은 admin이고 비밀번호는 docker-compose.yml에 설정한 GF_SECURITY_ADMIN_PASSWORD 값이다.
볼륨이 이미 생성된 상태에서 환경변수를 바꿔도 적용이 안 된다. 볼륨을 삭제하고 재시작해야 한다.
docker compose down docker volume rm monitoring_grafana_data docker compose up -d
Prometheus 데이터소스 연결
Connections → Data sources → Add data source → Prometheus
URL에 http://prometheus:9090 입력 후 Save & test.
- 컨테이너 이름으로 통신하므로 IP 대신 서비스 이름 사용
- 포트는 컨테이너 내부 포트인
9090(외부 포트19090아님)
Successfully queried the Prometheus API 가 뜨면 성공이다.
대시보드 Import
Dashboards → Import 에서 ID 1860 입력 후 Load.
Prometheus 데이터소스를 선택하고 Import하면 Node Exporter Full 대시보드가 추가된다. 상단 Job 드롭다운에서 thinkpad / oci를 전환하면 두 서버를 각각 모니터링할 수 있다.


8. 배터리 메트릭 수집 (ThinkPad 전용)
ThinkPad는 배터리가 있으니 powersupplyclass 컬렉터를 추가로 활성화했다.
sudo vi /etc/systemd/system/node_exporter.service
ExecStart 줄 수정:
ExecStart=/usr/local/bin/node_exporter --web.listen-address=":19100" --collector.powersupplyclass
sudo systemctl daemon-reload
sudo systemctl restart node_exporter
수집 확인:
curl http://localhost:19100/metrics | grep power_supply
수집되는 주요 메트릭:
| 메트릭 | 내용 |
|---|---|
node_power_supply_capacity |
배터리 잔량 (%) |
node_power_supply_online |
어댑터 연결 여부 (1=연결, 0=미연결) |
node_power_supply_power_watt |
현재 소비 전력 (W) |
node_power_supply_cyclecount |
배터리 충방전 횟수 |
Grafana 배터리 패널 추가
Dashboards → Edit → Add → Visualization
- Visualization: Gauge
- 쿼리:
node_power_supply_capacity - Standard options → Unit:
Percent (0-100) - Min:
0, Max:100 - Title:
Battery
접근 방식
Grafana와 Prometheus는 Portainer와 마찬가지로 외부에 열지 않고 Tailscale VPN 안에서만 접근한다.
Grafana → http://100.109.108.36:13000 (Tailscale VPN)
Prometheus → http://100.109.108.36:19090 (Tailscale VPN)
모니터링 툴을 외부에 노출하면 서버 내부 정보가 그대로 보이기 때문이다.
정리
- Node Exporter를 두 서버에 설치하고 Prometheus가 Tailscale VPN으로 수집하는 구조
- OCI의 Node Exporter 포트는 Tailscale 인터페이스에서만 허용할 것
- Grafana 데이터소스 URL은 컨테이너 서비스 이름(
prometheus:9090)으로 설정 - ThinkPad는
--collector.powersupplyclass옵션으로 배터리 메트릭도 수집 가능
다음 편에서는 OCI 서버 auth.log에 쌓인 SSH 브루트포스 공격을 Fail2ban으로 자동 차단하는 방법을 다룬다.