ARMボード色々でおうちDockerSwarmクラスタ prometheus/grafana/cadvisor編


クラスタを作っている所(進行形)なのでそのメモを残していきます。
この記事ではおうちARMボードをモニタリングできるようにしていきます。

今回は クラスタの状態を可視化したくなったのでPrometheusとその周りを整えてみます。

おうちクラスタシリーズ

  • 第1弾: ハードウェア編
  • 第2弾: Portainer編
  • 第3弾: Ceph編(失敗)
  • 第4弾: SeaweedFS編
  • 第5弾: traefik編
  • 第6弾: prometheus/grafana編

使うソフトウェアの紹介

今回は複数のソフトウェアを使うのでそれぞれ書きます

Prometheusについて

監視システムの基盤の一種です。メトリクスという形で死活情報を提供しているサービスから、ログを収集したり、ログに異常があればアラートを発行したり、ログを可視化したりできます。しかしながら、Prometheus自体はそれぞれの"基盤"(API)のみとなっており、ログを提供するExporter、実際にアラートを送るAlertManager、ログを可視化するVisualizationツールとともに利用する前提となっているようです。

cAdvisorについて

Dockerコンテナのリソース使用量やパフォーマンスなどのログを提供するExporterの一種です。(DockerデフォルトでもMetrics-Portを設定すればDocker自体からメトリクスを吐いてくれるようなのですが、触れられている記事が少なかったので、とりあえずcAdvisorを使ってみることにします)

node-exporterについて

動作しているOS自体のCPU/メモリ使用率などを提供するExporterの一種です。DockerHubを見たところ、ARM64/ARMv7に対応しているようだったのでそのまま使うことができます。が、DockerSwarmではこのまま使うと面倒なことになります(後述)

grafanaについて

Prometheus等様々な監視基盤の情報を可視化できるVisualizationツールです。現在の状態を可視化することが目的なので、細かく1つ1つログが見れるとかいうものではありません。(アプリの動作ログとかを可視化するなら elasticstack等?)

導入

ここまでで、PortainerとSeaweedFSをセットアップしたので、WebUIからサービスを追加できる、/mnt/seaweedfsに設定ファイルを保存できるという想定で進めます。

1 SwarmPromをよく読む

かなり古くてアーカイブまでされてしまっていますが、今でも参考になるプロジェクトです。ARMには対応していないので対応するイメージを多少探す必要がありますが、まずはこれを読みましょう。

node-exporterの独自イメージ

DockerSwarm内で動かすと、(SeaweedFSを導入する時に困ったのと同様に) 1サービスの各ノードで動かすコンテナそれぞれに対して同じ環境変数しか渡せないという課題があります。そのため、普通に渡すと各ノードのnode-exporterの名前が全て同じになってしまい、うまく可視化できなくなってしまいます。SeaweedFSのSwarm構成で私がやろうとしたように、ノードそれぞれを別サービスにして1台ずつ環境変数を渡して動かすこともできますが、設定が非常に不格好になります。そこで、このイメージにはホスト名をコンテナ起動時のShellで読み出し、設定ファイルに書き込むことで解決をしているようでした。今回は同様の措置をやっている4ヶ月前の野良ビルドをお借りしました。(プロダクションではちゃんと自分でビルドしましょう)

grafanaの独自イメージ

このイメージは単にはじめからSwarm用のダッシュボードを入れているだけのようです。最新のgrafanaのコンテナのボリュームとして、ここにあるダッシュボード群をマウントすれば代用可能です。DockerHubの公式イメージを見たところ、ARM64(v8)/ARMv7に対応しているようだったので最新版イメージをそのまま使うことができます。

prometheusの独自イメージ

このイメージは単にはじめからPrometheus用の設定ファイルを入れているだけのようです。最新のprometheusのコンテナのボリュームとして、ここにある設定ファイル群をマウントすれば代用可能です。DockerHubの公式イメージを見たところ、ARM64(v8)/ARMv7に対応しているようだったので最新版イメージをそのまま使うことができます。

cadvisor

SwarmPromでは公式イメージをそのまま使っています。ARM用ビルドがなかったので、このIssueを見て、一番新しそうな5ヶ月前の野良ビルドをお借りしました。(プロダクションではちゃんと自分でビルドしましょう)

caddy

caddyはGo製のWebサーバーの一種です。各ページのアクセスにBASIC認証をかけるために入れているようですが、今回はひとまず省略します。

alertmanager

負荷が高くなってもうヤバいってなったときにSlackなどに通知するやつです。今回は最低限で組みたいので省略します。(後日 LINE-Notifyとかさせるやつ使いたいな)

unsee

アラート履歴をWeb上で見れるようにするもののようですが、3年前で更新が止まっています。フォークを追った感じだと、今は karmaっていうのが使われているらしい?です。alertmanagerが無いので、どちらにせよ導入しないことにします。

2 下記ymlをデプロイする

ということで現時点で最新の野良イメージなどを入れたものがこちらになります

monitor-swarm.yml
version: "3.4"

services:
  cadvisor:
    image: zcube/cadvisor:v0.37.5
    command: -logtostderr
    networks:
      - monitoring
    volumes:
      - /:/rootfs:ro
      - /sys:/sys:ro
      - /var/run:/var/run:rw
      - /var/lib/docker/:/var/lib/docker:ro
    deploy:
      mode: global
      resources:
        limits:
          memory: 128M
        reservations:
          memory: 64M
      restart_policy:
        condition: on-failure
  node-exporter:
    image: dakotairene/swarmprom-node-exporter:latest
    networks:
      - monitoring
    environment:
      - NODE_ID={{.Node.ID}}
      - HOST_HOSTNAME=/etc/nodename
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/host/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.textfile.directory=/etc/node-exporter/'
      - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
      - '--no-collector.ipvs'
    volumes:
      - /:/host/rootfs
      - /proc:/host/proc
      - /sys:/host/sys
      - /etc/hostname:/etc/nodename
    deploy:
      mode: global
      resources:
        limits:
          memory: 128M
        reservations:
          memory: 64M
      restart_policy:
        condition: on-failure
  prometheus:
    image: prom/prometheus:v2.28.1
    networks:
      - monitoring
    ports:
      - '9054:9090'
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=15d'
    volumes:
      - /:/rootfs:ro
      - /sys:/sys:ro
      - /var/run:/var/run:rw
      - /var/lib/docker/:/var/lib/docker:ro
      - /mnt/seaweedfs/prometheus/volume:/prometheus
      - /mnt/seaweedfs/prometheus/config:/etc/prometheus
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      resources:
        limits:
          memory: 2048M
        reservations:
          memory: 128M
  grafana:
    image: grafana/grafana:7.5.10
    ports:
      - '9055:3000'
    networks:
      - monitoring
    environment:
      - GF_PATHS_PROVISIONING=/etc/grafana/provisioning/
      - GF_SECURITY_ADMIN_USER=grafana-admin
      - GF_SECURITY_ADMIN_PASSWORD=grafana-password-admin
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - GrafanaVolume:/var/lib/grafana
      - /mnt/seaweedfs/grafana/datasources:/etc/grafana/provisioning/datasources
      - /mnt/seaweedfs/grafana/swarmprom_dashboards.yml:/etc/grafana/provisioning/dashboards/swarmprom_dashboards.yml:ro
      - /mnt/seaweedfs/grafana/dashboards:/etc/grafana/dashboards
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      resources:
        limits:
          memory: 128M
        reservations:
          memory: 64M
networks:
  monitoring:
    driver: overlay
    attachable: true
volumes:
  GrafanaVolume:
    driver: local

2.5 デプロイ

(Portainerから 放り込むだけなので省略)

3 起動後に画面を開いてみる

わーかっこいー!(小学生並の感想)

完走した感想

激寒ギャグ

SeaweedFSくんが思ったよりよくないかもしれない

自分でDockerイメージ作るのが面倒なので全設定ファイルを/mnt/seaweedfsに置いたのですが、Traefikでもやらかしたように、読み書きがそこそこ発生するファイルでは NULに化けたりしてなんだかんだファイルが壊れました。(そこで /var/lib/grafanaは マウントせずにVolumeになっている) 読み取り専用のものを置く分には問題ないんですが、なかなか厄介な子みたいです。

温度表示がない

ラズパイの熱暴走が怖いので、温度が表示できることを期待して導入したのですが どうやら cAdvisorでは取ってこれない様子です。(ダッシュボードをカスタマイズして node_thermal_zone_temp を出そうとするも取得できなかった) 別途温度情報を出せるエクスポーターの追加が要りそうです。

参考