FluentdとOpenSearchによる中央集権的ログ管理システムの構築:ELK Stackに代わる「軽量」なソリューション

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

ログ管理とSSHの悩み

アプリケーションが500エラーを吐くたびに、ターミナルを開いてサーバーにSSHし、tail -fで複雑なログファイルを追いかける光景は、エンジニアにとって馴染み深いものでしょう。1台や2台のサーバーを管理するだけならこれでも問題ありません。しかし、システムが肥大化し、数十台のVPSでマイクロサービスが稼働するようになると、エラーの原因を探すためにウィンドウをあちこち切り替える作業は、まさに苦行となります。

私は以前、15台のサーバークラスターをPrometheusGrafanaで管理していました。この構成は異常を素早く検知するのには役立ちますが、CPU使用率が90%に跳ね上がったなどの「いつ」異常が起きたかしか教えてくれません。アプリケーションが「なぜ」クラッシュしたかを知るには、やはり手動でログを読み漁る必要がありました。その時、真の中央集権的ログ管理システム(Centralized Logging)が必要だと痛感したのです。

なぜELK StackではなくFluentdとOpenSearchを選ぶのか?

ログ管理といえば、ELK Stack(Elasticsearch – Logstash – Kibana)が筆頭に挙げられます。しかし、一つ大きな問題があります。ELKは非常にリソースを消費する点です。LogstashはJVM上で動作するため、起動するだけで約500MBから1GBのRAMを消費してしまいます。

低価格なVPSでELKの維持に苦労した後、私は**Fluentd**と**OpenSearch**のコンボに乗り換えました。これが「優れている」理由は以下の通りです:

  • Fluentd: C言語とRubyで書かれているため非常に軽量です。Logstashと同等のログ処理を行うのに、わずか40MB〜100MB程度のRAMしか消費しません。
  • OpenSearch: Elasticsearchからフォークされたオープンソース版です。高速な検索能力はそのままに、ライセンス面(Apache 2.0)でよりフレンドリーになっています。
  • エコシステム: Fluentdには500以上のプラグインがあります。わずか数行の設定で、S3からSlack、Telegramまで、どこにでもログを飛ばすことができます。

システムの準備

具体的なイメージを掴みやすくするため、Docker Composeを使用して以下の構成からなる実践的な環境を素早く構築します:

  1. OpenSearch: データ保存と検索の心臓部。
  2. OpenSearch Dashboards: ログを確認するための直感的なインターフェース(Kibanaの代替)。
  3. Fluentd: ログを収集してストレージに転送するエージェント。

Docker ComposeによるOpenSearchとFluentdのインストール

まず、プロジェクトディレクトリを作成します。Dockerを使えば、将来的にスケールさせたりサーバーを移転したりする際も、フォルダーをコピーするだけで即座に動作させられるので便利です。

version: '3'
services:
  opensearch:
    image: opensearchproject/opensearch:latest
    container_name: opensearch
    environment:
      - cluster.name=opensearch-cluster
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m" # 軽量化のためRAMを512MBに制限
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - 9200:9200

  opensearch-dashboards:
    image: opensearchproject/opensearch-dashboards:latest
    container_name: opensearch-dashboards
    ports:
      - 5601:5601
    environment:
      OPENSEARCH_HOSTS: '["https://opensearch:9200"]'

  fluentd:
    build: ./fluentd
    container_name: fluentd
    volumes:
      - ./fluentd/conf:/fluentd/etc
    links:
      - "opensearch"
    ports:
      - "24224:24224"
      - "24224:24224/udp"

重要な注意点: オリジナルのFluentdにはOpenSearch用のプラグインが標準搭載されていません。そのため、このプラグインを追加インストールするための専用のDockerfileを作成する必要があります。

# ./fluentd/Dockerfile ディレクトリ
FROM fluent/fluentd:v1.16-debian-1
USER root
RUN gem install fluent-plugin-opensearch
USER fluent

ログを「飲み込む」ためのFluentd設定

ここではデータフローを定義します。Fluentdにポート24224で待機させ、OpenSearchに転送するように指示します。./fluentd/conf/fluent.confファイルを作成します。

<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match *.**>
  @type opensearch
  host opensearch
  port 9200
  scheme https
  user admin
  password admin
  ssl_verify false
  logstash_format true
  logstash_prefix itfromzero-logs
  flush_interval 5s
</match>

この設定では、flush_interval 5sとしています。これにより、ログがほぼ即座に転送され、待つことなくリアルタイムでデバッグが可能になります。

成果の確認

docker-compose up -dを実行し、約1分待ちます。http://your-ip:5601にアクセスし、アカウントadmin/adminでログインします。

ログを表示するには、次の3つのステップに従ってください:

  1. Stack Management -> Index Patternsに移動します。
  2. 新しいパターンとして itfromzero-logs-* を作成します。
  3. Discover タブを開いて、成果を確認しましょう。

試しにダミーのログを送信してみましょう:

echo '{"message": "IT From Zeroからのテストログ", "level": "info"}' | fluent-cat debug.test

ログが即座にWebインターフェースに表示されます。何万行もの白黒のテキストの中から必死にgrepするよりも、ずっと快適なはずです。

実践から学んだ教訓

このシステムを導入する際、いくつか学んだ教訓を共有します:

  • バッファは保険: <buffer>の設定を追加しましょう。OpenSearchが一時的にダウンしても、Fluentdがログをディスクに保存し、復旧後に再送してくれるため、貴重なデータの消失を防げます。
  • アクセス権限エラー: Fluentdに/var/logから直接ファイルを読み取らせる場合は、fluentユーザーにread権限があることを確認してください。私は以前、ログファイルのchmodを忘れただけで午後を丸々潰したことがあります。
  • Docker Log Driverの活用: 他のサーバー上のすべてのDockerコンテナを、中央のFluentdへ直接ログを飛ばすように設定できます。これにより、各子ノードに追加のエージェントをインストールする必要がなくなり、非常にスリムな構成になります。

中央集権的ログシステムの構築は、DevOpsやSREの分野でさらに前進するために避けて通れないステップです。FluentdとOpenSearchがあれば、低スペックなVPSでもスムーズに動作する、強力かつ軽量な武器を手に入れることができます。

Share: