AmazonLinux2のシスログをCloudWatch Logs に転送させてみた

2018.02.02

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

AWSチームのすずきです。

次世代の Amazon Linux として、LTS Candidate ビルドが公開されているAmazon Linux2。 そのシスログファイルの管理のため、CloudWatch Logs エージェント(awslogs)の設定を行う機会がありましたので、紹介させていただきます。

Amazon CloudWatch ログ ユーザガイド

実行環境

  • AWS東京リージョンのEC2
  • AMI: amzn2-ami-hvm-2017.12.0.20180115-x86_64-gp2 (ami-c2680fa4)
  • IAM: 管理ポリシー 「CloudWatchLogsFullAccess」(arn:aws:iam::aws:policy/CloudWatchLogsFullAccess)をアタッチ

導入手順

インストール

  • Amazon Linux2 標準リポジトリのパッケージを利用しました。
yum install awslogs -y

設定

/etc/awslogs/awscli.conf

  • ログ転送先のリージョン、デフォルトのバージニアから東京リージョン「ap-northeast-1」に変更しました。
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1

/etc/awslogs/awslogs.conf

  • 「/var/log/」以下に出力されるシスログファイルを転送対象としました。
  • ロググループ名は「amazonlinux2-syslog」+ 「シスログファイル名」としました。
[general]
state_file = /var/lib/awslogs/agent-state

[/var/log/messages]
datetime_format = %b %d %H:%M:%S
file = /var/log/messages
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = amazonlinux2-syslog-/var/log/messages
[/var/log/cloud-init.log]
datetime_format = %b %d %H:%M:%S
file = /var/log/cloud-init.log
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = amazonlinux2-syslog-/var/log/cloud-init.log
[/var/log/cron]
datetime_format = %b %d %H:%M:%S
file = /var/log/cron
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = amazonlinux2-syslog-/var/log/cron
[/var/log/secure]
datetime_format = %b %d %H:%M:%S
file = /var/log/secure
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = amazonlinux2-syslog-/var/log/secure
[/var/log/yum.log]
datetime_format = %b %d %H:%M:%S
file = /var/log/yum.log
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = amazonlinux2-syslog-/var/log/yum.log

サービス設定

「systemctl」コマンドを利用してサービス設定を行いました。

起動
systemctl start awslogsd.service
起動確認
$ systemctl status awslogsd.service
● awslogsd.service - awslogs daemon
   Loaded: loaded (/usr/lib/systemd/system/awslogsd.service; enabled; vendor preset: disabled)
   Active: active (running) since 木 2018-02-01 ##:##:## UTC; ##min ago
 Main PID: 3404 (aws)
   CGroup: /system.slice/awslogsd.service
           └─3404 /usr/bin/python2 -s /usr/bin/aws logs push --config-file /etc/awslogs/awslogs.conf --additional-configs-dir /etc/awslogs/config

 2月 01 ##:##:## ip-172-31-27-###.ap-northeast-1.compute.internal systemd[1]: Started awslogs daemon.
 2月 01 ##:##:## ip-172-31-27-###.ap-northeast-1.compute.internal systemd[1]: Starting awslogs daemon...
自動起動設定
systemctl enable awslogsd.service
自動起動確認
$ systemctl is-enabled awslogsd.service
enabled

動作確認

ロググループ

  • Cloudwatchダッシュボードの「ログ」に、AmazonLinux2より転送したロググループが確認できました。

ログストリーム

  • 任意のロググループより、ログストリームとして「インスタンスID」の存在が確認できました。

イベントの検索

  • ログストリームの一覧画面で「イベントの検索」を実施することで、ログのフィルタ表示が可能です。

  • 「Secure」ログを「ssh2」でフィルターする事で、リモート接続記録の確認ができました。

まとめ

「systemd」を採用したAmazon Linux2では、サービス設定方法が変更となりましたが、 同等の手順で「awslogs」によるOSのシスログの退避を実現できました。

アプリなどから大量のログがシスログに流れ込む場合、ログ流入量に応じて発生するCloudwatchLogsの従量課金や、検索などの操作性などにも注意が必要となりますが、Amazon Linux2でも手軽に利用できるログ管理方法の一つとしてご活用ください。

Userdataサンプル

EC2インスタンスの初回起動時、Userdata(Cloud-init)を利用してawslogsの設定を行う事も可能です。

#!/bin/bash

# setting
LOGPREFIX="amazonlinux2-syslog"
RETENTIONDAYS="14"
LOGGROUP=(/var/log/messages /var/log/cloud-init.log /var/log/cron /var/log/secure /var/log/yum.log)

# install
yum install awslogs -y

# AWS_DEFAULT_REGION
REGION=`curl -s http://169.254.169.254/latest/meta-data/local-hostname | cut -d '.' -f2`
export AWS_DEFAULT_REGION=${REGION}

# backup
mkdir -p /root/backup/
cp --backup=numbered -f /etc/awslogs/awscli.conf  /root/backup/
cp --backup=numbered -f /etc/awslogs/awslogs.conf /root/backup/

# awscli.conf
cat /etc/awslogs/awscli.conf | sed "s/^region = us-east-1$/region = ${REGION}/g" | tee /etc/awslogs/awscli.conf.new
diff /etc/awslogs/awscli.conf.new /etc/awslogs/awscli.conf
if [ $? -eq 1 ]; then
  cp /etc/awslogs/awscli.conf /root/backup/
  cat /etc/awslogs/awscli.conf.new > /etc/awslogs/awscli.conf
fi

# awslogs.conf
cat << 'EoF' | tee /etc/awslogs/awslogs.conf
[general]
state_file = /var/lib/awslogs/agent-state
EoF

for LOGFILE in ${LOGGROUP[@]}; do
  LOGGROUPNAME="${LOGPREFIX}-${LOGFILE}"
  aws logs describe-log-groups --log-group-name-prefix ${LOGGROUPNAME} | grep logGroupName | grep "\"${LOGGROUPNAME}\"" > /dev/null
  if [ $? -eq 1 ]; then
    aws logs create-log-group --log-group-name ${LOGGROUPNAME}
    aws logs put-retention-policy --log-group-name ${LOGGROUPNAME} --retention-in-days ${RETENTIONDAYS}     
  fi
  echo -e "[${LOGFILE}] \ndatetime_format = %b %d %H:%M:%S \nfile = ${LOGFILE} \nbuffer_duration = 5000 \nlog_stream_name = {instance_id} \ninitial_position = start_of_file \nlog_group_name = ${LOGGROUPNAME}" | tee -a /etc/awslogs/awslogs.conf
done

# systemctl
systemctl start awslogsd.service
systemctl status awslogsd.service
systemctl enable awslogsd.service 
systemctl is-enabled awslogsd.service