TL;DR
- ทำให้ EC2 instances ของ AWS เริ่มและหยุดทำงานอัตโนมัติเพื่อประหยัดค่าใช้จ่าย
- สามารถประหยัดค่าใช้จ่ายได้สูงสุดถึง 71% ในสภาพแวดล้อมการพัฒนาและการทดสอบ
- ใช้ AWS Lambda ในการจัดการ instance และ AWS EventBridge สำหรับการกำหนดเวลา
- คู่มือนี้จะนำเสนอขั้นตอนในการปรับใช้ EC2 instance และการตั้งค่า Lambda functions ผ่าน CloudFormation
กฎเกณฑ์การคิดค่าใช้จ่ายของ AWS EC2
AWS จะไม่เรียกเก็บค่าใช้จ่ายเมื่อ EC2 instance ถูกหยุดใช้งาน ดังนั้นคุณสามารถหยุดทรัพยากร EC2 ได้เมื่อไม่มีการใช้งาน โดยทั่วไปแล้วทรัพยากรในการพัฒนาและการทดสอบไม่จำเป็นต้องทำงานตลอด 24 ชั่วโมงทุกวัน หากคุณปรับใช้การเริ่มและหยุดในช่วงเวลาทำงาน จะช่วยประหยัดค่าใช้จ่ายได้มากทีเดียว ลองมาดูตารางเปรียบเทียบต้นทุนในแต่ละสถานการณ์การใช้งาน EC2 instance t2.micro ที่มีการกำหนดการเริ่ม/หยุดทำงานโดยอัตโนมัติกับการทำงานอย่างต่อเนื่องตลอด 24 ชั่วโมง/7 วันกันดู
Cost Component | Instance Running 24/7 | Automated Start/Stop Configuration |
---|---|---|
EC2 Hourly Rate | $0.0116/hour | $0.0116/hour |
Total Running Hours per Month | 720 hours | 160 hours |
Monthly Cost for EC2 Instance | $8.352 | $1.856 |
EBS Volume Size | 8 GiB | 8 GiB |
EBS Monthly Cost | $0.80 | $0.80 |
Total Monthly Cost | $9.152 | $2.656 |
Savings Amount | - | $6.496 |
Percentage Savings | - | 71% |
ตอนนี้คุณสามารถประหยัดค่าใช้จ่ายได้ประมาณ 70% สำหรับสภาพแวดล้อมการพัฒนาและการทดสอบของคุณ
เลือก AWS Services เพื่อใช้ส่งคำสั่งเปิดปิด EC2 อัตโนมัติ
ผมเลือกใช้บริการเหล่านี้จาก AWS เพื่อให้การทำงานเป็นไปอย่างมีประสิทธิภาพ
- AWS Lambda เพื่อใช้ AWS-SDK ในการควบคุมการเริ่มและหยุด EC2 instances
- AWS EventBridge สำหรับการกำหนดเวลาที่จะเรียกใช้ Lambda Functions
การนำบริการเหล่านี้มาใช้จะช่วยให้การจัดการ EC2 instances ของคุณเป็นเรื่องง่ายและลดค่าใช้จ่ายลงได้อย่างมีนัยสำคัญ
มาเริ่มกันเลย
ติดตั้ง EC2 ด้วย AWS CloudFormation
ก่อนอื่นเราจะสร้าง EC2 instance โดยใช้ประเภท t2.micro เพื่อสาธิต ผมจะสร้าง instance ใน AWS Thai Region
AWSTemplateFormatVersion: '2010-09-09'
Description: EC2 instance with auto start/stop during business hours
Parameters:
InstanceType:
Type: String
Default: t2.micro
Description: EC2 instance type
KeyName:
Type: String
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance.
Resources:
# EC2 Instance
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
ImageId: ami-0c55b159cbfafe1f0
KeyName: !Ref KeyName
IamInstanceProfile: !Ref EC2InstanceProfile
Outputs:
InstanceId:
Description: The Instance ID of the EC2 instance.
Value: !Ref MyEC2Instance
รัน CloudFormation CLI เพื่อติดตั้ง จากนั้นคุณจะเห็น EC2 ที่สร้างขึ้นใน AWS Management Console
ตั้งค่า Lambda ฟังก์ชันสำหรับเริ่ม/หยุด EC2
เราสามารถใช้ AWS-SDK กับ AWS Lambda เพื่อเริ่ม/หยุด EC2 จากคอนโซลได้ ผมตัดสินใจใช้ NodeJS ก่อนอื่นเราจะสร้างโฟลเดอร์ชื่อว่า lambda_functions
และรัน npm init
จากนั้นสร้างไฟล์ 2 ไฟล์สำหรับแต่ละฟังก์ชันเริ่ม/หยุด
📁lambda_functions
└── package.json
└── startInstance.js
└── stopInstance.js
เริ่มจาก package.json
{
"name": "dev-ec2-start-stop-lambda-function",
"version": "1.0.0",
"type": "module",
"dependencies": {
"@aws-sdk/client-ec2": "^3.0.0"
}
}
และ startInstance.js
import { EC2Client, StartInstancesCommand } from '@aws-sdk/client-ec2';
const ec2Client = new EC2Client({ region: 'ap-southeast-7' });
export const handler = async (event) => {
const command = new StartInstancesCommand({ InstanceIds: [event.instance_id] });
await ec2Client.send(command);
return `Started your instance: ${event.instance_id}`;
};
และ stopInstance.js
import { EC2Client, StopInstancesCommand } from '@aws-sdk/client-ec2';
const ec2Client = new EC2Client({ region: 'ap-southeast-7' });
export const handler = async (event) => {
const command = new StopInstancesCommand({ InstanceIds: [event.instance_id] });
await ec2Client.send(command);
return `Stopped your instance: ${event.instance_id}`;
};
จากนั้นบีบอัดโฟลเดอร์และอัปโหลดไปยัง S3 Bucket เราจะใช้มันใน CloudFormation Template ถัดไป
ตั้งค่า Event Bridge ด้วย CloudFormation
ตอนนี้เราจะปรับเปลี่ยน CloudFormation template ของเราเพื่อเพิ่ม EventBridge ที่จะเรียกใช้ฟังก์ชัน Lambda เพื่อเริ่ม/หยุดภายในช่วงเวลาทำงาน
AWSTemplateFormatVersion: '2010-09-09'
Description: EC2 instance with auto start/stop during business hours in Thailand timezone
Parameters:
InstanceType:
Type: String
Default: t4g.nano
Description: EC2 instance type
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: Name of an existing EC2 KeyPair to enable SSH access to the instance.
S3Bucket:
Type: String
Description: S3 bucket where Lambda code is stored
S3Key:
Type: String
Description: S3 key for the Lambda code zip file
Resources:
DevEC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
ImageId: ami-08f3e969e66cd963a
KeyName: !Ref KeyName
DevSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 0.0.0.0/0
LambdaStartFunction:
Type: AWS::Lambda::Function
Properties:
Handler: './lambda_functions/startInstance.handler'
Role: !GetAtt LambdaExecutionRole.Arn
Code:
S3Bucket: !Ref S3Bucket
S3Key: !Ref S3Key
Runtime: nodejs18.x
Timeout: 30
LambdaStopFunction:
Type: AWS::Lambda::Function
Properties:
Handler: './lambda_functions/stopInstance.handler'
Role: !GetAtt LambdaExecutionRole.Arn
Code:
S3Bucket: !Ref S3Bucket
S3Key: !Ref S3Key
Runtime: nodejs18.x
Timeout: 30
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: EC2StartStopPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ec2:StartInstances
- ec2:StopInstances
Resource: '*'
StartInstanceRule:
Type: AWS::Events::Rule
Properties:
ScheduleExpression: 'cron(0 1 * * ? *)' # 08:00 UTC (Thailand Time)
Targets:
- Arn: !GetAtt LambdaStartFunction.Arn
Id: "StartEC2Instance"
Input: !Sub '{"instance_id": "${DevEC2Instance}"}'
StopInstanceRule:
Type: AWS::Events::Rule
Properties:
ScheduleExpression: 'cron(0 11 * * ? *)' # 18:00 UTC (Thailand Time)
Targets:
- Arn: !GetAtt LambdaStopFunction.Arn
Id: "StopEC2Instance"
Input: !Sub '{"instance_id": "${DevEC2Instance}"}'
EventRulePermissionStart:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref LambdaStartFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt StartInstanceRule.Arn
EventRulePermissionStop:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref LambdaStopFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt StopInstanceRule.Arn
Outputs:
InstanceId:
Description: "Instance ID of the newly created EC2 instance"
Value: !Ref DevEC2Instance
สรุป
หลังจากที่เราใช้ CloudFormation Template แล้ว EC2 Instance ของเราจะเริ่ม/หยุดอัตโนมัติในช่วงเวลาทำงานที่เรากำหนดใน Amazon EventBridge ซึ่งสามารถช่วยประหยัดค่าใช้จ่ายได้ประมาณ 70% สำหรับทรัพยากรที่ไม่จำเป็นต้องทำงานตลอด 24 ชั่วโมง 7 วัน เช่นเครื่อง Dev/Staging