AppBrew で LIPS のリードエンジニアをやってる Pin (@spinute)と申します。 半年ほど前に AppBrew でアルバイトをしながら転職活動をしていましたが、いい感じだったのでそのまましれっと AppBrew に入社しました。
今日の記事では、圧縮し忘れていたログを圧縮し、35万円/月の費用を削減した話を紹介します。 確認するだけなら一瞬なので、AWS を使ってる会社の方は、担当の方にこの記事を共有してみると思わぬ費用削減に繋がるかもしれません...!
LIPS のインフラ構成
弊社のデータ処理基盤は開発初期に深澤が入れてくれたもので、大まかな構成は今もそのままです。
LIPS のインフラは AWS 上に構築しています。ログは、Kinesis Firehose を使って、S3 および Redshift へと流し込んでいます。
バックエンドの部分を抜き出すと上のようになっています。 ポイントとしては、
スタートアップでも出来る分析基盤 - AppBrew Tech Blog
- EC2の各インスタンス上からfluentdでkinesisに投げる
- kinesisからfirehoseでredshiftのインスタンスに流し込む
- kinesisからfirehoseでS3に取り置く(Athenaで引ける(引くとは言っていない
- kinesisからlambdaを発火して、低レイテンシーでデータ分析用に使いたいデータ・サービスから改めて使いたいデータ(クリックログなど)をDynamoDBに流し込む
- Redash(Sassバージョン)を使い、Redshiftをメインのバックエンドとして利用する
- Redashは非エンジニア含む社員全員に公開している
問題発見の経緯
弊社では、この9月にインフラ部1というインフラ改善チームが発足しました。 インフラ部における今 Q の目標の1つに通信費削減を掲げることとなり、私はそのプロジェクトオーナーをすることにしました。
通信費の内訳を精査し、主な費用源であった AWS の費用内訳を Cost Explorer を使って掘り下げると、S3 の費用が思いのほか嵩んでいることがわかりました。
さらに、料金の内訳を調べると、以下のことがわかりました。
- データ転送量とデータ保存料でそれぞれ月20万円
- 保存料は毎月1.5万円ペースで伸び続けている(!)
LIPS ユーザ結構多いし、まあこんなもんなのかなーと思いながらも設定を見回していると、なんと一部のログを圧縮せずに保存し続けていたことが判明しました!
具体的には、Kinesis Firehose にデータを流すときの圧縮設定を有効にしておらず、ログ 80TB が未圧縮で保存されていたことがわかりました。
これが毎月20万円のデータ保存料の正体でした。毎月1.5万円ペースで費用が伸びていたので、このまま3年放っておくと1600万円、5年放っておくと4000万円の総費用がかかってしまいます!
対応
試しに gzip でいくつかログを圧縮してみると、10倍くらいは縮みそうでした。これで費用は月に数万円程度になるので、ひとまずこれ以上に凝ったこと2はしなくてよさそうです。
ということで、以下の2つの対応をしました:
- Firehose の圧縮設定を有効にし、入ってくるログが圧縮されるようにする
- 既存のログを圧縮する
Firehose のログ圧縮設定を有効にする
Firehose の設定画面にて、圧縮を有効にしました。3
これ(だけ)で、ログ容量が急速に増え続ける問題は解決しました。
既存のログを圧縮する
続いて、既存の(膨大な)ログを圧縮します。
一見、単にダウンロードして圧縮し、それを書き戻せばよさそうですが、どうでしょう?
- 僕の使っているマシンのストレージは 512GB なので、160回に分けての作業が必要
- データ転送・圧縮速度が 10 MB/秒だとして、800万秒=92日かかる
- データ転送量が70万円かかる4
...これはツラいので、別のやり方を検討した方がよさそうです。
作業用の EC2 インスタンスを建てれば、ストレージ容量やデータ転送料金の問題は解決しそうです5。また、転送・圧縮速度の問題を解決するには、並列処理すればよさそうです。Parallelでマルチコアを活かしたり、EC2 インスタンスをたくさん並べるのはどうでしょう?
92日分相当の圧縮処理を行う中のどこかで、ひとつでもエラーが発生する可能性は割と高そうです。ログはめちゃめちゃ大事なので、欠損は絶対に避けたく、エラー処理の仕組みをバグなく実装・実行するためには時間とメンタルをけっこう消耗しそうです。
そこで、AWS の機能をなるべくそのまま使うだけくらいの気軽さでやりたいなーと思っていたところ、s3-dist-cp というピッタリな機能を見つけました。
s3-dist-cp
s3-dist-cp は EMR(Elastic Map Reduce) を使って S3 からファイルをコピーするためのツールです。
主には、EMR で処理するような巨大なファイルを、S3 から HDFS 等へと効率的にコピーするためのツールですが、S3 から S3 へのコピーにも使えます。また、コピーの際に圧縮を挟むこともできます。つまり、S3 のオブジェクトを、並列分散圧縮するために使うことができます。
20台でクラスタを組み、20倍速で処理が進めば、今回の圧縮作業を数日で終えられそうです。6 また、料金は普通に EC2 インスタンスを立てた場合と比べて 25% 増程度で、十分リーズナブルです。
1台構成、20台構成で試走し、スループットがだいたい20倍になることを確認したあと、実際に全ログを圧縮しました。使い方はめちゃ簡単で、20台と入力するだけで20倍速になってくれて最高でした。
実行中に2回エラーログが出ていましたが、(失敗した処理を勝手に再実行してくれる)s3-dist-cp を採用したので放置しているだけで済みました。 もし自前で実装してるとここで泥沼化していたはず7なので、s3-dist-cp 使ってよかった...。
ログを削除する
最後に圧縮前のログファイルを消します。
ログの欠損は絶対に避けたいので、ログを消す前に(1)コピー先のファイルがあること(2)余分なファイルが無いこと(3)ファイルが空で無いこと、などのチェック項目を考え、テストするスクリプトを書きました。また、私はあまり私を信用していないので、oyuk さんにダブルチェックをお願いしました。
あとは消すだけです。消すオブジェクトは 1000万個程度だったので、S3 の CLI を使って雑に消しました。8
最後に、Cost Explorer から実際に費用が下がったことを確認し、満足感に浸ったらミッションコンプリートです。9
まとめ
この記事では、ログを圧縮し忘れたまま数年が経ち、大量の未圧縮ファイルが溜まってしまった場合の対処法を紹介しました。 早い段階で気づけば、お金も無駄にならず、この記事に書いたような対応も必要ないため、皆様もぜひ一度ログやそのバックアップがちゃんと圧縮されていることを確認してみていただければと思います。
弊社アプリ LIPS はかなり大きくなってきており、スケーラブルなインフラやアルゴリズムの重要性が増してきています。
弊社の会社紹介資料を作りました
— Yuta Fukazawa (@YFuka86) November 1, 2019
・LIPSと、その先に目指しているもの
・ティール/給与公開/360度評価などカルチャー面
などが紹介してあるので是非ご覧ください
(先ほど記事とリリースしましたが、スライド単体で再度シェアします)https://t.co/sQfYTmQk3m
私達と一緒に LIPS の成長を支えていくエンジニアを引き続き募集しております。興味がある方はぜひぜひご応募ください!
-
部署というよりは部活に近いと思っています↩
-
例えば、他の圧縮形式や S3 のストレージクラスの検討など↩
-
具体的には、Intermediate S3 destination という箇所の Compression 項目を GZIP に設定し、Amazon Redshift destination という箇所の COPY option という項目に gzip オプションを追加しました(参考:AWSのドキュメント)↩
-
8-9円/GBくらいhttps://aws.amazon.com/jp/s3/pricing/↩
-
S3・EC2 インスタンス間のデータ転送は、同一リージョンなら無料↩
-
20台にしたのは、それ以上並べるには事前申請が必要だったため↩
-
やり直すたびに max 100日分の CPU 使用量が課金される、再開ポイントを探すために、並列に吐かれた80TB分のログを漁ることになる、等↩
-
オペミス防止のため S3 のバージョニング機能を有効にしており、バージョンを指定して消す必要があることには注意が必要でした↩
-
今回の記事で紹介したのはログの保存料を削減する手順です。転送量は今回紹介したものとは別の作業の成果です↩