Journey to AWS
AWS 환경에서 인프라를 운영하다 보면 많은 비용이 발생하는 서비스들이 있습니다. 바로 CloudFront, RDS, EC2, Elasticache 등등이 해당됩니다. 이중에서도 EC2 비용은 서비스의 성장에 따라 인프라의 규모가 커지면서 기하급수적으로 늘어나곤 합니다. 이런 EC2 비용을 절약하기 위해서는 다양한 방법이 있습니다. 적정한 사양의 인스턴스를 선택하는 것은 당연한 것이고, RI를 구매하거나 Savings Plans를 구매하는 등의 방법이 있습니다. 하지만 스팟 인스턴스 도입을 통해서도 비용을 최적화할 수 있습니다. 특히 스팟 인스턴스는 Autoscaling Group과 (이하 ASG) 연동되어 ASG를 통해 인스턴스의 개수를 조절하는 서버군에도 도입할 수 있습니다. 오늘은 ASG와 연동해서 스팟 인스턴스를 사용하는 방법에 대해서 이야기해 보겠습니다.
ASG에 스팟 인스턴스를 도입하기 위해서는 Launch Configuration 이 아닌 Launch Template를 이용해야 합니다.
먼저 EC2 - Launch Template 메뉴에서 Create launch template를 클릭해서 새로운 Launch Template을 만들어 줍니다.
이름은 SpotInstanceTestTemplate으로 지정하고, AMI는 Amazon Linux 2 기본 이미지로, Instance type은 t3.medium, 마지막으로 Key pair는 생성되어 있는 키 페어 혹은 신규로 생성해서 지정합니다. 그리고 나머지는 기본값으로 두고 Launch Template을 생성합니다.
다음으로 EC2 - Auto Scaling groups 에서 새로운 ASG를 생성합니다. 이름은 SpotInstanceTestASG로, Launch Template에는 방금 우리가 만들어 준 SpotInstanceTestTemplate으로 지정합니다.
이다음 화면이 중요한데 여기서 스팟 인스턴스 도입과 관련된 설정을 할 수 있습니다. Instance purchase options를 Combine purchase options ans instance types로 설정합니다. ASG가 인스턴스를 생성할 때 온디멘드 인스턴스와 스팟 인스턴스를 어떤 비율로 생성할 것인지를 설정할 수 있게 됩니다. 우선 온디멘드 100%로 설정합니다.
그리고 밑으로 내려가면 인스턴스 타입도 설정할 수 있습니다. 우리가 Launch Template에서 설정한 인스턴스 타입은 t3.medium 입니다. 우선은 기본으로 설정된 값을 그대로 사용합니다. Additional instance types는 스팟 인스턴스를 도입할 때 Primary instance type에 지정한 인스턴스 사양이 스팟 인스턴스로 생성 불가할 경우 대체해서 사용할 수 있는 것들을 지정해 줍니다.
마지막으로 Network에서 서브넷 설정을 해줍니다.
우리는 ASG를 통해 스팟 인스턴스를 띄우려는 목적이기 때문에 나머지 설정들은 모두 기본 항목 그대로 두고 Skip to review 버튼을 클릭해서 넘어갑니다. 마지막 리뷰 후 생성 버튼을 클릭하면 아래와 같이 ASG가 생성됩니다. 기본 대수 1대를 맞추기 위해 인스턴스가 새롭게 생성됩니다.
그리고 EC2 인스턴스 페이지로 넘어가면 Lifecycle이 normal인 온디멘드 인스턴스가 1대 생성된 것을 볼 수 있습니다.
이제 ASG를 변경해서 스팟 인스턴스를 도입해 보겠습니다. 아까 생성한 SpotInstanceTestASG에서 아래와 같이 Purchase options ans instance types의 Edit를 클릭해서 수정하는 화면으로 넘어갑니다.
그리고 온디멘드 인스턴스와 스팟 인스턴스의 비율을 50:50으로 변경해 줍니다.
그럼 잠시 후 ASG가 lifecycle이 spot인 인스턴스 한 대를 생성합니다.
우리가 설정한 비율에 맞게 온디멘드 1대와 스팟 1대가 생성되었습니다. 이렇게 비율을 조절해서 ASG를 구성하고 있는 인스턴스 중 스팟 인스턴스 몇 대, 온디멘드 인스턴스 몇 대를 조절할 수 있습니다. 만약 10대의 인스턴스가 떴다면 위와 같은 경우에는 온디멘드 5대, 스팟 인스턴스 5대가 생성됩니다.
그리고 On-Demand base capacity는 최소한으로 유지해야 하는 온디멘드 서버의 대수를 의미합니다.
만약 평소에는 최소한 인스턴스가 3대 있어야 하고 그 외에 추가로 사용하는 인스턴스들은 모두 스팟 인스턴스를 사용하는 형태로 운영하고자 한다면 On-Demand base capacity를 3으로, 온디멘드 인스턴스와 스팟 인스턴스의 비율을 0:100 으로 설정하면 됩니다. 그럼 최소한 3대의 인스턴스는 온디멘드로 항시 유지되고 스팟 인스턴스는 죽었다 살았다를 반복하면서 유지되게 됩니다. 이렇게 서비스의 성격에 맞춰서 스팟 인스턴스를 활용해 가며 비용을 최적화하는 운영을 할 수 있습니다.
지금까지 ASG를 통해서 스팟 인스턴스를 도입하는 과정에 대해서 살펴봤습니다. 스팟 인스턴스를 사용하면 온디멘드 인스턴스를 사용하는 것보다 훨씬 더 많은 비용을 절약할 수 있습니다. 하지만 장점만 있을까요? 스팟 인스턴스를 사용하게 되면 치명적인 단점이 있습니다.
바로 언제든 인스턴스가 종료될 수 있다는 것입니다.
특히 API와 같이 클라이언트의 요청을 처리하는 역할을 하고 있는 인스턴스라면 갑작스러운 인스턴스의 종료가 에러를 발생시킬 수 있습니다. 그래서 이런 단점을 해결하기 위해 스팟 인스턴스 종료 핸들러를 만들어서 스팟 인스턴스가 종료될 때 Graceful 하게 종료될 수 있도록 구현해 줘야 합니다.
다행히도 EC2에서는 스팟 인스턴스가 종료되기 2분 전에 스팟 인스턴스가 종료될 것이라는 이벤트를 생성합니다. (https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/spot-interruptions.html)
그래서 이 이벤트를 받아서 스팟 인스턴스를 안전하게 종료시킬 수 있도록 TargetGroup에서 제외시키거나 SSM을 이용해서 서비스를 종료 시키거나 하는 등의 후처리 작업을 해주는 람다 함수를 만들어야 합니다.
serverless 프레임워크를 사용한다면 람다 함수에 아래와 같은 event 걸어 주면 됩니다.
스팟 인스턴스는 EC2 비용을 줄일 수 있는 좋은 선택지 중 하나입니다. 특히 갑작스러운 트래픽을 처리하기 위해 많은 수의 인스턴스가 필요할 때 많은 도움이 됩니다. 이벤트만 잘 넘기면 되는데 온디멘드 인스턴스를 사용하기에는 부담스럽고 일시적인 사용이기 때문에 RI나 Savings Plans를 통해 비용을 선지불 할 필요도 없기 때문입니다. 하지만 본문에 언급된 것처럼 스팟 인스턴스는 갑작스럽게 종료될 수 있기 때문에 종료 이벤트를 통한 핸들러만 잘 구현해 놓는다면 비용을 줄이는 데 많은 도움이 될 것입니다.
이번 글에서는 콘솔을 통해서 작업했는데 나중에 시간이 된다면 오픈소스 배포 도구 GoPloyer(https://goployer.dev/) 를 통해서 배포하고 스팟 인스턴스를 도입하는 과정에 대해서 다뤄 보겠습니다. 감사합니다.
ps. 클라우드를 사용하면서 피해 갈 수 없는 것이 비용일 것입니다. 그리고 비용을 최적화하기 위해 노력하는 FinOps라는 개념이 등장하고 있습니다. 최근 새롭게 만들어진 FinOps 커뮤니티에서 많은 분들과 좋은 정보를 나누고 이야기를 나누고 싶습니다. 많은 참여와 관심 부탁드립니다.
https://www.facebook.com/groups/finops.community1