【AWS初心者向け】EC2 インスタンスでのログ管理と logrotate の設定について

どうも、クラ本部の黒田です。
#### **今回は、Amazon EC2 インスタンス上でのログ管理する際の `logrotate` ツールを使用したログのローテーション設定手順をご紹介します。**


# ■　はじめに
## `logrotate` とは
Linux システム上でログファイルを管理するためのユーティリティです。ログファイルはアプリケーションやシステムが生成する重要な情報を含んでおり、時間が経つにつれてサイズが増加することがあります。`logrotate` は、ログファイルのサイズを制御し、過去のログを保持しつつディスクスペースを効率的に管理するために使用されます。

以下は `logrotate` の主な機能と役割です：

1. **ログファイルの圧縮と削除:** `logrotate` はログファイルを定期的にローテーションして、新しいログファイルを作成します。古いログファイルはアーカイブされ、必要に応じて圧縮された状態で保持されます。これにより、ディスクスペースの効率的な利用が可能になります。

2. **ログファイルの管理:** `logrotate` はログファイルを一定の期間やサイズに基づいて管理します。古いログファイルは一定の条件に基づいて削除されたりアーカイブされたりします。これにより、ディスクスペースが無駄に消費されるのを防ぎ、システムの正常な動作を維持します。

3. **カスタマイズ可能な設定:** `logrotate` の設定は、ログファイルごとに個別のルールを指定できるため、異なるログファイルに対して異なる設定を適用することが可能です。設定には、ログのローテーション間隔、最大保存期間、圧縮の有無などが含まれます。

4. **cron との連携:** 通常、`logrotate` は cron デーモンを使用して定期的に実行されます。cron ジョブによって、指定した間隔でログのローテーションが行われます。

`logrotate` はシステムのログ管理を容易にし、ディスクスペースの問題やログデータの有効性を維持するための重要なツールです。ログファイルの増加やディスクスペースの枯渇などの問題を防ぐために、定期的なログローテーションを実行することは重要です。

ログローテーションの世代管理は、システムやアプリケーションが生成するログファイルを効果的に管理するためのプラクティスです。ログローテーションの世代管理がなぜ必要なのかについて以下にまとめてみましょう。

**背景:**
- システムやアプリケーションはログファイルに重要な情報を記録します。これにはエラーメッセージ、警告、アクティビティのログなどが含まれます。
- ログファイルは時間が経過するにつれて増加し、ディスクスペースを消費する可能性があります。
- 古いログファイルを維持することは、トラブルシューティングやセキュリティ監査のために重要ですが、無制御に増え続けるとディスクスペースの問題を引き起こすことがあります。

**世代管理のメリット:**
1. **ディスクスペースの効率的な利用:** ログファイルは時間経過とともに大きくなるため、古いログを削除せずに保持するとディスクスペースの枯渇が発生する可能性があります。世代管理を行うことで、一定期間ごとにログファイルを削除またはアーカイブしてディスクスペースを効率的に利用できます。

2. **情報の整理と管理:** ログローテーションの世代管理を行うことで、適切な期間ごとにログファイルを整理・管理することが可能です。古いログは必要に応じてアクセスできる状態で保持し、不要なログは削除することでログデータの有用性を維持します。

3. **データリテンションの維持:** 一部の法的要件や業界規制では、一定の期間間ログデータを保持する必要があります。ログローテーションの世代管理は、データリテンションの要件を満たすために適切なデータを保持する手段となります。

4. **トラブルシューティング:** 適切なログの保持と管理はトラブルシューティングに不可欠です。古いログファイルが利用可能な場合、システムの障害や問題の原因を追跡するのが容易になります。

5. **セキュリティと監査:** セキュリティ攻撃や不正アクティビティの調査の際には、過去のログ情報が重要です。世代管理を行うことで、過去のアクティビティを復元し、セキュリティ監査を支援することができます。

総合的に言えば、ログローテーションの世代管理は、システムの健全性、セキュリティ、およびデータ管理の観点から非常に重要なプラクティスです。


それでは、やってみましょう。


# ■　 前提条件

- Amazon EC2 インスタンスが起動され、SSMやSSHに接続できる状態であること。

# ■　 設定手順

## 1. **ログの出力先とスクリプトの格納場所の準備**
   まず、ログファイルの出力先とログローテーション用のスクリプトの格納場所を準備します。
   ```bash
   sudo su --login root
   mkdir -p /infra/log
   mkdir -p /infra/script
   ```
![](https://cloud5.jp/wp-content/uploads/2023/08/1-1.jpg)
## 2. **ログローテーション用スクリプトの作成**
   `logrotate` の実行時にログ出力を行うためのスクリプトを作成し、実行権限を付与します。

   ```bash
   vi /infra/script/logrotate.sh
   ```

   スクリプトの内容は以下の通りです。

   ```bash
   #!/bin/bash
   # Create: 2023/08/14
   # Description: logrotate.sh
   #############################################
   # Local
   HOSTNAME=`hostname -s | awk -F"." '{print $1}'`
   LOG=/infra/log/logrotate.log
   #############################################
   # Main
   # ログ出力
   echo `LANG=C ; date` : "[INFO]:${HOSTNAME}:logrotate." | sudo tee -a ${LOG}
   exit 0
   ```

   実行権限を付与します。

   ```bash
   chmod +x /infra/script/logrotate.sh
   ```
![](https://cloud5.jp/wp-content/uploads/2023/08/2-1.jpg)
## 3. **Crontab にログローテーション用ジョブの設定**
   ジョブを定期的に実行するために、`crontab` を設定します。

   ```bash
   crontab -e
   ```

   以下の設定を追加して保存します。

   ```plaintext
   PATH=/sbin:/bin:/usr/sbin:/usr/bin
   MAILTO=""
   HOME=/

   # 毎10分に logrotate.sh を実行
   */10 * * * * /infra/script/logrotate.sh
   ```

## 4. **ログファイルの準備と検証**
   検証用のログファイルを7つ用意し、ログ出力が正しく行われることを確認します。
![](https://cloud5.jp/wp-content/uploads/2023/08/3-1.jpg)

## 5. **logrotate の設定ファイルの作成**
   `logrotate` の設定ファイルを作成し、ログのローテーション設定を行います。

   ```bash
   vi /etc/logrotate.d/logdelete
   ```

   設定ファイルの内容は以下の通りです。

   ```plaintext
   /infra/log/logrotate.log {
       rotate 7
       daily
       ifempty
       missingok
       create 0644 root root
       dateext
       dateformat -%Y%m%d
   }
   ```

## 6. **logrotate のデバッグ検証**
   `logrotate` の動作をデバッグモードで確認します。

   ```bash
   logrotate -d /etc/logrotate.d/logdelete
   ```
このコマンドを実行することで、/etc/logrotate.d/logdelete に記述されたログローテーションの設定をデバッグしながら確認できます。デバッグモードでは、実際のローテーションは行われませんが、どのように動作するかの情報を表示します。
![](https://cloud5.jp/wp-content/uploads/2023/08/4.jpg)
   ```bash
回転パターン: /infra/log/logrotate.log 1日後に回転 (7 回転)
空のログファイルは回転され、古いログは削除されます
ログ /infra/log/logrotate.log を検討しています
  現在: 2023-08-14 11:43
  最後の回転: 2023-08-11 02:22
  ログは回転が必要です
ログ /infra/log/logrotate.log を回転中、log-&gt;rotateCount は 7
' -%Y%m%d' を '-%Y%m%d' に変換しました
dateext サフィックス '-20230814'
glob パターン '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
デフォルトの作成コンテキストを system_u:object_r:root_t:s0 に設定
デフォルトの作成コンテキストを system_u:object_r:root_t:s0 に設定
/infra/log/logrotate.log を /infra/log/logrotate.log-20230814 に名前変更
新しい /infra/log/logrotate.log を作成 モード = 0644 uid = 0 gid = 0
古いログ /infra/log/logrotate.log-20230807 を削除
   ```

## 7. **自動実行の設定**
   `cron` の設定ファイルにおいて、`logrotate` を自動実行する設定を確認します。

   ```bash
   vi /etc/crontab
   `10 * * * * root run-parts /etc/cron.daily`
   ```
この設定により、毎時 10 分になると /etc/cron.daily 内のスクリプトが実行されるため、定期的なタスクを自動的に実行できます。
   ```bash
   SHELL=/bin/bash
   PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin/
   MAILTO=root
   # For details see man 4 crontabs
   # Example of job definition:
   # .---------------- minute (0 - 59)
   # |  .------------- hour (0 - 23)
   # |  |  .---------- day of month (1 - 31)
   # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
   # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) ORsun,mon,tue,wed,thu,fri,sat
   # |  |  |  |  |
   # *  *  *  *  * user-name  command to be executed
   10 * * * * root run-parts /etc/cron.daily
```
## 8. **/etc/cron.daily/logrotateが存在しているかの確認**
```bash
   cat /etc/cron.daily/logrotate
   【logrotateの詳細内容】ファイルがない場合、作成すること
   chmod 755 logrotate
   ```


   【logrotateの詳細内容】
   ```bash
   #!/bin/sh
   /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
   EXITVALUE=$?
   if [ $EXITVALUE != 0 ]; then
   /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
   fi
   exit 0
   ```

**【logrotateの詳細内容の解析】**
```bash
   #!/bin/sh:シェルスクリプトのシバン（shebang）行。この行により、シェルスクリプトが /bin/sh シェルで実行されることが指定されます。
   /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status
   /etc/logrotate.conf:
   /usr/sbin/logrotate プログラムを -s オプションを使用して実行し、状態ファイルを
   /var/lib/logrotate/logrotate.status に指定して /etc/logrotate.conf の設定を使
   てログローテーションを実行します。logrotate コマンドはログファイルのローテーショを
   います。
   EXITVALUE=$?:
   直前のコマンドの終了ステータスを EXITVALUE 変数に代入しています。
   if [ $EXITVALUE != 0 ]; then:
   EXITVALUE の値が 0 でない場合（つまり、コマンドがエラーで終了した場合）に以下のコマ
   ドを実行します。
   /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]":
   logger コマンドを使用して、エラーメッセージをログに記録します。エラーメッセージには
   ALERT exited abnormally with [$EXITVALUE] というテキストとエラーコードが含まれ
   す。これにより、エラーの発生がログに記録されます。
   exit 0:
   スクリプトの正常終了を示すため、終了ステータス 0 を返します。これにより、cron ジョ
   が正常に完了したことが示されます。
```
#  ■　動作確認
## crontabの設定修正
**crontabを現在の時間に沿って変更します。**
   ```bash
   vi /etc/crontab
   29 * * * * root run-parts /etc/cron.daily
   ```
## **実行結果の確認** 
   ```bash
# tail /var/log/cron
Aug 14 13:29:01 kuroda run-parts[1686]: (/etc/cron.daily) starting logrotate
Aug 14 13:29:01 kuroda run-parts[1686]: (/etc/cron.daily) finished logrotate
Aug 14 13:29:01 kuroda run-parts[1686]: (/etc/cron.daily) starting update-client-config-packages
Aug 14 13:29:02 kuroda run-parts[1686]: (/etc/cron.daily) finished update-client-config-packages
Aug 14 13:29:02 kuroda CROND[1685]: (root) CMDEND (run-parts /etc/cron.daily)
Aug 14 13:30:01 kuroda CROND[1705]: (root) CMD (/infra/script/logrotate.sh)
Aug 14 13:30:01 kuroda CROND[1704]: (root) CMDOUT (LANG=C)
Aug 14 13:30:01 kuroda CROND[1704]: (root) CMDOUT (date: extra operand ‘[INFO]:kuroda:logrotate.’)
Aug 14 13:30:01 kuroda CROND[1704]: (root) CMDOUT (Try 'date --help' for more information.)
Aug 14 13:30:01 kuroda CROND[1704]: (root) CMDEND (/infra/script/logrotate.sh)
      ```

> 対象logファイルが7世代交代管理されていることの確認対象logファイルが7世代交代管理されていることの確認

```bash
# ll -al /infra/log/
drwxr-xr-x. 2 root root 4096 Aug 14 13:29 .
drwxr-xr-x. 4 root root   31 Aug 10 23:49 ..
-rw-r--r--  1 root root  819 Aug 14 13:29 logrotate.log
-rw-r--r--. 1 root root  819 Aug 11 10:30 logrotate.log-20230808
-rw-r--r--. 1 root root  819 Aug 11 10:30 logrotate.log-20230809
-rw-r--r--. 1 root root  819 Aug 11 10:30 logrotate.log-20230810
-rw-r--r--. 1 root root  819 Aug 11 10:30 logrotate.log-20230811
-rw-r--r--. 1 root root  819 Aug 12 10:20 logrotate.log-20230812
-rw-r--r--. 1 root root  819 Aug 11 10:30 logrotate.log-20230813
-rw-r--r--  1 root root  819 Aug 14 13:07 logrotate.log-20230814
```
> **logrotate -d /etc/logrotate.d/logdeleteの通りに
/infra/log/logrotate.log を /infra/log/logrotate.log-20230814 に名前変更
古いログ /infra/log/logrotate.log-20230807 を削除済み**

**↓↓↓　Permissionエラーが出た場合、下記の記事より、エラー解消　↓↓↓**
```bash
(error: stat of /infra/log/logrotate.log failed: Permission denied)
```
- [EC2(RHEL)でSELinuxを無効化する](https://cloud5.jp/invalid-selinux-on-ec2/)

------------

#  ■　最後に

以上の手順に従うことで、Amazon EC2 インスタンス上でログファイルを効果的に管理し、`logrotate` を使用してログのローテーションを設定することができます。ログ管理はシステムの運用とセキュリティにおいて欠かせない重要なタスクですので、適切に実施するようにしましょう。

では、また！