「サーバーごとにバラバラなログ」という悩み
スタートアップのシステム管理者になりたての頃、私はマイクロサービスが稼働する10台のサーバー群を管理していました。システムに障害が発生するたびに、各サーバーにSSHでログインし、journalctl -u app -fを実行してエラーを追う日々でした。単一のサーバーなら問題ありませんが、連鎖的な障害(カスケード失敗)が発生したときは地獄でした。10個のターミナルを行ったり来たりしているうちに目が回り、結局どこがエラーの起点なのか特定できませんでした。
その時、私は確信しました。ログを1か所に集約しなければ、デバッグは「大海で針を探す」ようなものだと。しかし、当時のサーバーはRAMが1GBしかありませんでした。ELK(Elasticsearch – Logstash – Kibana)スタックやGrafana Lokiを導入しようものなら、サーバーはすぐにリソース不足で悲鳴を上げてしまいます。そこで必要だったのは、systemdのメタデータを保持でき、かつ極めて軽量で標準的なソリューションでした。
なぜsystemdのバイナリログは特別なのか?
Ubuntu、Debian、AlmaLinuxなどの現代的な Linuxディストリビューションの多くは、systemd-journaldを採用しています。/var/log/syslogにあるような純粋なテキストファイルとは異なり、systemdのログはバイナリ形式で保存されます。
この形式には大きな利点があります。プロセスID、ユニット名、マイクロ秒単位の正確な時間、実行ユーザーなどの情報がセットで保存されるのです。rsyslogを使用してログを転送する場合、通常はこれらをテキスト形式に変換する必要があります。しかし、それではjournalctlが活用できる豊かなデータ構造が失われてしまいます。
systemd-journal-remoteは、この問題を解決するために生まれました。これはネットワーク経由でバイナリファイルをそのまま転送します。クライアント側のすべてのメタデータは、集約サーバー(コレクター)に届いたときも完全に保持されます。
ログ管理手法の比較
設定に入る前に、一般的な選択肢を比較してみましょう:
- Rsyslog: 非常に軽量ですが、設定が複雑です。通常、ログをプレーンテキストに変換するため、メタデータが失われます。
- ELK Stack: 非常に強力ですが、リソースを大量に消費する「怪物」です。Elasticsearchのノードを安定して動かすには、最低でも4GBのRAMが必要です。
- Loki + Promtail: ELKよりはモダンで効率的ですが、サードパーティのプロンプト(エージェント)をインストールする必要があります。
systemd-journal-remoteは、最もミニマリストな選択肢です。systemdエコシステムの一部であり、外部データベースを必要とせず、消費するRAMもわずか数十MB程度です。
詳細な設定手順
ここでは、2台のサーバーがある構成を想定します:
- Log-Server (192.168.1.10): ログ受信側。
- Client-Node (192.168.1.20): ログ送信側。
ステップ 1: パッケージのインストール
このツールは、最小構成のインストールでは含まれていないことが多いです。両方のサーバーにインストールする必要があります。
Ubuntu/Debianの場合:
sudo apt update && sudo apt install systemd-journal-remote -y
RHEL/AlmaLinuxの場合:
sudo dnf install systemd-journal-remote -y
ステップ 2: Log-Server(受信側)の設定
内部ネットワーク内で迅速に展開するために、HTTPでリッスンするように設定します。注意:インターネット経由でログを転送する場合は、HTTPを使用しないでください。
ソケットを編集してポート19532を開放します:
sudo systemctl edit systemd-journal-remote.socket
以下の内容を追加します:
[Socket]
ListenStream=19532
サービスを有効化して起動します:
sudo systemctl enable --now systemd-journal-remote.socket
sudo systemctl start systemd-journal-remote.service
ログ保存ディレクトリに権限を付与します:
sudo mkdir -p /var/log/journal/remote
sudo chown systemd-journal-remote:systemd-journal-remote /var/log/journal/remote
ステップ 3: Client-Node(送信側)の設定
クライアント側では、systemd-journal-uploadを使用してログをプッシュします。
/etc/systemd/journal-upload.confファイルを開き、URLの行を修正します:
[Upload]
URL=http://192.168.1.10:19532
その後、サービスを起動します:
sudo systemctl enable --now systemd-journal-upload
ステップ 4: 結果の確認
Log-Serverに戻り、保存ディレクトリを確認します:
ls -l /var/log/journal/remote/
remote-192.168.1.20.journalという名前の新しいファイルが表示されるはずです。リモートログをリアルタイムで表示するには、次のように入力します:
journalctl --file /var/log/journal/remote/remote-192.168.1.20.journal -f
これで、クライアントサーバーからのすべてのログが、あたかもそのマシンで直接コマンドを打っているかのように、完全なメタデータ付きで表示されます。
運用における実践的なアドバイス
私は以前、ログが届かない原因の調査に午後の時間を丸々費やしたことがあります。注意すべき3つのポイントを挙げます:
- ファイアウォール: ポート19532を開放することを忘れないでください。
ufwを使用している場合は、すぐにsudo ufw allow 19532/tcpを実行しましょう。 - 書き込み権限:
systemd-journal-remoteがリモートディレクトリへの書き込み権限を持っていない場合、明確なエラーを出さずに停止することがあります。journalctl -u systemd-journal-remoteでログを確認してください。 - TLSセキュリティ: 信頼できない環境でログを転送する場合は、HTTPSが必須です。通信を暗号化し機密情報の漏えいを防ぐために、証明書(.pem)を作成する必要があります。
まとめ
ログの集約に、必ずしも重厚なシステムが必要なわけではありません。systemd-journal-remoteを使えば、強力で低リソースな「自家製」のソリューションが手に入ります。これは、トラブルのたびに各サーバーへ手動でSSHログインする手間を省き、よりプロフェッショナルなシステム管理を実現するための重要なステップとなるでしょう。

