ぽよメモ

レガシーシステム考古学専攻

Prometheus + cAdvisor + GrafanaでDockerコンテナごとのリソースを可視化する

背景

コンテナ数も増え,それに依存したサービスも増える中,サーバのapt upgrade後にPT3が行方不明になってこのすばの録画が死んだこともあり,いずれこれは把握できる範囲を超えるなと思ったため,監視ツールを何か導入する必要があると考えました.

いくつか候補は挙がったのですが,最終的にZabbixを選ぶか,Prometheusを選ぶかで悩んでGrafanaが最初からサポートしているという理由でPrometheusを選択しました.

今回はPrometheusでcAdvisorから情報を取得,Grafanaで可視化するまでを行います.Alertmanagerなどの導入はちゃんとできたらまた記事にします.

使うもの

Prometheus

prometheus.io

Prometheusはサーバ側から監視先を叩きに行くPull型の監視ツールです.詳しいことはQiitaの先人におまかせします.

qiita.com

exporterと呼ばれるエンドポイントを建てて情報を収集します.今回はホストの情報を収集するためにnode-exporterを使用します.

cAdvisor

cAdvisorはDockerホスト上のコンテナの監視ツールとしてGoogleが開発しているものです.Googleさまさまです.
単体で監視を行いますが,メモリ上に直近60秒の情報を保持するのみで保存しないため,InfluxDBとよく組み合わせられています*1.このcAdvisorは実はPrometheusに対応しており,デフォルトでhttp://cAdvisorへのアドレス:8080/metricsで各種のメトリクスを取得できます.

github.com

一つのDockerホストに一つずつcAdvisorが起動していれば後はまとめて叩いて回ってデータを集計するだけでいいというわけですね(うちにはホスト一つしか無いですが

Grafana

かっこいいダッシュボードを作るアプリケーションです(ざっくり

grafana.org

テンプレートが多数公開されており,それらをカスタマイズするだけで十分な機能を得られます.

環境

  • Ubuntu Server 16.04 LTS
  • Docker version 1.13.1
  • Docker compose version 1.8.0

設定

今回は全てDockerコンテナとして建てます.
ディレクトリ構造は以下の様にします.

.
├── docker-compose.yml
├── grafana
└── prometheus
    └── prometheus.yml

外側からアクセスするGrafanaと(一応)Prometheusには静的なIPを振っておきます*2.cAdvisorは直接触らないので,Dockerのネットワーク内に閉じ込めておきます.
以下の様なネットワークを作っておきます.

$ docker network create -d bridge -o "com.docker.network.bridge.name"="monitor_nw" monitor_nw

また,下記の過去記事で作成したmacvlanドライバのdmz_nwを使用します.

poyo.hatenablog.jp

Prometheusの設定

がつがつdocker-compose.ymlを書いていきます.

version: "2"
services:
  prometheus:
    image: prom/prometheus
    container_name: prometheus
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    expose:
      - "9090"
    networks:
      default:
        aliases:
          - prometheus
      dmz_nw:
        ipv4_address: xxx.xxx.xx.y
    restart: always
networks:
  default:
    external:
      name: monitor_nw
  dmz_nw:
    external:
      name: dmz_nw

macvlanでIPアドレスを割り振っているのでホストのポートとのマッピングはしていません.

設定ファイルであるprometheus.ymlはとりあえず最低限のことを書いておきます.
prometheus自身のメトリクスを取得する設定,後述のnode-exporterとcAdvisorから情報を取得する設定です.15秒間隔で情報を取りに行くようにしています.

global:
  scrape_interval: 15s
  external_labels:
    monitor: "monitor"

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["prometheus:9090"]
  - job_name: "node"
    static_configs:
      - targets: ["ホストのアドレス:9100"]
        labels:
          group: "docker-host"
  - job_name: "docker"
    static_configs:
      - targets: ["cadvisor:8080"]
        labels:
          group: "docker-container"

localhostを指定するとうまく動かないので,わざわざホストのアドレスも直打ちしています.
詳しい設定は公式ドキュメントを参照してください.

node-exporterの設定

node-exporterはホストの様々な情報を取得するexporterです.そのため,ホストのルートディレクトリをマウントする必要があります..また,hostネットワークを使用する必要があるため,ホストのポートとのマッピングを行いアクセスできるようにしています.

# 省略
  node-exporter:
    image: prom/node-exporter
    container_name: node-exporter
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    ports:
      - "9100:9100"
    network_mode: host
    restart: always
# 省略

cAdvisorの設定

権限を多く要求する怖いコンテナです.外側から直接アクセスできないようにDockerネットワークに封じ込めます.

# 省略
  cadvisor:
    image: google/cadvisor:latest
    container_name: cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro
    expose:
      - "8080"
    privileged: true
    networks:
      default:
        aliases:
          - cadvisor
    restart: always
# 省略

特にprivileged: trueが怖いのですが,僕の環境ではこれをオンにしないと動きませんでした*3

Grafanaの設定

最後にフロントエンドのGrafanaをセットアップします.今回はわざとしていませんが,過去記事のnginxとdocker-genを組み合わせたシステムでサブドメインを割り当てることも出来ると思います.
また,普通に起動するとusernameがadmin,パスワードもadminの状態になっており,サインアップも勝手に出来るようになっているので環境変数でそのあたりを制御します.

# 省略
  grafana:
    image: grafana/grafana
    container_name: grafana
    volumes:
      - ./grafana:/var/lib/grafana
    networks:
      default:
        aliases:
          - grafana
      dmz_nw:
        ipv4_address: xxx.xxx.xx.z
    restart: always
    environment:
      GF_SECURITY_ADMIN_USER: hoge
      GF_SECURITY_ADMIN_PASSWORD: fuga
      GF_USERS_ALLOW_SIGN_UP: "false"
      GF_USERS_ALLOW_ORG_CREATE: "false"
# 省略

GF_SECURITY_ADMIN_USERGF_SECURITY_ADMIN_PASSWORDがそれぞれ初期管理ユーザのユーザ名とパスワードになります.
GF_USERS_ALLOW_SIGN_UPはサインアップの無効化で,トップページからサインアップの項目が消えます.GF_USERS_ALLOW_ORG_CREATEは管理権限のあるユーザ以外のorgnizationの作成を無効にします.

起動

$ docker-compose up -d

この状態でまずprometheusに割り当てたアドレスxxx.xxx.xx.y:9090にアクセスして表示されるかを確認します.

次に,Grafanaに割り当てたxxx.xxx.xx.z:3000を開いて設定したユーザ名とパスワードでログインします.DataSourceを追加するときソースの種類をPrometheusで選択するとhttp://localhost:9090がサジェストされますがこれは使いません.prometheusで名前解決できるようになっているので,http://prometheus:9090/を指定します.

Grafanaのテンプレートは以下のものを使用しました.

grafana.net

何もいじっていない状態で以下の様になりました.loadの値が取れていませんが,まぁおいおい自分でいじくっていきたいと思います.

f:id:pudding_info:20170301005602p:plain

まとめ

思ったより簡単に値を取るところまではできました.後はGrafanaからクエリを叩いて表示していくだけです.難しそう.

また今回はAlertmanagerを含めていません.ここまではcAdvisor + InfluxDBでもできることになってしまうので,次はアラートの設定もしていこうと思います.

*1:この場合アラートなどの機能は無いので,今回はPrometheusのエンドポイントとしてのみ使用します

*2:取得できるメトリクスを見たいのと,クエリを簡単に確かめたいため.

*3:もしかしてたまたま?他の人の例では見ないので,もしかしたら勘違いかもしれないです.