Linuxのログ管理のしくみ(journald + rsyslog) | 若手エンジニアのブログ

若手エンジニアのブログ

文系出身の若手女子エンジニアによる技術ブログ。
日々の経験や学びをアウトプットするためにブログを書いています。
バックエンド(Java+SpringFramework)を経てインフラエンジニアになりました。
今は育休中につき、本で勉強したことを中心にアウトプットしています。

年末ですね!

体調を崩してしばらくブログを放置してましたが(※コロナではないです)

久しぶりに頑張って書きたいと思います◎

 

今回は前回の記事の続き(?)で、Linuxのログ管理について。

そもそもなぜログが必要なのか?は、前回の記事でまとめています。

 

 

なお確認環境は、CentOS8です。

 

もくじ

1.Linuxでのログの仕組み

2.journaldについて ( 概要設定ファイル / journal ログを直接確認する方法

3.rsyslogについて ( 概要設定ファイル / モジュールグローバルディレクティブルールおさらい

4.ログローテーションとは(概要のみ)

 

1.Linuxでのログ管理のしくみ

Linux OSでは、syslogまたはrsyslogという機能によって、ログ管理が行われていることが多い。

syslogは古くからある機能で、rsyslogはsyslogのパワーアップ版である。

CentOS7や8では、rsyslogがデフォルト利用されている。

 

CentOS7や8のログ管理は、デフォルトで以下2つの仕組みにより成り立っている。

 

  ・ログ収集: journaldが担当

  ・jounarldが収集したログを、変形し、ログファイルに出力: rsyslogが担当

 

 

システムでイベント(システムの何らかの動き)が起きると、

journaldという名前のデーモンがそのイベントを逐一記録して、journalログとしてjournal databaseに蓄積する。

rsyslogdはjounal databaseの内容を確認し、あらかじめ決められたルールに従って、

記録されたログを整形・分類して、ログファイルに出力する。

 

なおryslogは、自身のサーバ(ローカルサーバ)でのjounalログを確認することはもちろん、

設定によっては別のサーバのjournalログも確認することができる。

さらに、整形・分類したログを自サーバ内のログファイルに出力する以外に、

他のサーバに出力するよう設定することもできる。

ログの集中管理をしたい時に便利である。

 

journaldとrsyslogについて、以下で詳しく仕組みを見ていきたい。

 

2.journaldについて

◎概要

1.Linuxでのログ管理のしくみ にも書いた通り、イベントを逐一記録する役割を果たすのが、

jounaldというデーモンである。

 

↓図のオレンジの部分の話

 

※ちなみに、journaldは、それ単体でログ出力・管理を行う機能も持っている。
ただし、Linuxの代表格であるRedHat系やUbunts系では、デフォルトで、
journaldでログ収集、rsyslog(またはsyslog)でログ出力・管理とし、ログ関連の機能を分業している。

そのため、この記事でも、journaldがログ収集というデフォルトの役割を果たすものとして見ていく。

 

 

CentOS8のデフォルトでは、
journaldはログ収集を行い、収集したログ(journalログ)を、バイナリ状態でjournal databaseに保管する。

 

journal databaseの実体、すなわち物理的なログの保管先は、

設定ファイル(後述)の「Storage」パラメータの値によって以下のように変わってくる。

Storage
パラメータ値
保管先(journal databaseの在り処) 備考
auto

/var/log/journal
ただしファイルが無い場合は
/run/log/journal

デフォルト設定
volatile /run/log/journal 保管先となるファイルが無い場合、
作成される
persistent /var/log/journal(無い場合作成)
ただし書き込めなかった場合は
/run/log/journal
autoとの違いは、
/var/log/journalを作成するかどうか
none なし jounarlログをすべて廃棄する設定。
よほどのことがない限り設定しない

 

/run/log/journalと/var/log/journalが出てくるが、それらの違いについて確認しておきたい。
 

まず、/runディレクトリは揮発性ストレージとして利用される場所である。

従ってjournalログは、システムをシャットダウンすると消えてしまう。

しかもメモリが急に落ちると、最後らへんのログが最悪残らなかったりする…。

ただし、シャットダウンによりjournaldログが消えたとしても、

消える前にrsyslogできちんと処理された分までのログは、ログファイルとして残る。

 

一方、/var/log/journalは永続ファイルである。

そのため、ログローテーションやファイルサイズの最大値指定などをせずに放っておくと、ディスク容量の圧迫につながる。
 

以上を踏まえ、journalログの保管先は、

状況に応じて、/run配下と/var配下、どちらが良いか検討し、journaldの設定ファイルに明記しておくと良い。

 

◎設定ファイル

journaldの設定ファイルは以下に配置されている。(CentOS8の場合)

/etc/systemd/journald.conf

 

内容は以下の通り。コメントアウトされているが、記載値はすべてデフォルトで設定されている値となる。

(オレンジのコメント部分は筆者追記)

 $ cat /etc/systemd/journald.conf
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See journald.conf(5) for details.

[Journal]
#Storage=auto   
//journaldログの保管先
#Compress=yes  //journaldログを圧縮して保管するか
#Seal=yes          //FSSの有効化設定
#SplitMode=uid   //journalファイルをユーザ毎に作るか
#SyncIntervalSec=5m          //journaldファイルへのログ同期までの時間
#RateLimitIntervalSec=30s //この間隔内にRateLimitBurstを超えてログがあると廃棄する
#RateLimitBurst=10000 //RateLimitIntervalSecの間隔内にこの値を超えてログがあると廃棄する
#SystemMaxUse=         //journalが使えるディスク最大容量
#SystemKeepFree=       //journalが他システムのために空けておくべき容量
#SystemMaxFileSize=    //journalファイル(永続)の最大サイズ
#SystemMaxFiles=100   //journalファイル(永続)の最大数
#RuntimeMaxUse=        //ランタイムのjournalが使えるメモリ容量
#RuntimeKeepFree=     //ランタイムのjournalが他システムのために空けておくべき容量
#RuntimeMaxFileSize=  //ランタイムのjournalファイルの最大サイズ
#RuntimeMaxFiles=100  //ランタイムのjournalファイルの最大数
#MaxRetentionSec=      //journalエントリを廃棄するまでの最大時間(超えると廃棄する)
#MaxFileSec=1month    //journalエントリを1つのjournalファイルに格納する最大時間
#ForwardToSyslog=no   //syslogにjounalログを転送するか
#ForwardToKMsg=no    //カーネルログバッファにjounalログを転送するか
#ForwardToConsole=no  //コンソールにjounalログを転送するか
#ForwardToWall=yes  //全ログインユーザにログを転送するか
#TTYPath=/dev/console //使用するコンソールのパス(ForwardToConsole=yesで有効)
#MaxLevelStore=debug  //保管対象の最大ログレベル(デフォルトではdebug以上)
#MaxLevelSyslog=debug //syslogに転送する最大ログレベル(ForwardToSyslog=yesで有効)
#MaxLevelKMsg=notice //カーネルに転送する最大ログレベル(ForwardToKMsg=yesで有効)
#MaxLevelConsole=info //コンソールに転送する最大ログレベル(ForwardToConsole=yesで有効)
#MaxLevelWall=emerg //全ログインユーザに転送する最大ログレベル(ForwardToWall=yesで有効)
#LineMax=48K            //最大ログ長

 

前述の通り、Storageの値は必要に応じて変更することを推奨する。

 

その他、基本的にはデフォルト値を変更する必要はないと思うが、

容量圧迫回避のためにSystemMaxUseやRuntimeMaxUseなどの値(上限値を設ける)変更、

同じく容量圧迫回避のためにdebugレベルのログを出さない(MaxLevelStore=infoなど)とすることは検討しても良いと思う。


パラメータのより詳細情報を知りたい方は以下をご参照のこと。(英語です)

$ systemctl restart systemd-journald

◎journalログを直接確認する方法

journal databaseに格納されるログ情報は、バイナリであるため、catコマンドなどで直接中身を確認することはできない。

直接確認したい場合は、以下のコマンドを使う。

$ journalctl [オプション] [フィールド=値]

 

引数無しでもjournalログの確認は可能だが、そうするとすべてのjournalログ表示となり、膨大な量となるため、通常は引数を指定して確認する。

 

例えばこんな感じ。

--since、--untilオプションで、確認したいログの時間範囲を指定し、PRIORITYフィールドの値を5とすることで、noticeレベルのログだけを出力する設定としている。

$ journalctl --since="2020-12-13 10:00:00" --until="2020-12-13 10:30:00" PRIORITY=5
-- Logs begin at Sat 2020-11-21 19:10:26 JST, end at Sun 2020-12-13 10:26:50 JST. --
Dec 13 10:01:01 localhost run-parts[13869]: (/etc/cron.hourly) starting 0anacron
Dec 13 10:01:01 localhost run-parts[13875]: (/etc/cron.hourly) finished 0anacron
Dec 13 10:11:01 localhost anacron[13064]: Job `cron.weekly' started
Dec 13 10:11:01 localhost anacron[13064]: Job `cron.weekly' terminated
Dec 13 10:11:01 localhost anacron[13064]: Normal exit (2 jobs run)

 

 

3.rsyslogについて

◎概要

rsyslogdは、古くから利用されているログ管理デーモンsyslogdの拡張版であり、

各ログを分類・整形し、指定されたディレクトリにログファイルとして出力してくれる。

その他、1.Linuxでのログ管理のしくみ でも述べたように、外部サーバのログを出力するといったことも、rsyslogの仕組みで可能となっている。

 

↓図の色がついてる部分の話。

 

◎設定ファイル

rsyslogの設定は以下に記述する。

/etc/rsyslog.conf

 

CentOS8での設定ファイルのデフォルトは以下の通り。

設定ファイル内のコメントにも書かれているが、設定は3つ(モジュールグローバルディレクティブルール)のパートに分かれている。

$ # rsyslog configuration file

# For more information see /usr/share/doc/rsyslog-*/rsyslog_conf.html
# or latest version online at http://www.rsyslog.com/doc/rsyslog_conf.html
# If you experience problems, see http://www.rsyslog.com/doc/troubleshoot.html


#### MODULES ####

module(load="imuxsock"    # provides support for local system logging (e.g. via logger command)
       SysSock.Use="off") # Turn off message reception via local log socket;
                          # local messages are retrieved through imjournal now.
module(load="imjournal"             # provides access to the systemd journal
       StateFile="imjournal.state") # File to store the position in the journal
#module(load="imklog") # reads kernel messages (the same are read from journald)
#module(load"immark") # provides --MARK-- message capability

# Provides UDP syslog reception
# for parameters see http://www.rsyslog.com/doc/imudp.html
#module(load="imudp") # needs to be done just once
#input(type="imudp" port="514")

# Provides TCP syslog reception
# for parameters see http://www.rsyslog.com/doc/imtcp.html
#module(load="imtcp") # needs to be done just once
#input(type="imtcp" port="514")


#### GLOBAL DIRECTIVES ####

# Where to place auxiliary files
global(workDirectory="/var/lib/rsyslog")

# Use default timestamp format
module(load="builtin:omfile" Template="RSYSLOG_TraditionalFileFormat")

# Include all config files in /etc/rsyslog.d/
include(file="/etc/rsyslog.d/*.conf" mode="optional")


#### RULES ####

# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.*                                                 /dev/console

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none                /var/log/messages

# The authpriv file has restricted access.
authpriv.*                                              /var/log/secure

# Log all the mail messages in one place.
mail.*                                                  -/var/log/maillog


# Log cron stuff
cron.*                                                  /var/log/cron

# Everybody gets emergency messages
*.emerg                                                 :omusrmsg:*

# Save news errors of level crit and higher in a special file.
uucp,news.crit                                          /var/log/spooler

# Save boot messages also to boot.log
local7.*                                                /var/log/boot.log


# ### sample forwarding rule ###
# 以降すべてコメントのため省略

 

モジュール、グローバルディレクティブ、ルールの各設定について、詳細は以下の通りである。

 

◎設定1:モジュール

rsyslogは最低限の機能だけが実装されている。

そのため、journaldや外部サーバなどからのログ収集、ファイルや外部サーバへのログ出力、

ログの解析、整形(マスキングやフォーマッティング等)、監視などの各機能の利用には、

モジュールと呼ばれるオプション機能を読み込む必要がある。

 

イメージ↓


設定できるモジュールは多数ある(公式参照)が、デフォルトでは以下の2つが追加されている。
 ・imjournal
 ・imuxsock

 

imjournalは、journalログを収集するためのモジュールであり、

このモジュールがロードされていることで、journald + rsyslogによるログ管理を実現できるようになっている。

 

imuxsockは、自サーバのログを、rsyslogで受け取れるようにするためのモジュール。

といってもjournaldがログ収集の役割を担ってくれるので、必要なければロードしなくても良い。

 

その他、設定ファイルには明示されていないが、以下のモジュールが最初からロードされている。

 ・omfile(ログをファイルに出力するためのモジュール)

 ・ompipe(ログを名前付きパイプ(fifos)に出力するためのモジュール

(あと2つくらい最初からロードされているものがあったような気がしますが忘れました、ごめんなさい(-_-;))

 

 

モジュールを追加する書式は以下の通り。

$ module(load="モジュール名" [[パラメータ=値] ...])

 

上述の設定ファイル(デフォルト)から抜き出すと、例えばこのような感じ。

$ module(load="imjournal" StateFile="imjournal.state")

 

各モジュールにどのようなパラメータを渡せるかも、公式ドキュメントに細かく記載されているのでご参照のこと。

 

◎設定2:グローバルディレクティブ

rsyslog設定ファイルの2つ目のパート。

グローバルディレクティブは、簡単にいうと、rsyslogのログ管理全体に関わる設定ができるようになっている。

ただ、グローバルディレクティブが、具体的にどこまでの設定内容を示しているのかは、ドキュメント等によって異なっており、ぶっちゃけよく分からない。。(ご存じだったら教えてください)

 

参考までに…

・RedHatのドキュメント(redhat7

 global() で渡せるパラメータがグローバルディレクティブという書かれ方をしている。

 (↓ドキュメントを抜粋。青字の部分注目)

 

・デフォルトの設定内容

 先ほど出したデフォルトの設定内容の一部を再掲すると、「global()」で渡せるパラメータの他、module()やらinclude()やらが書かれている。前述のRedHatドキュメントとは矛盾しているように見える…。

#### GLOBAL DIRECTIVES ####

# Where to place auxiliary files
global(workDirectory="/var/lib/rsyslog")   
# ←global()の部分は確かにあるが…

# Use default timestamp format  # ↓最初からロードされているomfileモジュールの設定
module(load="builtin:omfile" Template="RSYSLOG_TraditionalFileFormat")

# Include all config files in /etc/rsyslog.d/  
# ↓設定ファイルとして別ファイルも含む記述あり
include(file="/etc/rsyslog.d/*.conf" mode="optional")

 

どこまでがグローバルディレクティブなのか謎(^-^;

 

・rsyslogのドキュメント

さらに混乱を生むのが、rsyslogのドキュメント。まさかの、「グローバルディレクティブ」という言葉が出てこない汗

「global()」は、RainerScriptというやつに含まれてる模様。スクリプトで記述できる特別なオブジェクトのような…(なんだそれ)

ちなみにRainerScriptのさらに大きなくくりは、Configuration(設定)となっていた。

(ドキュメントの目次を抜粋↓)

 

・・・ということで、何をもってグローバルディレクティブというのかは曖昧だが、

rsyslogのログ管理全体に関わる設定というふうに考えておけば、ひとまずOKだと思う。(たぶん)

いずれにせよ、「global()」のくくりで、各種パラメータを渡して、rsyslog全体に関する設定が出来るのは事実。

「global()」でどんなパラメータを渡せるかは、rsyslogのドキュメントに一覧があるのでご参照のこと。

 

 

◎設定3:ルール(ファシリティとプライオリティとアクション)

rsyslogの設定3つめ、ルールについて。

ルールとは、何に関するログを、どれくらい細かいレベルで、どこに出力するかという話。

 

例えば、カーネルに関するログを、infoレベル以上まで、/var/log/kernel.logに出力したい場合、

/etc/rsyslog.conf に以下の通り記載する。

kern.info     /var/log/kernel.log

# 何に関するログか.ログレベル       出力先

 

これらの各設定内容について、以下のように名前がついている。

内容 名称 例の対象箇所
何に関するログか ファシリティ kern
ログレベル プライオリティ(重要度、優先度) info
出力先 アクション /var/log/kernel.log

 

アクションに設定する値は任意だが、ファシリティ、プライオリティの値は、rsyslogによって予約されている。

ファシリティとプライオリティの一覧は「rsyslog ファシリティ プライオリティ」とかでググれば、すぐにわかると思うのでここでは割愛…。

 

ちなみに、、

ファシリティ、プライオリティには、正規表現「*」も設定することができる。

例えば以下のようにした場合、userに関するログであれば、どのようなプライオリティであっても出力する設定となる。

user.*     /var/log/user.log

 

また、ファシリティは複数を明示指定することもできる。

以下のようにした場合、uucpに関するログと、newsに関するログの、それぞれcrit以上のレベルを出力する設定となる。

uucp,news.crit                                          /var/log/spooler

 

 

◎ということで、おさらい

rsyslogに関して長くなったのでまとめておく。

 ・rsyslogのログの収集先は、デフォルトではローカルのjournaldデータベースとなっているが、

  モジュールの読み込み次第では、journald以外からも収集することができる。

 ・モジュールは、ログの収集だけでなく、出力先やログメッセージの整形などなど、拡張機能を多く提供しており、必要な機能をロードして利用することができる。

 ・グローバルディレクティブでは、rsyslog全般に関する設定を行う。

 ・ファシリティ×プライオリティ×アクションで、ログの出力ルールを決めることができる。

 

以上を踏まえて、再度、rsyslogの設定ファイルのデフォルト値を見て頂ければ、ある程度意味がつかめるはず。

図も再掲しておく。

 

 

4.ログローテーションとは

最後に。

ログファイルのローテーションについてもちょっとだけ…。

※ここまで説明してきたjournald + rsyslogdによるログ管理とは別の話となる。

 

rsyslogでログメッセージをログファイルに出力する場合、

何もせず放っておくと、過去のログが大量に残り、ディスク容量を圧迫してしまう。

そのため一定のタイミングで過去のログを削除し、不要なログがどんどん蓄積されることを防ぐ仕組みがある。この仕組みをログローテーションという。


Linuxではlogrotateコマンドとcron(ジョブ管理)の仕組みを利用したログローテーションが可能となっている。

 

 

…ただ記事が長くなってきたので、ローテーションに関しては次回記事とします!