Ceph 関連のログが、journald から Grafana Alloy を経由して Loki へ大量に転送されていることが分かりました。最初に疑ったのは Ceph クラスターの障害でしたが、状態は HEALTH_OK で、OSD、PG、容量、I/O 処理に異常はありませんでした。
問題はストレージの状態ではなく、Ceph が出力するクラスタログの粒度でした。今回確認した Ceph 20.2.1 では、mon_cluster_log_level のデフォルト値が debug です。そのため、正常なクラスタ状態を繰り返す DEBUG レベルのログも、mon の journald から外部ログ基盤へ転送されていました。
debug がデフォルトであること自体は異常ではありません。ただし、製品のデフォルト値が、すべてのログ収集構成や通常運用に適しているとは限りません。そこで今回は、INFO、WARN、ERROR のログと Prometheus のメトリクス監視を維持しながら、通常運用では不要だった DEBUG レベルのクラスタログを発生源で抑制しました。
クラスタの異常ではなくログ粒度の問題だった
ログ量が急増した場合でも、ログ設定を変更する前にクラスターの健全性を確認します。障害によってログが増えているのであれば、先に原因となる OSD、PG、ネットワーク、容量、I/O の問題へ対処する必要があるためです。
ceph health detail
ceph -s今回の環境では HEALTH_OK を維持していました。したがって、ログを減らすことが障害を隠す対応にならないかを確認したうえで、クラスタログの設定へ進みました。
短い間隔で pgmap が出力されていた
mon の journald には、次のような pgmap が短い間隔で繰り返し記録されていました。
[DBG] pgmap ... active+clean ... used ... avail ... op/spgmap には、PG の状態、使用容量、空き容量、I/O レートなど、Ceph クラスターの状態を示す情報が含まれています。情報そのものが不要なわけではありませんが、正常時にほぼ同じ内容を約 2 秒間隔で外部ログ基盤へ保存し続ける必要性は低いと判断しました。
容量、PG、I/O の継続監視は Prometheus のメトリクスとして取得しています。定常状態をログとメトリクスの両方で細かく保持していたため、監視情報が重複していました。
mon_cluster_log_level が制御する範囲
今回確認した設定は mon_cluster_log_level です。Ceph 20.2.1 の設定定義では、クラスタログファイルや外部ログサーバーへ含める最低レベルを制御し、デフォルト値は debug、ランタイム変更可能な項目として定義されています。
ceph config get mon mon_cluster_log_leveldebug今回の環境で観測した経路を単純化すると、クラスタログは次のように Loki へ到達していました。
Ceph mgr
-> Ceph cluster log
-> Ceph mon
-> journald
-> Grafana Alloy
-> Loki一方、mgr などの daemon が標準エラーへ直接出力するログは、別の経路で journald へ入る場合があります。mon_cluster_log_level を変更しても、Ceph 関連ログがすべて停止するわけではありません。設定変更後も一部の pgmap が残ったのは、この出力経路の違いによるものでした。
通常運用では info を選んだ
通常運用では DEBUG レベルのクラスタログを常時保持する必要がなかったため、info へ変更しました。
ceph config set mon mon_cluster_log_level info設定値は次のコマンドで確認できます。
ceph config get mon mon_cluster_log_levelinfoこの項目はランタイム変更に対応しているため、ログレベルの変更だけを目的とした Ceph daemon の再起動は実施していません。クラスターを停止せず、通常運用のまま反映を確認しました。
Ansible では設定値を永続管理する
CLI で設定した値と構成管理の定義がずれないように、Ansible 側にも同じ設定を追加します。たとえば、Ceph の設定項目をリストで管理するロールでは次のように定義できます。
- who: mon
option: mon_cluster_log_level
value: infoロールは、この定義を ceph config set mon mon_cluster_log_level info として永続反映します。手動変更だけで終えると、再デプロイ時に構成管理の値へ戻る可能性があるため、実際の設定値と宣言された設定を一致させます。
抑制したログと残した監視
今回抑制したのは、クラスタログとして流れる DEBUG レベルのメッセージです。次の情報は引き続き残します。
- INFO、WARN、ERROR のクラスタログ
- daemon が別経路で journald へ出力するログ
- Ceph のヘルス状態と OSD、PG の状態確認
- Prometheus による容量、PG、I/O のメトリクス監視
- Loki に保存された障害調査用のイベントログ
mon_cluster_log_level は OSD や PG の動作を変更する設定ではありません。Ceph のデータ処理やヘルス判定、Prometheus exporter のメトリクス取得にも影響しません。
log_to_stderr = false にしなかった理由
ログ量を減らす方法として、標準エラーへの出力そのものを止める案もあります。
log_to_stderr = falseしかし、この方法では DEBUG だけでなく、同じ出力経路を使う INFO、WARN、ERROR まで失う可能性があります。今回の問題は標準エラーへログが出ること自体ではなく、通常運用では不要な DEBUG レベルのクラスタログが短い間隔で繰り返されていたことです。
出力経路を丸ごと停止する変更は、問題の範囲に対して影響が大きすぎます。障害時に必要な情報を残すため、出力先ではなくログレベルを変更しました。
Alloy 側の強制除外を先にしなかった理由
Grafana Alloy 側でメッセージを判定し、pgmap や特定の DEBUG ログを破棄することもできます。この方法なら Loki の保存量は減りますが、Ceph でのログ生成、journald への書き込み、Alloy による読み取りと判定は残ります。
文字列に依存する除外条件は、Ceph のバージョンアップでログ形式が変わった場合に機能しなくなる可能性もあります。発生元に正式なログレベル設定がある場合は、まず発生源で制御し、ログ基盤側のフィルターは発生元で制御できないログや複数製品に共通するルールへ使う方針にしました。
ログとメトリクスの役割を分ける
pgmap に含まれる容量、PG、I/O などの継続監視には、Prometheus のメトリクスが適しています。時間変化をグラフで確認でき、閾値によるアラートも設定できるためです。
一方、ログはイベントや状態変化の原因を調査するために使います。同じ正常状態を数秒間隔で記録し続けると、保存量が増えるだけでなく、障害時に確認すべき WARN や ERROR が定常ログへ埋もれます。ログとメトリクスを両方取得することではなく、何を数値として監視し、何をイベントとして記録するかを分けることが重要です。
障害調査時は debug に戻せる
通常運用では info を使用し、詳細なクラスタログが必要な障害調査時だけ、一時的に debug へ戻せます。
ceph config set mon mon_cluster_log_level debug調査が終わったら、設定を info へ戻し、ログ量が通常水準へ戻ったことを確認します。debug と info のどちらかを常に正解とするのではなく、通常運用と障害調査で必要な粒度を分けます。
設定変更後に確認すること
ログレベルを変更した後は、設定値だけでなく、Ceph と監視基盤の両方を確認します。
ceph config get mon mon_cluster_log_level
ceph health detail
ceph -s
journalctl --since "10 minutes ago" | grep -i pgmap- 設定値が
infoになっていること - Ceph が
HEALTH_OKを維持していること - mon 側の DEBUG レベルの
pgmapが減っていること - INFO 以上のログが Loki で確認できること
- Prometheus の容量、PG、I/O メトリクスが継続していること
- 別経路で出力される daemon ログを誤って異常と判断していないこと
今回の変更後は、mon 側へ繰り返し出力されていた DEBUG レベルの pgmap が停止し、Loki へ転送される Ceph 関連ログも明確に減りました。Ceph は HEALTH_OK を維持し、Prometheus の監視にも影響はありませんでした。
デフォルト設定が通常運用に適するとは限らない
Ceph だけでログを確認する構成と、journald のログを外部基盤へ常時転送する構成では、同じデフォルト値でも影響が異なります。ローカルで短期間保持するだけなら許容できるログ量が、Loki へ集約して長期間保持すると、転送量、保存量、検索時のノイズとして現れます。
重要なのは、デフォルト値を無条件に変更することではありません。クラスターが正常であること、DEBUG ログが通常監視と重複していること、INFO 以上のログとメトリクスを残せることを確認し、自分たちの監視構成と運用目的に合うログレベルを選びます。
参考情報
まとめ
Ceph 関連ログが Loki へ大量に転送されていても、直ちにストレージ障害とは限りません。今回の環境ではクラスターは HEALTH_OK で、原因は mon_cluster_log_level のデフォルト値 debug と、journald のログを外部基盤へ常時転送する構成の組み合わせでした。
mon_cluster_log_level を info へ変更することで、INFO、WARN、ERROR と Prometheus の監視を維持しながら、通常運用では過剰だった DEBUG レベルのクラスタログを発生源で抑制できました。出力経路を停止したり、Alloy で文字列を強制除外したりする前に、発生元のログレベルで必要な粒度を選ぶことが重要です。

