Docker Swarmの監視:PrometheusとcAdvisorでReplicaとRolling Updateを診断する

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

データなしでDocker Swarmを運用する恐怖

初めてプロジェクトにDocker Swarmを導入した際、些細なミスのせいで徹夜したことがあります。当時は、Swarmがオーケストレーションをうまくやってくれるので、サービスが停止しても自動で復活するから心配ないと思っていました。しかし、現実はもっと過酷でした。設定ミスでサービスがCrashLoopBackOffに陥り、Swarmが再起動とクラッシュを繰り返したのです。サーバーのCPU使用率は95%に跳ね上がり、ログがディスクを埋め尽くしていることに、顧客から苦情の電話が来るまで気づきませんでした。

モニタリングなしで10〜15ノードのクラスターを管理するのは、霧の中を運転するようなものです。以前は各マネージャーノードにSSHで入り、docker service lsを何度も打ち込んで状態を確認していました。この手動の方法は非常に時間がかかり、ミスも起きやすいです。今ではダッシュボードを見るだけで、どのサービスのレプリカが不足しているか、どのノードが過負荷かがすぐに分かります。

3つのツール:Prometheus、cAdvisor、Docker Swarm

効果的な監視を行うには、個別にインストールするのではなく、自動的にデータを収集する仕組みが必要です。私は、Swarm自体の機能を活用して監視スタックを構築する方法を選びました。

  • cAdvisor (Container Advisor): 各ノードに常駐する「エージェント」のような存在です。各コンテナのCPU、RAM、ネットワークなどの統計情報を抽出します。Swarmでは、全ノードを漏れなくカバーするためにmode: globalで実行します。
  • Prometheus: 中央の「脳」の役割を果たします。定期的にcAdvisorにアクセスしてデータを取得(プル・メカニズム)し、時系列データベースに保存します。
  • Docker Engine Metrics: バージョン17.05以降、DockerはPrometheus形式のメトリクスを出力できるようになりました。この機能を有効にすることで、クラスター全体の真の状態を把握できます。

データ出力のためのDocker Engine設定

デフォルトでは、Dockerのメトリクスポートは閉じられています。Prometheusがレプリカ数のデータを読み取れるようにするには、すべてのノード/etc/docker/daemon.jsonファイルを編集する必要があります。

{
  "metrics-addr" : "0.0.0.0:9323",
  "experimental" : true
}

修正後、次のコマンドでDockerを再起動します:

sudo systemctl restart docker

重要な注意点:0.0.0.0:9323ポートを開放すると、サーバーがパブリックIPを持っている場合にセキュリティリスクが生じる可能性があります。ファイアウォール(UFW/Iptables)を使用して、クラスター内の内部IPのみがこのポートにアクセスできるように制限すべきです。

監視スタックのデプロイ

個別のコマンドを実行する代わりに、すべてをmonitoring-stack.ymlファイルにまとめます。この方法の利点は、一貫性が高いことです。以下は、イメージしやすいように簡略化した設定です:

version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - /var/run/docker.sock:/var/run/docker.sock:ro
    ports:
      - "9090:9090"
    networks:
      - monitor-net
    deploy:
      placement:
        constraints: [node.role == manager]

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    networks:
      - monitor-net
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    deploy:
      mode: global
      resources:
        limits:
          memory: 128M

networks:
  monitor-net:
    driver: overlay

Prometheusにおけるサービスディスカバリの威力

Swarm環境では、コンテナは頻繁にノード間を移動します。IPアドレスが絶えず変わるため、設定ファイルに静的なIPを記述することはできません。Prometheusは、dockerswarm_sd_configs機能によってこの問題を解決します。

下図は、Prometheusが自動的にノードを検出するための設定例です:

scrape_configs:
  - job_name: 'docker-swarm'
    dockerswarm_sd_configs:
      - host: unix:///var/run/docker.sock
        role: nodes
    relabel_configs:
      - target_label: __address__
        replacement: 127.0.0.1:9323

docker.sockファイルをPrometheusコンテナにマウントするのを忘れないでください。このステップを怠ると、Prometheusはアクセスを拒否され、Docker Swarmに稼働中のノードリストを問い合わせることができなくなります。

実践的なRolling Updateとレプリカの監視

データが収集されたら、通常は以下の3つの実践的なシナリオに注目します:

1. レプリカ不足のアラート

5つのレプリカを要求しているのに3つしか動いていない場合、システムは危険な状態にあります。以下のクエリを使うと、不足しているサービスを特定できます:

engine_daemon_swarm_service_tasks_total{state="running"}

2. Rolling Updateの制御

docker service updateを実行した際、新しいバージョンにバグがあるとアップデートプロセスがハングすることがあります。私はengine_daemon_container_states_containersメトリクスを監視しています。アップデート後にrestarting状態が急増した場合は、サービスの中断を防ぐために即座にロールバックを行います。

3. ノードのヘルスチェック

dockerswarm_node_statusメトリクスは非常に便利です。かつて、あるノードのネットワーク接続が切れましたが、Swarmがそのノードにトラフィックを振り分け続け、502エラーが多発したことがありました。Prometheusからのアラートのおかげで、2分以内に発見して対処することができました。

最後に

監視を設定するのは、単にきれいなグラフを描くためではありません。それは、夜ぐっすり眠るためのツールです。不安に怯える代わりに、Prometheusにシステムを見守らせましょう。もし、あなたのクラスターが本番環境で稼働しているのにcAdvisorやPrometheusを導入していないなら、今日30分かけてインストールしてください。それが将来、何時間ものデバッグの苦労からあなたを救ってくれるはずです。

Share: