ログが増え続けてディスクが窮屈、でも“とりあえずlogrotateを入れた”だけだと不安。
本番で止まるのは避けたいし、監査やインシデント調査で「必要な時に、必要なログが、必要な期間ぶん」手元にある状態を保ちたい——多くの現場での本音はここにあります。
この記事は、迷いがちな設計ポイントを最初に整理し、最小構成から運用までを一息で見通せるようにまとめます。
難しい仕組みを増やすのではなく、保持期間・容量・トリガという“芯”を決め、後から規模や要件に応じてじわっと強くできる道筋を用意します。
読者像は、1台のWebサーバや小さなアプリから始めて、やがて複数サービス・コンテナ・集中管理へと広げていく人。
まずは日々の運用が軽くなる最低限の設計を押さえ、将来の拡張(journald・S3アーカイブ・監視連携)に繋がる土台を一緒に作っていきます。
ここでは詳細設定の解説に踏み込みすぎず、どの見出しで何を決めるのかを明確にします。
手を動かす段に入ったら、付録のテンプレートやチェックリストを“最初の一歩”として活用してください。
この記事のゴール
本記事でできるようになること
この章では、ログローテーションの設計を「怖くないもの」に変えることを目指します。
まずは、ログが増え続けてもディスクを圧迫しない仕組みを、自分の環境に合わせて最小限の設定から始められるようになります。
保持期間をどう決めるか。容量の上限をどう置くか。回転のきっかけをサイズ基準にするのか日次にするのか。
運用で迷いがちな三つの芯を、順番に決めていく考え方を身につけます。
さらに、設定を変えたあとにサービスを止めずに反映する方法や、意図どおりに回っているかを確認する手順も扱います。
いきなり詳しいオプションを全部覚える必要はありません。まずは「最小構成で安全に回る状態」を作り、そのうえで必要に応じて強くしていく道筋を学びます。
もし将来、コンテナやクラウドに広げることになっても、この考え方は変わりません。
ログの置き場、回し方、残し方を分けて考えられるようになることが、最大のゴールです。
本記事で到達したい“変化”を短くまとめます。
- 読めない設定ファイルが、読める/書けるに変わる
- いつどれだけ残すかを、自分の言葉で説明できる
- 回っているか不安、が、確認できるに変わる
対象読者と前提
対象は、サーバ運用を始めたばかりの方、あるいはアプリ運用を任されてログが気になり始めた方です。
Linuxの基礎コマンドや、サービスの再読込といった基本操作は触れたことがある前提にしますが、logrotate や systemd-journald の細かい知識は不要です。
専門用語はできるだけ避け、避けられない言葉は本文中でゆっくり説明します。
設定サンプルは一気に複雑にせず、まずは最小の形から示し、あとで必要な機能を一つずつ足していきます。
現場では、理屈よりも「壊さずに試せること」が役に立ちます。
本記事でも、試す前に結果を確認できる手順や、万一のときに元に戻せる考え方を大事にします。
読者のゴールは、設定を丸暗記することではありません。
自分の環境に合わせて「残す/捨てる」の線を引き、その線をドキュメントとしてチームに共有できること。ここまで行ければ、運用はグッと楽になります。
まず決める3点(設計の芯)
保持期間の決め方(法務・監査・運用)
最初に決めるのは「どれくらいの期間、ログを残すか」です。
ゴールはきれいな数字にすることではなく、必要な時に必要なログが取り出せる状態を保つことです。
保持期間は三つの観点で考えると迷いにくくなります。
一つ目は法務や監査の要件です。業種や契約によっては、一定の期間を残す義務や慣習があります。
二つ目はトラブルシュートの現実的な期間です。障害の再発や再現調査が何日後に起きやすいかを、これまでの経験から見積もります。
三つ目はストレージの制約です。無限には置けません。圧縮を使っても限度はあります。
具体的には、まず最小の安全値を決めます。たとえば「アプリのエラーログは30日」「アクセスログは14日」。
次に、重要なログだけ長く残す方針を足します。「課金や監査に関係するログは90日」といった具合に、ログの種類ごとに差をつけます。
最後に、保持期間を「世代数」と「日数」のどちらで表現するかを決めます。日次で回すなら日数、サイズで回すなら世代数のほうが直感的です。
どちらを採っても構いません。後続の容量上限と組み合わせて、現実的な落としどころに寄せていきます。
容量上限の決め方(絶対値/パーセンテージ)
保持期間が決まったら、次は「どれだけの容量まで許すか」です。
容量は“ディスク全体”と“ログディレクトリ(またはサービス単位)”の二段構えで上限を置くと、暴走に強くなります。
上限の表し方は二種類あります。
絶対値(例:5GBまで)と、パーセンテージ(例:ディスクの20%まで)です。
単一ディスクで運用しているサーバではパーセンテージが便利ですが、ログ専用のパーティションがあるなら絶対値のほうが読みやすくなります。
考え方として、まず“通常時の平均的な1日の増分”を見ます。
その増分に、保持したい日数を掛け合わせ、圧縮の効果(gzipやzstdでどの程度減るか)をざっくり見積もります。
見積もり値に余裕を足して、上限を設定します。余裕は20〜50%程度から始めると、実運用で調整しやすいでしょう。
一点だけ強調しておきます。
容量上限は「先に決めて、監視に入れる」ことが重要です。
ディスクが90%に近づいたら通知、95%で緊急、のように、自分たちのチームで意味が伝わるしきい値を決めておきます。
回転トリガ(size/daily/weekly/併用)の基準
ログをいつ回すかは、運用感に直結します。
大きく分けて「サイズで回す」「時間で回す」の二つ、それに“併用”があります。
サイズで回す方法は、急に増えるタイプのログに向いています。
アクセスが集中した時にだけ回り、普段は落ち着いているため、無駄なローテーションが減ります。
ただし、深夜に静かであることを前提にした分析バッチなどとはタイミングが合わない場合があります。
時間で回す方法は、毎日または毎週の決まった時刻に回す形です。
運用が読みやすく、日次集計やバックアップと合わせやすいのが利点です。
一方で、想定外の急増があると1ファイルが極端に大きくなることがあり、後処理が重くなることがあります。
併用は、両方の弱点を軽くできます。
「基本は毎日回すが、サイズが一定以上になったらその時点でも回す」という考え方です。
高トラフィックのWebサーバや、ピークの振れ幅が大きいサービスでは、この形が扱いやすいことが多いです。
ごく小さな比較を置いておきます。
| トリガ | 向いている例 | 注意点 |
|---|---|---|
| size | アクセスが日によって大きく変わるサイト | 回転の時刻が読みにくい |
| daily/weekly | 集計やバックアップの時間が決まっている運用 | 突発増加で単一ファイルが巨大化 |
| 併用 | 高トラフィックや突発的なスパイクがあるサービス | 設定が少し増えるが運用は安定 |
まとめると、
まず“時間”で回す前提を置き、スパイクに備えて“サイズ”の安全弁を足す。
これが初学者にも運用にもやさしい出発点です。
ログの棚卸し(インベントリ)
対象サービスと出力場所の洗い出し
設計を始める前に、まずは今どのサービスがどこへログを書いているかをはっきりさせます。
「アプリケーション」「Webサーバ」「データベース」「OSやミドルウェア」など、役割ごとに思い浮かべていき、実際のファイルパスやコマンドで確認します。
大切なのは、頭の中の想定ではなく、サーバ上の事実を見に行くことです。
たとえば nginx なら /var/log/nginx/、アプリなら /var/log/<app>/ やサービスの標準出力、OS なら journalctl で存在を確かめます。設定ファイルに書いたつもりでも、権限やパスの違いで想定外の場所に出ていることは珍しくありません。
最初は完全な一覧を作れなくても構いません。見つかったものから記録し、後で抜けを埋めていく姿勢で十分です。
誰が見ても同じ理解になるように、サービス名とログの場所を同じフォーマットで書き残しておきます。将来の運用や監査で、このメモが大きな助けになります。
フォーマット(text/JSONL/binary)と再読込方法
次に、そのログがどの形式で出力されているかを確認します。
素のテキストか、1行1オブジェクトの JSONL か、systemd のバイナリジャーナルか。形式がわかるだけで、後段の圧縮や集約、検索方法の選択がぐっと現実的になります。
もうひとつ重要なのが、ローテーション後にアプリへどう合図を送るかです。
多くのサービスは設定を再読込するシグナルやコマンドを持っています。nginx は reload、多くのアプリは SIGHUP、systemd 管理下なら systemctl kill -s HUP <service> のように扱えます。
この“再読込の作法”をサービスごとに把握しておくと、copytruncate に頼らず安全にファイルを切り替えられるようになります。
形式と再読込方法を並べて持っておくと、設計時の判断が速くなります。
| サービス | フォーマット | 再読込方法の例 |
|---|---|---|
| nginx | text | systemctl reload nginx |
| 自作API | JSONL | systemctl kill -s HUP myapi |
| system | binary(journal) | 設定変更後に systemctl restart systemd-journald が必要な場合あり |
重要度・想定増加量・監査要件の整理
最後に、各ログの“重み”を揃えます。
すべてを同じように扱うと、ディスクも運用コストもすぐに膨らみます。どれが短期でよく、どれが長期で必要か、ここで線を引きます。
重要度は、障害対応や顧客影響の大きさで判断します。エラーログやセキュリティ関連は高く、アクセスログは分析用途なら中、詳細デバッグは低めに置くと整理しやすくなります。
想定増加量は、過去数日のサイズや行数を見ておおまかに掴みます。急増しやすいログはサイズ基準を厚めに、安定しているログは日次基準を中心に考えると、後の運用が読みやすくなります。
監査要件は、契約や社内規程に依存します。もし明文化されていないなら、関係者に確認してメモを残しておきます。ここを曖昧にすると、いざという時に判断が揺れます。
この三点が決まると、保持期間と容量上限の目安が自然に浮かびます。
たとえば「エラーログは重要度高・増加量中・監査なし」なら、30〜90日を候補にして圧縮を前提に。
「アクセスログは重要度中・増加量高・分析用途」なら、14〜30日を基本にし、外部集約があるなら短めに切り替える、といった具合です。
棚卸しは一度で終わりではありません。
新しいサービスが増えたら追記し、増え方が変わったら数値を更新します。
“いまの姿”を見える化し続けることが、無理のないログ運用の土台になります。
ログ命名・レイアウト方針
ディレクトリ階層とパーミッション
ログの置き場所は、後から見つけやすく、誤って触れにくいことが大切です。
基本は /var/log/<サービス名>/ の下にまとめ、役割ごとにファイルを分けます。アプリ名が長い場合は略称で構いませんが、チームで意味が通じる名前に揃えます。
権限は「読みたい人だけが読める」を出発点にします。
たとえばディレクトリは 750、ファイルは 640 を目安にし、グループに運用担当を入れて閲覧権限を付与します。アプリの実行ユーザに書き込み権限があることを必ず確認してください。必要に応じて setfacl を使って、特定のグループだけ読み取り可能にするのも実務的です。
配置と権限の例を一つだけ示します。
| パス | 役割 | 所有者:グループ | perm |
|---|---|---|---|
| /var/log/myapp/ | アプリ用ルート | myapp:ops | 750 |
| /var/log/myapp/app.log | アプリ本体 | myapp:ops | 640 |
| /var/log/myapp/app.error.log | エラー詳細 | myapp:ops | 640 |
| /var/log/myapp/jobs/worker.log | バッチ・キュー | myapp:ops | 640 |
ディレクトリを分けるのは、世代数や保持期間をログの種類ごとに変えやすくするためでもあります。
エラーは長め、アクセスは短め、といった方針を同じディレクトリに混在させると設定が複雑になります。最初から分けておくと運用が軽くなります。
ローテート後の命名規則(番号/日付/拡張子)
回した後のファイル名は、規則が一目でわかることを優先します。
番号を付ける方法(.1, .2, …)と、日付を付ける方法(.2025-09-24 など)があります。日次集計や外部転送と連携するなら日付のほうが扱いやすい場面が多いでしょう。
圧縮との順序も揃えます。app.log-2025-09-24.gz のように「元名-日付.圧縮拡張子」という並びにしておくと、ツールでのパターン指定が楽になります。
番号方式なら app.log.1.gz といった形で連番が増えていきます。どちらにするかは、後工程(集計スクリプトや転送処理)が読みやすいほうに合わせます。
日付方式を使う場合は、dateext と dateformat を設定して表記を固定します。%Y-%m-%d のような 4桁年‐2桁月‐2桁日の並びは、ソートしたときに時系列と同じ順番になるため扱いやすい表記です。
圧縮方針(gzip/zstd)とライフサイクル
圧縮はストレージを守る最初の防波堤です。
一般的には gzip で十分ですが、容量削減を優先するなら zstd も選択肢になります。zstd は圧縮率と速度のバランスが良く、回転直後の負荷も低めにできます。
ただし、直近のファイルはすぐに参照することが多いので、回転した翌世代までは圧縮を遅らせる設定にします。delaycompress を使うと、ひとつ前の世代から圧縮が始まるため、最新世代は常に非圧縮で素早く開けます。
長期の扱いは二段階で考えます。
まずローカルでは短めに保ち、必要に応じて月次アーカイブとして別領域へ移す。
さらに、アーカイブ側はオブジェクトストレージやバックアップに委ね、ライフサイクル(たとえば 90 日で低頻度、180 日でアーカイブ)を自動化します。サーバのディスクに長期を背負わせないのがポイントです。
圧縮と命名の組み合わせ例を一つだけ。
| ログ種別 | 命名例 | 保持の考え方 |
|---|---|---|
| アプリエラー | app.error.log-2025-09-24.gz | 30〜90日をローカル。重要期間は月次アーカイブへ移行 |
| アクセス | access.log-2025-09-24.gz | 14〜30日をローカル。分析基盤に送るならさらに短縮 |
最初はシンプルに、日付方式+gzip+delaycompress。
運用が安定してから、zstd やアーカイブ移行を追加する順番で十分です。
ローテーション戦略の選び方
size基準が向くケース/time基準が向くケース
ログをどのようなきっかけで回すかは、運用の安定感に大きく影響します。
size 基準は、ファイルの大きさが一定に達した時点で回す方式です。アクセスが急に増えるようなサービスに向いており、巨大なファイルが1つだけ残ることを防げます。
ただし、回るタイミングが日によってまちまちになるため、日次集計やバックアップとタイミングを揃えたい場合には扱いづらいことがあります。
一方で time 基準は、毎日や毎週など決まった時間で回す方式です。分析やバックアップの運用がしやすく、見通しも良いのが特徴です。
ただし、急激なアクセス増加があると1日の間に数ギガバイトに膨らむこともあり、ディスク圧迫や後処理の重さにつながります。
実務では、まず time 基準での運用を基本にし、必要に応じて size 基準を組み合わせるのが安定した方法です。
copytruncate と create/postrotate(SIGHUP)の使い分け
ログを回したあと、アプリがどう振る舞うかを理解することも重要です。
もっとも手軽なのが copytruncate です。既存ファイルをコピーして中身を保存し、元ファイルを空にする方式です。アプリには特別な合図を送らなくても動作します。
ただし、この間に新しいログが書き込まれると、コピーされなかったり二重に残ったりする可能性があります。負荷の高いサービスには向きません。
一方の create と postrotate を組み合わせる方式は、より堅実です。
新しい空ファイルを作り、適切な権限を与えたうえで、アプリに「新しいファイルを使ってください」という合図を送ります。この合図が SIGHUP や systemctl reload です。
動作が一度決まればログ欠落のリスクが低く、信頼性の高い運用が可能です。ただし、アプリごとに「どの合図で切り替えるか」を調べておく必要があります。
小規模で簡単に済ませたいときは copytruncate、大きなサービスや監査が厳しい環境では create+postrotate を使う。この切り替えが実務上の線引きになります。
delaycompress の適用判断
ログを圧縮するかどうかは、読み返す頻度とタイミングで決めます。
圧縮はストレージの節約になりますが、直近のログを確認するときにいちいち解凍が必要になるのは不便です。
そこで使えるのが delaycompress です。この設定を加えると、ローテートされた直後の世代は非圧縮のまま残り、次の世代から圧縮されます。つまり、最新と一つ前はすぐ開ける状態になり、それより古いものだけ圧縮されます。
日次でローテーションするなら、昨日分まではそのまま残す、といった運用に適しています。
頻繁に参照するエラーログや監視用ログには便利ですが、ほとんど分析基盤に流してしまうアクセスログには不要な場合もあります。
判断の目安は「昨日までのログをすぐに見たいかどうか」です。
現場の確認作業が多いなら delaycompress を付け、そうでなければ圧縮を早めてディスクを節約する。この柔軟さが logrotate の強みです。
logrotate の最小実装
最小設定例(/etc/logrotate.d/myapp)
ログローテーションを設計するとき、最初の一歩は「とりあえず回る最低限の設定」を持つことです。
例として、1つのアプリケーション用ログを日次で回し、7世代を残し、圧縮もしておく最小構成を示します。
/var/log/myapp/app.log {
daily
rotate 7
compress
missingok
notifempty
create 0640 myapp myapp
}
ここでは、毎日回して1週間分を保持し、古いものは自動で削除されます。compress によって gzip 圧縮されるため、容量もある程度は抑えられます。missingok はログが存在しなくてもエラーにしない、notifempty は空ファイルなら回さない、という意味です。
この段階で「ログがちゃんと回る」「古いものは消える」という安心感を得られれば十分です。細かい最適化は後から足していけばよいのです。
よく使うオプションの実務基準
実際の現場では、オプションを追加することで運用が安定していきます。
たとえば size を加えて「50Mを超えたら回す」とすれば、急な増加にも耐えられます。dateext を指定すれば、ファイル名に日付をつけて管理しやすくなります。
また、delaycompress を入れると、直近の世代を非圧縮のまま残せるので、確認作業がしやすくなります。
まとめると、基本形に次のようなオプションを足すと実務向きになります。
| オプション | 効果 |
|---|---|
| size 50M | サイズ超過時にも回転 |
| dateext | ローテート後に日付を付与 |
| delaycompress | 最新世代は非圧縮で保持 |
| postrotate / endscript | アプリに再読込を通知 |
これらを組み合わせていけば、業務で求められる水準に近づいていきます。大切なのは、意味を理解しながら少しずつ足すことです。
動作確認(dry-run/強制回転)
設定を書いたら、すぐに本番で試すのは危険です。
まずは logrotate -d を実行してみます。これは dry-run モードで、実際にはファイルを動かさずに「こういう動きをします」と出力してくれます。
出力を確認して、思ったとおりに世代が回るかどうかを確かめます。
さらに、意図的に logrotate -f を使って強制的に回してみると、エラーや権限の不備が見つかりやすくなります。
この2つのコマンドを習慣にしておくと、安心して新しい設定を追加できます。
logrotate は難しいツールではなく、「小さな設定から動作を確認し、少しずつ強化していく」ことができるツールです。
最小実装で一度成功体験を積むと、その後の拡張がずっと楽になります。
systemd-journald を使う場合
容量制御(SystemMaxUse/SystemMaxFileSize)
近年の Linux では、多くのログが systemd-journald によって扱われています。これはテキストではなくバイナリ形式で保存され、検索やフィルタリングが柔軟にできるのが特徴です。
ただし放置しておくと、気づかないうちにディスクを大きく占有することがあります。
ここで役立つのが容量を制御する設定です。SystemMaxUse はジャーナル全体で使える最大容量を決めます。たとえば 2G に設定すると、過去ログは古い順に削除され、常に 2G 以内に収まります。SystemMaxFileSize は1ファイルの上限を決めるものです。大きすぎると扱いにくいので、200M や 500M といった単位に区切るのがよくある実務値です。
この二つを組み合わせて、ファイルサイズと総容量の両面から制御することで、ログが暴走してディスクを圧迫するのを防げます。
保持期間(MaxRetentionSec)と掃除(vacuum)
journald では「どれくらいの期間を残すか」も設定できます。MaxRetentionSec に秒数を入れると、期間を超えたログは自動で削除されます。たとえば 1 カ月分なら 30day、半年なら 180day のように書けます。
一方で、手動で掃除したいときもあります。そのときは journalctl --vacuum-size=5G のように容量を指定して整理したり、--vacuum-time=30d のように期間で削除できます。
これは即時で効くため、ディスク残量が逼迫した時の緊急対応にも便利です。
期間か容量、どちらを優先するかは環境次第です。大切なのは「必ずどちらかを設定しておく」ことです。放置が一番危険です。
テキストログとの併用指針
journald は便利ですが、すべてをこれだけで回すと困る場面もあります。
たとえば、外部の解析ツールがテキストファイルしか受け付けない場合や、開発者が慣れている tail や grep を使いたい場合です。
その場合は、journald に加えて rsyslog などでテキストに吐き出す「二重出力」を組み合わせます。
一方で、ログが二重に溜まって容量が倍になるリスクもあるため、どちらを一次ソースにするかを決めておくことが大切です。
実務では、監査や障害調査は journald、日常の確認はテキストログと役割を分けるケースが多いです。
このように用途を意識して併用すれば、使い勝手と堅牢性を両立できます。
Web/Nginx の定番設計
アクセスログとエラーログの方針分離
Nginx を運用していると、アクセスログとエラーログの扱い方を同じにしてしまいがちです。
しかし、両者は用途も重要度も違うため、最初から方針を分けるのが良い設計です。
アクセスログはリクエストの数に比例して増えるため、非常に膨らみやすいのが特徴です。解析や統計のために利用されることが多いですが、サーバ上で長期に保管するより、外部の分析基盤に送って短めに残す方が実務的です。
一方でエラーログは、障害対応やトラブルシュートの際に必須の情報です。量はそれほど多くないので、アクセスログよりも長めに保管し、障害発生時にすぐ参照できる状態を維持しておくのが安心です。
こうした性質の違いを踏まえると、「アクセスログは短期、エラーログは長期」という考え方が自然に導かれます。
高トラフィック向け(size+daily併用)
Nginx のアクセスログは、トラフィックが急増すると一気に数百メガバイトから数ギガバイトになることがあります。
このとき daily だけで回していると、1 日分のファイルが巨大化して扱いにくくなります。
そこで実務でよく使われるのが、サイズと日次の併用です。
具体的には「毎日回す」「ただし 200M を超えたらその時点でも回す」といった設定にします。
こうすることで、ログのファイルサイズが常に扱いやすい範囲に収まり、集計や転送もスムーズになります。
さらに、圧縮方式を zstd に切り替えると、アクセスログの肥大化に強くなります。gzip より処理が速く、保存容量も抑えられるため、トラフィックの大きなサイトでよく選ばれる方法です。
再読込手順と共有スクリプト
Nginx のログはローテーション後に必ず再読込が必要です。postrotate セクションで systemctl reload nginx を実行するのが定番のやり方です。
これを忘れると、新しいログファイルに書き込みが始まらず、ログが欠落してしまうことがあります。
複数のサービスでローテーションを設定する場合は、毎回似たような postrotate スクリプトを書くより、共通のスクリプトを 1 本用意して呼び出すのがおすすめです。
共通化しておけば、再読込の方法を変える必要が出たときも、一箇所を直すだけで済みます。
Nginx のように利用者が多いソフトウェアは、設定の「定石」が多く共有されています。
まずはその形を踏襲し、自分の環境に合わせて容量や保持期間を調整するのが安全で効率の良い進め方です。
アプリケーションログ(JSON/構造化)
1行1イベント(JSONL)と後段集約の前提
近年のアプリケーションでは、ログをテキストではなく JSON 形式で出力することが増えています。
特に 1 行につき 1 イベントを表す JSON Lines(JSONL)形式 は、後から検索や解析を行うときに非常に扱いやすい形式です。
たとえば、エラーメッセージやリクエスト ID、ユーザー ID などを JSON のキーとして残しておけば、外部の集約基盤(Elastic、Loki、Fluent Bit など)でフィルタや集計を行うのが容易になります。
この段階で「人が読むこと」よりも「機械が処理すること」を重視すると、後の運用が格段に楽になります。
ただし、すべてを JSON にする必要はありません。すぐ目で見たい開発環境ではテキスト、集約が前提の本番では JSONL、と使い分けるのも現実的です。
PII・機微情報の扱い(マスキング/出力禁止)
アプリケーションログで必ず意識すべきなのが、個人情報や認証情報といった機微なデータです。
便利だからといってユーザーのメールアドレスやパスワード、セッション情報をそのまま出力してしまうと、思わぬ漏えいにつながります。
基本は 出さない のが一番安全です。どうしても必要な場合は、マスキングやハッシュ化を検討します。
たとえばメールアドレスなら user***@example.com のように伏せ字を入れる、クレジットカード番号なら下 4 桁だけ残す、といった工夫です。
監査や分析に必要な項目と、絶対に残してはいけない項目をチームでルール化し、それをコードやライブラリに落とし込むことが重要です。
ログレベルとサンプリング
アプリケーションログは、すべてを残してしまうとすぐに膨大な量になり、運用に耐えられなくなります。
そこで役立つのがログレベルの使い分けです。
INFO や DEBUG を細かく出すのは開発環境だけにして、本番では WARN や ERROR を中心に残す。
あるいは、本番でも INFO を出すが、アクセスログのように件数が膨大なものはサンプリングをかけて一部だけを残す。
こうした調整によって、容量を抑えながら必要な情報を確保できます。
ログは「全部残す」より「必要なものを絞って残す」ほうが、結果的に見やすく、管理しやすくなります。
アプリの成長とともに見直す項目でもあるため、定期的に棚卸しする習慣を持つと安心です。
Docker/Kubernetes の基本設計
stdout/stderr 集約を前提にした設計
コンテナ環境でのログ設計は、従来の「ファイルに書き出して logrotate で回す」方式とは少し考え方を変える必要があります。
コンテナは短命で入れ替わるのが前提のため、内部にファイルを溜め込んでも長期的には意味を持ちません。
そのため、基本はアプリケーションが stdout(標準出力)や stderr(標準エラー出力) にログを出し、ホスト側やオーケストレーション基盤がそれを集約する、という形が推奨されています。
この方式にすると、コンテナが停止してもログが収集され、別のノードに移ってもログの流れは途切れません。
「コンテナ内でファイルに吐いて回す」発想は持ち込まず、外側に任せるのが安定した運用の第一歩です。
コンテナのローテート設定(max-size/max-file)
Docker などのコンテナランタイムでも、ログが延々と増え続けないように基本的なローテーション機能が用意されています。
代表的なのが max-size と max-file です。
たとえば以下のように設定すると、1ファイル 100M までで 5世代を保持する、という挙動になります。
--log-opt max-size=100m --log-opt max-file=5
これでコンテナごとのログは一定の範囲で回転します。
ただし、この仕組みはあくまで最低限であり、分析や長期保管には向きません。運用の目的は「無限に膨らませないこと」と割り切って使います。
実際のところ、長期的にログを見たい場合は後述の Daemon やエージェントによる回収が前提になります。
Daemon/エージェント側での回収・転送
本格的にログを扱うなら、コンテナランタイムのローテーション機能に頼るのではなく、収集エージェントや Daemon 側での回収 を基本に据えることが多いです。
Fluent Bit、Filebeat、Loki エージェントなどを各ノードに配置し、stdout/stderr に出たログをまとめて転送する方式です。
この方法なら、ログをクラスタ全体で一元的に管理でき、保持期間や容量制限も中央でコントロールできます。さらに、検索や分析、アラートの仕組みとも連携しやすくなります。
Kubernetes の場合は、Pod ごとのログをノードの /var/log/containers/ に集約し、そこからエージェントが収集するのが一般的です。アプリの中で何か特別なことをする必要はなく、標準出力に流すだけで十分です。
コンテナ環境では「内部ではなく外部で回収する」。この発想を持つことが、従来型サーバ運用との大きな違いになります。
転送・集中管理への段階的拡張
rsyslog/syslog-ng による集約
単体サーバではローカルに回しておけば十分でも、台数が増えると「どのサーバの、どの時間帯の、どのログを見ればよいか」が急に難しくなります。
ここで活きるのが、転送して一箇所に集める設計です。はじめの一歩は rsyslog や syslog-ng を使ったセカンダリ集約です。
考え方はシンプルで、アプリやサービスが出したログを、ローカルでは短めに保持しつつ、同時に集約サーバへ送ります。
集約サーバ側ではディスク容量を厚めに取り、回転や圧縮、バックアップのポリシーを一元管理します。
ネットワーク経由になるため、到達性や遅延を意識して、転送先が落ちたときの振る舞い(バッファリングやドロップの基準)も決めておくと安全です。
集中の効果は、検索性が上がることだけではありません。
「どのサーバにも共通する設定」「例外的な設定」を分けて運用できるようになり、設計のばらつきが減ります。
まずは小さな集約サーバを立て、アクセスログなど肥大化しやすいものから転送を始めると、負荷と効果のバランスが取りやすくなります。
S3等オブジェクトストレージとライフサイクル
中長期の保管は、サーバのローカルディスクよりもオブジェクトストレージが向いています。
S3 のようなストレージに月次アーカイブを押し込み、保管クラスを自動で切り替えるライフサイクルルールを設定すると、容量とコストの見通しが立ちます。
流れとしては、短期はローカル、30〜90日で集約サーバに、90日以降は月次圧縮ファイルをストレージへ、という三段構えが扱いやすい形です。
「どの粒度でまとめて送るか」は後段の検索ニーズに依存します。テキストを丸ごと保存しておき、必要なときだけ取り出す運用なら、日次や週次のアーカイブが現実的です。
ライフサイクルは必ず自動化します。
手作業のアップロードや削除に頼ると、忙しい時期に確実に破綻します。保存期間とコストの上限を先に決め、ポリシーとして機械に守らせるのが、長続きする設計です。
改ざん検知(署名・ハッシュ)と暗号化保存
監査やセキュリティの観点が入ると、ログは「残っているだけ」では足りません。
改ざんされていないことと、外部に持ち出されても中身を読まれないことを担保する必要があります。
改ざん検知は、アーカイブ単位でハッシュ(SHA-256 など)を取り、ハッシュ値を別の系統に保管するところから始められます。
さらに一歩進めるなら、時刻署名やチェーン化(前回のハッシュを含めて次のハッシュを作る)で不可逆な連続性を作ると、欠落や書き換えの検出力が上がります。
暗号化は、転送経路では TLS、保存先ではサーバ側暗号化(SSE)やクライアント側暗号化(CSE)を使い分けます。
鍵管理は可能な限り専用の仕組みに預け、アプリや運用者が生の鍵に触れない設計にしておくと、運用負荷とリスクの両方を下げられます。
最後に、ポリシーを文章化しておくことが重要です。
「どのログを、どれだけ、どこへ、どの保護で、どの証跡を残すか」。
決めた内容をチームで共有し、変更があれば日付入りで更新していく。これが集中管理の価値を最大化します。
監視とアラート
ディスク使用量・肥大化・ローテート失敗の検知
ログローテーションは「設定したから終わり」ではなく、きちんと回っているかを継続的に確認する必要があります。
特に注意すべきなのはディスクの残量です。容量が枯渇すると、ログだけでなくアプリケーション全体の動作に影響が出てしまいます。
ディスク使用量は百分率と絶対値の両方で監視すると安心です。たとえば「80%で警告、90%で緊急」という閾値を設定しつつ、「残り容量が 2GB を下回ったら通知」といった基準を重ねます。
また、ログが急に増え続けている場合は、1 日ごとのファイルサイズを比較することで異常に気づけます。平常時よりも極端に大きいログファイルが出たときは、アプリの異常や攻撃の可能性を疑うきっかけになります。
さらに、logrotate がエラーを出して止まっていないか、ジャーナルが正常に掃除されているかも監視対象です。ローテート失敗は、運用者が気づかないまま数週間分のファイルが積み上がる原因になります。
“ログの新鮮さ”の監視指標
監視で意外と見落とされるのが「ログが更新され続けているか」です。
もしアプリが停止していたり、出力先の権限が変わっていたりすると、新しいログが一切記録されなくなることがあります。
この場合、ファイルの最終更新時刻をチェックするだけで簡単に検出できます。
「直近 5 分以内に更新がなければ警告」といった基準を設けておくと、障害の早期発見につながります。
ジャーナルの場合も同様で、journalctl --since "5 minutes ago" を実行して新しいログが出るかどうかを確認する仕組みを組み込めば、自動で鮮度を監視できます。
運用ダッシュボードの最小要素
監視を行うだけでなく、日常的に見える形で提示することも大切です。
ダッシュボードに「ディスク使用量」「最新ログのタイムスタンプ」「logrotate の直近実行結果」といった最小限の要素を置いておけば、運用者が毎朝眺めるだけで安心感が得られます。
ここで注意したいのは、情報を詰め込みすぎないことです。細かすぎるメトリクスは日常的に見られなくなり、いざというときに役に立ちません。
むしろ「赤信号が出ていないか一目でわかる」シンプルな表示に徹するほうが、現場では運用が長続きします。
監視とアラートは、ログを「残す」だけでなく「活かす」ための仕組みです。
問題が起きる前に気づき、素早く対応できる環境を整えることが、ログ設計の完成に近づく一歩となります。
権限・セキュリティ
読み取り主体の最小化とACL
ログは便利な反面、システムの内部状態や利用者の行動を含む「情報の宝庫」です。
だからこそ、誰でも自由に読める状態は危険です。まず考えるべきは「誰が読む必要があるのか」を整理し、それ以外には権限を与えないことです。
基本的には、アプリケーションの実行ユーザに書き込み権限を、運用担当のグループに読み取り権限を与える形にします。
それ以外のユーザはアクセスできないようにし、万一サーバに不正侵入された場合でも被害を最小化します。
もし複数のチームが部分的にアクセスする必要があるなら、setfacl を用いたきめ細かい権限付与が便利です。ACL を使えば、従来の「所有者/グループ/その他」の三段階だけでなく、特定のユーザやグループごとに細かく制御できます。
バックアップ・転送の暗号化
ログを別のサーバやストレージに転送するときは、経路上で盗み見られないように暗号化を必須とします。
rsyslog や syslog-ng であれば TLS を使った転送、オブジェクトストレージなら HTTPS 経由のアップロードが標準的です。
保存先での暗号化も欠かせません。S3 であればサーバ側暗号化(SSE)、オンプレミスなら暗号化されたボリュームに置く、など環境に応じた方法を選びます。
重要なのは「転送時」と「保存時」の両方で暗号化をかけることです。片方だけでは穴が残ります。
さらに、暗号鍵の管理は可能な限り自動化された仕組みに任せるのが理想です。人がファイルとして鍵を持ち歩くと、それ自体がリスクになります。専用の KMS(鍵管理サービス)や Vault を利用すれば、運用負荷を下げつつ安全性を確保できます。
削除・保全の方針(WORM・証跡)
ログの寿命をどのように扱うかも設計の一部です。
不要になったものは削除してディスクを空けますが、監査や法令遵守の観点から「消してはいけないログ」も存在します。
このような場合は WORM(Write Once Read Many)のような仕組みを使い、一度保存したら消せない状態にしておきます。クラウドストレージでも、一定期間削除禁止のポリシーを設定できるものがあります。
逆に削除してよいログも「いつ、誰が、どのルールで消したか」を証跡に残しておくと、後から説明が必要になったときに困りません。
保全と削除を区別し、ルールを文章化してチームに共有することが、セキュリティを保ちつつ運用負荷を減らす最良の方法です。
ログは単なる記録ではなく、場合によっては「証拠」になります。だからこそ、読み取り権限、転送経路、保管方法、削除の流れまでを含めたセキュリティ設計が欠かせません。
検証手順(壊さずに試す)
logrotate -d/-f と典型エラー
設定を書いたら、まずは動かさずに動きを確かめます。logrotate -d /etc/logrotate.conf を使うと、どのファイルが対象で、どの順に回り、どんな名前で保存されるかを“説明するだけ”で示してくれます。実ファイルは触られません。ここで想定外の対象パスや、世代数の誤りに気づけます。
次に、検証用の環境や影響の小さいログで logrotate -f /etc/logrotate.conf を試します。
強制的に回すことで、権限不足や postrotate の失敗など、dry-run では見えない問題が表に出ます。失敗時のメッセージは素っ気ないことが多いので、対象ログの所有者・グループ・パーミッション、postrotate 内のコマンドの終了コード、PATH の不足など、周辺を丁寧に確認します。
実運用前に一度だけでなく、設定を足すたびにこの二段階を繰り返すと、現場での事故はぐっと減ります。
lsof での“deleted”ハンドル検出
ログのローテーションで起こりがちな事故が「ファイルは消えたのに、プロセスが古いファイルに書き続けている」状態です。
ディスク上は“消えた扱い”でも、プロセスがファイルディスクリプタを掴んだままなら、実体は残り続けて容量を食い尽くします。
この状態は lsof | grep deleted で確認できます。
該当プロセスが見つかったら、正しい再読込(SIGHUP や systemctl reload)が postrotate に入っているか、そもそもアプリがその合図をサポートしているかを確認します。
どうしても切り替わらない場合は、copytruncate の暫定利用や、アプリ側のログローテーション対応(ライブラリ設定の見直し)を検討します。
負荷試験・急増時の挙動確認
平常時だけでなく、スパイク時の挙動も早めに確かめておきます。
アクセスログの生成を擬似的に増やすスクリプトを流し、size トリガで想定どおりのタイミングで回るか、圧縮や転送が詰まらないか、postrotate の再読込で遅延や失敗が出ないかを観察します。
テストの視点としては次の三つが要点です。
- 回転のタイミングがブレすぎないか
- 回転直後のアプリ書き込みが欠落しないか
- 圧縮や転送で CPU・I/O が跳ね上がらないか
小さな環境で一度でも再現できれば、本番でも落ち着いて対処できます。
よくある設計値・意思決定の目安
小規模・単一ホスト
まずは日次で回して 7〜14 世代。
アクセスログは 14 日、エラーログは 30 日を目安に置き、delaycompress で直近の確認をしやすくします。
容量は 100M〜200M を上限にし、スパイクに備えて size トリガを併用します。再読込は postrotate で必ず実行します。
中規模・複数サービス
サービスごとにディレクトリを分け、アクセスとエラーでポリシーを分離します。
アクセスは daily+size(200M 前後)で 14〜30 日、エラーは 30〜90 日。
集約サーバまたはログ基盤への転送を開始し、ローカルは短め、基盤側で長めに保つ運用へ移行します。圧縮は zstd も選択肢になります。
監査要件あり・長期保管
ローカルは短期、集約側で 90〜180 日、その後は月次アーカイブをオブジェクトストレージへ。
WORM 相当の保護とハッシュ署名を導入し、復旧テストと証跡の手順をドキュメント化します。
「何をどれだけ残すか」を契約や規程と突き合わせ、例外運用をなくします。
最小チェックリスト(配布用)
設計・設定・監視の必須確認事項
保持期間はログ種別ごとに決まっているか。
容量上限はディレクトリ単位またはサービス単位で定義され、監視のしきい値と連動しているか。
回転のトリガ(daily/size/併用)は根拠とともに記録されているか。
postrotate の再読込は確実に動作し、dry-run/強制回転で検証済みか。
圧縮・命名規則は統一され、後工程(集計・転送)に適合しているか。
ディスク残量、ローテート失敗、ログの新鮮さを監視しているか。
権限・ACL・転送暗号化・保管暗号化の方針が文章化されているか。
月次の棚卸しと手順書の更新が運用に組み込まれているか。
付録:スターターテンプレート
logrotate 共通テンプレ
/var/log/<service>/*.log {
daily
size 100M
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 <user> <group>
postrotate
/bin/systemctl kill -s HUP <service>.service >/dev/null 2>&1 || true
endscript
}
読み替えるのは <service> と <user>/<group>、そして size と rotate。
ここから必要に応じて dateext や zstd を追加します。
journald 最小設定例
# /etc/systemd/journald.conf.d/10-capacity.conf
[Journal]
SystemMaxUse=5G
SystemMaxFileSize=200M
MaxRetentionSec=30day
適用後は systemctl restart systemd-journald。
容量か期間のどちらかは必ず入れて、放置を避けます。
週次健全性チェック例(cron)
#!/usr/bin/env bash
set -euo pipefail
# logrotate の詳細ログを syslog に送る
logrotate -v /etc/logrotate.conf | logger -t logrotate
# journald の整合性チェック
journalctl --verify | logger -t journal-verify
# 直近更新のないログを簡易検出(例:5分以上停止)
find /var/log -type f -name "*.log" -mmin +5 -printf "%p last update: %TY-%Tm-%Td %TH:%TM\n" | logger -t log-freshness || true
まずはこの最小セットで“回る基盤”を作り、
現場の負担やトラブルの傾向を見ながら、保持期間・容量・転送先を段階的に強化していきましょう。
まとめと次のステップ
ここまでで、ログローテーションを設計するための流れを一通り整理しました。
保持期間・容量・トリガという三つの芯を最初に決め、サービスごとにログの棚卸しを行い、命名規則や圧縮方針を整える。
そのうえで logrotate や journald の基本設定を押さえ、Nginx やアプリケーション、コンテナ環境に応じた実務的な戦略へと広げていきました。
さらに、転送や集中管理を組み合わせ、監視とアラートで運用の目を置き、権限やセキュリティを含めた全体設計に進めることで、規模の拡大や監査要件にも対応できる形に近づきます。
最後に検証手順やテンプレートを紹介したのは、「壊さずに試せること」を運用に組み込んでほしいからです。どんな設定も、まずは小さく動かし、結果を見てから広げる。それが現場で安心して使える仕組みにつながります。
ログ設計は、一度決めて終わりではありません。サービスの成長や利用状況の変化に合わせて、保持期間や容量の目安は変わります。
「現状を棚卸しし、芯を見直す」ことを定期的に繰り返すことが、長く安定してログと付き合うための最も確実な方法です。
次のステップとしては、まず自分の環境にこの最小テンプレートを適用してみましょう。
動いた実感を得ることが第一歩です。そのうえで、アクセスログやエラーログ、アプリ固有のログといった種類ごとに、保持期間と容量を一つずつ調整していけば十分です。
シンプルな仕組みを守り、段階的に育てていくこと。
それが「ログに振り回されず、ログを活かす」運用への道筋になります。
参考リンク
- logrotate(8) — Linux manual page (man7.org)
logrotate の公式マニュアル。オプションや設定ファイルの書式を確認できます。 - systemd-journald.service — systemd Journal (man7.org)
journald の基本的な仕組みと設定項目についての公式ドキュメント。 - Red Hat: Rotating log files
Red Hat の管理者ガイド内にある logrotate の設計例と実践的な解説。 - Ubuntu: Log rotation with logrotate
Ubuntu 環境での logrotate の導入例。実際の設定ファイル例が掲載されています。 - Nginx Logging and Monitoring Best Practices
Nginx のアクセスログ・エラーログの取り扱いや監視方法の参考になる記事。 - Docker Logging Best Practices
Docker での stdout/stderr ログ出力と、ローテーション設定の公式ガイド。 - Kubernetes Logging Architecture
Kubernetes におけるログ設計の基本方針と、標準出力ログの収集方法。 - Fluent Bit Documentation
軽量なログ収集・転送エージェント Fluent Bit の公式ドキュメント。 - AWS S3 Object Lifecycle Management
長期保管やライフサイクル管理をクラウドで行う場合の参考に。

