ログ管理とSSHの悩み
アプリケーションが500エラーを吐くたびに、ターミナルを開いてサーバーにSSHし、tail -fで複雑なログファイルを追いかける光景は、エンジニアにとって馴染み深いものでしょう。1台や2台のサーバーを管理するだけならこれでも問題ありません。しかし、システムが肥大化し、数十台のVPSでマイクロサービスが稼働するようになると、エラーの原因を探すためにウィンドウをあちこち切り替える作業は、まさに苦行となります。
私は以前、15台のサーバークラスターをPrometheusとGrafanaで管理していました。この構成は異常を素早く検知するのには役立ちますが、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を使用して以下の構成からなる実践的な環境を素早く構築します:
- OpenSearch: データ保存と検索の心臓部。
- OpenSearch Dashboards: ログを確認するための直感的なインターフェース(Kibanaの代替)。
- 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つのステップに従ってください:
- Stack Management -> Index Patternsに移動します。
- 新しいパターンとして
itfromzero-logs-*を作成します。 - 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でもスムーズに動作する、強力かつ軽量な武器を手に入れることができます。

