どうも自分は監視についての知識や技術が乏しい、ということに気付いた。 そもそも何かを監視するという習慣を持っていないのがまず良くないと反省し、まずは自宅の環境を監視する練習から始めてみることにした。
監視とは役割ではなくスキルであり、チーム内の全員がある程度のレベルに至っておくべきです。
- 環境
- Ansible from macOS
- VictoriaMetricsによる監視
- Metricsの取得、収集
- SwitchBotによる温度/湿度/CO2濃度の取得
- Grafanaによる可視化
- Alertmanagerを使ったアラート通知
- まとめ
環境
国内のクラウドサービス でサーバを借りることにしたので、そこに環境を整えていく。
- OS: Ubuntu 24.04.1
Ansible from macOS
サーバ上で設定を編集して再起動したりとかをしたくない。すべて手元のMacBookからAnsibleで設定していくことにした。
とはいえmacOSからのAnsible実行にはいくつかの罠があるようだった。以下は自分がハマったもの。
$ brew install gnu-tar $ export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
- https://github.com/prometheus-community/ansible/tree/main/roles/node_exporter#requirements
- https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#running-on-macos-as-a-control-node
Ansible Galaxy
Ansibleにも不慣れで、できるだけ自分でYAMLを書かずに先人の知恵を借りていきたい。 極力Galaxyを使ってやっていくことにした。
$ ansible-galaxy collection install prometheus.prometheus $ ansible-galaxy collection install victoriametrics.cluster $ ansible-galaxy collection install grafana.grafana $ ansible-galaxy collection install community.general $ ansible-galaxy collection install community.grafana
VictoriaMetricsによる監視
監視の定番は Prometheus かもしれないが、ここでは VictoriaMetrics を使ってみることにした。
Prometheusとの互換性を持ちつつも 収集・保存・クエリ・アラートなどがそれぞれ独立したコンポーネントとして提供されていて、必要に応じて組み合わせて使うことができる。そしてそれらはクラスタ化してスケールアウトする運用もしやすくなっているようだ。
個人で1台のサーバで使うぶんには Single-node version で十分で、これは vminsert
, vmselect
, vmstorage
を一つにまとめたもの、になっているようだ。
結局Prometheusを立てるのとそんなに変わらないのかもしれないが、データの長期保存に向いているなどの特徴もあるようなので、メリットは十分にありそう。
Metricsの取得、収集
VictoriaMetrics自体は何かのmetricsを取れるわけではないので(自身のプロセスのmetricsは取れるが)、それこそPrometheusコミュニティで使われているようなExporterを使っていくことになる。
Node Exporter
まずは定番のNode Exporter。 Galaxyで提供されているのでroleを参照するだけ。
- name: Install node_exporter hosts: servers roles: - prometheus.prometheus.node_exporter
これでport :9100
で node_exporter
が起動し、metricsを取得できるようになる。
VictoriaMetrics (vmsingle, vmagent)
それからVictoriaMetricsを立ち上げ、Node Exporterからのmetricsを収集していく。
Single-node version の vmsingle
にも収集機能はあるようだが、ここでは別プロセスで vmagent
を動かすようにする。
- name: Install monitoring tools hosts: monitoring become: true roles: - role: victoriametrics.cluster.vmsingle - role: victoriametrics.cluster.vmagent vars: vmagent_scrape_config: scrape_configs: - job_name: node-exporter static_configs: - targets: - 127.0.0.1:9100
これでport :8428
で victoriametrics
が起動し、また vmagent
が --remoteWrite.url=http://localhost:8428/api/v1/write
というオプションで起動するので、上記 scrape_configs
に従って node_exporter
のmetricsを定期的に収集し、 victoriametrics
に書き込むようになる。
:8428/vmui/
にアクセスするとGUIでデータを確認できる。
SwitchBotによる温度/湿度/CO2濃度の取得
実際に自宅の環境を監視していくためのデータ取得。
センサ機器は Raspberry Pi とか使って自作すれば良いのかもしれないけど、手軽に始めたかったのでとりあえず SwitchBot のものを購入してみた。
これ一つで温度、湿度、CO2濃度を取得できる。が、後で知ったのだけど単体ではスマホアプリからBluetoothで繋いでデータを閲覧するくらいで、外部からAPIでデータを取得するようなことはできない。別途ハブを購入して そちらからインターネット接続することで実現できる。
赤外線操作の機能もあるらしいが、うちのテレビやエアコンに試してみた限りでは上手く動かず…。CO2濃度にこだわらなければ Nature Remo を買った方がよかったかも?
Exporter
ともかくセンサとハブが繋がっていれば、Open Token, Secret Keyを使って SwitchBot API でデータを取得できるようになる。
このAPIを使うための便利ライブラリが既に公開されていて、
さらにそれを使ってPrometheus向けのmetricsを出力してくれるExporterまで公開されている!
有り難くこれを使わせていただくことで、1行もコードを書かずにSwitchBotのセンサデータをmetricsとして収集することができるようになる。
とはいえ、CO2の値の取得に対応されたのは数ヶ月前で、その変更は最新のリリースには含まれていないし Linuxで動作するバイナリも配布はされていないので、main
branchからLinux向けのバイナリを自分でビルドする必要がある。
#!/bin/bash REPO_URL="https://github.com/nasa9084/switchbot-exporter.git" OUTPUT_BINARY="switchbot-exporter_linux_amd64" git clone --depth=1 --branch=master "${REPO_URL}" GOOS=linux GOARCH=amd64 go build -o "${OUTPUT_BINARY}"
あとはこのバイナリを送り、systemdで起動するように設定する。
- name: Send switchbot-exporter binary ansible.builtin.copy: src: "./switchbot-exporter_linux_amd64" dest: "{{ switchbot_exporter_binary_path }}" mode: "0755" - name: Create switchbot-exporter envfile ansible.builtin.template: src: "./switchbot-exporter.env.j2" dest: "{{ switchbot_exporter_envfile_path }}" mode: "0644" register: envfile - name: Create switchbot-exporter service ansible.builtin.template: src: "./switchbot-exporter.service.j2" dest: "/etc/systemd/system/switchbot-exporter.service" mode: "0644" register: service - name: Reload systemd if envfile or service changed when: envfile.changed or service.changed ansible.builtin.systemd: daemon_reload: true notify: Restart switchbot-exporter service - name: Start switchbot-exporter service ansible.builtin.systemd: name: switchbot-exporter state: started enabled: true when: not ansible_check_mode | bool
-web.listen-address
で指定したアドレスでmetricsが取れるようになるので、 vmagent
の scrape_configs
に追加してやれば良い。
- role: victoriametrics.cluster.vmagent vars: vmagent_scrape_config: scrape_configs: - job_name: node-exporter static_configs: - targets: - 127.0.0.1:9100 - job_name: switchbot metrics_path: /metrics static_configs: - targets: - B0E9FE56AF0D - D53535302D51 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: {{ switchbot_exporter_address }}
設定例も README に書いてあり、こうすることで targets
に指定したDevice IDを instance
として取得できるようになるらしい。
Grafanaによる可視化
無事にSwitchBotで取得した温度・湿度・CO2濃度のデータをVictoriaMetricsで収集、保存ができるようになったので、次はそれを可視化していく。
ここは定番のGrafanaで。
- name: Install grafana hosts: monitoring become: true roles: - role: grafana.grafana.grafana vars: grafana_ini: server: ... security: admin_user: admin admin_password: ...
最低限の設定で起動してWebUIにアクセスできるようになるので、そこでDashboardを作成していく。 互換性のおかげで、ちゃんと Prometheus datasource としてVictoriaMetricsを指定できる。
温湿度計だけのものも併用して別の部屋に置いているので、2つの部屋の状態の違いなども一目でわかるようになっている。
Alertmanagerを使ったアラート通知
あとはアラート、通知送信。
CO2濃度の値が一定以上になったらアラートを出すようにする。 その対応は簡単に自動化できるものでもないので、とりあえずSlackの適当なChannelに通知を送信するようにする。
Grafanaにもアラート機能があるようだけど、ここでは Prometheusの Alertmanager を使うことにする。 (機能の違いなどをまだ把握していない)
Alertmanagerのインストール
- name: Install monitoring tools hosts: monitoring become: true roles: - role: prometheus.prometheus.alertmanager
デフォルトで :9093
で起動してWebUIにもアクセスできるようになる。
vmalert によるアラート
VictoriaMetricsではアラートを出すためのコンポーネントも vmalert
として独立したものが提供されている。
- role: victoriametrics.cluster.vmalert vars: vic_vm_alert_rules: - name: SwitchBot rules: - alert: HighCO2LevelWarning expr: switchbot_meter_CO2 > 1200 for: 5m labels: severity: warning annotations: summary: "CO2 level exceeds 1200 ppm (Warning)" description: "{% raw %}The current CO2 level is {{ $value }} ppm.{% endraw %}" - alert: HighCO2LevelCritical expr: switchbot_meter_CO2 > 1800 for: 5m labels: severity: critical annotations: summary: "CO2 level exceeds 1800 ppm (Critical)" description: "{% raw %}The current CO2 level is {{ $value }} ppm.{% endraw %}"
これもデフォルトで --datasource.url
として VictoriaMetrics (vmsingle) の http://localhost:8428
を、--notifier.url
として Alertmanager の http://localhost:9093
を指定して起動するようになっているので、ruleだけ設定すればアラートが発報されるようになる。
とりあえず2つの閾値を設定し、 warning
と critical
の2種類の severity
をlabelにつけている。
CO2濃度は 1,000 ppm 以下が基準となっているようだけど、閾値が低すぎると我が家の環境では結構頻繁にアラート出てしまうのでちょっと調整している…。
Alerting rulesなどは {{ $value }}
といったテンプレートを使用でき、それをAnsibleから指定しようとするとJinja2のテンプレートと混ざらないよう気をつける必要があり、まぁまぁ面倒…。
Slackへの通知設定
改めてAlertmanagerの設定。
receivers: - name: noop - name: slack_critical slack_configs: - api_url: https://hooks.slack.com/services/... color: danger text: "{{ .CommonAnnotations.description }}" title: "{{ .CommonAnnotations.summary }}" - name: slack_warning slack_configs: - api_url: https://hooks.slack.com/services/... color: '{{ if eq .Status "firing" }}warning{{ else }}good{{ end }}' send_resolved: true text: '{{ if eq .Status "firing" }}{{ .CommonAnnotations.description }}{{ else }}Resolved.{{ end }}' title: "{{ .CommonAnnotations.summary }}" inhibit_rules: - equal: - instance source_match: severity: critical target_match: severity: warning route: receiver: noop routes: - match: severity: critical receiver: slack_critical - match: severity: warning receiver: slack_warning
送信先の api_url
は同一だが warning
用と critical
用で設定を変えて、 warning
の方は解決したときにもその旨を通知するようにしている。
これで、常にGrafana Dashboardを眺めていなくても自宅の環境が異常になっていることを通知によって気付くことができるようになった。
まとめ
監視に馴染みがなく不慣れながらも、どうにか自宅の環境を監視する環境を整えることができた。
これからも継続して運用・改善していきつつ、他にも監視対象にできるものがあれば追加したりしていきたい。