4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ECS Fargateのログ管理コスト削減(Firehose + S3 + Athena)

Last updated at Posted at 2020-10-02

前提

ECS Fargateを利用していて、以下に当てはまる場合はコスト改善できるかもしれないので読み進めてもいいかもしれないです。

  • CloudWatch Logsのコストが高い。
  • CloudWatch Logsにログ連携しているがalermは設定していない。
  • リアルタムなログ閲覧は求めていない。

経緯

最近携わっているプロダクトではECS Fargateを利用しているのですが、請求書の内訳を確認してみたところ、CloudWatchLogsのPutLogEventsに、全体の1/3以上のコストが発生していました。ログにそんなにお金を払うのは辛いです。

原因

全TaskのLog driverがawslogになっており、ログがCloudwatch Logsに連携されいたことがコスト増加の原因でした。
LogDriver.png

Cloudwatch Logsは、ログを検索する際にはとても便利なのですが、ログをリアルタイムで監視するようなalermを設定していないのであれば、S3にログを保存しておいて、見たい時にAthenaで検索するというやり方でも十分運用できそうです。というAWS有識者からのアドバイスもあり、構成変更を実施してみました。

改善案

いままでは、FargateからCloudWatchに月間2TB(*1)ほどログを転送しており0.76USD/GBの課金が発生していましたが、変更後の構成ではFargate-Firehose-S3への転送で0.036USD/GBになりますので、ログの取り込みコストだけをみれば1556ドル->73ドルという予測になります。

log.png

他にも保存や分析にかかる費用がそれぞれありますが、取り込みコストの差を考えれば変更する価値は十分ありそうです。
詳しくはAWSのページをご確認ください。

https://aws.amazon.com/jp/cloudwatch/pricing/
https://aws.amazon.com/jp/kinesis/data-firehose/pricing/
https://aws.amazon.com/jp/athena/pricing/

*1 ログ取り込み量は以下のようなコマンドで1日分を出して、ざっくり31をかけて1ヶ月分としました。

aws cloudwatch get-metric-statistics \
--namespace "AWS/Logs" \
--dimensions Name=LogGroupName,Value="ロググループ名" \
--metric-name "IncomingBytes" \
--statistics "Sum" \
--start-time "2020-09-26T00:00:00Z" \
--end-time "2020-09-27T00:00:00Z" \
--period 86400 \
--query "reverse(sort_by(Datapoints,&Timestamp)[?Sum>\`0\`].{Sum:Sum,Timestamp:Timestamp})" \
--output text

やってみた

構成

検証用の環境は以下のような構成にしました。
log-2.png

手順

今回はAWSコンソール上から作成していきます。

1. S3 Bucketの作成

任意の名前でバケットを作成してください(作成手順は省略)

No
1 region ap-northeast-1
2 バケット名 example-bucket-20200929

2. Delivery streamの作成

Kinesisのコンソール画面から「Create delivery stream」をクリックする

step1.png

step2.png

ログの書き込み先はS3を指定しています。
step3.png

S3 prefixはAthenaのパーテション分割が1時間単位になるように設定しました。
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/partitions.html

■ Prefix
nginx-access/dt=!{timestamp:yyyy}-!{timestamp:MM}-!{timestamp:dd}-!{timestamp:HH}-00/

■ Error prefix
nginx-error/dt=!{timestamp:yyyy}-!{timestamp:MM}-!{timestamp:dd}-!{timestamp:HH}-00/!{firehose:error-output-type}

step4.png

S3 buffer conditionsはバッファーサイズが5MBを超えた場合、または5分たったらS3にログを書き込むように設定しています。
圧縮と暗号化はDisabledにしています。
step5.png

3. ALBの作成

alb1.png

alb2.png

alb3.png

4. Fargateの設定

Task Roleの作成

TaskRoleを作成して、Firehoseへのアクセスを許可しておく。

iam.png

CloudFormationだと以下のようになります。

  ecsTaskRoleExample:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: 'Allow'
          Principal:
            Service: 'ecs-tasks.amazonaws.com'
          Action: 'sts:AssumeRole'
      Policies:
        - PolicyDocument:
            Statement:
              - Effect: 'Allow'
                Action:
                  - 'firehose:PutRecordBatch'
                Resource: '*'
          PolicyName: 'firehose-example'
Clusterの作成

cluster.png

Task Definitionの作成

Task Roleには事前に作成したroleを割り当てます。

task1.png

Task sizeは最小に設定しています。

task2.png

Add containerをクリックしてコンテナを追加します。
task7.png

Log configurationでawsfirelensを選択し、作成したDelivery streamの値を設定します。

task6.png

Log Router Integrationは、今回はfluentbitを選択します。

task4.png

Serviceの作成

service1.png

service2.png

service3.png

service4.png

service5.png

5. Athenaで検索してみる

S3には以下のようにログが保存されます。

スクリーンショット 2020-09-30 13.39.03.png

ログの出力結果は以下のようになります。

{
  "container_id": "xxxxxxxx",
  "container_name": "/ecs-example-task-2-nginx-xxxxxx",
  "ecs_cluster": "arn:aws:ecs:ap-southeast-1:XXXXXXX:cluster/example-cluster",
  "ecs_task_arn": "arn:aws:ecs:ap-southeast-1:XXXXXXX:task/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "ecs_task_definition": "example-task:2",
  "log": "172.31.42.126 - - [30/Sep/2020:04:12:04 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"ELB-HealthChecker/2.0\" \"-\"",
  "source": "stdout"
}

Athenaでテーブルとパーティションを作成します。

athena1.png

CREATE EXTERNAL TABLE nginx_log (
    container_id string,
    container_name string,
    ecs_cluster string,
    ecs_task_arn string,
    ecs_task_definition string,
    log string,
    source string)
PARTITIONED BY (dt string)
ROW FORMAT  serde 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://example-bucket-20200929/nginx-access/' ;

パーティションにデータをロードします。

athena2.png

MSCK REPAIR TABLE nginx_log;

期間を変更して検索してみると、スキャンしたデータのサイズが変わっていることが確認できると思います。

athena3.png

athena4.png

おわりに

正規表現を利用したログのフィルタリングも可能とのことなので、引き続き検証していきたいと思います。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/using_firelens.html

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?