구성 개요

모니터링 스택은 세 가지로 구성된다.

  • 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를 전환하면 두 서버를 각각 모니터링할 수 있다.

Grafana Node Exporter Full 대시보드

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으로 자동 차단하는 방법을 다룬다.