AWS 비용 최적화(1) : 요청 시 EC2 실행

김두현·2024년 12월 27일
1

AWS

목록 보기
2/3
post-thumbnail

📍개요


Java Spring + AWS 클라우드 환경에서 실서비스를 운영 중인데, 비용이 너무 많이 청구되어 감당할 수 없는 수준에 이르렀다.
더군다나 최근 비상식적으로 오른 달러 환율에 의해 더이상 눈감을 수 없어 최적화 작업을 진행하기로 했다.

✔️ 기존 주요 서비스

  • EC2(Linux) 4개
    • 개발 환경 t2.micro 2개
    • 운영 환경 t3.small 2개
  • VPC 중 IPv4 6개
    • 개발 환경 자동 할당 IP 2개
    • 개발 환경 Elastic IP 2개
    • 운영 환경 자동 할당 IP 2개
  • Elastic Load Balancing
    • for HTTPS

세 서비스 모두 시간 당 요금이 청구되는 방식이다.


✔️ 요구사항

팀 내 개발자는 5명으로, 개발 환경의 서버가 24시간 활성화 할 필요가 없다.

따라서 누군가가 요청을 보내면, EC2가 활성화되고 jar 파일이 자동 실행되게끔 구현하고자 한다.

즉, 이 작업은 AWS 서비스 중 가장 많은 금액이 청구되는 EC2의 활성화 시간을 줄이는 과정이다.
EC2가 중지되면 자동 할당되는 퍼블릭 IPv4또한 사라지기 때문에, 시간 당 금액이 청구되는 VPC와 EC2의 요금이 모두 감소한다.

추가로, Elastic IP는 오직 편의성만을 위한 것이므로 과감하게 삭제했다.

📍AWS 아키텍처


🔑 활용 서비스

  • AWS IAM
  • AWS Lambda
  • AWS API Gateway
  1. 사용자가 API Gateway에 요청을 보낸다.
  2. 해당 API Gateway가 트리거로 설정된 Lambda 함수(EC2 실행)가 실행된다.
  3. Lambda 함수가 실행되면 EC2가 부팅되고, jar 파일이 자동 실행된다.

1️⃣ AWS IAM 역할 생성


Lambda 함수가 EC2를 실행할 수 있도록 권한을 부여해야 하는데, 이를 위한 AWS IAM 역할을 생성했다.

1. 권한 정책 생성

우선 IAM 역할에 부여하기 위한 권한 정책을 생성했다.

IAM > 정책 > 정책 생성 > 정책 편집기 JSON으로 이동해 아래 코드를 삽입했으며,
Cloudwatch 쓰기 권한과 EC2 읽기, 쓰기 권한을 부여하는 내용이다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Start*",
        "ec2:Stop*"
      ],
      "Resource": "*"
    }
  ]
}

2. 역할 생성

IAM > 역할 > 역할 생성으로 이동해 아래와 같이 설정한 후, 앞서 생성한 권한 정책을 부여해 역할 생성을 마무리했다.

2️⃣ AWS Lambda 생성


이제 Lambda를 생성해야 한다.
Lambda > 함수 > 함수 생성으로 이동한 후, 아래와 같이 설정했다.

Python으로 작성할 것이므로 런타임을 Python3으로 설정하고, 기본 실행 역할을 앞서 생성한 IAM 역할로 설정했다.

3️⃣ EC2 활성화 코드 구현


Lambda를 생성했으므로, 이제 함수를 구현할 차례다.
Python의 boto3 라이브러리를 활용하면 아주 간단하게 EC2를 시작할 수 있다.

사진의 코드 소스 영역에 코드를 아래와 같이 작성했다.

import boto3
region = 'ap-northeast-2'
# 활성화 할 EC2의 인스턴스 ID
instances = ['i-xxxxxxxxxxx']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.start_instances(InstanceIds=instances)

이후 코드 소스 왼쪽의 Deploy를 클릭하면 Lambda에 소스코드가 적용된다.

참고로 사진의 API Gateway는 캡쳐 시점이 다른 것이기 때문에, 현재 단계에서는 없는게 정상이다.

4️⃣ AWS API Gateway 생성


이제 Lambda 함수를 실행시킬 트리거인 API Gateway를 생성할 차례다.
API Gateway는 API를 손쉽게 생성 및 배포하기 위한 서비스로 Lambda를 포함해 다양한 AWS 서비스와 통합이 가능하다.

API Gateway > API 생성으로 이동 후 필자는 REST API를 선택했는데, 본 포스팅에서는 다루지 않았지만 추후 API 응답 양식을 편하게 제어하기 위함이었다. 물론 HTTP API로도 손쉽게 가능하다.

API가 생성되었다면, 해당 리소스에 들어가 메서드 생성을 하면 된다.

통합 유형으로 Lambda 함수를 선택한 후, 아래에서 앞서 구현한 Lambda 함수를 연결했다.

필자는 개발 환경에 EC2를 두 개 운영 중이므로, 아래와 같이 리소스를 두 개 생성하여 두 개의 Lambda와 연결했다.

5️⃣ AWS Lambda 트리거 설정


이제 앞서 생성한 API Gateway를 Lambda와 연결만 하면 AWS 설정은 끝이다.

Lambda 함수에 들어가 함수 개요 > 트리거 설정으로 들어간 뒤, 앞서 생성한 API Gateway 정보로 설정했다.

트리거가 잘 연결되었다면, Lambda 함수 > 구성에서 아래와 같이 생성된 API 엔드포인트를 확인할 수 있다.

이제 이 엔드포인트에 접속하면, Lambda 함수가 실행되어 EC2가 활성화된다!

6️⃣ JAR 파일 자동 실행 설정


이제 AWS 설정은 끝이 났고, EC2에 접속해 부팅 시 jar 파일이 실행되도록 설정할 것이다.

이를 위해 EC2에 접속한 후, Linux가 실행할 스크립트 파일을 생성했다.

sudo nano /etc/systemd/system/module-user.service

스크립트 파일은 아래와 같이 작성했다. jar 파일의 경로에 유의해야 한다.
yml에 정의한 환경변수는 Environment 키워드를 통해 작성하면 된다.

[Unit]
Description=Module User JAR Service
# 네트워크 설정을 마치면 실행
After=network.target

[Service]
# jar 파일 실행
ExecStart=/bin/bash -c "exec java -jar /home/ubuntu/module-user-0.0.1-SNAPSHOT.jar"
Restart=on-failure
RestartSec=5

# 환경변수 설정
Environment=profile=dev
# ... 기타 환경변수


[Install]
WantedBy=multi-user.target

이렇게 스크립트 파일을 마쳤다면, 이제 아래 명령을 거쳐 EC2가 부팅되면 해당 스크립트 파일을 실행하도록 설정하면 전부 끝이다.

# 파일 권한 설정
sudo chmod 755 /etc/systemd/system/module-user.service

# 서버 재시작
sudo systemctl daemon-reload

# 파일 실행
sudo systemctl start module-user.service

#### EC2 부팅 시 자동 실행 (핵심!!!) ####
sudo systemctl enable module-user.service

# 서비스 상태 확인
sudo systemctl status module-user.service

결과적으로, EC2를 재부팅하면 jar 또한 실행되어 API 요청이 정상적으로 되는 것을 확인했다.⛳️

👏 마무리


위 과정을 통해 개발 시에만 EC2를 활성화하여 IPv4 무효화 시간은 물론 EC2의 활성 시간을 줄여 비용을 대폭 절감할 수 있게 되었다.

그러나, 아직 한 가지 과정이 더 남았다.
현재 구조에서는 개발이 끝나고 EC2를 끄는 것을 깜빡하면, 결국 다시 영원히 EC2가 활성화되어 비용이 청구된다.

즉, 사용하지 않는 상태를 모니터링하여 EC2가 종료되는 기능이 필요하다.
다음 포스팅에서는 다른 형태의 트리거를 통해 EC2 자동 종료 기능을 구현해보자.

참고 자료

API Gateway + Lambda로 AWS EC2 실행
EC2 활성화 시 jar 자동 실행


💕오류 지적 및 피드백은 언제든 환영입니다. 복제시 출처 남겨주세요!💕
💕좋아요와 댓글은 큰 힘이 됩니다.💕
profile
I AM WHO I AM

0개의 댓글

관련 채용 정보