皆様こんにちは!
ネットワールドでAWSやMicrosoftのクラウド製品を担当しているSEの碇です。
今回は、AWSのAmazon Data Firehoseというサービスを利用して、
Cloudwatch logsに格納したログデータをS3に圧縮させて格納させる方法をご紹介します。
Cloudwatch logsのログデータをS3に自動的に移動させる方法として、Eventbridge+Lambdaを利用する方法もありますが、AWSサポートに確認したところリアルタイムで移動させることができるという点でData Firehoseが推奨だそうですので、今回はData Firehoseについてご紹介していきたいと思います。
- Amazon Data Firehoseとは
- 作業の流れ
- 作業手順
Amazon Data Firehoseとは
早速ですが、まずはAmazon Data Firehoseというサービスについてご紹介します。
Amazon Data Firehose は、宛先(S3など)にストリーミングデータをリアルタイムで配信するフルマネージドサービスです。
Amazon Data Firehose とは何ですか? - Amazon Data Firehose

少しややこしいのですが、今回は以下のような理由と方法でData Firehoseを利用します。
①EC2にCloudwatch Agentを導入して、Cloudwatch logsを利用してOS内のログを取得している
↓
②Cloudwatch logsに格納するデータは、OS内でログが取得されてから30日間で削除するというサイクルにしたいが、ログ自体は365日残しておきたい
↓
③Cloudwatch logsで30日後に削除される前に、ログを圧縮してS3に格納させる
S3は圧縮して格納でき安く済むという点と、Cloudwatch logsに格納するよりS3に格納している方が安く済むという、コスト面から、
「Cloudwatch logsからS3に移動させる」という構成にします。
今回は、③の「Cloudwatch logsのデータを圧縮させてS3に格納させる」という箇所をData Firehoseで実装させたいと思います。
※今回は①の「Cloudwatch Agentでlogsにログを取得させる」の箇所は説明を割愛させていただきます
【参考URL】
CloudWatch エージェントを使用してメトリクス、ログ、トレースを収集する - Amazon CloudWatch
作業の流れ
⓪Cloudwatch logsに対象のログが格納されていること
①CloudWatch Logs 専用のS3バケットを作成
②Amazon Data Firehose 配信ストリームを作成する(左記のストリームがS3にデータを置くためのIAMロールも併せて作成します)
③CloudWatch Logs サブスクリプションという機能を利用して、ログイベントをAmazon Data Firehoseに送信するフィルターを作成する
以下のAWSドキュメントを参考にしています。
ロググループレベルのサブスクリプションフィルター - Amazon CloudWatch Logs
作業の流れとしては簡単に見えますが、CLI(Cloudshell)でのIAMロール作成などもあり、複雑な箇所もありますので、このブログを見ながら順に進めていきましょう。
作業手順
⓪Cloudwatch logsに対象のログが格納されていること
今回は、先ほども少し触れた通りCloudwatch Agentを利用して、EC2のログを格納させています。
30日が過ぎたら、CloudWatch Logsからはデータが削除されるように設定します。
①CloudWatch Logs 専用のS3バケットを作成
今回は特に特別な設定は加えずにデフォルトで作成したので、S3の作成方法については割愛します。
【参考URL】
Amazon S3 の開始方法 - Amazon Simple Storage Service
②Data Firehoseに対して、 S3にデータを置くためのアクセス許可を付与する
Data Firehoseに対して付与するIAMロールとIAMポリシーを作成します。
今回はCloudshellを利用して1~4の順番で作成します。
1.TrustPolicyForFirehose.jsonファイルを作成
IAMロールのもととなるjsonファイルを以下の手順で作成します。
・PCのローカル上に「TrustPolicyForFirehose.json」名でファイルを保存します。
・上記のファイルの中身を以下のように編集して保存します。
{
"Statement": {
"Effect": "Allow",
"Principal": { "Service": "firehose.amazonaws.com" },
"Action": "sts:AssumeRole"
}
}
・AWSコンソールから「Cloudshell」を検索または右上の「Cloudshell」をクリックして、Cloudshellを起動させます。

・Cloudshellが起動できたら、右上のアクションから、「ファイルをアップロード」をクリックします。

・PCのエクスプローラーが自動で表示されるので、先ほど作成した「TrustPolicyForFirehose.json」ファイルを選択し、アップロードします。
・アップロードが完了したら、正常にアップロードが完了した旨通知されるまで待ちます。

2.create-role コマンドでIAMロールを作成
・先ほど起動したCloudshellで以下のコマンドを実行します。
aws iam create-role \
--role-name FirehosetoS3Role \
--assume-role-policy-document file://~/TrustPolicyForFirehose.json
⇒先ほど作成したファイル「TrustPolicyForFirehose.json」の内容で、IAMロールを作成します。
上記の例では、作成するIAMロール名が「FirehosetoS3Role」となっていますが、任意の名前に変更可能です。
・AWSコンソールを確認し、作成したIAMロールが表示されていることを確認します。
・create-roleコマンドの実行結果または、AWSコンソールから、作成したIAMロールのARN値をコピーしておきます。
3.PermissionsForFirehose.jsonファイルを作成
IAMポリシーのもととなるjsonファイルを以下の手順で作成します。
・PCのローカル上に「PermissionsForFirehose.json」名でファイルを保存します。
・上記のファイルの中身を以下のように編集して保存します。
{
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
"s3:PutObject" ],
"Resource": [
"arn:aws:s3:::datahose-cloudwatch-archivetest",
"arn:aws:s3:::datahose-cloudwatch-archivetest/*" ]
}
]
}
⇒「datahose-cloudwatch-archivetest」は作業手順①で作成したS3のバケット名です。S3のバケット名を入力してください。
以降は「1.TrustPolicyForFirehose.jsonファイルを作成」と同じ作業を実施します。
・Cloudshellに移動し、右上のアクションから、「ファイルをアップロード」をクリックします。
・PCのエクスプローラーが自動で表示されるので、先ほど作成した「PermissionsForFirehose.json」ファイルを選択し、アップロードします。
・アップロードが完了したら、正常にアップロードが完了した旨通知されるまで待ちます。
4.put-role-policy コマンドを使用して、アクセス許可ポリシーをロールに関連付ける
手順3で作成した「PermissionsForFirehose.json」名のアクセス許可ポリシーを、手順2で作成した「FirehosetoS3Role」名のIAMロールに関連付けます。
・Cloudshellに移動して以下のコマンドを実行します。
aws iam put-role-policy --role-name FirehosetoS3Role --policy-name Permissions-Policy-For-Firehose --policy-document file://~/PermissionsForFirehose.json
ここまでで、Data Firehoseに紐づけるIAMロールが完成しました。
③送信先 Firehose 配信ストリームを作成する
続いて、Cloudwatch logsの送信先であるFirehose 配信ストリームを作成します。
・Cloudshellに移動して、以下のコマンドを実行します。
aws firehose create-delivery-stream \
--delivery-stream-name 'my-delivery-stream' \
--s3-destination-configuration \
'{"RoleARN": "arn:aws:iam::123456789101:role/FirehosetoS3Role", "BucketARN": "arn:aws:s3:::datahose-cloudwatch-archivetest"}'
⇒上記の例では、作成する配信ストリーム名が「my-delivery-stream」となっていますが、任意の名前に変更可能です。
⇒「123456789101」はAWSのアカウントID、「FirehosetoS3Role」は手順②で作成したIAMロール、「arn:aws:s3:::datahose-cloudwatch-archivetest」は手順①で作成したS3を指定してください。
・コマンドが問題なく成功したら、AWSコンソールからAmazon Data Firehoseを検索してFirehose配信ストリームが作成できていることを確認します。

・create-delivery-streamコマンドの実行結果または、AWSコンソールから、作成したFirehose配信ストリームのARN値をコピーしておきます。
④CloudWatch Logsに対して、 Firehose 配信ストリームにデータを置くためのアクセス許可を付与する
手順②と同じ要領で、Cloudshellを利用してIAMロールを作成していきます。
1.TrustPolicyForCWL.jsonファイルを作成
IAMロールのもととなるjsonファイルを以下の手順で作成します。
・PCのローカル上に「TrustPolicyForCWL.json」名でファイルを保存します。
・上記のファイルの中身を以下のように編集して保存します。
{
"Statement": {
"Effect": "Allow",
"Principal": { "Service": "logs.amazonaws.com" },
"Action": "sts:AssumeRole",
"Condition": {
"StringLike": {
"aws:SourceArn": "arn:aws:logs:ap-northeast-1:123456789101:*"
}
}
}
}
⇒「123456789101」はAWSのアカウントIDを指定してください。
・Cloudshellに移動し、右上のアクションから、「ファイルをアップロード」をクリックします。
・PCのエクスプローラーが自動で表示されるので、先ほど作成した「TrustPolicyForCWL.json」ファイルを選択し、アップロードします。
・アップロードが完了したら、正常にアップロードが完了した旨通知されるまで待ちます。
2.create-role コマンドでIAMロールを作成
・先ほど起動したCloudshellで以下のコマンドを実行します。
aws iam create-role \
--role-name CWLtoKinesisFirehoseRole \
--assume-role-policy-document file://~/TrustPolicyForCWL.json
⇒先ほど作成したファイル「TrustPolicyForCWL.json」の内容で、IAMロールを作成します。
上記の例では、作成するIAMロール名が「CWLtoKinesisFirehoseRole」となっていますが、任意の名前に変更可能です。
・AWSコンソールを確認し、作成したIAMロールが表示されていることを確認します。
・create-roleコマンドの実行結果または、AWSコンソールから、作成したIAMロールのARN値をコピーしておきます。
3.PermissionsForCWL.jsonファイルを作成
IAMポリシーのもととなるjsonファイルを以下の手順で作成します。
・PCのローカル上に「PermissionsForCWL.json」名でファイルを保存します。
・上記のファイルの中身を以下のように編集して保存します。
{
"Statement":[
{
"Effect":"Allow",
"Action":["firehose:PutRecord"],
"Resource":[
"arn:aws:firehose:ap-northeast-1:123456789101:deliverystream/my-delivery-stream"]
}
]
}
⇒「arn:aws:firehose:ap-northeast-1:123456789101:deliverystream/my-delivery-stream」には作業手順③で作成したData Firehoseの配信ストリームのARN値を入力してください。
・Cloudshellに移動し、右上のアクションから、「ファイルをアップロード」をクリックします。
・PCのエクスプローラーが自動で表示されるので、先ほど作成した「PermissionsForCWL.json」ファイルを選択し、アップロードします。
・アップロードが完了したら、正常にアップロードが完了した旨通知されるまで待ちます。
4.put-role-policy コマンドを使用して、アクセス許可ポリシーをロールに関連付ける
手順3で作成した「PermissionsForCWL.json」名のアクセス許可ポリシーを、手順2で作成した「CWLtoKinesisFirehoseRole」名のIAMロールに関連付けます。
・Cloudshellに移動して以下のコマンドを実行します。
aws iam put-role-policy --role-name CWLtoKinesisFirehoseRole --policy-name Permissions-Policy-For-CWL --policy-document file://~/PermissionsForCWL.json
ここまでで、CloudWatch Logsに紐づけるIAMロールが完成しました。
⑤CloudWatch Logs サブスクリプションフィルターを作成する
作業前に以下2点を確認してください。
☆Amazon Data Firehose 配信ストリームがアクティブ状態になっていること
☆IAM ロールが作成されていること
・Cloudshellに移動し、以下のコマンドを実行してサブスクリプションフィルターを作成します。
aws logs put-subscription-filter \
--log-group-name "messages" \
--filter-name "subscription-filter" \
--filter-pattern "" \
--destination-arn "arn:aws:firehose:ap-northeast-1:123456789101:deliverystream/my-delivery-stream" \
--role-arn "arn:aws:iam::123456789101:role/CWLtoKinesisFirehoseRole"
⇒「messages」は今回Cloudwatch logsに取得しているOSのログのログストリーム名となります。対象のログストリーム名を入力してください。
⇒「subscription-filter」は上記のコマンドで作成できるサブスクリプションフィルター名となります。任意の値を入力してください。
⇒「arn:aws:firehose:ap-northeast-1:123456789101:deliverystream/my-delivery-stream」に作業手順③で作成したData Firehoseの配信ストリームのARN値を入力してください。
⇒「arn:aws:iam::123456789101:role/CWLtoKinesisFirehoseRole」には手順④で作成したIAMロールのARN値を入力してください。
・コマンドが正常に終了したら、AWSコンソールからCloudwatch logsのサブスクリプションフィルターが作成されていることが確認できます。
AWSコンソールから、Cloudwatch>ログ>ログ管理>対象のロググループをクリックし、「サブスクリプションフィルター」をクリックしてください。

サブスクリプションフィルターが作成されたら、作成したフィルターの条件通りにS3バケットにデータが格納されていることを確認します。
AWSコンソールからS3をクリックし、今回作業手順①で作成したバケット「datahose-cloudwatch-archivetest」のオブジェクトを確認します。

S3バケット>オブジェクトから、日付の順に移動していくと、「作成したData Firehose名+日付+ランダムな英数字」名でオブジェクトが作成されていることが確認できました。

⑥S3へ格納されたオブジェクトのダウンロードとログの確認
オブジェクトをクリックまたは選択し、ダウンロードをクリックするとデータをダウンロードできます。

ダウンロードができたら、このデータを解凍することで、メモ帳等でログの内容を確認することができます。
Data Firehoseの機能でもデータを解凍することが可能なのですが、解凍する度に料金がかかってしまうため、今回は7zipを使ってローカルPC上で解凍しました。
Data Firehoseはストリーミングデータをリアルタイムで配信するフルマネージドサービスですが、実際に内容を確認してみたところ、Cloudwatch logsに出力されていたログをS3でダウンロードしたデータ上でも確認することができました。
なお、S3には1日一つではなくいくつかのデータが作成されます。
新しいデータができる条件は、バッファサイズ、バッファ間隔値で決まります。先にどちらかの条件を満たした場合にS3 へのデータ配信がトリガーされます。
バッファサイズ、バッファ間隔値は、作成したData Firehose配信ストリームの設定から確認できます。
S3からオブジェクトをダウンロードすると、例えば以下のようなログがありました。
{"id":"12379458905~~~~~~","timestamp":1776235960556,"message":"Apr 15 06:52:40 systemd[1]: Started session-1.scope - Session 1 of User ec2-user."}
確かにApr 15 06:52:40(日本時刻なので、UTC+9で15:52ごろ)、teratemを利用して「ec2-user」ユーザーでEC2に接続したので、正しいログが取得できていることが確認できました。
なおidは、Data Firehose が付与したIDでAWSのIAMユーザーやOSのユーザーなどのIDではありません。
また、timestampはUNIX時間で、単位がミリ秒になっているので注意してください。
以上で、Amazon Data Firehoseとは何か?から、Cloudwatch logsのログをS3に格納させるところまで実装・ログの確認方法までご紹介しました。
少しややこしい部分はありますが、順を追って作業してみると理解が深まると思います。
この記事が参考になれば幸いです。
*******************************************************************
本ブログに掲載されている内容は、執筆時点の情報および筆者の知見に基づいています。
内容の正確性や最新性については可能な限り配慮しておりますが、
その完全性や有用性を保証するものではありません。
本ブログに記載されている見解や意見は、筆者個人のものであり、
当社の公式な見解、方針、または保証を示すものではありません。
本ブログの情報を利用したことにより生じたいかなる損害についても、
当社および筆者は一切の責任を負いかねます。
製品の導入や設定、運用にあたっては、各ベンダーの公式ドキュメントや
契約内容をご確認のうえ、自己責任にてご判断ください。
*******************************************************************