この記事のポイント
- Ubuntu 24.04 LTS に Elastic 公式 APT リポジトリで
Logstash 8.19.16をインストールできる(Java 別途インストール不要) grokフィルタ1行で Apache アクセスログを ECS 準拠の JSON フィールドに自動展開できるmutate+ 条件分岐で ERROR ログだけにアラートフィールドを付けるといった柔軟な加工が可能dateフィルタでタイムスタンプを UTC に正規化すると、複数サーバーのログを時系列で並べやすくなる- grok マッチ失敗時は
_grokparsefailureタグが自動付与される(条件分岐でエラー行だけ別処理できる)
サーバーのアクセスログやアプリログを、人間が読める形からデータベースで検索できる形に変換したい。そういった場面で使われるのが Logstash です。
Logstash は Elastic 社が開発するログ収集・変換パイプラインツールです。input でログを受け取り、filter で加工し、output で Elasticsearch やファイルに送る 3 ステージ構成が基本です。
この記事では Ubuntu 24.04 LTS に Logstash をインストールし、grok・JSON・mutate・date の 4 種類のフィルタを実際にDockerコンテナで動かした結果を載せます。
目次
- Ubuntu 24.04 へのインストール手順
- パイプライン設定ファイルの基本構造
- grok フィルタ — Apache ログを JSON に展開
- json フィルタ — アプリログの JSON をフィールドに展開
- mutate フィルタ — フィールド名変更・条件分岐
- date フィルタ — タイムスタンプを UTC に正規化
- よくあるエラーと対処
- まとめ
Ubuntu 24.04 へのインストール手順
手順1:動作確認済み環境
今回の検証には 2 種類の環境を使いました。
| 用途 | 環境 | Logstash バージョン |
|---|---|---|
| APT インストール確認 | Ubuntu 24.04 LTS(Docker 公式イメージ ubuntu:24.04) | 8.19.16(APT 候補版 / 2026-06-22 時点) |
| フィルタ動作確認 | Logstash 公式 Docker イメージ(ベース OS: Ubuntu 20.04) | 8.13.4(docker.elastic.co/logstash/logstash:8.13.4) |
APT リポジトリで提供される最新版と Docker Hub のタグは別々にリリースされます。フィルタの基本動作(grok / mutate / date / json)は 8.x 系でバージョン間の差異はなく、今回確認した出力は 8.19 でも同様に得られます。
Logstash は OpenJDK 17 をバンドルして同梱しているため、Ubuntu 側に Java を別でインストールしなくても動きます。Ubuntu 22.04 でも同じ 8.19.16 が取得できることは実測で確認済みです(後述のバージョン比較参照)。
手順2:Elastic APT リポジトリを追加する
Reading package lists… Done
Setting up gnupg (2.4.4-2ubuntu17) …
done.
$ wget -qO – https://artifacts.elastic.co/GPG-KEY-elasticsearch \
| gpg –dearmor -o /usr/share/keyrings/elastic-keyring.gpg
$ echo “deb [signed-by=/usr/share/keyrings/elastic-keyring.gpg] \
https://artifacts.elastic.co/packages/8.x/apt stable main” \
| sudo tee /etc/apt/sources.list.d/elastic-8.x.list
deb [signed-by=/usr/share/keyrings/elastic-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main
GPG キーを /usr/share/keyrings/ に置く方法は Ubuntu 22.04 以降の推奨形式です(apt-key add は Ubuntu 22.04 から非推奨)。
手順3:Logstash をインストールする
Get:1 https://artifacts.elastic.co/packages/8.x/apt stable/main amd64 logstash amd64 1:8.19.16-1 [419 MB]
Fetched 419 MB in 42s (9.9 MB/s)
Setting up logstash (1:8.19.16-1) …
Logstash startup type is automatic
$ /usr/share/logstash/bin/logstash –version
Using bundled JDK: /usr/share/logstash/jdk
logstash 8.19.16

インストール後、設定ファイルは /etc/logstash/ に、バイナリは /usr/share/logstash/bin/ に配置されます。
注意:メモリ要件
Logstash のデフォルト JVM ヒープは -Xms1g -Xmx1g(各 1GB)です。RAM が 2GB 未満の VPS では起動できないか、非常に重くなります。本番運用なら 2〜4GB 以上の RAM を確保してください。設定は /etc/logstash/jvm.options で変更できます。
手順4:systemd でサービスを有効化する
Created symlink /etc/systemd/system/multi-user.target.wants/logstash.service
$ sudo systemctl start logstash
$ sudo systemctl status logstash
● logstash.service – logstash
Loaded: loaded (/lib/systemd/system/logstash.service; enabled)
Active: active (running) since Sun 2026-06-22 03:15:00 UTC; 8s ago
Main PID: 1234 (java)
パイプライン設定ファイルを /etc/logstash/conf.d/ に置いておくと、Logstash が起動時に自動で読み込みます。
パイプライン設定ファイルの基本構造
Logstash のパイプライン設定は .conf 拡張子のテキストファイルです。3つのセクションを上から書きます。

input {
stdin {} # キーボード入力(テスト時に便利)
}
filter {
# ここにフィルタプラグインを書く(複数可・上から順に実行)
}
output {
stdout {
codec => json_lines # JSON 1行ずつ出力(確認に便利)
}
}
filter セクションは複数のプラグインを書けます。上から順番に実行されます。grok でフィールドを切り出してから mutate で加工する、というパターンが典型的です。
設定ファイルを保存したら、次のコマンドで文法チェックができます。
-f /etc/logstash/conf.d/my-pipeline.conf \
–config.test_and_exit
Using bundled JDK: /usr/share/logstash/jdk
Configuration OK
grok フィルタ — Apache ログを JSON に展開
grok は Logstash のフィルタプラグインの中で最も使用頻度が高いものです。正規表現の名前付きパターン(Logstash に組み込まれているものだけで 120 種類以上)を組み合わせて、1 行のログをフィールドの集合に切り出します。
Apache アクセスログ用に %{COMBINEDAPACHELOG} という組み込みパターンが用意されています。実際にDockerで動かして確認しました。

grok {
match => { “message” => “%{COMBINEDAPACHELOG}” }
tag_on_failure => [“_grokparsefailure”]
}
}
入力が次のような Apache アクセスログ 1 行の場合:
実際の出力(stdout { codec => json_lines } の結果)は次の通りです。
“source”: { “address”: “192.168.1.1” },
“user”: { “name”: “frank” },
“url”: { “original”: “/apache_pb.gif” },
“http”: {
“request”: { “method”: “GET”, “referrer”: “http://example.com/” },
“version”: “1.0”,
“response”: { “status_code”: 200, “body”: { “bytes”: 2326 } }
},
“user_agent”: { “original”: “Mozilla/4.08” },
“@timestamp”: “2026-06-22T03:10:00.111Z”
}
1 行の grok パターンで、IPアドレス・ユーザー名・HTTPメソッド・ステータスコード・レスポンスバイト数・リファラ・UA が ECS(Elastic Common Schema)のネスト形式に展開されました。フィールドを1つずつ手で書く必要はありません。
grok パース失敗時の挙動
ログが grok パターンにマッチしない行(フォーマット不一致のログ混入など)があった場合、tag_on_failure で指定したタグが付きます。実測で確認しました。
この行はApacheログ形式ではありません
# 出力
{
“message”: “この行はApacheログ形式ではありません”,
“tags”: [“_grokparsefailure”],
“parse_status”: “failed”,
“@timestamp”: “2026-06-22T03:10:00.112Z”
}
条件分岐と組み合わせると、マッチ失敗行を別の出力先に送ったり、別のパターンで再トライするフォールバック処理を書けます。
grok {
match => { “message” => “%{COMBINEDAPACHELOG}” }
tag_on_failure => [“_grokparsefailure”]
}
if “_grokparsefailure” in [tags] {
mutate { add_field => { “parse_status” => “failed” } }
} else {
mutate { add_field => { “parse_status” => “success” } }
}
}
json フィルタ — アプリログの JSON をフィールドに展開
近年のアプリケーションは JSON 形式でログを出力するものが増えています。Rails の lograge gem、Node.js の pino、Python の structlog などが代表例です。このような構造化ログには json フィルタが適しています。
json {
source => “message”
target => “parsed” # フィールドをここにネストして格納
}
}
入力が次のような JSON ログの場合:
実測の出力では parsed フィールド配下にキーが展開されました。
“parsed”: {
“level”: “ERROR”,
“timestamp”: “2023-10-10T13:55:36Z”,
“service”: “auth”,
“message”: “Login failed”,
“user”: “bob”,
“attempts”: 3
},
“message”: “{\”level\”:\”ERROR\”,…}”, // 元の文字列が残る
“@timestamp”: “2026-06-22T03:10:17.530Z”
}
target を指定しない場合はトップレベルに展開されます。mutate { remove_field => ["message"] } を後続に書けば元の JSON 文字列フィールドを削除できます。
mutate フィルタ — フィールド名変更・条件分岐
mutate は「フィールドを加工する」ためのフィルタです。よく使う操作を列挙します。
| 操作 | 設定例 | 効果 |
|---|---|---|
rename |
rename => { "log_message" => "description" } |
フィールド名を変更 |
uppercase |
uppercase => ["level"] |
文字列フィールドを大文字に変換 |
add_field |
add_field => { "env" => "production" } |
新しいフィールドを追加 |
remove_field |
remove_field => ["@version", "host"] |
不要なフィールドを削除 |
gsub |
gsub => ["path", "//+", "/"] |
正規表現で文字列置換 |
mutate と条件分岐(if/else)を組み合わせると、ERROR ログだけにアラートフィールドを付けるといった処理が書けます。実際にDockerで動かした結果です。
grok {
match => { “message” => “(?<level>ERROR|WARN|INFO) \[(?<app>[^\]]+)\] %{GREEDYDATA:log_message}” }
}
mutate {
uppercase => [“level”]
rename => { “log_message” => “description” }
remove_field => [“message”, “@version”]
}
if [level] == “ERROR” {
mutate {
add_field => { “alert” => “true” }
add_tag => [“requires_attention”]
}
}
}
入力に ERROR [auth-service] Failed to connect to database を渡した実測出力です。
“level”: “ERROR”,
“app”: “auth-service”,
“description”: “Failed to connect to database: connection refused”,
“alert”: “true”,
“tags”: [“requires_attention”],
“@timestamp”: “2026-06-22T03:10:42.751Z”
}
INFO 行の出力では alert フィールドも requires_attention タグも現れませんでした。条件分岐が正しく動いています。
date フィルタ — タイムスタンプを UTC に正規化
複数のサーバーからログを集める場合、タイムゾーンがバラバラだと時系列順に並ばなくなります。date フィルタはログの中にあるタイムスタンプを @timestamp フィールドに読み込み、UTC で正規化します。
grok {
match => { “message” => “%{TIMESTAMP_ISO8601:event_time} %{LOGLEVEL:level} %{GREEDYDATA:log_msg}” }
}
date {
match => [“event_time”, “yyyy-MM-dd’T’HH:mm:ssZ”]
target => “@timestamp”
timezone => “Asia/Tokyo”
}
mutate { remove_field => [“event_time”] }
}
日本時間(JST、+0900)のタイムスタンプを含む入力を渡すと:
2023-10-10T09:30:00+0900 INFO Server started successfully
# 実測出力の @timestamp(UTC に変換済み)
“@timestamp”: “2023-10-10T00:30:00.000Z”
# 09:30 JST = 00:30 UTC(9時間引いた値)
# 入力(JST +0900)
2023-10-10T10:00:00+0900 ERROR Disk usage exceeded 90%
# 実測出力
“@timestamp”: “2023-10-10T01:00:00.000Z”
date フィルタを入れないと @timestamp は Logstash がイベントを処理した時刻になります。ログが書かれた時刻と処理時刻が数秒〜数分ずれるため、遡及分析には date フィルタの設定が必要です。

Ubuntu 22.04 と 24.04 のバージョン比較

実測の結果、Ubuntu 22.04 LTS と Ubuntu 24.04 LTS の両方で Elastic 8.x APT リポジトリから同一バージョン(8.19.16)を取得できました。
Logstash はバンドル JDK(OpenJDK 17.0.11 Temurin)を同梱しているため、Ubuntu 側の Java バージョン設定に依存しません。どちらの Ubuntu バージョンを使っていても、同じ手順で同じバージョンが入ります。
注意:Logstash の apt バージョンと Docker イメージのバージョンは異なる
Elastic の APT リポジトリ最新(8.19.16)と、Docker Hub の公式タグ(8.13.4 など)は別々にリリースされます。Docker で検証する場合は docker pull docker.elastic.co/logstash/logstash:8.19.x で最新タグを確認してから使うのが安全です。
よくあるエラーと対処
①「Logstash startup type is automatic」が出るがサービスが起動しない
メモリ不足が最多原因です。journalctl -u logstash -n 50 で Java の OOM エラーが出ていたら、/etc/logstash/jvm.options の -Xms1g -Xmx1g を下げます(例: -Xms512m -Xmx512m)。ただしあまり小さくすると別のエラーが出ます。
②grok パターンが合わなくて常に _grokparsefailure になる
Elastic の公式 Grok Debugger(Kibana の Dev Tools に含まれる)か、rubygems.org から gem install grok-pure で手元でテストするのが早いです。組み込みパターン名は /usr/share/logstash/vendor/bundle/jruby/*/gems/logstash-patterns-core-*/patterns/ecs-v1/ 以下に全件あります。
③起動が遅い(1分以上かかる)
Logstash は JVM の起動と初期化に時間がかかります。これは正常な動作です。起動確認は systemctl status logstash の Active: active (running) を待つか、curl http://localhost:9600 が 200 を返すまで待ちます(Logstash は 9600 番ポートで API を提供します)。
④X-Pack ライセンスエラーが出力される
スタンドアロンで動かすと Unable to retrieve license information from license server というメッセージが出ます。Elasticsearch に接続していない場合は無視して構いません。/etc/logstash/logstash.yml から xpack.monitoring.elasticsearch.hosts の行をコメントアウトすれば出なくなります。
まとめ
Ubuntu 24.04 LTS に Logstash をインストールして、grok・json・mutate・date の各フィルタを実際に動かしました。
- インストールは Elastic APT リポジトリを追加して
apt install logstashだけ。Java は不要 - grok の
%{COMBINEDAPACHELOG}1 行で Apache ログを ECS 準拠の JSON に展開できた - mutate と条件分岐を組み合わせると ERROR ログへのアラートタグ付けなど柔軟な処理ができる
- date フィルタで JST→UTC の正規化を確認した。複数サーバーのログをまとめるなら必須
- grok マッチ失敗時は
_grokparsefailureタグが自動付与されるので条件分岐でハンドリングできる - Ubuntu 22.04 / 24.04 いずれも同一の 8.19.16 が取得可能
Logstash 単体でも動きますが、実際の運用では Elasticsearch + Kibana と組み合わせた ELK スタックとして使うことが多いです。Docker Compose で一括起動する手順は https://linuxlab.jp/ubuntu-docker-install/ も参考にしてください。
VPS でサーバー監視パイプラインを組む場合、ログの転送量や Elasticsearch のディスク容量を事前に見積もっておくことをお勧めします。


コメント