0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EC2コスト削減の実践ガイド:リザーブドインスタンスとSavings Plansを使い分ける

0
Posted at

EC2コスト削減の実践ガイド:リザーブドインスタンスとSavings Plansを使い分ける

この記事でわかること

  • EC2の料金体系(オンデマンド・RI・Savings Plans)の違いと使い分け
  • Compute Optimizer を使ったリサイジング推奨の読み方
  • EventBridge Scheduler + Lambda でEC2の自動起動・停止を実装する方法
  • 実際にどれくらいコスト削減できるかの試算方法

実務での背景

AWSの請求書を眺めていると「EC2だけでこんなにかかってるの?」と驚くことがあります。特に開発環境や検証環境では、夜間・休日もEC2が動き続けているケースが非常に多いです。

また、本番環境では適切なコミットメントディスカウント(RI・Savings Plans)を使っていないために、オンデマンド料金をそのまま払い続けているケースも多く見受けられます。

本記事では「今日から使える」コスト削減の実践的な手順を解説します。


解決方法

アプローチ1:開発・検証環境の自動停止

最もインパクトが大きい施策です。開発環境が24時間365日動いている場合、夜間(18時〜9時)と休日を止めるだけで約73%の削減になります。

週間稼働時間の比較:
- 現状(常時稼働): 168時間/週
- 平日 9:00〜18:00 のみ: 45時間/週
- 削減率: (168 - 45) / 168 ≈ 73%

アプローチ2:Compute Optimizerでリサイジング

過剰スペックのインスタンスをダウングレードします。t3.xlarge → t3.medium への変更で約50%削減できます。

アプローチ3:Savings PlansまたはRIの購入

安定稼働している本番環境には、コミットメントディスカウントを適用します。最大66〜72%割引になります。


具体的な手順

Step 1: Compute Optimizer で最適化推奨を確認

# Compute Optimizer の推奨を取得
aws compute-optimizer get-ec2-instance-recommendations \
  --query 'instanceRecommendations[*].[instanceArn,finding,recommendationOptions[0].instanceType,recommendationOptions[0].estimatedMonthlySavings.value]' \
  --output table

出力例:

----------------------------------------------------------------------
|        GetEC2InstanceRecommendations                               |
+---------------------+------------------+----------+-------+       |
|  i-0abc123def456    | OVER_PROVISIONED | t3.medium| 45.20 |       |
+---------------------+------------------+----------+-------+

Step 2: Lambda 関数でEC2の起動・停止を実装

import boto3

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    action = event.get('action', 'stop')  # 'start' or 'stop'

    # タグ AutoStop=true のインスタンスを対象とする
    state_filter = 'running' if action == 'stop' else 'stopped'
    response = ec2.describe_instances(
        Filters=[
            {'Name': 'tag:AutoStop', 'Values': ['true']},
            {'Name': 'instance-state-name', 'Values': [state_filter]}
        ]
    )

    instance_ids = [
        i['InstanceId']
        for r in response['Reservations']
        for i in r['Instances']
    ]

    if not instance_ids:
        print("対象インスタンスなし")
        return {'stopped': [], 'started': []}

    if action == 'stop':
        ec2.stop_instances(InstanceIds=instance_ids)
        print(f"停止対象: {instance_ids}")
    else:
        ec2.start_instances(InstanceIds=instance_ids)
        print(f"起動対象: {instance_ids}")

    return {action: instance_ids}

Step 3: EventBridge Scheduler でタイムゾーン指定のスケジュール設定

推奨: 従来の aws events put-rule ではcronがUTC固定でした。EventBridge Scheduler を使うとタイムゾーンを直接指定できます。

# 平日 18:00 JST に停止(タイムゾーン直接指定)
aws scheduler create-schedule \
  --name "ec2-auto-stop-weekdays" \
  --schedule-expression "cron(0 18 ? * MON-FRI *)" \
  --schedule-expression-timezone "Asia/Tokyo" \
  --flexible-time-window Mode=OFF \
  --target '{
    "Arn": "arn:aws:lambda:ap-northeast-1:123456789012:function:ec2-scheduler",
    "RoleArn": "arn:aws:iam::123456789012:role/EventBridgeSchedulerRole",
    "Input": "{\"action\": \"stop\"}"
  }'

# 平日 9:00 JST に起動
aws scheduler create-schedule \
  --name "ec2-auto-start-weekdays" \
  --schedule-expression "cron(0 9 ? * MON-FRI *)" \
  --schedule-expression-timezone "Asia/Tokyo" \
  --flexible-time-window Mode=OFF \
  --target '{
    "Arn": "arn:aws:lambda:ap-northeast-1:123456789012:function:ec2-scheduler",
    "RoleArn": "arn:aws:iam::123456789012:role/EventBridgeSchedulerRole",
    "Input": "{\"action\": \"start\"}"
  }'

Step 4: Savings Plans の購入判断

# 過去1ヶ月のEC2使用状況を確認(us-east-1 固定)
aws ce get-cost-and-usage \
  --time-period Start=2024-01-01,End=2024-02-01 \
  --granularity DAILY \
  --metrics UsageQuantity \
  --group-by Type=DIMENSION,Key=INSTANCE_TYPE \
  --output table \
  --region us-east-1

構成図

image.png


ハマりポイント

❌ RDSを止め忘れる

EC2を止めてもRDSが動いていると意外とコストがかかります。RDSも同様にスケジュール停止できます。

# RDS停止(手動)
aws rds stop-db-instance --db-instance-identifier dev-mysql

# RDS自動停止はLambdaで実装
import boto3
def stop_rds(instance_id):
    boto3.client('rds').stop_db_instance(DBInstanceIdentifier=instance_id)

注意: RDSは最大7日間しか停止状態を維持できません。7日経つと自動的に再起動します。

❌ Savings PlansとRIの違いを混同する

項目 リザーブドインスタンス(RI) Savings Plans
柔軟性 低(特定インスタンスタイプ・リージョン固定) 高(Compute SPはファミリー横断・リージョン問わず)
割引率 最大72%(全額前払い) 最大66%(Compute SP)
向き インスタンスタイプが固定の本番環境 変化しやすい環境・ECS Fargate・Lambda

❌ Lambdaのタイムアウトを短くしすぎる

対象インスタンスが多い場合、Lambda関数の実行時間が伸びます。デフォルト3秒では足りないため、タイムアウトを60〜300秒に設定しましょう。


まとめ

施策 対象 削減率(目安) 難易度
自動停止 開発・検証環境 〜73%
リサイジング 過剰スペック環境 〜50%
Savings Plans 本番環境 〜30〜66%

コスト削減は「どれか1つやれば終わり」ではなく、複数の施策を重ねることで大きな効果が出ます。 まずは「開発環境の自動停止」から始めるのが最も費用対効果が高くおすすめです。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?