子供はまだゲームできるほどの大きさではないのだが、自分がこっそりゲームするタイプだったので、将来多分子供もこっそりゲームをするのであろう。
そういう風に育った時、「学校の調べ物をするためにPC使ってるはずが、CPU利用率張り付いているの何でやねん」と子供に突っ込めるようにしておきたい。
ということで、Windows内のリソースの使用状況の高騰をキャッチして通知するシステムを作る。
父のPCに監視基盤となるPrometheus、AlertManager、Grafanaを構築し、子のPCにWindowsのメトリクスを公開するWindows Exporter(WMI Exporter)を導入する。
父のPCからメトリクスを定期的に取得し、負荷状況を確認し、負荷のレベルによってはメールにてアラート通知を行う。
なお、常時監視する都合上、前提として父のPCは立ち上げっぱなしとする。
電気代が気になる方はRaspberry Piとかに置き換えるのも多分可能だが、ここでは割愛する。
また、子供がゲームをするのにスマートフォンを使うケースの方が圧倒的に多そうだが、スマートフォン向けのPrometheus Exporterを導入するには脱獄が必要そうな気がするので、こちらも今回は割愛する。
子のPCのセットアップ
Windows PCのメトリクスを公開するためのPrometheus Exporterとして WMI Exporterがあるのでこれを使う。
インストール時のオプションでメトリクスを公開するポート等が変更できるようだが、ここではデフォルト値でインストールする。
Release Noteではmsi形式とexe形式の2種類のバイナリが用意されているが、msi形式だとサービスの作成やFirewallの穴あけもやってくれるので、ここではmsi形式のバイナリを使ってインストールする。
ダウンロードしてインストールすると、Windowsのサービス
にwindows_exporter
が追加される。
また、http://localhost:9182にアクセスするとWindows ExporterのWeb画面にアクセスできるようになっている。
これの/metrics
を使って監視する。
父のPCのセットアップ
監視で利用するPrometheus、AlertManager、Grafanaはdocker-composeを使って構築する。
docker-composeを使ってるので、MacやLinuxでも多分動くはず。
コンテナを使う都合上、WSL(Windows Subsystem for Linux)が有効になっていて、WSLを起動して進めるものとする。
docker、docker-composeのインストール
snap
で導入し、sudo
なしで利用できるようユーザをdockerのグループに追加する。
sudo snap install docker
sudo snap install docker-compose
sudo usermod -aG docker $USER
exit
Prometheus、AlertManager、Grafanaの構築
こちらで配布されていたdocker-composeのYAMLにAlertManagerとデータの永続化の設定を追加したものを作って構築する。
最初にそれぞれの設定ファイルを置くためのディレクトリを作成する。
mkdir prometheus grafana alertmanager
Prometheusでスクレイプ設定をする際に指定する、子供のPCのIPを環境変数で定義しておく。
TARGET_IP=192.168.0.41
なお、DHCPでIPを割り当てている場合はDNSを別途用意するか、サービスディスカバリの仕組みを取り入れるなどIPが変わっても追従できるようにしておく。(面倒なら固定IPを割り当てる)
次にPrometheusの設定ファイルを作成する。
cat <<EOF > ./prometheus/prometheus.yml
global:
scrape_interval: 15s
scrape_timeout: 10s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
scheme: http
timeout: 10s
rule_files:
- "rules-game-check.yml"
scrape_configs:
- job_name: prometheus
honor_timestamps: true
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- localhost:9090
- job_name: windows
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- $TARGET_IP:9182
job_name: windows
の箇所でWindows Exporter(=子供のPC)をスクレイプするようにしている。
また、アラートの条件はrules-game-check.yml
に書いている。
ということで、アラートの条件定義であるrules-game-check.yml
を作成する。
cat <<'EOF' > ./prometheus/rules-game-check.yml
groups:
- name: game-check
rules:
- alert: WindowsServerCpuUsage
expr: 100 - (avg by (instance) (rate(windows_cpu_time_total{mode="idle"}[2m])) * 100) > 70
for: 5m
labels:
severity: warning
annotations:
summary: Windows Server CPU Usage (instance {{ $labels.instance }})
description: "CPU Usage is more than 80%\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
EOF
条件式はAwsome Prometheus Alertsから拝借した。
CPU以外の条件でアラートを上げたい人はAwsome Prometheus Alertを参照すると他の条件式も確認できるので、必要に応じて参照してほしい。
評価式は以下部分となる。
expr: 100 - (avg by (instance) (rate(windows_cpu_time_total{mode="idle"}[2m])) * 100) > 70
for: 5m
2分
間のアイドル時間の割合をベースにCPU利用率を算出し、70%
を超える利用率が5分
続くとアラートを上げる、という意味となる。
環境によってここはかなり異なるので、ここは子供のPCのリソース使用状況を見ながらチューニングするとよい。
なお、評価式はメトリクスがないと評価されないので、子供のPCがシャットダウンしている場合はアラートは飛んでこない。
次にAlertManagerの設定ファイルを作成する。ここではGmailを使ってメールで通知する設定としている。
MY_MAILADDRESS=mymailaddress@gmail.com
MY_APP_PASSWORD=abcdhijkefghlmno
cat <<'EOF' > ./alertmanager/config.yml
global:
smtp_smarthost: 'smtp.gmail.com:465'
smtp_auth_username: "${MY_MAILADDRESS}"
smtp_auth_password: "${MY_APP_PASSWORD}"
smtp_require_tls: false
smtp_from: 'Alertmanager <alertmanager@localhost.localdomain>'
route:
receiver: 'game-check'
receivers:
- name: 'game-check'
email_configs:
- to: "${MY_MAILADDRESS}"
EOF
注意点として、ここでのパスワードはGoogleログイン時に使用するものではなく、アプリケーションが使うためのパスワードとなる。
発行方法はこちらを参照のこと。
次にGrafanaの設定ファイルを作成する。
cat <<EOF > ./grafana/datasource.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
isDefault: true
access: proxy
editable: true
EOF
最後にdocker-compose用のファイルを作成する。
cat <<EOF > ./compose.yaml
services:
prometheus:
image: prom/prometheus
container_name: prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- 9090:9090
restart: unless-stopped
volumes:
- ./prometheus:/etc/prometheus
- prom_data:/prometheus
grafana:
image: grafana/grafana
container_name: grafana
ports:
- 3000:3000
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=grafana
volumes:
- ./grafana:/etc/grafana/provisioning/datasources
- grafana_storage:/var/lib/grafana
alertmanager:
image: prom/alertmanager
container_name: alertmanager
volumes:
- ./alertmanager:/etc/alertmanager
command: "--config.file=/etc/alertmanager/config.yml"
ports:
- 9093:9093
restart: always
volumes:
prom_data: {}
grafana_storage: {}
データの永続化のためにPrometheusとGrafanaにはVolumeを割り当てている。
以上で設定が揃ったので起動する。
docker-compose up -d
起動に成功すると、それぞれ以下でアクセスできる。
- Prometheus: http://localhost:9090
- AlertManager: http://localhost:9093
- Grafana: http://localhost:3000 ※ID/PW:admin/grafana
子供のPCが見えているかは、PrometheusのStatus
->Targets
で確認できる。
Grafanaに関してはダッシュボードを用意していないので、今の状態では使えない。後ほど用意する。
動作確認
アラートの発行の確認
子供のPCにCPU負荷をかけてアラートが飛ぶか確認する。
負荷のかけ方は何でもよいが、特に重いゲームなどを持っていなかったのでここではMicrosoftが配布しているsysinternalsというツールキット内のCPUSTRES64.EXE
を実行し、以下の画像のように複数スレッドで同時に負荷をかける。
するとPrometheusのAlerts
タブからアラートの条件に引っかかっていることが確認できる。
Pending
は条件(expr
)は満たしているが、期間(for
)を満たしていない状態を示している。
しばらく待つと状態がfiring
に変わり、以下のようにGmailに通知が届く。
なお、上手く届かない場合はAlertManagerのログを確認するとよい。
例えば以下はアプリパスワードが設定できていなかった時の例。
$ docker logs alertmanager
ts=2024-04-01T07:41:13.682Z caller=notify.go:848 level=warn component=dispatcher receiver=game-check integration=email[0] aggrGroup={}:{} msg="Notify attempt failed, will retry later" attempts=7 err="*email.loginAuth auth: 534 5.7.9 Application-specific password required. For more information, go to\n5.7.9 https://support.google.com/mail/?p=InvalidSecondFactor fa17-20020a056a002d1100b006f6b52eb59asm7164300pfb.126 - gsmtp"
ダッシュボードによる確認
アラートルールを作る際や、意図していないメトリクスのスパイクを確認するためにGrafanaのダッシュボードは活用した方がよい。
デフォルトではダッシュボードは用意されていないので、自力で作成するか有りものを流用することになる。
有りものを流用する場合、Grafana LabsがDashboardsを配布しているDashboardsでWindowsで検索するといくつかWindows Exporter用のダッシュボードが確認できるので、これらを流用すると一からダッシュボードを用意するよりは楽に用意することができる。
ここではそこそこ使えそうだったID:14694を導入してみる。
Grafanaにログインし、Dashboards
->New
->Import
を選択する。
Find and import dashboards for common applications at grafana.com/dashboards
の入力欄に14694
と入力してLoad
をクリックし、データソースにPrometheus
を入力後、Import
をクリックするとダッシュボードが取り込まれる。
取り込まれたダッシュボードを参照すると、以下のような感じでCPU負荷などが確認できる。
ディスクI/Oなども見れるので、変なものをダウンロードしていないかとかも気にする人は確認するといいかも。
終わりに
こっそりやると親子関係が破綻するかもしれないので、子供にはちゃんと監視してる旨を通知した方がいいかも。
あと仕組みを教えてあげて迂回路を考えてもらうと、子供の勉強にいいのかもしれない。