Ubuntu 26.04 上に Cephadm で構築した Ceph クラスターで、logrotate.service が終了コード 1 になっていました。原因は、ホスト側の ceph-common と cephadm が、同じ /var/log/ceph/cephadm.log をそれぞれローテーション対象として定義していたことです。
今回発生していたのは、ログローテーション機能そのものの停止ではありません。cephadm.log のローテーションは成功していた一方で、設定競合が残っていたため、logrotate プロセス全体が失敗判定になっていました。個別処理の結果とジョブ全体の終了状態が一致しない事例です。
| 対象 | 確認結果 |
|---|---|
cephadm.log のローテーション | 成功 |
ceph-common の定義 | 重複エラー |
logrotate.service | 終了コード 1 |
| Ceph クラスター | HEALTH_OK |
確認した環境
| 項目 | 内容 |
|---|---|
| OS | Ubuntu 26.04 |
| Ceph クラスター | Ceph 20.2.1 Tentacle |
ホスト側 ceph-common | 20.2.0-0ubuntu2 |
| 構築方式 | cephadm |
| ログ管理 | systemd-journald、Grafana Alloy、Loki、Grafana |
| 構成管理 | Ansible |
Cephadm 環境では、Ceph daemon はコンテナとして動作します。一方、ホスト OS には Ceph CLI やクライアント機能を利用するための ceph-common がインストールされていました。
そのため、コンテナ内の Ceph とホスト側の ceph-common でバージョン表示が異なる場合があります。今回もクラスター側は Ceph 20.2.1、ホスト側は 20.2.0 でしたが、このバージョン差を競合の直接原因と確定したわけではありません。本記事では、この環境で実際に確認した設定ファイルの組み合わせと挙動を扱います。
ログ集中管理から logrotate の異常を発見した
異常は Ceph のヘルスチェックではなく、ホスト OS のログから発見しました。ログは次の経路で集約しています。
systemd-journald
-> Grafana Alloy
-> Loki
-> Grafanalogrotate.timer から起動された logrotate.service には、次のエラーが記録されていました。
error: ceph-common:1 duplicate log entry for /var/log/ceph/cephadm.log
error: found error in file ceph-common, skippingsystemd 上の状態も失敗となっていました。
Active: failed (Result: exit-code)
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf
status=1/FAILURE状態確認、該当時間帯のログ、設定解析を順に確認します。
sudo systemctl status logrotate.service --no-pager -l
sudo journalctl -u logrotate.service --since "3 hours ago" --no-pager
sudo logrotate --debug /etc/logrotate.confsystemctl status でサービス全体の失敗を確認し、journalctl と logrotate --debug で原因を cephadm.log の重複定義まで絞り込みました。
原因はワイルドカードと個別パスの重複だった
Cephadm サーバーには、2 つの logrotate 定義が存在していました。
ceph-common 側の定義
/etc/logrotate.d/ceph-common/var/log/ceph/*.log {
rotate 7
daily
compress
sharedscripts
missingok
notifempty
su root ceph
}cephadm 側の定義
/etc/logrotate.d/cephadm/var/log/ceph/cephadm.log {
rotate 7
daily
compress
missingok
notifempty
su root root
}対象パスの関係は次のとおりです。
/etc/logrotate.d/ceph-common
-> /var/log/ceph/*.log
-> /var/log/ceph/cephadm.log
/etc/logrotate.d/cephadm
-> /var/log/ceph/cephadm.logceph-common のワイルドカードと cephadm の個別指定が、同じ実ファイルへ展開されていました。
エラーメッセージから確定できる範囲
エラーは、重複を検出した設定ファイルとして ceph-common を示しています。この実行結果から確定できるのは次の点です。
ceph-commonの定義を処理した時点でcephadm.logが重複対象として検出されたceph-commonの設定ファイルが正常に処理されなかった- 設定エラーが存在したため logrotate 全体が終了コード 1 になった
一方、今回の調査では、/etc/logrotate.d/ 配下の厳密な読み込みログ、サービス実行時の LANG と LC_COLLATE、対象バージョンのソート実装を記録していません。そのため、なぜ ceph-common 側で重複が検出されたのかを、ファイル名の並び順やロケールから推測しません。
同様の事象を再調査する場合は、設定変更前に次の出力を保存します。
sudo logrotate --debug /etc/logrotate.conf 2>&1 | grep 'reading config file'
systemctl show logrotate.service -p Environment -p EnvironmentFiles
sudo systemctl cat logrotate.service
sudo systemctl show-environmentceph-common のワイルドカードが管理する実ファイルを確認した
/etc/logrotate.d/ceph-common を削除する前に、そのワイルドカードが cephadm.log 以外のログを管理していないか確認しました。
sudo find /var/log/ceph -maxdepth 1 -type f -name '*.log' -printf '%f|%s bytes\n' | sort確認時点で一致したのは次の 1 ファイルだけでした。
cephadm.log|228908 bytes次のファイルは /var/log/ceph/*.log に一致しません。
/var/log/ceph/cephadm.log.1.gz
/var/log/ceph/cephadm.log.2.gz
/var/log/ceph/<FSID>/ceph-osd.0.log
/var/log/ceph/<FSID>/ceph-volume.log*.logは末尾が.log.1.gzや.log.2.gzのファイルに一致しない- glob はサブディレクトリを再帰的に検索しない
- FSID 配下のログはクラスター固有の別定義が管理している
| ログ | 管理する定義 |
|---|---|
/var/log/ceph/cephadm.log | /etc/logrotate.d/cephadm |
/var/log/ceph/<FSID>/*.log | /etc/logrotate.d/ceph-<FSID> |
Ceph 20 Tentacle の公式ドキュメントでは、Cephadm 自身のログがデフォルトで /var/log/ceph/cephadm.log に記録され、ファイル出力を有効にした Ceph daemon のログが /var/log/ceph/<cluster-fsid> に配置されると説明されています。
公式ドキュメントに記載されたクラスタ固有の logrotate 定義は /etc/logrotate.d/ceph.<cluster-fsid> ですが、今回のホストで確認したファイル名は /etc/logrotate.d/ceph-<FSID> でした。区切り文字が異なるため、ファイル名を決め打ちせず、実際の配置を確認します。
sudo grep -RIn '/var/log/ceph' /etc/logrotate.conf /etc/logrotate.d失敗期間中も cephadm.log はローテーションされていた
logrotate.service が失敗しているという事実だけでは、個々のログが処理されたかどうかは判断できません。状態データベース、ローテーション済みファイル、新旧ログのタイムスタンプを確認しました。
logrotate の状態データベースには次の値が記録されていました。
"/var/log/ceph/cephadm.log" 2026-7-11-0:24:41時刻を比較しやすい形式へ直すと 2026-07-11 00:24:41 です。ローテーション後には /var/log/ceph/cephadm.log.1.gz が生成されていました。
| 確認対象 | 値 |
|---|---|
| 旧ログの最初 | 2026-07-10 00:49:30 |
| 旧ログの最後 | 2026-07-11 00:24:30 |
| 旧ログの行数 | 18,977 行 |
| 状態データベースの処理時刻 | 2026-07-11 00:24:41 |
| 新ログの最初 | 2026-07-11 00:25:32 |
旧ログが cephadm.log.1.gz へ移され、その後、新しい cephadm.log への記録が再開したことを確認できました。
ceph-common definition
-> duplicate detected
-> definition skipped
cephadm definition
-> cephadm.log rotated
logrotate process
-> exit code 1 because a configuration error remained実際の影響は日次ジョブの失敗状態だった
Ceph クラスターの状態は正常でした。
sudo ceph healthHEALTH_OK今回確認した影響は次の範囲です。
logrotate.serviceが毎日failedになる- systemd 上に失敗状態が残る
- 同じ設定エラーが継続的に通知される
ceph-common側の定義が正常に処理されない- 別の logrotate 障害が発生した場合に既知の失敗状態と区別しにくい
一方、Ceph のデータパス停止、クラスターのヘルス異常、cephadm.log のローテーション停止、ログの継続的な肥大化、ログデータの消失は確認されませんでした。緊急復旧ではなく、設定競合を解消し、日次ジョブの終了判定を実際の運用状態へ合わせるための修正です。
採用した対応は競合する定義だけを削除すること
ceph-common パッケージは残し、Cephadm サーバーにある競合定義だけを削除しました。
/etc/logrotate.d/ceph-commonAnsible では次のように期待状態を定義できます。
- name: Remove conflicting ceph-common logrotate definition
become: true
ansible.builtin.file:
path: /etc/logrotate.d/ceph-common
state: absentCephadm サーバーと Ceph クライアントでは配置される定義が異なるため、この処理は Cephadm サーバーへ限定します。
| ホスト | ceph-common 定義 | cephadm 定義 | 競合 |
|---|---|---|---|
| Cephadm サーバー | あり | あり | あり |
| Ceph クライアント | あり | なし | なし |
ceph-common パッケージを削除しなかった理由
ceph-common には Ceph CLI とクライアント機能が含まれます。Cephadm サーバーでも次の管理コマンドを使用するため、パッケージそのものは必要です。
ceph health
ceph status
ceph orch host ls
ceph orch ps不要だったのは、cephadm 専用定義と対象が重複していた logrotate 定義です。修正単位をパッケージ全体から設定ファイルへ絞り、さらにその設定ファイルが管理する実ログを確認しました。
package
-> configuration file
-> actual log files matched by the configuration設定ファイル単位まで絞っても、ワイルドカードがほかの実ログを担当していないか確認しなければ、変更範囲を適切に限定したとは判断できません。
conffile の削除状態を Ansible で管理する
/etc/logrotate.d/ceph-common は dpkg が管理する conffile です。dpkg は、前回のパッケージに含まれた内容、ホスト上の現在の内容、新しいパッケージに含まれる内容を比較し、MD5 ダイジェストを使って変更状態を判定します。
管理者が conffile を削除した場合、その欠落自体がローカル変更として扱われ、通常のアップグレードでは自動的に復元されません。ただし、ホスト再構築、OS イメージからの再展開、purge 後の再インストール、--force-confmiss、手動復元、パッケージ側の管理方式変更では再配置される可能性があります。
Ansible で state: absent を宣言する目的は、通常のパッケージ更新だけへの対策ではありません。ホスト再構築を含めたライフサイクル全体で、Cephadm サーバーの期待状態を再現するためです。
修正後の検証
logrotate の設定解析
sudo logrotate --debug /etc/logrotate.confrc=0
duplicate log entry: nonesystemd 上の実行結果
sudo systemctl reset-failed logrotate.service
sudo systemctl start logrotate.service
sudo systemctl show logrotate.service -p ActiveState -p SubState -p Result -p ExecMainStatusActiveState=inactive
SubState=dead
Result=success
ExecMainStatus=0logrotate.service は処理後に常駐しないため、成功後の inactive/dead は正常です。成功判定には Result=success と ExecMainStatus=0 を使用します。
対象ログと定義の網羅性
sudo find /var/log/ceph -type f -name '*.log' -printf '%p\n' | sort
sudo grep -RIn '/var/log/ceph' /etc/logrotate.conf /etc/logrotate.d| ログ | 修正後の管理定義 |
|---|---|
/var/log/ceph/cephadm.log | /etc/logrotate.d/cephadm |
/var/log/ceph/<FSID>/*.log | /etc/logrotate.d/ceph-<FSID> |
ceph-common の定義を削除した後も、確認対象となった Ceph ログには、それぞれ有効な管理定義が残っていました。
Ceph と Ansible の状態
sudo ceph healthHEALTH_OKAnsible を 2 回実行し、2 回目が changed=0、failed=0 になることも確認しました。
| 検証対象 | 結果 |
|---|---|
| logrotate の設定解析 | 成功 |
| systemd の実行結果 | 成功 |
| 対象ログの網羅性 | 未管理ログなし |
| Ceph クラスター | HEALTH_OK |
| Ansible の冪等性 | changed=0 |
ほかの環境へ適用する時の判断基準
今回のパッケージ構成やファイル名を、すべての Cephadm 環境へそのまま適用することはできません。Ceph リリース、ディストリビューション、パッケージ提供元によって、logrotate 定義やファイル名が異なる可能性があります。
一方、次の調査方法はほかの環境にも適用できます。
- systemd の終了結果と個別ログの処理結果を分けて確認する
- ワイルドカードを実ファイルへ展開して対象を確定する
- 重複定義を削除する前に、ほかのログを管理していないか確認する
- 修正後にもログと管理定義の対応関係を再確認する
- パッケージ全体ではなく、競合している設定と責務まで修正単位を絞る
- 未取得の読み込み順や内部実装をファイル名だけから推測しない
logrotate の調査では、設定ファイルの解析結果、個別ログの処理結果、プロセス全体の終了結果を分けて考えます。これらは常に同じ結果になるとは限りません。
参考情報
- Ceph Documentation 20 Tentacle – Cephadm Operations
- Ceph Documentation 20 Tentacle – Enable Ceph CLI
- Debian Policy Manual – Automatic handling of configuration files by dpkg
まとめ
今回の問題は、ceph-common と cephadm が同じ cephadm.log を管理していたことによる設定競合でした。cephadm.log 自体はローテーションされていましたが、重複エラーが残ったため、logrotate プロセス全体は終了コード 1 になっていました。
対応では、汎用定義が管理する実ログを確認したうえで、ceph-common パッケージを残し、競合する logrotate 定義だけを Cephadm サーバーから削除しました。修正後には、同じログが複数の定義から管理されていないことと、必要なログが未管理になっていないことを両方確認しています。
設定競合の解消では、エラーメッセージを消すだけでは不十分です。二重管理を取り除くことと、管理対象の網羅性を維持することを、変更後の実状態から確認する必要があります。


