PrometheusとWindows ExporterによるWindows Server監視ガイド:CPU、RAM、Servicesの詳細モニタリング

Monitoring tutorial - IT technology blog
Monitoring tutorial - IT technology blog

なぜWindows Server用に個別でセットアップする必要があるのか?

このブログのPrometheus + Grafanaインストール記事を読んだことがある方は、ほとんどの説明がnode_exporterを使ったLinux向けであることに気づいているはずです。Windows Serverは別の話です — ファイルシステムも違えば、サービス管理の仕組みも異なる。そして何よりWindows Servicesは独立して監視する必要があります。

以前、IISを動かしているWindowsサーバーで夜中の3時にサービスがフリーズしたことがあります。お客様から電話がくるまで誰も気づかなかった。その経験があってから、本腰を入れてWindows用の監視をセットアップしました。この記事はまさにその問題に集中します:CPU、RAM、ディスク、そしてServicesの状態 — 余計な話は省きます。

Windowsを監視するためのオプションは何があるか?

何かインストールする前に、どんな選択肢があるか把握しておきましょう:

1. Windows Exporter(Prometheus向け)

wmi_exporterからフォークされ、現在はPrometheusコミュニティの公式プロジェクトです。HTTPエンドポイント経由でメトリクスをエクスポートし、Prometheusが定期的にスクレイプします。バックグラウンドのWindows Serviceとして動作し、フットプリントが小さく — わずか15〜20MB程度のRAMしか使いません。

2. Telegraf + InfluxDB

InfluxDataの汎用エージェントで、ネイティブのWindows Performance Countersを使用するwin_perf_countersプラグインを備えています。Windows対応は優れていますが、より重く(~50MB RAM)、設定が多く、InfluxDBの追加かoutputプラグイン経由でPrometheusへの転送が必要です。

3. Zabbix Agent

Zabbixには独自のWindows用エージェントがあり、充実したテンプレートが揃っています。しかしPrometheusをメインバックエンドとして使っている場合、Zabbixを追加するのは不必要な複雑さを招きます — 二つのエコシステムを並行して、二箇所でメンテナンスが必要になる。

4. SNMP / WMI 直接利用

エージェントをインストールせずにPrometheusからメトリクスをプルします。シンプルに聞こえますが、レイテンシが高く、設定が複雑で、アプリケーションレベルの監視には詳細が不足しています。通常はエージェントをインストールできないネットワーク機器に対してのみ使用します。

簡易比較

アプローチ メリット デメリット
Windows Exporter Prometheusネイティブ、軽量(~15MB RAM)、豊富なメトリクス Prometheusが必要
Telegraf 汎用性が高く、多くのoutputプラグインあり より重め(~50MB)、設定が多い
Zabbix Agent 豊富なテンプレート、洗練されたUI 独自エコシステムでPrometheusとは共用不可
SNMP/WMI エージェント不要 レイテンシが高く、アプリレベルの詳細が不足

どれを選ぶべきか?

LinuxサーバーにPrometheus + Grafanaを使っているなら?答えはほぼ常にWindows Exporterです。同じスクレイプ設定、同じAlertmanager、同じGrafana — 新しいターゲットを一つ追加するだけ。新しいスタックを学ぶ必要はありません。

唯一の例外:すでにZabbixを使っていてWindows Serverが少数の場合 → 統一性のためにZabbix Agentを使う。それ以外は、この記事はWindows Exporterに直進します。

デプロイメントガイド

ステップ1:Windows ServerにWindows Exporterをインストールする

prometheus-community/windows_exporterのGitHubリリースから最新のMSIをダウンロードします。執筆時点ではv0.29.2です。

Administratorの権限でPowerShellからインストールします:

# MSIをダウンロード
$version = "0.29.2"
$url = "https://github.com/prometheus-community/windows_exporter/releases/download/v$version/windows_exporter-$version-amd64.msi"
Invoke-WebRequest -Uri $url -OutFile "windows_exporter.msi"

# 必要なコレクターと共にインストール
msiexec /i windows_exporter.msi `
  ENABLED_COLLECTORS="cpu,memory,logical_disk,net,os,service,system" `
  LISTEN_PORT="9182" /quiet

GUIから手動でインストールすることもできます。ポート9182(デフォルト)を選択してください。インストール後、windows_exporterという名前のWindows Serviceが自動的に起動します。

サービスが実行中であることを確認します:

Get-Service windows_exporter
# ステータスはRunningであること

そのサーバーから直接メトリクスエンドポイントをテストします:

Invoke-WebRequest -Uri http://localhost:9182/metrics | Select-Object -ExpandProperty Content | Select-String "windows_cpu"

ステップ2:PrometheusスクレイプのためにFirewallを開放する

New-NetFirewallRule `
  -DisplayName "Windows Exporter" `
  -Direction Inbound `
  -Protocol TCP `
  -LocalPort 9182 `
  -Action Allow

全体を開放するのではなく、PrometheusサーバーのIPだけにルールを制限するのが望ましい — -RemoteAddress 192.168.1.50を一行追加するだけで十分です。

ステップ3:PrometheusにターゲットをAddする

Prometheusサーバー(Linux)でprometheus.ymlを編集します:

scrape_configs:
  # ... 既存のLinuxジョブ ...

  - job_name: 'windows_servers'
    static_configs:
      - targets:
          - '192.168.1.100:9182'   # Windowsサーバー1
          - '192.168.1.101:9182'   # Windowsサーバー2
        labels:
          env: 'production'
          os: 'windows'

Prometheusをリロードして適用します:

curl -X POST http://localhost:9090/-/reload
# または
systemctl reload prometheus

Prometheus UI → Status → Targetsに移動すると、windows_serversターゲットのstateがUPになっているはずです。DOWNになっている場合は、まずFirewallを確認してください — 10件中9件はそれが原因です。

ステップ4:GrafanaダッシュボードをImportする

ダッシュボードID 14694(Windows Exporter Node)はコミュニティで最も人気のある選択肢です。Grafanaにインポートします:

  1. Grafana → Dashboards → Import
  2. ID 14694を入力 → Load
  3. Prometheusデータソースを選択 → Import

ダッシュボードにはCPU使用率、RAM、ディスクI/O、ネットワークスループットのパネルが揃っています。instance変数を調整して、確認したいサーバーを選択してください。複数のサーバーがある場合、この変数はドロップダウン形式で表示されます — 非常に便利です。

ステップ5:特定のWindows Servicesを監視する

これがLinux監視との最大の違いです。使用するメトリクスはwindows_service_stateです:

# サービスが実行中かどうかを確認(1 = running)
windows_service_state{state="running", name="W3SVC"}       # IIS
windows_service_state{state="running", name="MSSQLSERVER"}  # SQL Server
windows_service_state{state="running", name="wuauserv"}     # Windows Update

# サービスが突然停止した際にアラート — シンプルで効果的な方法
windows_service_state{name=~"W3SVC|MSSQLSERVER|SQLSERVERAGENT", state="running"} == 0

上記のクエリを使ったパネルをGrafanaに追加し、Stat形式またはTable形式のビジュアライゼーションで各サービスの状態を視覚的に確認できます。

実践的なアラートルール

この部分が最初に最も時間がかかった箇所です。アラート疲れ(Alert fatigue)は抽象的な概念ではありません — 実際に経験しました:セットアップ完了後、実際のワークロードに合わないthresholdのせいで夜中の2時に頻繁にアラートが飛んでくる。無効にして無視し、システム全体への信頼を失う。何度もチューニングを繰り返してようやく安定しました。

現在使用しているwindows_alerts.ymlファイルです。Grafanaのメールアラート設定と組み合わせることで、アラート通知チャネルを一元管理できます:

groups:
  - name: windows_server
    rules:
      # 10分間継続してCPUが高い場合 — 短時間のスパイクは正常なのでアラートしない
      - alert: WindowsCPUHigh
        expr: |
          100 - (avg by (instance) (
            rate(windows_cpu_time_total{mode="idle"}[5m])
          ) * 100) > 85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "{{ $labels.instance }}でCPUが高い"
          description: "CPU使用率 {{ $value | printf \"%.1f\" }}%が10分間継続"

      # 残りRAMが500MB未満(絶対値、%ではない)
      - alert: WindowsLowMemory
        expr: windows_os_physical_memory_free_bytes < 500 * 1024 * 1024
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.instance }}でRAMが低い"
          description: "空きRAMが{{ $value | humanize1024 }}Bのみ"

      # ディスクが10%未満
      - alert: WindowsDiskLow
        expr: |
          (windows_logical_disk_free_bytes{volume!~"HarddiskVolume.*"}
          / windows_logical_disk_size_bytes) * 100 < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "{{ $labels.instance }}の{{ $labels.volume }}ディスク容量が少ない"

      # 重要なサービスが停止した場合
      - alert: WindowsServiceDown
        expr: |
          windows_service_state{
            name=~"W3SVC|MSSQLSERVER|SQLSERVERAGENT",
            state="running"
          } == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.instance }}でサービス{{ $labels.name }}が停止"

ルールをPrometheusに読み込むにはprometheus.ymlに以下を追加します:

rule_files:
  - "/etc/prometheus/rules/windows_alerts.yml"

深夜のアラートで叩き起こされた後の教訓

理論ではなく、痛い経験から得た教訓です:

  • for: 10mを使い、即座にトリガーしない — バックアップ実行やWindows Updateの際の1分程度のCPUスパイクは正常です。10分間継続してCPUが高い場合のみ問題です。
  • severityはwarningから始め、criticalにしない — criticalは本当に夜中の3時に起き上がって修正が必要な時だけ使います。
  • Alertmanagerを有効にする前に1〜2週間監視する — サーバーの実際のパターンを確認し、感覚ではなく実際の数値に基づいてthresholdを設定します。
  • 特定のサービス名でアラートを設定する、停止した全サービスにアラートを出さない — Windowsには常時起動が不要なサービスが数十個あり、全部アラートするとすぐに混乱します。

パイプライン全体のテスト

# Prometheusサーバーから手動で接続テスト
curl http://192.168.1.100:9182/metrics | grep -E "windows_(cpu|memory|service)"

# このクエリはPrometheus UIで結果を返すはずです:
# windows_os_physical_memory_free_bytes{instance="192.168.1.100:9182"}

PrometheusにメトリクスがあらわれてGrafanaダッシュボードにデータが読み込まれれば、パイプラインは正常に動作しています。あとはサーバーごとにアラートのthresholdを調整するだけです。

Share: