AWS

AWSのコストを削減するためにやったこと

AWSアカウントの状況

ある日、会社で使っているとあるAWSアカウントの管理者を任されました。
そのアカウントは開発環境用で、開発者・運用者が結構好き勝手に触っている環境でした。
もちろんコスト管理もあまりされてなく、1日約1000ドル垂れ流している日もあるぐらいでした。
それを1日約100ドルまで削減できたので、せっかくなので行なったことをメモして置こうと思います。
尚、自分が管理していたアカウントではほぼEC2とRDSにコストがかかっていたので、その二つにフォーカスしています。

現状の把握

まずは「AWS費用がやたら高いけど、なんで高いの?」の確認からはじめました。

請求書を見る

請求ダッシュボード -> 請求書から月ごとの請求金額が見れます(月途中の金額も見れます)。
サービス毎に請求金額が表示されるので、ここで大まかにどのサービスでコストがかかっているのか確認できます。

自分が管理していたアカウントは2/3がEC2、1/3がRDSというような状況でした。

Cost Explorerを見る

Cost Explorerは請求金額をグラフで表示できます。
日毎でグラフ化できるので、デイリーで請求金額の推移を見たい場合に使います。
また、色々フィルタリングできるのでコストの細分化に役立ちます。

Cost ExplorerでAWSの利用状況を把握する

やったこと

EC2

上でも書きましたが、自分が見ていたアカウントで一番コストがかかっていたのでEC2でした。
EC2は動かした分料金がかかるため、いかに稼働時間を抑えるかがコストを抑えるポイントだと考えています。

EC2Schedulerの導入

業務時間以外はEC2の稼働はほとんどの場合無駄になります。
とはいえ、出社時と退勤時にインスタンスを起動・停止するのは大変だし忘れがちになります。
というわけで導入したのがAWSが提供しているEC2Schedulerです。
https://aws.amazon.com/jp/answers/infrastructure-management/instance-scheduler/

Lambda、Dynamodb、CloudWatch Eventsを組み合わせてEC2の起動・停止を自動化します。導入もCloudFormationのテンプレートが用意されているので簡単です。
詳しい使い方はクラスメソッドさんの記事などが詳しいので参考にしてください。

スケジューリングで失敗したこと

EC2SchedulerはEC2のタグに起動・停止時間や曜日などの条件を書いてスケジューリングします。
考えてみれば当然だと思うのですが、起動時間より停止時間が小さいと想定通りに動きません。
スケジューラーに記述する時間はUTC形式で、JSTからそのまま書き換えて動かしてたら見落としていました。

例えば日本時間の8:00〜18:00にEC2を動かしたい場合、タグに

キー
scheduler:ec2-startstop:hogehoge 2300;0900;utc;weekdays

こんな感じで記述すると金曜日の夜に止まらず土日にインスタンスが動きっぱなしになります(weekdaysは平日指定)。
下記のようにスケジューリングを二つに分けると想定通りに動きます。

キー
scheduler:ec2-startstop:start 2300;none;utc;sun,mon,tue,web,thu
scheduler:ec2-startstop:stop none;0900;utc;weekdays

低稼働なインスタンスの停止・削除

動かしているけど全然使っていないインスタンスは止めましょう。
EC2の課金が抑えられます。

ただ、止めただけだとEBS(EC2に付属するストレージ)の課金がかかり続けます。
ストレージのサイズと課金額は比例するので、大きいサイズのEBSは特に気をつけましょう。
基本停止状態で滅多に使わないインスタンスはいっそのこと削除した方がよいです。
バックアップしておきたい場合はAMIをとっておきましょう。
また、AMIを取るときは起動テンプレート(Launch Templates)ですぐに起動できる状態にしておくと便利です。

インスタンスタイプの見直し

インスタンスタイプの性能がよければよいほど課金額が大きくなります。
モニタリング状況を見てオーバースペックなインスタンスサイズを指定していたらサイズ変更します。
インスタンスが停止状態ならサイズ変更できます。

スポットインスタンスの活用

いつ死んでもOKなインスタンスはスポットで動かすとコストが下がります。
インスタンスタイプやAZによっては価格が違うので、使う際事前にチェックしましょう。

オートスケーリンググループのスケジューリング

オートスケーリンググループ(以下ASG)の機能にインスタンス数をスケジュールできる機能があります。
ASGで管理してて夜間は止めて大丈夫なインスタンスはスケジューリングしてしまいましょう。
cronのような形式で設定できます。これも時間がUTCなので設定の際は注意しましょう。

EBS

アタッチされていないEBSの削除

EC2インスタンスを立ち上げる時のEBSの設定にEC2削除後もEBSを残す設定をすると、インスタンス削除後にもEBSが残り続けます。
インスタンスにアタッチされていないEBSも課金されてしまうので、不要な場合は削除しましょう。

サイズの見直し

EBSはサイズが大きいほど高いので、余裕を持ちすぎている場合は下げることを検討します。
・・・と、言ってもEBSのサイズ変更は上げることは可能ですが下げることはできません。
ですので、下げる場合は一旦EC2を(必要ならAMIをとって)削除して作り直しましょう。

RDS

不要なインスタンスの削除

使っていないRDSインスタンスがある場合、(必要なら)スナップショットをとって削除してしまいましょう。

インスタンスタイプの見直し

EC2と同じくモニタリングをチェックしてオーバースペックだったらインスタンスサイズを下げましょう。

マルチAZからシングルAZに

不要だけどマルチAZ構成になっている場合、シングルAZにしてしまいましょう。
必要になったら後からマルチAZにも変更できます。

止められるインスタンスの停止

止められるインスタンスは停止してしまいましょう。
Auroraは停止できません・・・。
自分は年末年始の長期休暇前はAuroraのインスタンスサイズを一番低いものにしてコストを抑えました。

停止できるインスタンスについてはAWSが提供しているAWS Instance Schedulerというソリューションがあります。EC2とRDSに対応しているので、EC2も合わせてEC2Schedulerよりこちらを使っても良いかもしれません。

2018/08/10追記

Auroraを使っている場合、Aurora Serverlessがリリースされたので、使用頻度が低い開発環境などはServerlessに置き換えるとコストが抑えられる可能性があります。
https://aws.amazon.com/jp/rds/aurora/serverless/

低稼働なELBの削除

ELBはあるだけでお金がかかります。
インスタンスがアタッチされてないELBや、アタッチされてるけどインスタンスがずっと停止状態になってる場合は思い切って一旦削除を検討しましょう。

不要なNATゲートウェイの削除

NATゲートウェイもあるだけで費用がかかってしまいます。
使われてないVPCや、マルチAZ化されてるけど開発環境だからシングルAZでもいいよ、などの場合は削除してしまいましょう。
NATゲートウェイをケチるために、プライベートサブネットで動かすべきインスタンスをパブリックに移動したりするのはセキュリティ的によろしくないので注意しましょう。

検討したけどやらなかったこと

リザーブドインスタンスの活用

平日の業務時間しか動かさないインスタンスがほとんどだったので、あまりリザーブドの効果は期待できなかったので断念しました。

コスト意識を維持・高めるために

タグ付けの徹底

開発環境の場合、各開発者が割と自由にインスタンスを立てたりできるようになってます。
そのため、誰がどのプロジェクトのために使っているのか各サービスにタグ付けを徹底しました。
Ownerタグ → 開発者の名前
ProjectNameタグ → プロジェクト名

作成したタグを請求ダッシュボードのコスト配分タグに登録することにより、
上で書いたCost Explorerのグラフをタグでフィルタリングできるようになるので、誰がどのプロジェクトでコストをかけてしまっているのかチェックすることができます。

Trusted Advisorの活用

サポートプランがビジネス以上だとTrusted Advisorでコストについて無駄がないかチェックできます。

おわりに

開発環境のような開発者個々人が自由に触れる環境だと一人一人がコスト意識を持つことが大事だと感じました。
AWSでサービスを使うにあたって何に課金されるか把握するのも大事!
あとは、とにかく最初は現状を把握することからだと思います。