Graylog:複数のLinuxサーバーからのログを集中管理・分析する

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

システムが大きくなるにつれたログ管理:誰もが避けたいが誰もが直面する問題

最初に2〜3台のサーバーをセットアップした頃は、各マシンにSSHで直接接続してtail -f /var/log/syslogでデバッグしていた。それで十分だった — サーバーが8台、15台と増えるまでは。深夜2時に本番環境でエラーが発生し、エラーメッセージを探すために各マシンにSSHしなければならないとき、それが集中ログ管理を本当に必要とする瞬間だ。

Graylogは「十分に痛い思い」をした後に本番環境に導入したものだ。6ヶ月間の実運用を経て、本当に役立ったことだけをまとめる — 公式ドキュメントのコピーではなく。

Graylogとは何か、なぜELK Stackを使わないのか?

率直に言おう:Graylogはすべてのサーバーからログを受け取り、OpenSearchにインデックス化し、単一のUIから検索とアラート作成を可能にする。10個のターミナルタブを開いて各マシンでgrepする光景はもう終わりだ。

アーキテクチャは3つの主要コンポーネントで構成される:

  • Graylog Server:ログの処理、パース、ルーティング
  • MongoDB:メタデータの保存 — 設定、ユーザー、ストリーム、アラート
  • OpenSearch(またはElasticsearch):全文検索エンジン — ログが実際に保存・クエリされる場所

ELK Stackはどうか?両方試した。ELKはカスタマイズ性が高いが、正しくセットアップするのに2〜3日かかる。Graylogなら半日で完了する。専任のDevOpsがいない小さなチームにとって、その差は大きい — 特にアラートとストリーム管理の面ではGraylogが明らかに優れている。

Docker ComposeでGraylogをインストールする

Docker Composeは最も手軽にGraylogを動かす方法だ。開発環境から小規模本番環境まで使っている — 1日50GB以下のログ量なら安定して動作する。

docker-compose.ymlファイルを作成する:

version: '3.8'
services:
  mongodb:
    image: mongo:6.0
    volumes:
      - mongodb_data:/data/db
    restart: unless-stopped

  opensearch:
    image: opensearchproject/opensearch:2.11.0
    environment:
      - discovery.type=single-node
      - DISABLE_SECURITY_PLUGIN=true
      - OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - opensearch_data:/usr/share/opensearch/data
    restart: unless-stopped

  graylog:
    image: graylog/graylog:5.2
    environment:
      - GRAYLOG_PASSWORD_SECRET=somepasswordpepper1234567890abc
      - GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
      - GRAYLOG_HTTP_EXTERNAL_URI=http://YOUR_SERVER_IP:9000/
      - GRAYLOG_ELASTICSEARCH_HOSTS=http://opensearch:9200
      - GRAYLOG_MONGODB_URI=mongodb://mongodb:27017/graylog
    depends_on:
      - mongodb
      - opensearch
    ports:
      - "9000:9000"        # Web UI
      - "12201:12201/udp"  # GELF UDP入力
      - "514:514/udp"      # Syslog UDP入力
    volumes:
      - graylog_data:/usr/share/graylog/data
    restart: unless-stopped

volumes:
  mongodb_data:
  opensearch_data:
  graylog_data:

重要:上記のGRAYLOG_ROOT_PASSWORD_SHA2は「admin」という文字列のハッシュ値だ。実際にデプロイする前に必ず変更すること:

echo -n "your_strong_password" | sha256sum | cut -d' ' -f1

スタックを起動する:

docker compose up -d
# Graylogが完全に起動するまで60〜90秒待つ
docker compose logs -f graylog

Web UIはhttp://YOUR_SERVER_IP:9000で起動する。adminと先ほど作成したパスワードでログインする。

ログを受け取るInputの作成

Web UIでSystem → Inputsを開く。まずこの2つのInputを作成する:

1. Syslog UDP(ポート514)

Syslog UDPを選び、bind addressを0.0.0.0、ポートを514に設定する。このInputはrsyslogから直接ログを受け取る — 高速でシンプル、追加エージェントのインストールは不要だ。

2. GELF UDP(ポート12201)

GELF UDPを選び、ポートを12201に設定する。GELF(Graylog Extended Log Format)は構造化されたJSONフォーマットだ — カスタムフィールドをサポートしており、Dockerコンテナのログやカスタムアプリケーションのログに適している。

クライアントサーバーでrsyslogを設定する

Graylogにログを送信する各Linuxサーバーでrsyslogを設定する:

sudo nano /etc/rsyslog.d/90-graylog.conf

ファイルに次の1行を追加する:

# すべてのログをUDP経由でGraylogに送信する
*.* @GRAYLOG_SERVER_IP:514;RSYSLOG_SyslogProtocol23Format

rsyslogを再起動してすぐにテストする:

sudo systemctl restart rsyslog

# テストメッセージを送信
logger -t test "Hello from $(hostname)"

Graylog Web UI → Searchを開き、source:自分のホスト名で検索する — 「Hello from…」メッセージが表示されれば完了だ。

GELF経由でDockerコンテナのログを送信する

Dockerの場合、監視が必要なサービスのdocker-compose.ymlにログドライバーを追加する:

services:
  my_app:
    image: my_app:latest
    logging:
      driver: gelf
      options:
        gelf-address: "udp://GRAYLOG_SERVER_IP:12201"
        tag: "my_app"

ストリームとアラートの作成

ストリームはGraylogで最も気に入っている機能だ。ルールに従ってログを専用の「チャンネル」にルーティングする — Nginx用、SSH認証用、アプリケーションエラー用にそれぞれ専用ストリームを用意する。サービスごとにデバッグする際、全体のログに埋もれることなく確認できるので非常に便利だ。

Streams → Create Streamでストリームを作成する。便利なルールの例:

  • Field source contains webserver-01 — 特定のサーバーのログをフィルタリング
  • Field message matches regex ERROR|CRITICAL|FATAL — すべてのエラーをキャッチ
  • Field facility equals auth — 認証ログのみ取得(SSH、sudo)

ストリームを作成したらAlert Conditionを追加する。例:「5分間に10件以上のERRORメッセージがあれば通知を送る」。Notificationと組み合わせてSlack、メール、webhookに送信できる — 好みに応じて設定すればいい。

正直に言うと:アラート疲れは最初から直面した現実の問題だ。閾値を低く設定しすぎてアラートが連続して発火し、やがてすべて無視するようになった。何度もチューニングが必要だった:閾値を上げ、AND条件を追加し、特定のソースをホワイトリストに入れる。得た教訓:高い閾値から始め、1〜2週間観察してシステムのベースラインを把握してから徐々に下げること。本番環境には独自のトラフィックパターンがある — どこかのブログの数値をそのままコピーしてはいけない。

6ヶ月の実運用後の結論

Graylogは「ログはどこに?」という問題を本当に効果的に解決する。半年間で気づいたこと:

  • インシデントのデバッグ時間が約30分から約5分に短縮 — 1つのUIでサーバーをまたいだ検索が可能になったため
  • 失敗した認証ログのアラートにより、SSHブルートフォース攻撃を2回検出できた
  • リテンションポリシー(30日以上経過したログを自動削除)によりディスク使用量を安定維持 — 突然のディスク枯渇を心配しなくて済む

事前に知っておくべき点:GraylogはRAMをかなり消費する。1ノードクラスターの場合、安定稼働に最低8GBが必要だった — OpenSearchだけで2〜4GBを消費する。スペックの低いサーバーの場合はGrafana Lokiを検討するといい:はるかに軽量で検索性能は少し劣るが、ほとんどのケースには十分だ。

予算があって20台以上のサーバーを管理しているなら — Graylogはまだ信頼できる選択だ。一度セットアップすれば長く使える。次に深夜2時にデバッグする時は、ずっと楽になるはずだ。

Share: