11
7

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 料金60%節約のアイデア

Posted at

背景

システムには Production・Staging・Dev の3つの環境があり、それぞれで EC2インスタンス が動作しています。特に Staging環境 は Production環境に近い仕様 となっています。

課題

Staging環境の利用者は EndUserではなく、主にProduct Owner です。そのため、SLAを99%まで維持する必要はなく、業務時間内に利用できれば問題ありません。

アイデア

Product Ownerの 勤務時間外 は、EC2を 停止(Stop)・休止(Hibernate) し、勤務時間に再起動します。停止・休止中は課金されない ため、大幅なコスト削減が可能です。

実施方法
EventBridge を使用し、EC2の Start・Stop処理を実行するLambda をスケジュール実行します。

定量的な効果

どれくらいコスト削減できるか試算してみます!

  • 1年間=365日= 52週間
  • 月から金曜日まで5日稼働したら、稼働日=52週x5日= 260日
  • 日本公休日(土日含まない): 約16日
  • 労働法律で1年間に最低有給を5日取らないといけない(計画有給): 5日 
  • 1日で稼働時間:~12時間= 0.5日 (*)

では、
→ 年間の稼働日数: (260日 - 16日 - 5日) × 0.5 = 約120日

→ 年間の非稼働日数: 365日 - 120日 = 245日

非稼働時間の割合: 245日 / 365日 ≈ 67%
約67%のコスト削減が可能!

「塵も積もれば山となる」ですね。 💰✨

実行

深く理解するために模擬案件を進めましょう。

構築図

Screenshot 2025-02-22 at 0.11.03.png

  • EventBridgeでlambdaトリガーのスケジュールを登録
    • イベントのペーロードを通じて
      • EC2起動
      • EC2停止
  • Lambdaでコードを行ってEC2を起動・停止
  • Tag役割はEC2起動・停止を管理すること
  • EventBridgeとラムダ料金がほぼ無料です!

下記に詳細ステップを説明します。

EC2用意

ConsoleでEC2サービスに入ってください。
image.png

新規作成

  • auto-start-stopというtagを作成
  • インスタンスを2台作成
  • 課金されないように、無料な仕様を使う
  • 残ってる設定をデフォルトにする
    image.png

結果チェック
image.png

Lambda用意

Lambdaサービスに入って、Nodejs Funtionをデフォルトに作成

image.png

コード

ソースコードを表示(折りたたみ)
import {
  EC2Client,
  DescribeInstancesCommand,
  StartInstancesCommand,
  StopInstancesCommand,
} from "@aws-sdk/client-ec2";


// EC2につけたタグ
const TAG_KEY = "auto-start-stop";
const TAG_VALUE = "true";
const REGION = "ap-northeast-1";

const ec2Client = new EC2Client({
  region: REGION,
});

export const handler = async (event) => {
  try { 
  // Schedule 設定する時、payloadで 起動・停止か決めます
   const action = event.action

   // タグでインスタントを絞り込みます
   const describeCommand = new DescribeInstancesCommand({
     Filters: [{ Name: `tag:${TAG_KEY}`, Values: [TAG_VALUE] }],
   });

   const instancesData = await ec2Client.send(describeCommand);

   // 見つけない場合
   if (
     !instancesData.Reservations ||
     instancesData.Reservations.length === 0
   ) {
     console.log("インスタンスが見つけません");
     return;
   }

   for (const reservation of instancesData.Reservations) {
     for (const instance of reservation.Instances) {
       const instanceId = instance.InstanceId;
       const instanceState = instance.State.Name;

       if (action === "stop" && instanceState === "running") {
         // Stop the instance
         const stopCommand = new StopInstancesCommand({
           InstanceIds: [instanceId],
         });
         await ec2Client.send(stopCommand);
         console.log(`「${instanceId}」とのEC2インスタンスが停止されました!`);
       } else if (action === "start" && instanceState === "stopped") {
         // Start the instance
         const startCommand = new StartInstancesCommand({
           InstanceIds: [instanceId],
         });
         await ec2Client.send(startCommand);
         console.log(`「${instanceId}」とのEC2インスタンスが起動されました`);
       } else {
         console.log(
           `飛ばします、だって「${instanceId}」とのECインスタンスは状態が 「${instanceState}」からです.`
         );
       }
     }
   }
 } catch (error) {
   console.error("エラーはこちら:", error);
 }
};

「デプロイ」を押下しないと反映されません。

模擬案件ですから、「デプロイを押下」までします。実際に、Lambda versionを使って下さい詳細はこちら

権限付与

EC2を操作するため、Lambdaのロールに必要な権限を付与しなといけません。

image.png

自動的に生成されたLambdaロールに入ります。

image.png

image.png

 ポリシを表示(折りたたみ)
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "Ec2StartStop", 
			"Effect": "Allow",
			"Action": [  
			    "ec2:DescribeInstances",
                "ec2:StartInstances",
                "ec2:StopInstances"
                ],
			"Resource": "*"
		}
	]
}

ポリシー名を自由に設定ください。
Screenshot 2025-02-22 at 0.39.54.png

テスト

lambdaに戻ってテストします。
image.png

JSONでstart・stop イベントを作成ください。

 停止テスト(折りたたみ)

stop_ec2

{
  "action": "stop"
}

image.png
EC2インスタンス一覧で確認
image.png

 起動テスト(折りたたみ)

start_ec2

{
  "action": "start"
}

image.png
image.png
image.png

EventBridge

EventBridgeサービスに入って下さい。

スケジュール作成

停止設定

image.png

新規スケジュールを作成

create schedule copy.jpg

image.png

いくつか注意ください

  • (2) 時間帯
  • (4) トリガータイミング。下に詳細タイミングも表示
  • 記事を書いているタイミングは2025年2月22日0時55分です、テストために15後で停止
  • 停止時間は2025年2月22日1時10分に設定

次に進めます

image.png

payloadでactionを設定
image.png

起動設定

上記のように起動スケジュールを作成します。
起動時間は2025年2月22日1時20分です。

留意
actionstart

image.png

結果

Screenshot 2025-02-22 at 1.01.44.png

流れ検証

CloudWatchで確認

Lambdaに戻って、該当ログを開きましょう。
image.png

Cloudwatchのログは即時に反映されないから、少々待って下さい。

結果

停止

時間帯はUTC+0ですから16時です。日本時間は16+9 = 25 -> 翌日1時

 エビデンス(折りたたみ)

時間:1時10分

CloudWatch group

image.png

image.png

EC2インスタンス一覧

image.png

起動
 エビデンス(折りたたみ)

時間:1時20分

CloudWatch group

image.png

EC2インスタンス一覧
image.png

請求チェック

効果を定量的にチェックするのは必要です。

AWS Billing -> Billに入って月額をチェックできます。
(私アカウントは1年間Free tierですから)

image.png

その他

EC2インスタンスを停止すると、再起動時にアプリを改めて立ち上げる必要があります。そのため、 プログラミング言語ごとに適切な起動スクリプトを用意することが必要です。

代替案は 休止(Hibernate)の活用です。 EC2インスタンスを 休止すれば、アプリは停止せず、動作状態を維持できます。 しかし、停止(Stop)に比べるとコスト削減効果は低くなります。

留意: 課金されないように、リソースを削除してください。

最後まで読んで頂いて有り難うございます。:bow:
役に立つを感じしたらハートやコメントやを残ってください:bow:

参考

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/ec2/
https://docs.aws.amazon.com/scheduler/latest/UserGuide/what-is-scheduler.html
https://aws.amazon.com/ec2/pricing/on-demand/
https://repost.aws/knowledge-center/ec2-billing-terminated
https://aws.amazon.com/eventbridge/pricing/
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Hibernate.html
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-ec2-instance-stop-start-works.html

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?