🍥

PrometheusとGrafanaでホストとコンテナのリソースを可視化してみた

に公開

はじめに

複数のコンテナサービスのリソースを監視するため、以下のコンポーネントを利用してダッシュボードで表示します。コンテナを利用した監視系サービスを構築したことが無かったので、初学者向けに、ダッシュボードで可視化するまでのクイックスタートを本記事で紹介します。

コンポーネント 概要
Prometheus メトリクスを収集し、時系列データとして保存する監視基盤
Node Exporter ホスト(コンテナを稼働させているOS側)のメトリクスを取得・表示するエージェント
cAdvisor Dockerコンテナ単位のリソース使用状況メトリクスを収集・表示するコンポーネント
Grafana 収集されたメトリクスを可視化するためのダッシュボードUIツール

想定読者

  • Docker は触ったことがあるが、監視はこれからの初学者
  • 「ホスト資源(CPU/メモリ/ディスク/ネットワーク)と各コンテナの使用状況を可視化したい」
  • まずはメトリクス監視から始めたい
  • 構成をファイル管理(IaC)したい

ゴール

  1. docker-compose up -d だけで Prometheus / Node Exporter / cAdvisor / Grafana が起動
  2. ダッシュボードテンプレートを利用してダッシュボードを表示
  3. ホストのリソース & コンテナの状況がダッシュボードで確認

0. 動作環境

項目 バージョン
OS Ubuntu 22.04 LTS
Docker 28.5.2
Docker Compose 3.9
ネットワーク 社内ネットワーク
外部へHTTP(S) 到達できること
プロキシ HTTP/HTTPS を必ず経由

1. 全体構成

[ Host OS ]
  ├─ docker-compose.yml
  ├─ prometheus/
  │    └─ prometheus.yml
  ├─ grafana/
  │    ├─ provisioning/
  │    │     ├─ datasources/
  │    │     │    └─ prometheus.yml
  │    │     └─ dashboards/
  │    │          ├─ dashboards.yml
  │    │          └─ <任意のダッシュボードテンプレート>.json
  │    ├─ grafana.ini
  │    └─ .env
  └─ certs/ (プロキシ環境下など証明書対応が必要な場合)
  
         ↓ (Docker network内部通信)
  +------------------------------+
  |  prometheus  |  node-exporter|
  |  cadvisor    |  grafana      |
  +------------------------------+

2. ファイル構成

以下のファイルを用意します。

docker-compose.yml

version: "3.9"

services:
  prometheus:
    image: prom/prometheus:v3.7.3  # imageのバージョンは最新を指定
    container_name: prometheus
    restart: unless-stopped
    volumes:
      # 設定ファイルをコンテナ内へ読み取り専用マウント
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro  
      # 時系列データベースの永続化
      - prometheus-data:/prometheus
    command:
      # 設定ファイルを指定
      - '--config.file=/etc/prometheus/prometheus.yml'
      # データの保持期間
      - '--storage.tsdb.retention.time=15d'
      - '--storage.tsdb.retention.size=10GB'
    ports:
      - "9090:9090"
    networks:
      - monitor

  node-exporter:
    image: prom/node-exporter:v1.10.2
    container_name: node-exporter
    restart: unless-stopped
    ports:
      - "9100:9100"

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.49.1
    container_name: cadvisor
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro               # ホストファイルシステム情報
      - /var/run:/var/run:ro       # Docker ソケットや cgroup 関連
      - /sys:/sys:ro               # CPU/メモリなどシステム情報
      - /var/lib/docker/:/var/lib/docker:ro # コンテナレイヤ情報
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /dev/kmsg:/dev/kmsg:ro
    networks:
      - monitor

  grafana:
    image: grafana/grafana:12.4.0-19363970803
    container_name: grafana
    restart: unless-stopped
    env_file:
      - grafana/.env
    volumes:
      # Dashboards/ユーザ設定永続化
      - grafana-data:/var/lib/grafana                     
      # DataSource / Dashboard 自動プロビジョニング
      - ./grafana/provisioning:/etc/grafana/provisioning  
      # 設定ファイル
      - ./grafana/grafana.ini:/etc/grafana/grafana.ini:ro
      # TLS証明書 (必要な場合のみ)
      - ./certs:/certs:ro                                 
    ports:
      - "3000:3000"
    networks:
      - monitor

networks:
  monitor:
    driver: bridge

# 匿名ボリュームではなく名前付きでライフサイクルを管理しやすく
volumes:
  prometheus-data:         
  grafana-data:

prometheus/prometheus.yml

Prometheusと何を連携させるかを記述します。今回はprometheus自身とnode-exporter、cadvisorを連携するので、それぞれをjob_name毎に定義していきます。URLはdocker-compose.ymlで定義したサービス名に対応します。

global:
  # データをスクレイピングする間隔
  scrape_interval: 15s
  # メトリクスが古くなるまでの時間
  evaluation_interval: 15s

scrape_configs:
  - job_name: prometheus
    static_configs:
      - targets: ["prometheus:9090"]

  - job_name: node-exporter
    static_configs:
      # 環境により異なる
      - targets: ["localhost:9100"]

  - job_name: cadvisor
    static_configs:
      - targets: ["cadvisor:8080"]

grafana/provisioning/datasources/prometheus.yml

Grafanaで利用するPrometheusのデータソースを設定します。Grafanaがどのデータベースから値を取得するかを定義しています。

apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: true

grafana/provisioning/dashboards/dashboards.yml

Grafanaでダッシュボードをプロビジョニングする方法を設定します。

apiVersion: 1

providers:
  - name: 'local-dashboards'
    orgId: 1
    folder: ''
    type: file
    disableDeletion: true
    updateIntervalSeconds: 30
    options:
      path: /var/lib/grafana/dashboards

grafana/provisioning/dashboards/<任意の名前>.json

Grafanaで表示するダッシュボードを定義したJSONファイルです。Grafanaが公開しているダッシュボードテンプレートを利用します。
ダッシュボードはテンプレートは以下リンクから好きなものを選択して、JSONファイルをダウンロードします。
https://grafana.com/ja/grafana/dashboards/

今回は以下を利用します。

  • Node Exporter:Node Exporter Full(ID:1860
  • cAdbvisor:Docker Container & Host Metrics(ID:10619)

jsonファイルから、${DS_PROMETHEUS}と記載の部分をgrafana/provisioning/datasources/prometheus.ymlで定義したnameに置換します。
今回だとPrometheusになります。
ダッシュボードテンプレートによっては、${DS_PROMETHEUS}以外の変数(例: ${xxx})もデータソース名に置換する必要がある場合があります。

<<長いので省略>>

ダッシュボードテンプレートによっては、k8sを利用する前提になっていることもあったので、出来る限り現在の環境に近いものを選択する必要があります。

grafana/grafana.ini

Grafanaのアプリケーション側の設定ファイルです。このファイルは無くてもいいですが、個別設定をファイル管理する場合は利用してください。

[session]
; ユーザーがログイン状態を維持できる最大期間
cookie_max_age = 12h

[log]
; Grafanaの内部ログ設定(デバッグ用)
; level = info
; filters = alerting:debug rendering:info

[users]
; ユーザーが削除された際のダッシュボードやアノテーションの削除設定
auto_assign_org_role = Viewer
default_theme = dark
allow_sign_up = false ; 外部ユーザーのサインアップを許可しない

grafana/.env

Grafanaにログインするときのユーザ・パスワードです。本番運用では絶対に利用しないでください。
docker-compose.ymlにべた書きはセキュリティ上良くないので、環境変数ファイルに記載します。

GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=admin

3. 起動手順

git clone <この構成を含むリポジトリURL>

# docker-compose.ymlが配置されているディレクトリへ移動
cd <xxx>

# コンテナを起動
docker compose up -d

コンテナ確認

起動確認

docker ps
# prometheus / node-exporter / cadvisor / grafana がすべて Up

ログの確認

各コンテナのログでERRORWARNINGが無いかを確認します。

docker compose logs <コンテナ名> --follow

通信タイムアウトや証明書関連のエラーが出ていれば、証明書を設定します。
私の場合は以下を行いました。

  • grafanaとprometheusの通信でエラーのため、プロキシを経由させずに通信するNO_PROXYprometheusを追加しました。
  • Grafanaからの通信で証明書のエラーのため、grafanaの公開鍵を/etc/ssl/certsへマウントしました。

各UIにアクセス

各画面が表示されればセットアップ完了です。

各サービスを表示

Grafanaのダッシュボードを表示

データソース設定やダッシュボードテンプレートの修正漏れがある場合は、ダッシュボード表示時にエラーが表示されます。
No DataN/Aはデータが無い(アクセス権限なし・メトリクス収集に必要なマウント設定をしていない等)可能性があるので、表示が出来ていないかの切り分けが必要になります。

Discussion