Amazon S3とCloudWatch Logsのログ保存料金とサイズを見てみた

2021.09.18

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

いわさです。

EC2のログファイルを外部に転送したいケース多いと思います。
色々な方法が考えられると思いますが、CloudWatchエージェントを使ってCloudWatch Logsへ転送する方法があります。 さらに、サブスクリプションフィルターを使ってKinesis Firehoseを経由してS3へ転送させることも出来ます。

CloudWatch Logsで保管し続けることも出来ますが、S3へ保管してCloudWatch Logsは短期間で削除するとコスト的に良さそうなイメージがあります。

実際は、上記記事でも紹介のあるように、CloudWatch Logsは高いイメージがあるかもしれませんが、高いのはCloudWatch Logsへの転送部分であって、保存料金はS3と大きく変わりません。

AWS Pricing Calculatorで計算してみた

そして、どれくらい変わるのかをAWS Pricing Calculatorで先日計算してみました。

100GBくらいのログを取り込んだら場合で考えてみます。

Amazon S3

S3はこんな計算になるでしょうか

100GBだと2.5USD

CloudWatch Logs

CloudWatch Logsだとこんな感じでしょうか。

100GBだと0.495USD
CloudWatch Logsのほうが安くなってしまいました。えっ?

よく見てみましょう。

ログボリュームはアーカイブされると、取り込まれたログボリュームの 15% になると推測されます (圧縮による)。
100.00 GB per month x 0.15 Storage compression factor x 1 Logs retention factor x 0.033 USD = 0.495 USD

なるほど。計算上15%のサイズに圧縮される前提となっていたようです。
100%だと3.3USDですね。

圧縮についてしらべる

推測15%と記載がありましたが、実際どの程度圧縮されるのか気になりました。
そしてそれをS3へ転送した場合どうなるのか。

試してみました。

やること

上記のようにサブスクリプションフィルター + Kinesis Delivery Streamで、S3へ転送するというパターンを取ってみたいと思います。
今回はEC2のApacheログをCloudWatchエージェントでCloudWatch Logsへ転送するシーンを想定します。

いちおうログをS3まで転送する部分のCloudFormationテンプレートを作っておきました。

Apacheはインストールしません。
その代わりに、Apacheアクセスログのような形式でダミーログを作成してくれる以下を利用させて頂きました。

やってみる

アクセスログを生成

EC2にセッションマネージャーでリモートアクセスし、apache-loggenをインストールして475,000行のアクセスログを生成します。

sh-4.2$ sudo gem install apache-loggen
Fetching: apache-loggen-0.0.5.gem (100%)
Successfully installed apache-loggen-0.0.5
Parsing documentation for apache-loggen-0.0.5
Installing ri documentation for apache-loggen-0.0.5
1 gem installed
sh-4.2$ apache-loggen --limit=475000 /var/log/httpd/access_log
sh-4.2$ ls -alh /var/log/httpd/
total 101M
drwxrwxrwx 2 root     root       24 Sep 16 11:41 .
drwxr-xr-x 8 root     root     4.0K Sep 16 11:40 ..
-rw-r--r-- 1 ssm-user ssm-user 101M Sep 16 11:41 access_log

101MBのファイルが作成されましたね。

CloudWatch Logsの確認

では、CloudWatch Logsに転送されているか見てみましょう

配信されていますね。
すごいですね。本物のログみたいです。

次に、ログのサイズを確認してみましょう。
保管サイズを確認出来るCLIコマンドが2つあります。

ただし、describe-log-streamsでは保管サイズは今は取得出来ないみたいです。
describe-log-groupsで確認する必要があるようです。

Important: On June 17, 2019, this parameter was deprecated for log streams, and is always reported as zero. This change applies only to log streams. The storedBytes parameter for log groups is not affecte

確認してみましょう。

[cloudshell-user@ip-10-0-169-180 ~]$ aws logs describe-log-streams --log-group-name iwasalogs
{
    "logStreams": [
        {
            "logStreamName": "i-00feb732e442e2b40",
            "creationTime": 1631792496519,
            "firstEventTimestamp": 1631792495984,
            "lastEventTimestamp": 1631792496244,
            "lastIngestionTime": 1631792529965,
            "uploadSequenceToken": "49621415831550584682944274944792899798370299252576523714",
            "arn": "arn:aws:logs:ap-northeast-1:123456789012:log-group:iwasalogs:log-stream:i-00feb732e442e2b40",
            "storedBytes": 0
        }
    ]
}
[cloudshell-user@ip-10-0-169-180 ~]$ aws logs describe-log-groups --log-group-name iwasalogs
{
    "logGroups": [
        {
            "logGroupName": "iwasalogs",
            "creationTime": 1631792189994,
            "retentionInDays": 7,
            "metricFilterCount": 0,
            "arn": "arn:aws:logs:ap-northeast-1:123456789012:log-group:iwasalogs:*",
            "storedBytes": 0
        }
    ]
}

おや、どちらもサイズが確認出来ないですね。
ドキュメントに記載が見当たらなかったのですが、どうやらサイズの反映はかなり時間差がかかるみたいです。
私が確認した時は、17時間後くらい経過してサイズが取得出来るようになりました。

[cloudshell-user@ip-10-0-171-84 ~]$ aws logs describe-log-groups --log-group-name iwasalogs
{
    "logGroups": [
        {
            "logGroupName": "iwasalogs",
            "creationTime": 1631792189994,
            "retentionInDays": 7,
            "metricFilterCount": 0,
            "arn": "arn:aws:logs:ap-northeast-1:123456789012:log-group:iwasalogs:*",
            "storedBytes": 23990229
        }
    ]
}

23MiBですね。
圧縮率80%くらいでした。

S3の確認

S3にも転送されていますね。
サイズを確認してみましょう。

[cloudshell-user@ip-10-0-169-180 ~]$ aws s3 ls s3://iwasa-cwlogs-123456789012 --recursive --human-readable --sum
2021-09-16 11:41:52    5.1 MiB 2021/09/16/11/iwasa-firehose-deliverystream-httpdaccess-1-2021-09-16-11-38-52-739620b0-257f-40d7-bddf-e7a895e57fde
2021-09-16 11:42:08    5.0 MiB 2021/09/16/11/iwasa-firehose-deliverystream-httpdaccess-1-2021-09-16-11-41-50-f6e62e85-d8ec-45b6-9336-af0a37fc27d2
2021-09-16 11:47:12    1.2 MiB 2021/09/16/11/iwasa-firehose-deliverystream-httpdaccess-1-2021-09-16-11-42-10-f905b492-dd55-4895-9ae2-7824d7dcaae6

Total Objects: 3
   Total Size: 11.3 MiB

合計サイズは11.3MiBになっていました。えっ?
さらに圧縮されているのだろうか。
それとも全てのログレコードが転送されていないのか。

ダウンロードして解凍し、サイズを確認してみましょう。

iwasa.takahito@hoge s3logs % ls -lh
total 307192
-rw-r--r--  1 iwasa.takahito  staff    67M  9 16 20:52 iwasa-firehose-deliverystream-httpdaccess-1-2021-09-16-11-38-52-739620b0-257f-40d7-bddf-e7a895e57fde
-rw-r--r--  1 iwasa.takahito  staff    67M  9 16 20:52 iwasa-firehose-deliverystream-httpdaccess-1-2021-09-16-11-41-50-f6e62e85-d8ec-45b6-9336-af0a37fc27d2
-rw-r--r--  1 iwasa.takahito  staff    15M  9 16 20:51 iwasa-firehose-deliverystream-httpdaccess-1-2021-09-16-11-42-10-f905b492-dd55-4895-9ae2-7824d7dcaae6

元のログデータよりかなり大きいですね、サイズが。

S3に格納されたログファイルは生データの状態ではなくて、加工されたJson形式になっており、ある属性に生データが全部入っています。 そのせいで、オリジンデータよりサイズが増えているようです。

どういうフォーマットになっているのかは以前こちらの記事で少しまとめましたので宜しければ見てみてください。

Jsonファイルの中のmessageキーワードが何件あるのか調べてみました。
だいたいのログレコード件数がわかるはずです。

iwasa.takahito@hoge zip % grep -o -i "message" iwasa1.log| wc -l
  213033
iwasa.takahito@hoge zip % grep -o -i "message" iwasa2.log| wc -l
  213234
iwasa.takahito@hoge zip % grep -o -i "message" iwasa3.log| wc -l
   48961

だいたい475,000件ちょっとなので、ログレコードが転送されておらず、サイズが削減されているわけではなさそうですね。

さいごに

というわけで序盤の計算はApacheダミーアクセスログで試したところ以下のようになりました。

ログ サイズ
生データ 101 MiB
CloudWatch Logs 23 MiB
S3 11.3 MiB

Calculatorで15%くらいの圧縮率で計算されていますが、大きく乖離はしてなさそうですね。
そして、S3へ転送する場合はその圧縮率程度のサイズはキープはされそうなので、S3側の見積もりを行う際にも圧縮率を考慮するのが良さそうです。

もちろんログの内容によって圧縮率というのは上下するので、一概には言えないと思いますが。
ひとつの参考になるかなと思いました。

上記によると、

CloudWatch Logs から Amazon Kinesis Data Firehose に送信されたデータは、すでに gzip レベル 6 圧縮で圧縮されているため、Kinesis Data Firehose 送信ストリーム内で圧縮を使用する必要はありません。

とありまして、gzip レベル6で圧縮されているようです。
圧縮率を検証されている方がいらっしゃったので参考にさせて頂きましたがレベル6だと80%強の圧縮率だったようですので、たしかに近い値が出ていますね。なるほど。

ただ、CloudWatch LogsからS3へ無圧縮で転送してる場合でも半分程度のサイズになる部分はちょっとわかりませんでした。
もし、ディープダイブした後にこちらの世界に返ってこれた人がいらっしゃれば、このあたりの秘密を教えてもらえると嬉しいです。