Log Management

Linux ログ管理 包括ガイド

目次

  1. はじめに
  2. 従来型 syslog (rsyslog)
  3. systemd-journald
  4. logrotate
  5. 集中ログ管理
  6. ELK Stack 概要
  7. Fluentd / Fluent Bit
  8. ログ分析
  9. ログベースアラート
  10. 監査ログ (auditd)
  11. トラブルシューティング
  12. ベストプラクティス
  13. 参考資料

1. はじめに

ログ管理はシステム運用の根幹である。セキュリティインシデントの調査、パフォーマンス問題の分析、コンプライアンス要件への対応など、あらゆる場面でログが重要な役割を果たす。

Linux における主要なログ管理コンポーネントは以下の通りである。

コンポーネント役割主な設定ファイル
rsyslog従来型 syslog デーモン/etc/rsyslog.conf
systemd-journaldsystemd のジャーナルシステム/etc/systemd/journald.conf
logrotateログローテーション/etc/logrotate.conf
auditdカーネル監査システム/etc/audit/auditd.conf

主要なログファイルの場所

ファイル内容
/var/log/messagesシステム全般(RHEL系)
/var/log/syslogシステム全般(Debian系)
/var/log/auth.log認証ログ(Debian系)
/var/log/secure認証ログ(RHEL系)
/var/log/kern.logカーネルログ
/var/log/boot.logブートログ
/var/log/croncron ログ
/var/log/maillogメールログ
/var/log/audit/audit.log監査ログ
/var/log/httpd/Apache ログ
/var/log/nginx/Nginx ログ
/run/log/journal/journald 揮発性ログ
/var/log/journal/journald 永続ログ

2. 従来型 syslog (rsyslog)

2.1 rsyslog の基本構造

rsyslog は syslog プロトコル (RFC 5424) を実装した高性能ログデーモンである。

# rsyslog の状態確認
$ systemctl status rsyslog
● rsyslog.service - System Logging Service
     Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled)
     Active: active (running) since Mon 2026-03-01 10:00:00 JST; 40 days ago
       Docs: man:rsyslogd(8)
   Main PID: 1234 (rsyslogd)
      Tasks: 3 (limit: 23456)
     Memory: 4.5M
     CGroup: /system.slice/rsyslog.service
             └─1234 /usr/sbin/rsyslogd -n

# バージョン確認
$ rsyslogd -v
rsyslogd  8.2102.0-15.el9 (aka 2021.02) compiled with:
    PLATFORM:                x86_64-redhat-linux-gnu
    FEATURE_REGEXP:          Yes
    GSSAPI Kerberos 5:       Yes
    FEATURE_DEBUG:           Yes
    feature 64bit integers:  Yes
    feature TLS (GnuTLS):    Yes
    feature RELP:            Yes

2.2 ファシリティとプライオリティ

ファシリティ(ログの発生源)

ファシリティコード説明
kern0カーネルメッセージ
user1ユーザレベルメッセージ
mail2メールシステム
daemon3デーモンプロセス
auth4認証・セキュリティ
syslog5syslog 自体のメッセージ
lpr6プリンタ
news7ニュースシステム
uucp8UUCP
cron9cron デーモン
authpriv10プライベート認証メッセージ
ftp11FTP デーモン
local0-local716-23ローカル使用(カスタム用途)

プライオリティ(重要度)

プライオリティコード説明用途例
emerg0システム使用不能カーネルパニック
alert1即座の対応が必要DB破損
crit2クリティカルハードウェア障害
err3エラーアプリケーションエラー
warning4警告ディスク容量不足
notice5注意(正常だが重要)設定変更通知
info6情報サービス起動完了
debug7デバッグ詳細なデバッグ情報

2.3 rsyslog 設定

メイン設定ファイル

# /etc/rsyslog.conf

#################
#### MODULES ####
#################

# imuxsock: ローカル syslog ソケット
module(load="imuxsock")

# imklog: カーネルログ
module(load="imklog")

# imjournal: systemd ジャーナルからの入力
module(load="imjournal"
       StateFile="imjournal.state"
       ratelimit.interval="600"
       ratelimit.burst="20000")

# imtcp: TCP 経由でのリモートログ受信
# module(load="imtcp")
# input(type="imtcp" port="514")

# imudp: UDP 経由でのリモートログ受信
# module(load="imudp")
# input(type="imudp" port="514")

###########################
#### GLOBAL DIRECTIVES ####
###########################

# タイムスタンプフォーマット
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

# ファイルの所有者・パーミッション
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022

# ワークディレクトリ
$WorkDirectory /var/lib/rsyslog

###############
#### RULES ####
###############

# カーネルメッセージ
kern.*                                                 /var/log/kern.log

# 認証関連
auth,authpriv.*                                        /var/log/auth.log

# メール関連
mail.*                                                 -/var/log/mail.log
# (-) はバッファリングを有効にする(パフォーマンス向上)

# cron 関連
cron.*                                                 /var/log/cron.log

# 緊急メッセージは全ユーザに送信
*.emerg                                                :omusrmsg:*

# 全般(認証とメール以外)
*.*;auth,authpriv.none;mail.none;cron.none             /var/log/messages

# 追加の設定ファイル読み込み
$IncludeConfig /etc/rsyslog.d/*.conf

カスタムフィルタリングルール

# /etc/rsyslog.d/50-custom.conf

# プロパティベースフィルタ: 特定プログラムのログを分離
:programname, isequal, "sshd" /var/log/sshd.log
& stop    # このメッセージはここで処理を停止

# プロパティベースフィルタ: 特定メッセージパターンをフィルタ
:msg, contains, "failed password" /var/log/failed_auth.log

# RainerScript (高度なフィルタリング)
if $programname == 'nginx' and $syslogseverity <= 4 then {
    action(type="omfile" file="/var/log/nginx/error.log")
    stop
}

# テンプレート定義(カスタムログフォーマット)
template(name="CustomFormat" type="string"
    string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n")

# テンプレートを使用したルール
local0.* action(type="omfile" file="/var/log/myapp.log" template="CustomFormat")

# JSON形式のテンプレート
template(name="JsonFormat" type="list") {
    constant(value="{")
    constant(value="\"timestamp\":\"")     property(name="timereported" dateFormat="rfc3339")
    constant(value="\",\"host\":\"")       property(name="hostname")
    constant(value="\",\"severity\":\"")   property(name="syslogseverity-text")
    constant(value="\",\"facility\":\"")   property(name="syslogfacility-text")
    constant(value="\",\"program\":\"")    property(name="programname")
    constant(value="\",\"message\":\"")    property(name="msg" format="jsonf")
    constant(value="\"}\n")
}

local1.* action(type="omfile" file="/var/log/myapp-json.log" template="JsonFormat")

2.4 リモートログ転送

ログ送信側の設定

# /etc/rsyslog.d/60-remote.conf

# UDP 経由でリモートサーバに転送
*.* @logserver.example.com:514

# TCP 経由でリモートサーバに転送(信頼性が高い)
*.* @@logserver.example.com:514

# 特定のファシリティ/プライオリティのみ転送
auth,authpriv.* @@logserver.example.com:514
*.err @@logserver.example.com:514

# TLS 暗号化転送
$DefaultNetstreamDriverCAFile /etc/pki/tls/certs/ca-bundle.crt
$DefaultNetstreamDriverCertFile /etc/pki/tls/certs/rsyslog-client.crt
$DefaultNetstreamDriverKeyFile /etc/pki/tls/private/rsyslog-client.key

$ActionSendStreamDriver gtls
$ActionSendStreamDriverMode 1
$ActionSendStreamDriverAuthMode x509/name
$ActionSendStreamDriverPermittedPeer logserver.example.com

*.* @@logserver.example.com:6514

# キューイング(ネットワーク障害時のバッファリング)
$ActionQueueType LinkedList
$ActionQueueFileName remote_fwd
$ActionResumeRetryCount -1
$ActionQueueSaveOnShutdown on
$ActionQueueMaxDiskSpace 1g

ログ受信側の設定

# /etc/rsyslog.d/10-remote-receive.conf

# TCP で受信
module(load="imtcp")
input(type="imtcp" port="514")

# UDP で受信
module(load="imudp")
input(type="imudp" port="514")

# ホスト名別にログファイルを分離
template(name="RemoteHostLog" type="string"
    string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log")

# リモートホストからのログを分離保存
if $fromhost-ip != '127.0.0.1' then {
    action(type="omfile" dynaFile="RemoteHostLog")
    stop
}

# TLS 受信
module(load="imtcp"
    StreamDriver.Name="gtls"
    StreamDriver.Mode="1"
    StreamDriver.AuthMode="x509/fingerprint")

input(type="imtcp" port="6514")

3. systemd-journald

3.1 journalctl の基本操作

journald は systemd に統合されたログシステムで、構造化されたバイナリ形式でログを保存する。

# 全ログ表示(最新から)
$ journalctl

# 最新のログからリバース表示
$ journalctl -r

# 末尾のログをリアルタイム表示(tail -f 相当)
$ journalctl -f

# 直近のN行を表示
$ journalctl -n 50

# 今回のブート以降のログ
$ journalctl -b

# 前回のブートのログ
$ journalctl -b -1

# ブートID一覧
$ journalctl --list-boots
 -2 abc12345 Mon 2026-04-01 10:00:00 JST — Mon 2026-04-05 08:30:00 JST
 -1 def67890 Mon 2026-04-05 08:35:00 JST — Thu 2026-04-08 15:00:00 JST
  0 ghi13579 Thu 2026-04-08 15:05:00 JST — Fri 2026-04-10 14:00:00 JST

# 特定ユニット(サービス)のログ
$ journalctl -u sshd.service
$ journalctl -u nginx.service --since "1 hour ago"

# 特定プライオリティ以上
$ journalctl -p err         # err, crit, alert, emerg
$ journalctl -p warning     # warning 以上

# 時間範囲指定
$ journalctl --since "2026-04-10 09:00:00" --until "2026-04-10 17:00:00"
$ journalctl --since "2 hours ago"
$ journalctl --since today
$ journalctl --since yesterday --until today

# カーネルメッセージ(dmesg 相当)
$ journalctl -k
$ journalctl -k -b -1     # 前回ブートのカーネルメッセージ

# 特定PIDのログ
$ journalctl _PID=3421

# 特定UID(ユーザ)のログ
$ journalctl _UID=1000

# 特定実行ファイルのログ
$ journalctl /usr/sbin/sshd

# 出力フォーマット指定
$ journalctl -o json-pretty   # 構造化JSON
$ journalctl -o short-iso     # ISO8601 タイムスタンプ
$ journalctl -o verbose        # 全フィールド表示
$ journalctl -o cat            # メッセージのみ(メタデータなし)

# ディスク使用量確認
$ journalctl --disk-usage
Archived and active journals take up 1.2G in the file system.

# ログの手動クリーンアップ
$ sudo journalctl --vacuum-size=500M   # 500MB以下に削減
$ sudo journalctl --vacuum-time=30d    # 30日より古いログを削除
$ sudo journalctl --vacuum-files=5     # ファイル数を5以下に削減

journalctl 出力フォーマット比較:

フォーマット説明用途
shortデフォルト(syslog風)日常的な確認
short-isoISO 8601 タイムスタンプ正確な時刻確認
jsonJSON (1行)スクリプト処理
json-prettyJSON (整形)デバッグ
verbose全メタデータ詳細調査
catメッセージのみシンプルな確認
exportバイナリシリアライズログ転送

3.2 journald の設定

# /etc/systemd/journald.conf

[Journal]
# ログの保存先
# volatile = /run/log/journal/ (揮発性、再起動で消失)
# persistent = /var/log/journal/ (永続)
# auto = /var/log/journal/ があれば永続、なければ揮発性
Storage=persistent

# 圧縮を有効にする
Compress=yes

# 永続ストレージの最大サイズ(ファイルシステムの10%がデフォルト)
SystemMaxUse=2G

# 個別ジャーナルファイルの最大サイズ
SystemMaxFileSize=128M

# 空き容量の最低保証
SystemKeepFree=4G

# 揮発性ストレージの最大サイズ
RuntimeMaxUse=500M

# ログのレート制限
RateLimitIntervalSec=30s
RateLimitBurst=10000

# 転送先設定
# yes = rsyslog にも転送する(デフォルト)
ForwardToSyslog=yes
ForwardToKMsg=no
ForwardToConsole=no
ForwardToWall=yes

# 最大保存期間
MaxRetentionSec=1month

# ログレベルのフィルタ(保存する最大レベル)
MaxLevelStore=debug
MaxLevelSyslog=debug
MaxLevelKMsg=notice
MaxLevelConsole=info
MaxLevelWall=emerg
# 設定変更後の反映
$ sudo systemctl restart systemd-journald

3.3 永続ストレージ

# 永続ストレージ用ディレクトリを作成
$ sudo mkdir -p /var/log/journal
$ sudo systemd-tmpfiles --create --prefix /var/log/journal

# パーミッション確認
$ ls -la /var/log/journal/
drwxr-sr-x+ 3 root systemd-journal 4096 Apr  1 10:00 .
drwxr-xr-x 20 root root            4096 Apr  1 10:00 ..
drwxr-sr-x+ 2 root systemd-journal 4096 Apr 10 14:00 abc123def456

# journald を再起動して永続化を有効にする
$ sudo systemctl restart systemd-journald

# 状態確認
$ journalctl --header | head -20

4. logrotate

logrotate はログファイルのローテーション(アーカイブ・圧縮・削除)を自動化するツール。

メイン設定

# /etc/logrotate.conf

# ローテーション頻度(デフォルト)
weekly

# 保持する世代数
rotate 4

# ローテーション後に空ファイルを作成
create

# 圧縮を有効にする
compress

# 1世代前は圧縮しない(直前のログをすぐ参照できるように)
delaycompress

# 日付をファイル名に付加
dateext
dateformat -%Y%m%d

# サブ設定ファイルの読み込み
include /etc/logrotate.d

アプリケーション別の設定例

# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
    endscript
}

# /etc/logrotate.d/syslog
/var/log/messages
/var/log/secure
/var/log/maillog
/var/log/cron {
    weekly
    rotate 12
    compress
    delaycompress
    missingok
    notifempty
    sharedscripts
    postrotate
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
    endscript
}

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 90
    compress
    delaycompress
    missingok
    notifempty
    create 0644 myapp myapp
    
    # サイズベースのローテーション
    size 100M
    
    # ローテーション前の処理
    prerotate
        echo "Log rotation starting at $(date)" >> /var/log/myapp/rotation.log
    endscript
    
    # ローテーション後の処理
    postrotate
        systemctl reload myapp.service >/dev/null 2>&1 || true
    endscript
    
    # 最後に1回だけ実行(sharedscriptsと組み合わせ)
    lastaction
        /usr/local/bin/notify-rotation.sh myapp
    endscript
}

logrotate の主要ディレクティブ:

ディレクティブ説明
daily / weekly / monthlyローテーション頻度
rotate N保持する世代数
compressgzip で圧縮
delaycompress1世代前は圧縮しない
missingokログファイルがなくてもエラーにしない
notifempty空ファイルはローテーションしない
create MODE OWNER GROUP新しい空ファイルを作成
copytruncateコピーして元ファイルを切り詰め(シグナル不要)
sharedscriptsスクリプトを全ファイルで1回だけ実行
size SIZEサイズ超過時にローテーション
maxage NN日より古いファイルを削除
dateext日付をファイル名に付加
# logrotate のテスト実行(ドライラン)
$ sudo logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Handling 1 logs
rotating pattern: /var/log/nginx/*.log  after 1 days (30 rotations)

# 手動でローテーション実行
$ sudo logrotate -f /etc/logrotate.d/nginx

# logrotate の状態確認
$ cat /var/lib/logrotate/status
logrotate state -- version 2
"/var/log/nginx/access.log" 2026-4-10-3:0:0
"/var/log/nginx/error.log" 2026-4-10-3:0:0
"/var/log/messages" 2026-4-7-3:0:0

5. 集中ログ管理

アーキテクチャパターン

パターン1: rsyslog 直接転送
┌─────────┐     rsyslog TCP/TLS     ┌──────────────┐
│ Server A │ ──────────────────────→ │ Central Log  │
│ Server B │ ──────────────────────→ │   Server     │
│ Server C │ ──────────────────────→ │  (rsyslog)   │
└─────────┘                          └──────────────┘

パターン2: ELK Stack
┌─────────┐     Filebeat     ┌──────────┐     ┌───────────────┐     ┌────────┐
│ Server A │ ──────────────→ │ Logstash │ ──→ │ Elasticsearch │ ←── │ Kibana │
│ Server B │ ──────────────→ │          │     │               │     │        │
│ Server C │ ──────────────→ │          │     │               │     │        │
└─────────┘                  └──────────┘     └───────────────┘     └────────┘

パターン3: Fluentd/Fluent Bit
┌─────────┐    Fluent Bit    ┌──────────┐     ┌───────────────┐
│ Server A │ ──────────────→ │ Fluentd  │ ──→ │ Elasticsearch │
│ Server B │ ──────────────→ │(集約)    │ ──→ │ S3 / GCS     │
│ Server C │ ──────────────→ │          │ ──→ │ Kafka         │
└─────────┘                  └──────────┘     └───────────────┘

集中ログ管理ソリューション比較

項目rsyslog集中収集ELK StackFluentd + ESLoki + Grafana
難易度
リソース消費
検索性能低(grep)
スケーラビリティ
可視化なしKibanaKibana/GrafanaGrafana
コスト無料無料/有料無料/有料無料/有料

6. ELK Stack 概要

6.1 Elasticsearch

# Elasticsearch インストール(RPM)
$ sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

$ cat > /etc/yum.repos.d/elasticsearch.repo << 'EOF'
[elasticsearch]
name=Elasticsearch repository
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF

$ sudo dnf install elasticsearch
# /etc/elasticsearch/elasticsearch.yml
cluster.name: logging-cluster
node.name: es-node-01
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

network.host: 0.0.0.0
http.port: 9200

discovery.seed_hosts:
  - "es-node-01"
  - "es-node-02"
  - "es-node-03"

cluster.initial_master_nodes:
  - "es-node-01"

# JVMヒープサイズ(物理メモリの50%以下、32GB以下を推奨)
# /etc/elasticsearch/jvm.options.d/heap.options
# -Xms8g
# -Xmx8g

# インデックスライフサイクル管理 (ILM)
# 30日後にウォームフェーズ、90日後に削除
# 起動
$ sudo systemctl enable --now elasticsearch

# クラスタ状態確認
$ curl -s http://localhost:9200/_cluster/health?pretty
{
  "cluster_name" : "logging-cluster",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 45,
  "active_shards" : 90,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0
}

# インデックス一覧
$ curl -s http://localhost:9200/_cat/indices?v
health status index                   uuid                   pri rep docs.count store.size
green  open   logs-2026.04.10         abc123                   1   1    1234567      2.3gb
green  open   logs-2026.04.09         def456                   1   1    2345678      3.1gb

6.2 Logstash

# Logstash インストール
$ sudo dnf install logstash
# /etc/logstash/conf.d/syslog.conf

input {
  beats {
    port => 5044
    ssl => false
  }
  
  # syslog 直接受信
  syslog {
    port => 5514
    type => "syslog"
  }
}

filter {
  # syslog メッセージのパース
  if [type] == "syslog" {
    grok {
      match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" }
    }
    date {
      match => [ "syslog_timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]
    }
  }

  # Nginx アクセスログのパース
  if [fields][log_type] == "nginx_access" {
    grok {
      match => { "message" => "%{IPORHOST:clientip} - %{USER:ident} \[%{HTTPDATE:timestamp}\] \"%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response} %{NUMBER:bytes} \"%{DATA:referrer}\" \"%{DATA:agent}\"" }
    }
    geoip {
      source => "clientip"
      target => "geoip"
    }
    useragent {
      source => "agent"
      target => "user_agent"
    }
  }

  # SSH 認証失敗ログのパース
  if [program] == "sshd" {
    grok {
      match => { "message" => "Failed %{WORD:auth_method} for %{USER:username} from %{IP:src_ip} port %{INT:src_port}" }
      tag_on_failure => ["_sshd_grok_failure"]
    }
  }

  # 不要フィールドの削除
  mutate {
    remove_field => [ "beat", "input_type", "offset", "tags" ]
  }
}

output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "logs-%{+YYYY.MM.dd}"
    
    # インデックスライフサイクル管理
    ilm_enabled => true
    ilm_rollover_alias => "logs"
    ilm_pattern => "{now/d}-000001"
    ilm_policy => "logs_policy"
  }

  # デバッグ用(標準出力に表示)
  # stdout { codec => rubydebug }
}

Filebeat (ログ収集エージェント)

# /etc/filebeat/filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/messages
      - /var/log/secure
    fields:
      log_type: syslog

  - type: log
    enabled: true
    paths:
      - /var/log/nginx/access.log
    fields:
      log_type: nginx_access

  - type: log
    enabled: true
    paths:
      - /var/log/nginx/error.log
    fields:
      log_type: nginx_error

output.logstash:
  hosts: ["logstash-server:5044"]
  
  # ロードバランシング
  loadbalance: true
  
  # TLS設定
  # ssl.certificate_authorities: ["/etc/pki/tls/certs/ca-bundle.crt"]
  # ssl.certificate: "/etc/pki/tls/certs/filebeat.crt"
  # ssl.key: "/etc/pki/tls/private/filebeat.key"

# プロセッサ(軽量な前処理)
processors:
  - add_host_metadata:
      when.not.contains.tags: forwarded
  - add_cloud_metadata: ~
  - drop_fields:
      fields: ["agent.ephemeral_id", "agent.id", "agent.name", "ecs.version"]

6.3 Kibana

# /etc/kibana/kibana.yml
server.port: 5601
server.host: "0.0.0.0"
server.name: "kibana-server"

elasticsearch.hosts: ["http://localhost:9200"]

# セキュリティ設定
# elasticsearch.username: "kibana_system"
# elasticsearch.password: "changeme"

# ログ設定
logging.root.level: info
logging.appenders.file.type: file
logging.appenders.file.fileName: /var/log/kibana/kibana.log
logging.appenders.file.layout.type: json
# 起動
$ sudo systemctl enable --now kibana

# Kibana ダッシュボードへのアクセス: http://kibana-server:5601

7. Fluentd / Fluent Bit

Fluentd

# インストール (td-agent)
$ curl -fsSL https://toolbelt.treasuredata.com/sh/install-redhat-fluent-package5-lts.sh | sh

# または gem でインストール
$ sudo gem install fluentd
<!-- /etc/fluent/fluentd.conf -->

<!-- syslog 入力 -->
<source>
  @type syslog
  port 5140
  tag system
  <parse>
    message_format auto
  </parse>
</source>

<!-- ファイル入力 -->
<source>
  @type tail
  path /var/log/nginx/access.log
  pos_file /var/log/fluentd/nginx-access.pos
  tag nginx.access
  <parse>
    @type nginx
  </parse>
</source>

<!-- ファイル入力(JSON形式のアプリログ) -->
<source>
  @type tail
  path /var/log/myapp/*.log
  pos_file /var/log/fluentd/myapp.pos
  tag myapp
  <parse>
    @type json
    time_key timestamp
    time_format %Y-%m-%dT%H:%M:%S.%NZ
  </parse>
</source>

<!-- フィルタ: フィールド追加 -->
<filter **>
  @type record_transformer
  <record>
    hostname "#{Socket.gethostname}"
    environment production
  </record>
</filter>

<!-- フィルタ: 不要ログの除外 -->
<filter nginx.access>
  @type grep
  <exclude>
    key path
    pattern /\/(health|ready)/
  </exclude>
</filter>

<!-- Elasticsearch への出力 -->
<match **>
  @type elasticsearch
  host elasticsearch-server
  port 9200
  logstash_format true
  logstash_prefix logs
  
  <buffer>
    @type file
    path /var/log/fluentd/buffer/elasticsearch
    flush_interval 10s
    chunk_limit_size 8MB
    queue_limit_length 256
    retry_max_interval 30
    retry_forever true
  </buffer>
</match>

<!-- S3 への出力(アーカイブ用) -->
<match archive.**>
  @type s3
  s3_bucket my-log-archive
  s3_region ap-northeast-1
  path logs/%Y/%m/%d/
  
  <buffer time>
    @type file
    path /var/log/fluentd/buffer/s3
    timekey 3600
    timekey_wait 10m
  </buffer>
  
  <format>
    @type json
  </format>
</match>

Fluent Bit (軽量版)

# /etc/fluent-bit/fluent-bit.conf

[SERVICE]
    Flush         5
    Daemon        Off
    Log_Level     info
    Parsers_File  parsers.conf
    HTTP_Server   On
    HTTP_Listen   0.0.0.0
    HTTP_Port     2020

[INPUT]
    Name              tail
    Path              /var/log/messages
    Tag               syslog
    Parser            syslog-rfc3164
    Refresh_Interval  10
    Mem_Buf_Limit     5MB

[INPUT]
    Name              systemd
    Tag               journal.*
    Systemd_Filter    _SYSTEMD_UNIT=sshd.service
    Systemd_Filter    _SYSTEMD_UNIT=nginx.service
    Read_From_Tail    On

[INPUT]
    Name              tail
    Path              /var/log/nginx/access.log
    Tag               nginx.access
    Parser            nginx
    Refresh_Interval  5

[FILTER]
    Name              modify
    Match             *
    Add               hostname ${HOSTNAME}

[FILTER]
    Name              grep
    Match             nginx.access
    Exclude           path /health

[OUTPUT]
    Name              forward
    Match             *
    Host              fluentd-aggregator
    Port              24224

[OUTPUT]
    Name              es
    Match             *
    Host              elasticsearch-server
    Port              9200
    Index             logs
    Type              _doc
    Logstash_Format   On
    Logstash_Prefix   logs
    Retry_Limit       5

Fluentd vs Fluent Bit 比較:

特徴FluentdFluent Bit
言語Ruby + CC
メモリ使用量~40MB~450KB
プラグイン数700+100+
用途集約・ルーティングエッジ・軽量収集
パフォーマンス非常に高
設定の柔軟性非常に高
Kubernetes対応推奨(DaemonSet)

8. ログ分析

コマンドラインでのログ分析

# アクセスログの基本分析

# IPアドレス別アクセス数(上位10件)
$ awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
   4567 192.168.1.100
   3456 10.0.0.50
   2345 172.16.0.25
   1234 192.168.1.200

# HTTPステータスコード別集計
$ awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
  45678 200
   5678 301
   3456 404
    567 500
    234 403

# 時間帯別アクセス数
$ awk -F'[' '{print $2}' /var/log/nginx/access.log | awk -F: '{print $2}' | sort | uniq -c
   1234 00
   1100 01
    890 02
   ...
   5678 10
   6789 11
   ...

# エラーログの分析
$ grep "error" /var/log/nginx/error.log | awk '{print $NF}' | sort | uniq -c | sort -rn | head -10

# SSH認証失敗の分析
$ grep "Failed password" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -rn | head -10
    456 192.168.1.50
    234 10.0.0.100
    123 172.16.0.99

# 特定期間のログ抽出(journalctl)
$ journalctl -u sshd --since "2026-04-10 00:00" --until "2026-04-10 23:59" | grep "Failed" | wc -l
45

# ログのリアルタイム監視(複数ファイル)
$ tail -f /var/log/messages /var/log/secure /var/log/nginx/error.log

# awk を使った高度な分析
$ awk '/Failed password/{
    match($0, /from ([0-9.]+)/, arr);
    ips[arr[1]]++
}
END {
    for (ip in ips) printf "%6d %s\n", ips[ip], ip
}' /var/log/secure | sort -rn | head -10

ログ分析ツール

# GoAccess(リアルタイムWebログ分析)
$ sudo dnf install goaccess

# ターミナルで表示
$ goaccess /var/log/nginx/access.log --log-format=COMBINED

# HTML レポート生成
$ goaccess /var/log/nginx/access.log --log-format=COMBINED -o /var/www/html/report.html

# lnav(高機能ログビューア)
$ sudo dnf install lnav
$ lnav /var/log/messages /var/log/secure

9. ログベースアラート

rsyslog でのアラート

# /etc/rsyslog.d/70-alerts.conf

# OOM Killer 検知時にメール送信
if $msg contains "Out of memory" then {
    action(type="ommail"
        server="smtp.example.com"
        port="25"
        mailfrom="alert@example.com"
        mailto="ops@example.com"
        subject.template="OOM_Alert"
        body.enable="on")
}

# SSH ブルートフォース検知
template(name="SSHAlert" type="string"
    string="SSH brute force detected: %msg%\nHost: %HOSTNAME%\nTime: %timereported%\n")

if $programname == 'sshd' and $msg contains 'Failed password' then {
    action(type="omfile" file="/var/log/ssh-alerts.log")
    # 外部スクリプト呼び出し
    action(type="omprog" binary="/usr/local/bin/ssh-alert.sh")
}

Prometheus + Alertmanager でのログアラート

# Prometheus アラートルール(mtail等と組み合わせ)
groups:
  - name: log_alerts
    rules:
      - alert: HighErrorRate
        expr: rate(log_errors_total[5m]) > 10
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "High error rate in logs"
          description: "Error rate is {{ $value }}/s on {{ $labels.instance }}"

      - alert: SSHBruteForce
        expr: rate(ssh_failed_logins_total[5m]) > 5
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "SSH brute force detected on {{ $labels.instance }}"

fail2ban(ログベースの自動防御)

# /etc/fail2ban/jail.local

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
backend = systemd

[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 3
bantime = 86400

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 5
# fail2ban の状態確認
$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 3
|  |- Total failed:     45
|  `- File list:        /var/log/secure
`- Actions
   |- Currently banned: 2
   |- Total banned:     12
   `- Banned IP list:   192.168.1.50 10.0.0.100

10. 監査ログ (auditd)

10.1 auditd の設定

auditd はカーネルの監査サブシステムであり、セキュリティ関連のイベントを詳細に記録する。

# インストール確認
$ rpm -qa | grep audit
audit-3.0.7-1.el9.x86_64
audit-libs-3.0.7-1.el9.x86_64

# サービス状態確認
$ sudo systemctl status auditd
$ sudo auditctl -s
enabled 1
failure 1
pid 1234
rate_limit 0
backlog_limit 8192
lost 0
backlog 0

メイン設定

# /etc/audit/auditd.conf
log_file = /var/log/audit/audit.log
log_group = root
log_format = ENRICHED
flush = INCREMENTAL_ASYNC
freq = 50
max_log_file = 50
num_logs = 10
max_log_file_action = ROTATE
space_left = 75
space_left_action = SYSLOG
admin_space_left = 50
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND

# ネットワーク経由のログ転送
# tcp_listen_port = 60
# tcp_listen_queue = 5
# tcp_max_per_addr = 1

監査ルール

# /etc/audit/rules.d/audit.rules

# 既存ルールの削除
-D

# バッファサイズ
-b 8192

# 失敗時の動作(0=何もしない、1=printk、2=panic)
-f 1

# ============================================
# ファイルアクセス監視
# ============================================

# passwd, shadow, group ファイルの変更監視
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/gshadow -p wa -k identity

# sudoers の変更監視
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers

# SSH設定の変更監視
-w /etc/ssh/sshd_config -p wa -k sshd_config

# cron設定の変更監視
-w /etc/crontab -p wa -k cron
-w /etc/cron.d/ -p wa -k cron
-w /var/spool/cron/ -p wa -k cron

# ============================================
# システムコール監視
# ============================================

# ファイル削除の監視(uid >= 1000 の一般ユーザ)
-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k file_deletion

# 権限昇格の監視
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=4294967295 -k privilege_escalation

# ネットワーク設定変更の監視
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k network_changes

# 時刻変更の監視
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time_change
-w /etc/localtime -p wa -k time_change

# ログイン・ログアウトの監視
-w /var/log/lastlog -p wa -k logins
-w /var/run/faillock/ -p wa -k logins
-w /var/log/tallylog -p wa -k logins

# カーネルモジュールの操作監視
-a always,exit -F arch=b64 -S init_module -S delete_module -S finit_module -k kernel_modules
-w /sbin/insmod -p x -k kernel_modules
-w /sbin/rmmod -p x -k kernel_modules
-w /sbin/modprobe -p x -k kernel_modules

# ============================================
# 設定を不変にする(最後に記述)
# ============================================
-e 2
# ルールの適用
$ sudo augenrules --load
$ sudo auditctl -l    # 現在のルール一覧表示

# ルールの一時追加
$ sudo auditctl -w /tmp/testfile -p rwxa -k test_watch
$ sudo auditctl -a always,exit -F arch=b64 -S open -F dir=/etc -F success=0 -k etc_access_fail

監査ルールのフラグ:

フラグ説明
-wファイル/ディレクトリの監視
-pパーミッション: r(read), w(write), x(execute), a(attribute)
-kキー(検索用タグ)
-aシステムコールルールの追加
-Fフィルタ条件
-S監視するシステムコール

10.2 ausearch

# キーで検索
$ sudo ausearch -k identity
----
time->Fri Apr 10 10:30:15 2026
type=CONFIG_CHANGE msg=audit(1712717415.123:456): auid=1000 ses=2 subj=unconfined op=updated_rules path="/etc/passwd" key="identity" list=4 res=1

# 時間範囲で検索
$ sudo ausearch --start 04/10/2026 09:00:00 --end 04/10/2026 17:00:00

# ユーザIDで検索
$ sudo ausearch -ua 1000

# システムコールで検索
$ sudo ausearch -sc execve

# 結果をインタプリット(人間が読みやすい形式)
$ sudo ausearch -k identity -i
----
type=CONFIG_CHANGE msg=audit(2026/04/10 10:30:15.123:456): auid=sysadmin ses=2 subj=unconfined op=updated_rules path="/etc/passwd" key="identity" list=exit res=yes

# 失敗したアクセスのみ
$ sudo ausearch --success no

# 特定のコマンド実行を検索
$ sudo ausearch -c sudo

# 特定ファイルへのアクセスを検索
$ sudo ausearch -f /etc/shadow

# CSV形式で出力
$ sudo ausearch -k identity --format csv

10.3 aureport

# サマリレポート
$ sudo aureport --summary

Summary Report
======================
Range of time in logs: 04/01/2026 00:00:00.000 - 04/10/2026 14:00:00.000
Selected time for report: 04/01/2026 00:00:00.000 - 04/10/2026 14:00:00.000
Number of changes in configuration: 45
Number of changes to accounts, groups, or roles: 12
Number of logins: 234
Number of failed logins: 56
Number of authentications: 345
Number of failed authentications: 78
Number of users: 15
Number of terminals: 8
Number of host names: 5
Number of executables: 45
Number of commands: 123
Number of files: 234
Number of AVC's: 0
Number of MAC events: 12
Number of failed syscalls: 890
Number of anomaly events: 3
Number of responses to anomaly events: 0
Number of crypto events: 567
Number of integrity events: 0
Number of virt events: 0
Number of keys: 8
Number of process IDs: 1234
Number of events: 12345

# 認証レポート
$ sudo aureport -au
Authentication Report
============================================
# date time acct host term exe success event
============================================
1. 04/10/2026 09:15:01 admin 192.168.1.100 ssh /usr/sbin/sshd yes 1234
2. 04/10/2026 09:20:15 root 192.168.1.50 ssh /usr/sbin/sshd no 1235
3. 04/10/2026 10:30:00 admin ? /dev/pts/0 /usr/bin/sudo yes 1236

# 失敗した認証のみ
$ sudo aureport -au --failed

# ログインレポート
$ sudo aureport -l

# ファイルアクセスレポート
$ sudo aureport -f

# 実行可能ファイルレポート
$ sudo aureport -x

# 異常イベントレポート
$ sudo aureport --anomaly

# キー別レポート
$ sudo aureport -k
Key Report
===============================================
# date time key success exe auid event
===============================================
1. 04/10/2026 10:30:15 identity yes /usr/sbin/useradd 1000 456
2. 04/10/2026 11:00:00 sudoers yes /usr/bin/vi 1000 789
3. 04/10/2026 12:15:30 sshd_config yes /usr/bin/vi 1000 1012

# 時間範囲指定
$ sudo aureport -au --start 04/10/2026 09:00:00 --end 04/10/2026 17:00:00

11. トラブルシューティング

rsyslog のトラブルシューティング

# rsyslog の構文チェック
$ rsyslogd -N 1
rsyslogd: version 8.2102.0, config validation run...
rsyslogd: End of config validation run. Bye.

# デバッグモードで起動
$ sudo rsyslogd -dn

# rsyslog の内部統計
$ sudo rsyslogd -N 1 -o fullmain

# ログが書き込まれない場合
# 1. パーミッション確認
$ ls -la /var/log/messages
-rw------- 1 root root 1234567 Apr 10 14:00 /var/log/messages

# 2. SELinux コンテキスト確認
$ ls -Z /var/log/messages
system_u:object_r:var_log_t:s0 /var/log/messages

# 3. ディスク容量確認
$ df -h /var/log

# 4. rsyslog のエラーログ確認
$ journalctl -u rsyslog --since "1 hour ago"

journald のトラブルシューティング

# ジャーナルの整合性チェック
$ journalctl --verify
PASS: /var/log/journal/abc123/system.journal
PASS: /var/log/journal/abc123/user-1000.journal

# ジャーナルのディスク使用量
$ journalctl --disk-usage
Archived and active journals take up 1.2G in the file system.

# ジャーナルファイルの直接確認
$ ls -la /var/log/journal/*/

# ログが永続化されない場合
# 1. ディレクトリの存在確認
$ ls -la /var/log/journal/
# 2. 設定確認
$ grep Storage /etc/systemd/journald.conf
# 3. パーミッション確認
$ stat /var/log/journal/

auditd のトラブルシューティング

# 監査ログのバックログ確認
$ sudo auditctl -s
enabled 1
failure 1
pid 1234
rate_limit 0
backlog_limit 8192
lost 0        # ここが > 0 ならログロスト
backlog 45

# バックログが溢れる場合
$ sudo auditctl -b 16384   # バッファサイズを増加

# ルールが多すぎてパフォーマンスに影響する場合
$ sudo auditctl -l | wc -l    # ルール数確認

# 特定ルールの除外(高頻度すぎるルール)
$ sudo auditctl -a never,exit -F dir=/tmp/high_io_dir

12. ベストプラクティス

ログ管理全般

  1. ログの集中管理を実装する -- 各サーバのログを1箇所に集約し、検索・分析を容易にする
  2. ログのローテーションを確実に設定する -- ディスク枯渇を防止
  3. タイムスタンプを統一する -- NTP でシステム時刻を同期し、全サーバで UTC または同一タイムゾーンを使用
  4. 構造化ログを採用する -- JSON 形式など、パーサブルなフォーマットを使用
  5. ログレベルを適切に設定する -- 本番環境では info 以上、デバッグが必要な場合のみ debug

セキュリティ

  1. 監査ログは分離して保存する -- 攻撃者による改竄を困難にする
  2. ログの転送は暗号化する -- TLS を使用
  3. ログの改竄検知を実装する -- ハッシュベースの整合性チェック
  4. アクセス権限を最小化する -- ログファイルの読み取り権限を制限
  5. コンプライアンス要件に従った保存期間を設定する -- PCI DSS は最低1年

パフォーマンス

  1. 非同期書き込みを使用する -- rsyslog の - プレフィックスやバッファリング
  2. レート制限を設定する -- ログストームによるシステム障害を防止
  3. 不要なログを早期にフィルタリングする -- 転送前に不要ログを除外
  4. ディスクI/O への影響を監視する -- 特に高トラフィック環境

保存と管理

# ログ保存期間の推奨値
# セキュリティログ: 最低1年(コンプライアンスに応じて)
# アプリケーションログ: 3-6ヶ月
# デバッグログ: 1-4週間
# アクセスログ: 3-12ヶ月

# ストレージ見積もりの例
# 1サーバあたり 1GB/日 のログ
# 10サーバ x 1GB/日 x 90日 = 900GB
# 圧縮率 ~10:1 = ~90GB の実ストレージ

ログ管理チェックリスト

項目確認事項
収集全サーバでログ収集エージェントが稼働しているか
転送ログが集中サーバに到達しているか
保存ローテーションが正しく動作しているか
検索必要なログを迅速に検索できるか
アラート重要イベントのアラートが設定されているか
監査コンプライアンス要件を満たしているか
バックアップログのバックアップが取られているか
アクセス制御ログへのアクセス権限が適切か

13. 参考資料


最終更新: 2026-04-10
対象OS: RHEL 8/9, Ubuntu 22.04/24.04, 及び systemd ベースの主要Linuxディストリビューション