티스토리 뷰

현재 회사에서는 스테이지용 EC2 인스턴스 8개, RDS 인스턴스 1개 총 9개가 있습니다.

 

인스턴스들이 24시간 가동되어 비용이 적지 않게 나오고 있는데 어떻게 하면 비용을 줄일 수 있을까 고민을 했습니다.

그래서 개발자들이 업무하는 시간대에만 가동하고 퇴근 후에는 중지해놓으면 비용을 절감할 수 있다고 생각했습니다.

하지만 매번 수동으로 하게되면  리소스가 상당히 소모될 수 있습니다.

 

AWS에서는 AWS Instance-Scheduler 라는 솔루션을 제안하는데 이 솔루션을 활용하면 EC2, RDS를 원하는 시간대에 시작 및 중지를 할 수 있게끔 해줍니다.

 

위 공식 문서에서는 Amazon CloudWatch, AWS CloudFormation, AWS DynomoDB, AWS Lambda 4개의 서비스를 이용하였지만 Amazon EventBridge, AWS Lambda로만 구성해두어도 쉽게 될 것 같아서 이 두 개를 이용해보려고 합니다.

 

시작 및 중지 전략

  • EC2 인스턴스를 매주 평일 오전7시에 시작 / 오후9시에 중지
  • RDS 인스턴스를 매주 평일 오전6시 40분에 시작 / 오후9시에 중지

 

EC2, RDS 인스턴스 생성하기

EC2와 RDS 인스턴스를 1개씩 생성합니다. EC2와 RDS의 식별이 되는 정보는 미노출 하였습니다.

 

 

IAM 역할 생성

AWS Lambda 함수를 생성할 때 기본적으로 CloudWatch Logs에 로그 메세지를 전송할 수 있는 권한이 있는 IAM 역할이 부여됩니다. 하지만 Lambda 함수가 EC2와 RDS에 대해 시작, 중지를 할 수 있어야함으로 두 정책도 추가로 넣어줍니다.

 

 

AWS Lambda 함수 생성

이제 Lambda 함수를 생성합니다. 런타임은 Node.js 18.x를 선택하고 기존 역할은 위에서 생성해둔 역할을 지정합니다.

 

 

Lambda 함수는 총 4개로 구성되어 있으며 EC2와 RDS를 각각 시작, 중지할 Lambda 함수입니다.

 

 

AWS Lambda 함수 코드 작성

Lambda 함수 > 코드 탭을 확인해보시면 index.mjs라는 파일이 있습니다.

여기에다 Lambda 함수가 실행할 코드를 작성 후 우측의 Deploy 버튼을 클릭하시면 Lambda 함수에 배포됩니다.

이제 Lambda 함수가 실행할 코드를 작성하겠습니다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// EC2 Start
import { createRequire } from 'module';
import { StartInstancesCommand } from '@aws-sdk/client-ec2'
const require = createRequire(import.meta.url);
const { EC2Client } = require('@aws-sdk/client-ec2');
 
export const handler = async(event=> {
    const client = new EC2Client({region: 'ap-northeast-2'});
    
    const instanceIds = {
        InstanceIds: [
            'i-00000000000000000'
        ]
    };
    
    try {
        const data = await client.send(new StartInstancesCommand(instanceIds));
        console.log(data);
        return {
            statusCode: 200,
            body: JSON.stringify({
                message: 'EC2 instance started successfully'
            })
        };
    } catch (error) {
        console.log(error);
        return {
            statusCode: 500,
            body: JSON.stringify({
                message: 'Error starting EC2 instance'
            })
        };
    }
};
 
// EC2 Stop
import { createRequire } from 'module';
import { StopInstancesCommand } from '@aws-sdk/client-ec2'
const require = createRequire(import.meta.url);
const { EC2Client } = require('@aws-sdk/client-ec2');
export const handler = async(event=> {
    const client = new EC2Client({region: 'ap-northeast-2'});
    
    const instanceIds = {
        InstanceIds: [
            'i-00000000000000000'
        ]
    };
    try {
        const data = await client.send(new StopInstancesCommand(instanceIds));
        console.log(data);
        return {
            statusCode: 200,
            body: JSON.stringify({
                message: 'EC2 instance stoped successfully'
            })
        };
    } catch (error) {
        console.log(error);
        return {
            statusCode: 500,
            body: JSON.stringify({
                message: 'Error stoping EC2 instance'
            })
        };
    }
};
cs

EC2 인스턴스를 시작하는 Lambda 함수와 중지하는 Lambda 함수에 코드를 작성해줍니다.

위 코드는 AWS re:Post AWS JavaScript EC2 SDK를 참고하였습니다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// RDS Start
import { createRequire } from 'module';
import { StartDBClusterCommand } from '@aws-sdk/client-rds'
const require = createRequire(import.meta.url);
const { RDSClient } = require('@aws-sdk/client-rds');
 
export const handler = async(event=> {
    const client = new RDSClient({region: 'ap-northeast-2'});
    
    const params = {
        DBClusterIdentifier: 'DB 식별자명'
    };
 
    try {
        const data = await client.send(new StartDBClusterCommand(params));
        console.log(data);
        return {
            statusCode: 200,
            body: JSON.stringify({
                message: 'RDS instance started successfully'
            })
        };
    } catch (error) {
        console.log(error);
        return {
            statusCode: 500,
            body: JSON.stringify({
                message: 'Error starting RDS instance'
            })
        };
    }
};
 
// RDS Stop
import { createRequire } from 'module';
import { StopDBClusterCommand } from '@aws-sdk/client-rds'
const require = createRequire(import.meta.url);
const { RDSClient } = require('@aws-sdk/client-rds');
 
export const handler = async(event=> {
    const client = new RDSClient({region: 'ap-northeast-2'});
    
    const params = {
        DBClusterIdentifier: 'DB 식별자명'
    };
 
    try {
        const data = await client.send(new StopDBClusterCommand(params));
        console.log(data);
        return {
            statusCode: 200,
            body: JSON.stringify({
                message: 'RDS instance stoped successfully'
            })
        };
    } catch (error) {
        console.log(error);
        return {
            statusCode: 500,
            body: JSON.stringify({
                message: 'Error stoping RDS instance'
            })
        };
    }
};
cs

RDS를 시작하는 Lambda 함수와 중지하는 Lambda 함수에도 코드를 작성해줍니다.

위 코드는 AWS JavaScript RDS SDK를 참고하였습니다.

 

 

Amazon EventBridge 규칙 생성

EC2 인스턴스를 매주 평일 오전7시에 시작하는 이벤트를 생성해둡니다. 규칙 유형은 일정을 선택합니다.

 

 

cron은 0 22 ? * 1-5 *  라고 입력합니다. Amazon EventBridge 규칙의 cron은 UTC 기준입니다.

그래서 cron을 입력할 때 UTC 기준으로 입력해주셔야 합니다. cron에 관한 내용은 여기를 참고바랍니다.

 

 

대상 선택을 Lambda 함수로 지정하고 함수는 위에서 생성한 ec2-start를 선택 후 규칙을 생성합니다.

 

 

 

1
2
3
4
5
ec2-start -> 0 22 ? * 1-5 *
ec2-stop  -> 0 12 ? * 2-6 *
 
rds-start -> 40 21 ? * 1-5 *
rds-stop  -> 0 12 ? * 2-6 *
cs

 

그리고 규칙을 추가로 3개 더 생성해야 합니다. EC2 중지, RDS 시작, RDS 중지 할 때도 필요하기 때문입니다. 

평일 오전 6시 40분에는 RDS 시작하게끔 하고 평일 오후 9시에는 EC2,  RDS 모두 중지하게끔 cron 식을 작성합니다.

 

 

위처럼 생성되었으면 모든작업은 완료되었습니다. 

 

이제 평일 오전 7시가 되면 Amazon EventBridge 규칙인 ec2-start 규칙이 트리거 되며 ec2-start라는 Lambda 함수가 호출됩니다. 나머지도 마찬가지로 정해진 시간에 정해진 규칙 및 Lambda 함수가 실행됩니다.

728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함