EC2 Image Builder 도입기

Docker Image에서 CMI로

Younghoon Yun
KLleon
6 min readApr 13, 2023

--

안녕하세요. MLOps Infra파트입니다.

지금까지는 Minikube를 통해 CI/CD 파이프라인을 구축하는 방법에 대해서 다루었는데요. 이번 글에서는 실제로 Kubernetes로 서비스를 운영하면서 Docker Image를 Pull하는 것에 너무 오랜 시간이 소요되는 문제와 이를 해결하는 과정을 공유드리고자 합니다.

본 글은 AWS EKS와 Kubernetes에 대한 이해가 있다는 전제 하에 작성됩니다.

AWS의 EKS에는 Cluster AutoScaler(CA) 라는 기능이 존재하는데, CA가 배포된 클러스터에 Pending 상태인 Pod가 있을 때 해당 Pod가 할당될 수 있는 Node Group의 Node를 새로 생성하여 Pod가 Initialize될 수 있게 해주는 기능을 하고 해당 기능은 주로 Kubernetes의 AutoScaling 기능과 함께 사용되곤 합니다.

EKS 와 Kubernete HPA

저희 KLleon 또한 딥러닝 서비스 운영에 EKS-CA와 Kubernetes의 AutoScaling 을 적용하고 있는데요. 서비스가 Scale Out 됐을 때, 서비스가 실행될 때까지의 과정은 다음과 같습니다.

Pod 생성(Pending 상태)-> Cluster AutoScaler의 Node 생성 -> Pod 할당 -> Pod Init -> Container Create( Image Pull ) -> Pod Running

저희 딥러닝 서비스에 사용되고 있는 Docker Image는 크기가 20GB보다 클 정도로 큰 편에 속하는데요. 이로 인해 Scale Out 이후에 서비스가 실행될 때까지 소요되는 시간이 너무 길다는 문제를 겪고 있었습니다.

이를 해결하기 위해 저희가 첫 번째로 시도한 방법은 Image 경량화 였습니다.

전략 1 : Docker Image 경량화

기존에 사용하던 Docker Image는 pytorch:pytorch:*-devel 이미지를 기반으로 작성되어 경량화에 한계가 있었습니다. 따라서 기반 이미지의 변경이 필요하다고 판단하였고, 기존에 사용하던 pytorch 이미지의 layer를 분석하여 저희 서비스에 불필요한 레이어는 걷어내고 필요한 레이어만 남겨 약 40% 정도 경량화 시킬 수 있었습니다.

하지만 그럼에도 불구하고 아직 이미지는 10GB보다 컸고, 이미지 로드에 약 2분 가량의 시간이 소모되었습니다. 따라서 이미지 로드 시간을 줄이는 전략이 아닌 다른 전략을 탐색하게 되었습니다.
그 과정에서 눈에 들어온 것은 AWS의 CMI 기능이었습니다.

전략 2: AWS CMI

CMI는 Custom AMI(Amazon Machine Image) 의 약자로 사용자가 직접 정의한 AMI를 의미합니다. AWS에서 EC2 Instance들은 사전에 정의된 AMI를 기반으로 Init 되고, 사용한 AMI에 포함된 환경과 동일한 환경을 갖는 노드로서 존재하게 됩니다. Docker image가 특정 환경을 갖는 컨테이너를 파일화 한 것이었다면, AMI는 특정 환경을 갖는 머신(노드)를 파일화 한 것이라고 생각하시면 됩니다.

다시 처음으로 돌아가서 저희가 Docker 경량화를 해야했던 이유를 생각해보면 Scale Out이 될 때마다 이미지를 새로 로드해서 서비스가 실행이 되는 것에서 시간 소모와 비용 소모 때문이었습니다. 이미지의 크기에 얽매일 필요 없이 서비스가 빨리 뜰 수만 있으면 되는 상황이었던 것이죠. 이런 상황에 적합한 것이 위에서 말씀드린 CMI 였습니다.

기존에 EKS에서 사용되는 default AMI에 저희 서비스의 이미지를 포함시켜 CMI로 만들고, Scale Out되는 노드가 해당 CMI를 기반으로 init되게 함으로써 이미지 로드에 소모되는 시간을 0에 가깝에 줄일 수 있던 것이었습니다.

따라서 저희는 CMI를 사용하기로 결정하였고, CMI 빌드에 소모되는 코스트를 최소화 하고자 AWS의 EC2 Image Builder 구축을 진행하였습니다.

EC2 Image Builder

Image Builder는 사전에 정해놓은 AMI와 Setting, Script를 이용하여 CMI를 자동으로 빌드해주는 파이프라인 개념의 기능입니다.

해당 기능을 사용하지 않으면 직접 EC2노드를 생성하고 노드에 접속하여 Docker Image를 로드하고, 이 노드를 다시 이미지로 만드는 과정을 담당자가 직접 진행해야합니다. 어려운 작업은 아니지만, 번거롭고 시간이 다소 소요되는 작업입니다.

EC2 Image Builder

EKS에서 사용할 수 있는 CMI 기반 노드 그룹을 만들기 위해 신경써주셔야할 부분은 크게 두 가지가 있습니다. Recipe와 Launch Template의 User Data 입니다.

Recipe는 CMI를 빌드할 때, 빌드 이전에 노드에서 실행하고 싶은 커맨드를 기입할 수 있는 기능으로 Docker Image 로드가 사전에 필요한 경우 Docker Image로드 스크립트를 넣을 수 있습니다. 이외에도 자유롭게 스크립트를 작성하여 파이프라인에 포함시킬 수 있게 해줍니다.

Launch Template의 User Data는 EKS의 경우에만 해당하는데요. EKS의 경우에는 User Data에 해당 노드를 eks cluster에 포함시키기 위한 스크립트가 필수적으로 포함되어야 합니다. 포함에 필수적인 스크립트는 사전에 생성된 eks cluster의 default AMI의 User Data에서 확인하실 수 있으며, 저희가 사용하고 있는 Launch Template 또한 스크립트가 기입되어 있습니다.

두 부분만 상황에 맞게 작성된다면, 무리없이 서비스에 바로 적용할 수 있습니다.

마치며

이번 글에서는 저희 KLleon의 딥러닝 서비스 운영에 있어 아주 중요한 부분인 AutoScaling을 보다 효율적으로 작동하게 하기 위한 과도기를 다루었습니다. 스타트업 입장에서 중요한 클라우드 비용 또한 절감할 수 있게 해주고, 담당자가 이미지 빌드에 사용하는 시간을 줄여주는 기능이었던 것 같습니다. Scale Out에서 Image 로드 시간 때문에 고민이 있으신 분들이라면, 도입을 고려해보셔도 좋을 것 같습니다.

--

--