とあるシステムをオンプレミスからAWSへ移行するプロジェクトにおいて、監査やインシデント管理のためcloudwatchのメトリクスを長期保存する必要があったのでS3とAthenaを使ったメトリクスを長期保存するがすぐに取り出せる構成について備忘録として残しておきます。
前提
日常的なオブザーバビリティはDatadogを使っています。
EC2はもちろんやその他AWSのRDSやECSなどのマネージドサービスも全てインテグレーションをして可視化している状況です。
その状況下でDatadogを導入し始めた頃にはさほど気にならなかったメトリクスデータやログの保存にかかる費用が年月が経つとともに、目につくようになりクラウド利用に関するコストの削減対象になってしまいました。
ただ、ポリシーとしては保存期間を設けて過去のデータを捨てることが許容されずに、利用頻度が低くとも即座に過去に戻って状況を確認する必要があります。
ハイブリッド構成
当然ながらコストの問題がクリアできればDatadogで全て期間における監視データ、分析を閲覧できることがベストですが右肩上がりに費用が嵩んでいくため、直近はDatadogで秒単位のリアルタイム性を担保する。一定期間が経過したのちの過去分については秒単位のリアルタイム性は必要ないためDatadogでは管理せずにS3+Athenaのハイブリッドな構成としました。
- 直近のデータ:今起こっている障害に対応するために秒単位のリアルタイム性が必要
- 過去のデータ:トレンド分析や監査対応のため秒単位にリアルタイム性は不要、データが保存してあることが重要
直近3ヶ月は従来通りのDatadog + Cloudwatchで監視対応、それ以前のデータはS3に退避させてAthenaでクエリすることとしました。
S3+Athena
構成自体は至極シンプルです。
CloudWatch Metric StreamからKinesis Data Firehoseを経由してS3に保存するだけ。
(意外とCloudWatch Metric Streamを使っている方は少ない印象ですが。。)
ただ、この構成を使えるレベルにするにはいくつか落とし穴があったので以降でまとめてみます。
1. JSONのまま保存しない。
CloudWatch Metric StreamsからS3に保存する際に形式が選べますが、よく使われるのはJSONだと思います。
そのほか、OpenTelemetry形式でも保存できますが汎用性の高いJSONが選択されることが多いかと思います。
ところがJSONのままS3に保存をして、後からAthenaで検索する時に痛い目を見ます。
Athenaによるスキャン量が膨大になりクエリの度に課金されていきます。
Athenaを使う人にクエリの工夫がなければお金の垂れ流しです。
今回はオブザーバビリティに関するコスト削減が主な目的だったので、 Parquet形式へ変換し、さらにSnappy圧縮をすることで対策しました。
これで検索速度が向上し、コストも大幅に抑えることができます。
Parquetに変換しておくことで、データレイクハウス構築プロジェクトでのicebergにも親和性があり拡張性にも役に立ちました。
2. パーティション管理
S3に時系列データを保存する時にフォルダ構成(パーティション)をどうするかはよく考えないといけません。
Kinesis Data FirehoseのDynamic Partitioningを使って下記のように日別で整理するのが定石です。
metrics/year=2025/month=10/day=11
ただ、定石通りこのままで保存するとデータが増えるたび、つまり今回のケースだと日常的に MSCK REPAIR TABLE でパーティションを認識させないといけないため、毎度一手間かかってしまいます。もちろん、自動化は可能ですが極力やるべきことは減らした方がいいです。
そこで今回はAthenaの Partition Projection(パーティション射影) を使うことにしました。
これが割と便利で、S3にの中身をわざわざ見に行かなくても、「ルール上、ここにあるはず」と割り出してくれます。
AthenaのDDLの設定を書くだけで、数年分のデータ範囲であっても一瞬で検索範囲を特定できます。
-- 実際のDDLはこんな感じです。
CREATE EXTERNAL TABLE cloudwatch_metrics (
-- カラム定義(省略)
)
PARTITIONED BY (year string, month string, day string)
STORED AS PARQUET
LOCATION 's3://my-metrics-bucket/metrics/'
TBLPROPERTIES (
'projection.enabled' = 'true',
'projection.year.type' = 'integer',
'projection.year.range' = '2024,2030',
-- 日付のルールを書いておくだけでOK
'storage.location.template' = 's3://my-metrics-bucket/metrics/year=${year}/month=${month}/day=${day}/'
);
コストがどうなるか
実際にこの構成を使ったコストを試算してみるとざっくりでも大きく差があります。
月間100GBくらいのメトリクスやログデータが出るシステムだとして、DatadogやNewrelicなどのSaaSのアーカイブオプションだとざっと数十万円かかります。
これがS3+Athenaの組み合わせだと保存料とMetric Streamの利用料合わせても数千円〜数万円になります。
必要な時にAthenaのクエリに対するスキャン料金が発生しますが、Parquet+Snappy圧縮にしておけば1回数円レベルです。
オブザーバビリティのデータに対して監査に必要だから長期間にわたる過去分も保存しておきたい。という要件を満たすことができそうです。
まとめ
CloudWatch Metric StreamsとS3、Athenaの組み合わせだと単なるログ置き場ではなく、SaaS利用のコスト制約から解放され「必要な時に、必要なだけ過去のデータを深掘りできる」という第二のオブザーバビリティ基盤として使えるのではないかと思います。
過去データを対象にせずに今時点のデータにも活用することにより、SaaSがダウンした時の障害対策としても活用できそうです。