💸

AWSのコストを最適化した話

2024/04/26に公開

HousmartでCTOをしている佐藤です。
SREの施策としてAWSのコスト最適化に取り組んだ話になります。

背景

インフラの構成は、AWSを利用しているのですが、利用ユーザーやデータ量の増加に伴いリソースの増強などで インフラ コストが増加傾向にありました。また、急激な円安等の流れもあり見直しが必要になったため、コスト最適化を取り組むことにしました。

データ転送料の削減

データ転送料が、毎月 $1,500 以上 の状態となっていて、原因を調べてみたら S3の転送料ということがわかりました。S3に保存している画像などをCDNのキャッシュサービスを利用して配信しているのですが、キャッシュが効いていない状態で キャッシュを効かせるには、S3のオブジェクトのメタデータにCache-Controlの設定が必要でしたので、以下の手順で対応しました。

AWS CLI でS3オブジェクトのメタデータを変更

aws s3 cp s3://bucket-name/xxxx.jpeg s3://bucket-name/xxxx.jpeg --metadata-directive "REPLACE" --cache-control "max-age=86400" --recursive

cache-control max-age=86400 は キャッシュの有効期限を86400秒(1日)で設定しています。
特定のバケットを対象に一括で変更したかったので、以下のスクリプトを用意して設定することにしました。

#!/bin/bash
BUCKET_NAME="bucket-name"
CACHE_CONTROL="max-age=86400"
TAB="$(printf '\\\011')"

for key in $(aws s3 ls $BUCKET_NAME/ --recursive | sed -E 's/[${TAB} ]+/ /g' | cut -d " " -f 4); do
  ContentType=$(aws s3api head-object --bucket $BUCKET_NAME --key $key | jq '.ContentType')
  aws s3 cp s3://$BUCKET_NAME/$key s3://$BUCKET_NAME/$key --metadata-directive "REPLACE" --content-type $(echo $ContentType | sed 's/"//g')  --cache-control $CACHE_CONTROL 
done

設定してからはデータ転送料の月額が、およそ1/3まで下げることができました。

不要なリソースの停止と削除

EC2のインスタンスなどは、稼働していなければ課金されないイメージがありますが、停止していてもインスタンスに割り当たっているストレージ等は、容量に応じて料金が加算されます。また、バックアップなどで取得するスナップショットやEC2などのインスタンスに紐づけられていない Elastic IPも料金がかかるケースがあります。

長くサービスを運用している中で、増えていくデータやバックアップ、サービスの運用変更等で不要になってしまったインスタンス等を確認しながらコスト削減を行いました。すべてではないですが 主に確認・対応した内容を ピックアップしました。

S3

  • 不要なオブジェクトの削除
  • アクセス頻度の少ないオブジェクトのライフサイクルとストレージクラスの設定

EC2

  • 不要なインスタンスの終了
  • アタッチされていないEBSの削除
  • 不要なスナップショット

Elastic IP

  • 関連付けられていないEIPの削除

RDS

  • 不要なインスタンスの削除
  • 不要なスナップショットの削除

AWSのサポートプランがビジネスサポート以上であれば AWS Trusted Advisor のコスト最適化を利用して不要なリソースの洗い出しができるのでおすすめです。

Fargate Spotの導入

Fargate Spotとは?

Fargate Spotは、AWSクラウドの空きキャパシティを活用してタスクを実行します。Fargate Spotが空きキャパシティを確保できるかぎり、ユーザーは指定したタスクを起動することができます。AWSにキャパシティが必要になったとき、Fargate Spotで稼働するタスクは2分前の通知とともに中断されることになります。Fargate Spot用のキャパシティが使用できなくなると、Fargateは稼働中の通常のタスクを保持しながら、Fargate Spotで稼働するタスクをスケールダウンします。
引用: AWS Fargate Spotの発表 – Fargateとスポットインスタンスの統合

東京リージョンにおける、オンデマンドタスクとSpotタスクの料金を比較

種別 オンデマンド Spot オンデマンドに対するSpotの料金比率
1 時間あたりの vCPU 単位 $0.050560 $0.015168 30%
1 時間あたりの GB 単位 $0.005530 $0.001659 30%

Spotのデメリットは、AWSの都合で中断することがありますが、中断しても問題にならないような 検証環境や途中で中断しても影響がなく 短時間しか実行しないようなバッチ処理などならデメリットを最小限で利用できコストを削減できます。

TerraformでAWS Fargate Spotの対応

インフラの管理をTerrformで行っていますので、Terraformでの導入方法を紹介します。

デフォルトキャパシティプロバイダーの設定

ECSクラスターでデフォルトキャパシティープロバイダーを設定します。

resource "aws_ecs_cluster_capacity_providers" "ecs_cluster_capacity_providers" {
  cluster_name       = "test_cluster"
  capacity_providers = ["FARGATE", "FARGATE_SPOT"]

  default_capacity_provider_strategy {
    capacity_provider = "FARGATE"
    base              = 0
    weight            = 1
  }

  default_capacity_provider_strategy {
    capacity_provider = "FARGATE_SPOT"
    base              = 0
    weight           = 1
  }
}

Service毎のキャパシティプロバイダーの設定

ECSでFargate Spotを利用するにはキャパシティープロバイダーの設定が必要です。
キャパシティープロバイダーの起動数や割合の設定はこちらを参考にしてください。
launch_type を設定している場合は削除

resource "aws_ecs_service" "ecs_service" {
  ... 省略
  launch_type = "FARGATE" (削除)

  capacity_provider_strategy {
    capacity_provider = "FARGATE"
    base              = 0
    weight            = 0
  }
  capacity_provider_strategy {
    capacity_provider = "FARGATE_SPOT"
    base              = 1
    weight            = 1
  }
}

Savings Plansとリザーブドインスタンスの導入

AWSは利用した使用量に応じた従量課金となっていますが、Savings Plansとリザーブドインスタンスは、1年または3年の期間の利用をコミットすることで割引を受けられるサービスです。

利用しているサービスとSavings Plans、リザーブドインスタンスのそれぞれの特徴を検討して適用しました。

Savings Plans

1年または3年、1時間あたりUSD単位で一定の使用量を契約することで EC2 および コンピューティングの料金が割引になります。ECS・EC2・Fargate と適用範囲が広く柔軟性が高いため 主に EC2, Fargate の1時間当たりの利用料を算出して Compute Savings Plans のコミット料金を決定しました。Savings Plans 推奨事項を使ってコミット料金を決めるのもおすすめです。

リザーブドインスタンス

1年または3年、インスタンスファミリー、インスタンスタイプなどのスペックを指定して契約することで料金が割引になります。リザーブドインスタンス対象のインスタンスが稼働していない場合でも、契約期間中は料金が請求されます。インスタンスファミリーを変更すると対象から外れてしまうケースがありますので、注意が必要です。
主に RDSで適用しました。ElastiCasheにも同様の割引サービス(リザーブドキャッシュノード)があり適用しました。

最後に

今回のコスト最適化でおよそ30%~40%ほど月額費用を削減することができました。
まだ、コスト最適ができそうな箇所はありそうですが、定期的に見直しながら最適化を実施していければとおもいます。

Discussion