1台のVPSで自己ホスト型ログ管理を始める方法
1台のVPSでログを管理するなら、まずjournaldとlogrotateで十分か判断します。LokiやOpenSearchの選び方、必要なRAM容量、保持期間の決め方を解説します。
1 台の VPS で自己ホスト型ログ管理に実際にかかるコスト
1 台の VPS(virtual private server)で自己ホスト型のログ管理を行う場合、要点は 1 つです。検索クラスターが必要なのか、それともローテーションと grep で十分なのかを判断します。多くのベンダーガイドは、最初のログ 1 行を送る前から 3 ノードと 12 GB の RAM を前提にします。1 台のサーバーではこの前提は役に立たないため、以下では各方式が小規模なサーバー上でデータを保持する前に必要とするリソースを比較します。
サーバーが 1 台または 2 台で、先週の火曜日に何が起きたかを確認したいだけなら、systemd-journald と logrotate ですでに対応できます。その場合は次のセクションまでで十分です。複数のマシンのログを 1 か所に集約し、数週間分を検索する必要がある場合は、Grafana Loki が小規模なサーバーに適しています。ログ行の本文ではなくラベルをインデックス化するためです。Elasticsearch と OpenSearch では本格的な全文検索を利用できますが、その分メモリを消費します。JVM(Java virtual machine)のヒープには、下回れない最低容量があるためです。
journald から始めます。多くの場合、ここで解決します
現在の Ubuntu または Debian サーバーでは、systemd-journald はすでに起動しています。すべての service unit の標準出力、カーネルメッセージ、syslog に送信された内容を収集します。ほとんどのインシデントは、4 つのコマンドで対応できます。
journalctl -u nginx.service --since "2026-08-14 09:00" --until "2026-08-14 10:00"
journalctl -p err -b
journalctl -f -u ssh.service
journalctl --disk-usage最後のコマンドは、Archived and active journals take up 1.1G in the file system. のような行を出力します。これは、追加の対応が必要かどうかを判断する数値です。数百 MB と表示され、-u と --since で必要な情報を見つけられるなら、対応は完了です。
journal が再起動後も残るかどうかは、Storage= と /var/log/journal の有無で決まります。一般的な Storage=auto 設定では、そのディレクトリが存在する場合、journald は /var/log/journal に書き込みます。存在しない場合は /run/log/journal に書き込みます。/run はメモリ上に作成されるため、そのディレクトリがないサーバーでは、ログを読みたい再起動時にすべてのログが消去されます。Ubuntu のイメージにはこのディレクトリが含まれています。最小構成のイメージやコンテナベースのイメージには含まれていないことがよくあります。
ls -d /var/log/journal
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
journalctl --disk-usage再起動後、journalctl --disk-usage は /run ではなく、/var/log/journal 未満のサイズを報告するはずです。デフォルト値にはすでに上限が設定されています。これが、journald が単なる代替策ではなく、十分に実用的な解決策である主な理由です。journald.conf の man ページでは、SystemMaxUse= をファイルシステム容量の 10%、SystemKeepFree= を 15% に設定し、計算された各デフォルト値を 4G で上限設定しています。SystemMaxFileSize= のデフォルト値は SystemMaxUse= の 8 分の 1 で、上限は 128M です。そのため、通常はローテーション済みのファイルを 7 個保持します。MaxRetentionSec= のデフォルト値は 0 で、経過時間に基づく削除を無効にします。この最後のデフォルト値をもう一度確認してください。初期状態では、journal はサイズだけで制限され、経過時間では制限されません。
[Journal]
Storage=persistent
SystemMaxUse=2G
MaxRetentionSec=30dayその設定を /etc/systemd/journald.conf.d/99-size.conf に書き込み、journald を再起動してから、journalctl --disk-usage が新しい上限に近づいたことを確認します。次回のローテーションを待たずにすぐ空き容量を確保するには、sudo journalctl --vacuum-size=500M または sudo journalctl --vacuum-time=14d を実行します。どちらも削除したファイルをすべて出力するため、何も出力されなければ削除対象はありません。
journal の外側にある /var/log/nginx/access.log などのログは、logrotate の担当です。logrotate は systemd timer から毎日実行されます。df のバグのように見えるため、知っておくべき問題が 1 つあります。ローテーション後、古いファイルはディレクトリ一覧から消えますが、daemon はそのファイルを開いたままにします。そのため、df -h はディスクが満杯だと報告する一方、du -sh /var/log は大幅に少ない使用量を報告します。プロセスがログを再び開いたときにだけ空き容量が戻ります。設定内の postrotate reload 行は、そのために使用されます。sudo lsof -nP +L1 は、削除済みでありながら開いたままのファイルを一覧表示し、それぞれを保持しているプロセス名も表示します。何も変更せずにルールをテストするには、sudo logrotate -d /etc/logrotate.d/nginx を使用します。
複数のサーバーから1台の収集サーバーへログを送信する
サーバーが1台を超えると、複数の Linux サーバーをまとめて管理する場合、ログを1か所に集めると運用しやすくなります。ほとんどのディストリビューションには rsyslog がすでにインストールされているため、最も簡単な中央収集方法は、各送信元に1つの設定を置くことです。
*.* action(type="omfwd" target="logs.example.com" port="514" protocol="tcp")これを /etc/rsyslog.d/50-forward.conf として保存し、sudo rsyslogd -N1 で確認します。このコマンドは設定を検証して終了し、何も起動しません。その後、rsyslog を再起動します。収集サーバーでは、TCP 入力を有効にします。
module(load="imtcp")
input(type="imtcp" port="514")注意点が2つあります。どちらも仕組みに関するものです。通常の syslog には暗号化も認証もありません。そのため、514 番ポートに到達できるホストは、実際のログと見分けがつかないログ行を注入できます。プライベートネットワークまたは VPN にバインドし、ファイアウォールでポートを制限してください。もう1つは、デフォルトのアクションキューがメモリ上にあることです。収集サーバーに接続できないとキューが満杯になり、保持用のコピーがないままメッセージが破棄されます。この場合のディスク補助キューについては、rsyslog の信頼性の高い転送に関するチュートリアルで説明されています。
小規模 VPS に ELK スタックが適さない理由
ELK は、保存と検索を担う Elasticsearch、取り込みパイプラインを担う Logstash、インターフェースを提供する Kibana を指します。最低限必要な容量は JVM ヒープで、ログを受信する前に確保されます。
Elastic のドキュメントでは、各 Elasticsearch ノードのヒープを、利用可能な総メモリの 50% 以下に設定するよう説明しています。プロセスはオフヒープバッファーも使用し、インデックスファイルを高速に読み取るためにオペレーティングシステムのファイルキャッシュにも依存するためです。したがって、2 GB のヒープには、Kibana の分と、そのサーバー本来の用途に必要な分を除いても、4 GB のマシンが必要です。Elastic は、Elasticsearch がノードのロールと総メモリからヒープサイズを自動的に決定すると説明しています。つまり、小規模なマシンではヒープも小さくなり、処理時間の多くをガベージコレクションに費やします。
小規模な予算で最初に問題になるのは Logstash です。Elastic 自身の JVM 設定ページでは、一般的な取り込み用途に 4GB 以上、8GB 以下のヒープを推奨しています。これは 4 GB VPS 全体に相当し、しかもパイプライン中央の 1 プロセスだけで消費します。
The data behind this chart
[
{
"label": "Loki plus Alloy (no JVM)",
"documented_heap_mb": 0
},
{
"label": "OpenSearch demo compose",
"documented_heap_mb": 512
},
{
"label": "OpenSearch production example",
"documented_heap_mb": 2048
},
{
"label": "Logstash recommended minimum",
"documented_heap_mb": 4096
}
]これらは各プロジェクトが独自のドキュメントで公開している値です。テスト用マシンで測定した値ではなく、実際のワークロードによって変わります。OpenSearch のサンプル compose ファイルでは、デモ用にノードあたり 512 MB、本番環境の例に 2048 MB を設定しています。一方、Logstash の推奨下限は 4096 MB です。Loki と Alloy のヒープ欄が 0 なのは、これらが JVM ヒープを予約しない Go プログラムだからです。この違いは 1 つの数値に集約できます。JVM コンポーネントは、ログが到着するかどうかにかかわらず、ヒープを予約します。
それでも 1 台の小規模サーバーで Elastic スタックを使う場合は、Logstash を外し、軽量なコレクターから Elasticsearch に直接送信します。Logstash は大量のデータを解析・変換するためのものです。1 台構成では、その処理をエッジ側で行うか、省略できます。
Elasticsearch と OpenSearch では、インデックスファイルをメモリーマップするため、vm.max_map_count も 262144 に引き上げる必要があります。Linux のデフォルト上限は低すぎます。新しいマシンでコンテナが起動数秒後に終了する場合、通常はこれが原因です。
OpenSearch と Elasticsearch のどちらをデプロイできますか?
ソフトウェアの使用許諾条件によって、実行できる内容が決まります。経緯を簡単に説明します。2021 年 1 月、Elastic は Elasticsearch と Kibana のライセンスを Apache 2.0 から、SSPL(server side public license)と Elastic License 2.0 のデュアルライセンスモデルへ変更しました。AWS は最後の Apache 2.0 版のコードをフォークして OpenSearch を作成しました。OpenSearch は Apache 2.0 のままです。2024 年 9 月、Elastic は無償で利用できるソースコードの選択肢として AGPLv3(GNU Affero General Public License version 3)も追加しました。1 人が 1 台の VPS でセルフホストする場合、これらのライセンスはいずれもその用途を許可しています。ライセンスが問題になるのは、ソフトウェアをマネージドサービスとして他者に提供する場合です。
小規模なサーバーでの実際の違いは、経緯から受ける印象ほど大きくありません。どちらも内部では同じエンジンを使用しているためです。名称は異なります。OpenSearch ではインデックスのライフサイクル管理を ISM(index state management)と呼び、Elasticsearch では ILM(index lifecycle management)と呼びます。2026 年 8 月時点では、OpenSearch 2.12 以降は初回起動時に管理者パスワードを設定していないと起動しません。
sudo sysctl -w vm.max_map_count=262144
printf 'vm.max_map_count = 262144\n' | sudo tee /etc/sysctl.d/99-opensearch.conf
docker run -d -p 9200:9200 -p 9600:9600 -e "discovery.type=single-node" \
-e "OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password>" \
opensearchproject/opensearch:latestsysctl -w の行で設定が直ちに適用され、/etc/sysctl.d/ のファイルが再起動後にも設定を保持する部分です。curl -k -u admin:<password> https://localhost:9200 でコンテナが起動したことを確認します。デモ証明書を使用して https で応答するため、-k で証明書の検証を省略します。正常な応答は、クラスタ名とバージョンを示す小さな JSON ブロックです。OpenSearch のインストールページでは、Docker Desktop ユーザーに対してホストに少なくとも 4 GB のメモリを割り当てるよう案内しています。これは、プロセスが必要とするメモリ量の目安になります。
Loki が小規模で済む理由: 完全なテキストインデックスではなくラベルを使う
Loki はラベルに対する 1 つのインデックスを保持し、ログ行を圧縮チャンクとして保存します。クエリでは、最初にストリームを選択し、次にテキストを絞り込みます。{unit="ssh.service"} |= "Failed password" はラベルによってストリームを選択し、その後、チャンク内から文字列を検索します。行の本文にはインデックスを作成しないため、取り込みのコストを抑えられ、メモリ上で反転インデックスを維持する必要もありません。コストはクエリ時に移ります。通常、調査対象のサービスが分かっている場合、このトレードオフは有効です。
Grafana のドキュメントでは、モノリシックモード、つまり -target=all を含む Loki 全体を 1 つのプロセスで実行する構成について、読み取り量と書き込み量が 1 日あたりおよそ 20GB 以下の環境を対象にしています。1 台の VPS であれば、この範囲に十分収まります。
注意が必要なのはラベルのカーディナリティです。ラベル値の組み合わせが異なるたびに 1 つのストリームが作成され、ストリーム数が Loki のメモリ使用量とインデックスサイズを左右します。クライアント IP アドレスやリクエスト識別子を保持するラベルを追加すると、値ごとにストリームが作成されます。そのため、負荷の高い Web サーバーでは 1 日で数万のストリームが生成され、カーネルがプロセスを停止するまでメモリ使用量が増加することがあります。ラベルには、紙に書いて数えられる程度の値だけを使用してください。たとえば unit、host、job、level です。変動する詳細情報は行そのものに含めてください。クエリ時にフィルター式で検索できます。
1 台の VPS に Loki と Alloy をインストールする
2 つのプロセスが処理を分担します。Loki はログを保存し、クエリに応答します。Grafana Alloy はログを読み取り、Loki に送信します。以前は Promtail が送信を担っていましたが、2026 年 3 月 2 日にサポートが終了しました。そのため、新規インストールでは Alloy を使用します。Loki の Docker 公式例でも、現在は Alloy の設定ファイルが使われています。
wget https://raw.githubusercontent.com/grafana/loki/v3.7.0/cmd/loki/loki-local-config.yaml -O loki-config.yaml使用する前に、そのファイルを確認してください。ファイルでは path_prefix: /tmp/loki に /tmp/loki/chunks 配下のチャンクを設定しています。これはデモには適していますが、サーバーでは不適切です。コンテナの /tmp 配下にあるデータは、コンテナを再作成するとすべて失われるため、次回のイメージ更新時に履歴も消えます。ホストからマウントするパスを指定してください。
common:
instance_addr: 127.0.0.1
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemorydocker volume create loki-data
docker run --name loki -d \
-v $(pwd):/mnt/config -v loki-data:/loki \
-p 127.0.0.1:3100:3100 \
grafana/loki:3.7.0 -config.file=/mnt/config/loki-config.yaml
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3100/ready最後のコマンドは 200 を表示するはずです。Loki がトラフィックを受け付けられる状態になると、/ready は HTTP 200 を返すためです。それ以外の場合は、プロセスがまだ起動中か、設定が拒否されています。原因は docker logs loki で確認できます。run コマンドの 2 つの設定には意図があります。サンプル設定には auth_enabled: false が含まれており、Loki 自体にはユーザー認証機能がないため、ポートを 127.0.0.1 にだけ公開しています。3100 番ポートに到達できるすべての相手が、すべてのログを読み取り、偽のログを書き込めるためです。loopback 上に限定するか、VPN または認証機能を持つリバースプロキシの背後に置いてください。名前付きボリュームも重要です。イメージは UID 10001 のユーザー loki で実行されるため、root 所有のホストディレクトリを bind mount すると、コンテナから書き込めません。
sudo apt-get update && sudo apt-get install -y gpg wget
sudo mkdir -p /etc/apt/keyrings/
sudo wget -O /etc/apt/keyrings/grafana.asc https://apt.grafana.com/gpg-full.key
echo "deb [signed-by=/etc/apt/keyrings/grafana.asc] https://apt.grafana.com stable main" \
| sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install -y alloyAlloy は /etc/alloy/config.alloy を読み取ります。この設定は、system journal と 1 セットのファイルを読み取り、両方をローカルの Loki に送信します。
loki.write "local" {
endpoint {
url = "http://127.0.0.1:3100/loki/api/v1/push"
}
}
loki.relabel "journal" {
forward_to = []
rule {
source_labels = ["__journal__systemd_unit"]
target_label = "unit"
}
}
loki.source.journal "read" {
forward_to = [loki.write.local.receiver]
relabel_rules = loki.relabel.journal.rules
labels = {job = "systemd-journal", host = "app-01"}
}
local.file_match "nginx" {
path_targets = [{"__path__" = "/var/log/nginx/*.log", "job" = "nginx", "host" = "app-01"}]
}
loki.source.file "nginx" {
targets = local.file_match.nginx.targets
forward_to = [loki.write.local.receiver]
}relabel ルールは、journal フィールド __journal__systemd_unit を unit という名前のラベルにコピーします。これにより、後で {unit="ssh.service"} を使用できます。このルールがない場合、unit 名はラベルではなくエントリ内に格納されます。そのため、unit 名で選択できず、すべてのクエリで全件を走査する必要があります。
sudo systemctl reload alloy
systemctl show -p User alloy
sudo journalctl -n 5
sudo -u alloy journalctl -n 5多くの構成で問題になるのがここです。Alloy は root ではなく専用のサービスアカウントで実行されます。system journal の読み取りには systemd-journal グループへの所属が必要です。また、Debian と Ubuntu では /var/log/nginx 配下のファイルは adm グループに属します。最後のコマンドが表示した systemctl show のアカウントに置き換えてください。root で実行した場合よりもエントリ数が大幅に少ない場合、そのアカウントは system journal を読み取れません。設定が正しくても、Loki は空のままです。sudo usermod -aG systemd-journal,adm alloy を実行してグループを追加し、sudo systemctl restart alloy で再起動してください。
curl -G -s "http://127.0.0.1:3100/loki/api/v1/query_range" \
--data-urlencode 'query={job="systemd-journal"}' \
--data-urlencode 'limit=5' | jq '.data.result | length'0 より大きい数値は、そのラベルを持つストリームが存在し、エントリを保持していることを示します。0 は、そのラベルではまだ何も到着していないことを示します。よくある誤検知につながるデフォルト設定があります。loki.source.journal は max_age を 7h に設定するため、新規起動時には journal の直近 7 時間だけを読み取り、それより古いデータは読み取りません。人間向けのインターフェースには、同じホストで Grafana を実行し、Loki のデータソースを http://127.0.0.1:3100. に設定します。コンテナログには別のデータソースが必要です。Alloy は実行中の Docker コンテナを検出してログを tail します。これは Loki の公式 getting started 例と同じ方式です。また、VPS 上の単一ノード k3s クラスターでは、そのジョブは kubelet が書き込む pod ログディレクトリを対象にします。
保持期間: ログを削除する日を決める
ほとんどの人は、ディスクがいっぱいになるまで保持期間を決めません。その時点で、サービスを停止したまま午前 3 時に決めることになります。初日に、次の 2 つの質問から決めてください。実際にどこまで過去のログを参照するのか。来月のインシデントレビューで何を残しておく必要があるのか。単一サーバーであれば、14 日から 30 日で両方に対応できます。
Loki は compactor を有効にするまで、何も削除しません。保持期間はデフォルトで無効です。設定内で retention_period が何もせずに残ったまま、ボリュームがいっぱいになることがあるため、意外に感じる人もいます。
limits_config:
retention_period: 744h
compactor:
working_directory: /loki/retention
compaction_interval: 10m
retention_enabled: true
retention_delete_delay: 2h
retention_delete_worker_count: 150
delete_request_store: filesystem744h は 31 日です。このブロックには、4 つの文書化されたルールがあります。
- 保持期間は compactor によって適用されます。Grafana のドキュメントでは、compactor を単一インスタンスとして実行するように説明されています。1 台の VPS では、その状態が自動的に実現します。
- 保持期間の最小値は 24h です。また、保持期間が機能するのは index period が 24h の場合だけです。サンプルの
schema_configはすでにperiod: 24hを使用しているため、変更しないでください。 retention_enabledが true の場合、delete_request_storeが必要です。これは削除要求を保存するストアを指定します。ファイルシステムを使用する単一ノード構成では、スキーマ内ですでに指定されているobject_store: filesystemと一致します。- チャンクはまず削除対象としてマークされ、
retention_delete_delayの経過後に削除されます。ここでは 2h なので、空き容量が戻るのはポリシーが示す時点より後になります。reload の 5 分後にdfを確認して、設定の成否を判断しないでください。
OpenSearch は個々の行ではなくインデックス全体を削除します。そのため、ログインデックスは日単位で作成します。ISM ポリシーはインデックスを状態間で遷移させ、十分に古くなった時点で削除します。さらに、ism_template を新しいインデックスに適用すれば、手動で覚えておく必要がなくなります。
14 日後にログインデックスを削除する ISM ポリシー
{
"policy": {
"description": "delete log indexes after 14 days",
"default_state": "hot",
"states": [
{
"name": "hot",
"actions": [],
"transitions": [
{ "state_name": "delete", "conditions": { "min_index_age": "14d" } }
]
},
{
"name": "delete",
"actions": [ { "delete": {} } ],
"transitions": []
}
],
"ism_template": { "index_patterns": ["logs-*"], "priority": 100 }
}
}_plugins/_ism/policies/logs-retention に PUT して作成します。テンプレートはポリシーの作成後に作られたインデックスに適用されます。そのため、すでにディスク上にあるインデックスには手動でポリシーを適用する必要があります。
どちらのシステムを運用する場合でも、保持期間の値は、その背後にある空き容量の確認が適切であって初めて意味を持ちます。14 日後に削除する設定でも、10 日分のログですでにボリュームがいっぱいなら問題は解決しません。そのため、VPS のディスク健全性監視と保持率 80% のアラートをポリシーと組み合わせてください。
ログ 1GB あたりに必要なディスク容量
正確な値はログの行数やフィールドによって異なるため、公表されている比率をそのまま信頼せず、自分のデータで測定してください。仕組みによって傾向は十分に異なります。OpenSearch と Elasticsearch は、保存するドキュメントに加えて、インデックス対象のすべてのフィールドに対する転置インデックスを書き込みます。そのため、ディスクに保存されるデータは生のテキストより大きくなり、レプリカごとに容量も増加します。単一ノードではレプリカ数を 0 に設定してください。同じノード上のレプリカシャードは、そのノードの障害に耐えられないためです。1 のままにすると、ディスク使用量が 2 倍になり、クラスターの状態が常に yellow のままになります。Loki は、圧縮したチャンクと小規模なラベルインデックスを書き込むため、使用容量はログ行の圧縮後のサイズにほぼ比例します。
sudo du -sh /var/lib/docker/volumes/loki-data/_data
curl -k -u admin:<password> "https://localhost:9200/_cat/indices?v&h=index,docs.count,store.size"該当する方法を、連続する 2 日間に実行してください。差分が 1 日あたりの増加量です。これに保持日数を掛け、コンパクションとマージ用に約 30% の余裕を加えてから、ボリュームの容量と比較します。収まらない場合は、ディスクを購入する前に保持期間を短縮してください。容量を増やしても、同じ問題が数週間先送りされるだけです。
小規模なサーバーで最初に問題になるもの
最初に枯渇するのはメモリです。カーネルの OOM(out of memory)killer は大きなプロセスを選択します。ログサーバーで最大のプロセスは JVM です。journalctl -k | grep -i "killed process"には、プロセス名を角括弧で示した kill の記録が表示されます。必ずしもログ基盤が対象になるとは限りません。sshd やデータベースが選択されることもあります。その結果、ログを取得したかったアプリケーションまで、ログ収集の検証によって停止する場合があります。障害の影響先を意図した範囲に限定できるよう、コンテナには明示的な上限を設定してください。Docker Compose のメモリ制限はそのための機能です。
次に枯渇するのはディスクです。検索エンジンは、ディスク容量が不足すると特有の、判別しやすい動作をします。Elasticsearch と OpenSearch は、複数のレベルでディスク使用率を監視します。low watermark は 85%、high watermark は 90% です。flood stage の 95% に達すると、そのノード上に shard があるすべての index に index.blocks.read_only_allow_delete の block が設定され、書き込みは blocked by: [FORBIDDEN/12/index read-only / allow delete (api)] で失敗します。使用率が high watermark を下回ると、block は解除されます。まず空き容量を確保してください。その後も block が残る場合に限り、手動で解除します。
curl -k -u admin:<password> -X PUT "https://localhost:9200/_all/_settings" \
-H 'Content-Type: application/json' \
-d '{"index.blocks.read_only_allow_delete": null}'Loki は、より静かに失敗します。read-only mode に移行する仕組みがないため、ボリュームが満杯になると送信元では push の失敗として現れ、クエリ結果には欠落が生じます。また、cardinality の問題はエラーではなく、メモリ使用量が徐々に増える形で現れます。障害発生後ではなく、定期的に chunks ディレクトリのサイズを監視してください。
最後の障害は、誤ったデータを投入することです。ログシステムはメトリクスシステムではありません。10 秒ごとに取得した CPU load をテキストとして保存すると、保持コストが高く、グラフ化もしにくくなります。この処理には、Ubuntu 24.04 上の Zabbix 監視サーバーのようなシステムを使います。アプリケーション例外には、グルーピング、重複排除、stack trace の表示が必要です。これは自己ホスト型のエラートラッカーが担当します。サイトが停止しているかどうかの確認は、さらに別の役割です。Uptime Kuma などの稼働監視とステータスページで対応します。ログシステムには、人が読むテキスト行を保存してください。
FAQ
サーバーのログを検索するために Elasticsearch は必要ですか?
サーバーが 1 台または 2 台だけなら必要ありません。journalctl では、unit、優先度、ブート、時間範囲ですでに絞り込めます。ローテーションされたファイルには grep と zgrep で対応できます。多数のマシンを管理している場合、すべてのログを対象に全文検索を同時に実行する必要がある場合、または複数の担当者が共有インターフェースを使う場合は、検索クラスターを導入する価値があります。それ以外では、サイズ上限と保持期間を設定した journald で同じ処理を追加の RAM なしで実行できます。
自己ホスト型のログ管理にはどの程度の RAM が必要ですか?
経験則ではなく、各プロジェクトが公開している値を使用してください。Loki と Alloy は Go プログラムであり、起動前に確保しておくヒープはありません。Grafana のドキュメントでは、モノリシック構成の Loki は 1 日あたり最大約 20GB とされています。OpenSearch のサンプル compose ではデモ用に 512 MB のヒープが設定され、本番環境の例では 2 GB が設定されています。また、Elastic はヒープを総メモリの 50% 以下にする必要があると説明しています。そのため、2 GB のヒープを使用する場合、Kibana を追加する前に 4 GB のマシンが必要です。Logstash のドキュメントでは、単独で少なくとも 4GB のヒープを推奨しています。これらは文書化された設定値であり、ベンチマーク結果ではありません。実際の負荷を測定してから構成を決めてください。
Loki と OpenSearch のログにおける実際の違いは何ですか?
インデックスのモデルです。Loki はラベルだけをインデックス化し、ログ本文は圧縮チャンクとして保持してクエリ実行時にスキャンします。そのため書き込みは安価ですが、広範囲のクエリでは検索コストが高くなります。OpenSearch はフィールドの内容をインデックス化するため、任意の全文検索は高速です。一方で、インデックスのためにメモリとディスクの両方を消費します。対象のサービスと時間範囲が決まっている場合は Loki を選択してください。事前に内容を予測できないテキストを検索する必要がある場合は OpenSearch を選択してください。
VPS ではログをどのくらいの期間保持すべきですか?
ディスク容量に決められる前に、保持期間を決めてください。各システムで設定箇所は 1 か所だけにします。journald では MaxRetentionSec= と SystemMaxUse=、Loki では compactor を有効にした retention_period、OpenSearch では min_index_age を使用する ISM ポリシーを設定します。単一サーバーの多くの構成では、14 日から 30 日あればデバッグとインシデントレビューに対応できます。それより長く保持する必要があるデータは、サーバー外に保存したコピーに含めてください。障害が発生したサーバーだけに保存されたログは、記録として機能しないためです。
Promtail は現在も Loki にログを送信する方法ですか?
いいえ。Promtail は 2026 年 3 月 2 日にサポート終了となり、Grafana Alloy に置き換えられました。Loki 独自の Docker インストール例では、現在 Alloy の設定を使用しています。Grafana は、既存の Promtail 設定を Alloy 構文に変換するコンバーターも提供しています。既存の Promtail インストールは動作し続けますが、修正は提供されません。そのため、移行は無期限に先送りできるアップグレードではなく、保守作業として扱ってください。