サイトアイコン 協栄情報ブログ

シェルスクリプトを利用して、ログをS3バケットへ自動アップロードしてみました

目的

ログファイルは、システムの状態をチェックし、監視する為には重要なデータです。
しかし、サーバ上での運用が長時間化するとログが肥大化し、下記影響が生じる可能性があります。

 
そこで今回は、これらの影響を最小限に抑えるために、シェルスクリプトを使用した自動ログローテート(S3バケットへのアップロード + サーバ上のログ削除) を行いました。
 

今回、構築する環境

■構成図

利用するメイン部分となるAWSサービス 利用目的
Amazon EC2 apacheをインストールし、アクセスログを取得/シェルスクリプト実行の為
AWS CLI AWSリソース(S3バケット)を管理・操作する為に、EC2にインストールする
Amazon S3 Apacheアクセスログのエクスポート先として使う為
Application Load Balancer 今回の利用目的としては、EC2とのヘルスチェックを行い、アクセスログを出力させる為
その他のAWSサービス 利用目的
CloudWatch Alarm ALBの死活監視に利用し、閾値を超えればメールで通知する
Amazon Simple Notification Service アラーム発生時のメール送信先トピックを作成する為

前提条件

事前に、各セキュリティグループ・IAMロール・VPCを準備しておくこと.

 

■S3バケット作成

まず初めに、Apacheアクセスログのエクスポート先となるS3バケットを作成します。
1.サービスからS3、サイドメニューからバケットを選択し、「バケットを作成」を押下。
2.以下の設定値を入力。

設定項目 入力値 備考
バケット名 任意 大文字が使えず、バケット名は世界で一意である必要がある
リージョン eu-west-1 遠隔に保管する必要がないのでVPCと同一のリージョンとしました
オブジェクト所有者 ACL無効 検証用で自身が利用する為
パブリックアクセス制限 すべてブロック パブリックアクセスを行わない為
バージョニング 無効 要件がないのでコストを考慮し無効
暗号化キータイプ SSE-S3 要件がないので、デフォルト値とします


 

■EC2作成

Apacheアクセスログ元となるEC2を作成していきます。
1.サービスからEC2、サイドメニューからインスタンスを選択し、「インスタンスを起動」を押下。
2.以下の設定値を入力。

設定項目 入力値
名前 任意
OS Red Hat
AMI Red Hat Enterprise Linux 9 (HVM), SSD Volume Type(無料枠)
インスタンスタイプ t2.micro(無料枠)
キーペア 使用しているものを選択
VPC 事前に作成したもの
サブネット 事前に作成したもの
パブリックIPの自動割り当て 有効化
SG 事前に作成したもの※1

3.高度な設定を開き、IAMインスタンスプロフィールに、事前に作成したIAMロール※2を付与する。

4.ユーザーデータに下記スクリプトを記入する。
ユーザーデータを設定することで、インスタンスを起動した段階で自動的に入力しておいたコマンドが実行されます。
※本来はインスタンス起動後に、コンソールからコマンド入力するので、その手間が省けます。

#!/bin/bash
sudo yum install python -y
sudo dnf install -y wget
sudo wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

sudo curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
sudo yum install zip unzip -y
unzip awscliv2.zip
sudo ./aws/install
source ~/.bash_profile

sudo yum install httpd -y
sudo systemctl enable httpd.service
sudo systemctl start httpd.service

echo "hello!" | sudo tee /var/www/html/index.html

sudo chmod 2755 /var/log/httpd/

起動時に Linux インスタンスでコマンドを実行するより引用

上記作成手順で2台目も作成する。
 

■Application Load Balancer作成

1.ALBは、事前に作成した2つのサブネットを含んだものを作成して下さい。
事前に作成したSG※3をALBにアタッチすること。

2.ターゲットグループは、先程作成したEC2インスタンスをターゲットに登録すること。

 

■Amazon Simple Notification Service と CloudWatch Alarmの作成

本記事では、シェルスクリプトの作成がメインとなる為、SNSとCWAlarmの作成を割愛させていただきます。
詳細は、下に記載の記事を参考にして作成して下さい。

ALBのターゲットで指定したEC2インスタンスが、一台でもヘルスステータスが[unhealthy]となると、メールで通知が来ます。
運用上あった方が、障害(異常)にすぐに気が付くことができるので便利ですね。
 

■シェルスクリプトの作成

そもそもシェルスクリプトとは

 
図のように、シェルはユーザーからのコマンドを受付け、動作した結果を出力するプログラムです。
LinuxやUnixでは、原則コマンド入力によるOS操作を行ないます。
その際に入力するコマンドは、シェルによって解釈・実行され、ユーザーに結果が表示されます。
シェルスクリプトは、シェルによる操作(解釈・実行)がまとめられた台本(スクリプト)となります。
 

■logrotate.shの作成(EC2からS3バケットへファイルをアップロードするシェルスクリプト)

1.作成したEC2インスタンスに、事前に作成したIAMロール※2をアタッチする。
2.SSHで、EC2へログインする。
3.cd /var/log/httpd/ で /var/log/httpd/ へ移動する。
4.sudo vi logrotate.sh でlogrotate.shという名のファイルを作成する。
5.i を押下し、INSERT(編集)モードに変更し、シェルスクリプト(台本)を記入する。
6.スクリプトの記入が完了したら、ESCを押下し :wq と記載しENTERで保存。

#!/bin/bash

#aws_cli-path
export PATH=/usr/local/aws-cli/v2/current/bin:$PATH

# S3バケット名
bucket_name="shiraiwa-s3-shellscript"

# ログエクスポートフォルダパス
export_folder="shellscript_logexport"

# アクセスログファイルパス
access_log="/var/log/httpd/access_log"

# 10分ごとに繰り返し実行
while true; do
     # 現在の日時を取得
     current_date=$(date +"%Y%m%d%H%M")

     # ファイル名に日時を付けてアップロード
     aws s3 cp $access_log s3://$bucket_name/$export_folder/access_log-$current_date.gz

     # アクセスログを空にする
     echo -n > $access_log

     # 10分待機
     sleep 600
done

下の図のような動きになります。

 
7.sudo chmod 755 logrotate.sh でシェルスクリプトを実行できるよう権限を変更し、ls -l で確認し下記画像と同じであることを確認する。


 

■アップロード元となる/var/log/httpd 配下の access_logファイルの内容を確認する

アップロード元となるaccess_logファイルの中身を事前に確認することで、S3へのアップロード後に整合性の確認ができます。
1.tailコマンドを使用して、access_logの中を見てみます。
sudo tail -f /var/log/httpd/access_log

2.ALBのヘルスチェックから、200のステータスコードのレスポンスと日時が確認できました。
出力された値をスクショ又はメモ帳にコピーし、残しておきましょう。
 

■シェルスクリプト実行

アップロード元となるaccess_logファイルの内容が確認できましたので、シェルスクリプトを実行していきます。
1.logrotate.sh の権限が確認できたところで、sudo ./logrotate.sh とコンソールに記入しENTERを押下。
アップロードが成功すると下の画像のようなコメントが表示されます。
※シェルスクリプトを実行する際は、作成したディレクトリにいること。
今回は /var/log/httpd/ です。

2.マネジメントコンソールから、実際にS3バケットのshellscript_logexportフォルダへ、access_log-日時.gz ファイルがアップロードされていることを確認できました。

3.実際にS3へアップロードされたファイルと、先程tailコマンドで出力した内容を比較していきます。
S3へアップロードしたファイルを選択し、ダウンロードを押下します。
ダウンロードできたら、解凍しメモ帳などで開きます。

整合性の確認が取れましたので、S3へのアップロードが成功となります。
このままシェルスクリプトの実行を止めなければ、10分毎にS3へ自動アップロードされることが確認できます。
確認後、Ctrl + c で実行キャンセルすることを忘れずに。
 

■logrotate.sh(改良版)

先程、作成したシェルスクリプトは10分毎に実行されるようプログラムしましたが、実際には1日に1回の頻度でS3バケットへアップロード出来れば十分です。
10分毎にアップロードをすると、S3バケットのフォルダ内に大量のバックアップが出来てしまいます、、、
なので、改良版ではシェルスクリプト内のループ処理を削除し、 cron コマンドで処理を定期実行させます。

1.cd /var/log/httpd/ でシェルスクリプトを作成したディレクトリへ移動します。
2.sudo vi logrotate.sh でファイルを開きます。
※同じ名前のファイルが存在する場合は、新規でファイルが作成されず、既存のファイルを開きます。
3.i を押下し、INSERT(編集)モードに変更し、シェルスクリプト内のwhile構文を削除します。

#!/bin/bash

#aws_cli-path
export PATH=/usr/local/aws-cli/v2/current/bin:$PATH

# S3バケット名
bucket_name="shiraiwa-s3-shellscript"

# ログエクスポートフォルダパス
export_folder="shellscript_logexport"

# アクセスログファイルパス
access_log="/var/log/httpd/access_log"

# 現在の日時を取得
current_date=$(date +"%Y%m%d%H%M")

# ファイル名に日時を付けてアップロード
aws s3 cp $access_log s3://$bucket_name/$export_folder/access_log-$current_date.gz

# アクセスログを空にする
echo -n > $access_log

4.crontab -e で cron を開く。
5.i を押下し、INSERT(編集)モードに変更。
6.cronの設定を行う(今回は月~金の0:00にスクリプトを実行する)
0 0 * * 1-5 /var/log/httpd/logrotate.sh
分 時 日 月 曜日 コマンド(シェルスクリプト名)
7.ESCを押下し :wq と記載しENTERで保存。
※vi コマンドと同様です。

8.保存されると、指定した日時でスクリプトが実行されます。
実際に実行されているか crontab -l で確認します。

月~金の0:00にアクセスログのファイルが、S3へ保存されているのが確認できたら成功です。
※今回アイルランドの環境での検証となるため、同環境で実行する場合は時差も考慮してください。
 

まとめ

今回はEC2インスタンス上にシェルスクリプトを作成し、スクリプト内にAWS CLIのPATHを記入する方法で、自動化しました。
.bash_profileにAWS CLIのPATHを記入する方法もありますので、ご参考までに。

ちなみに、シェルスクリプトを学習する上で、LPICやLinuCといった資格学習はお勧めです!
 

モバイルバージョンを終了