AWS 기술 블로그

Amazon ECS와 Amazon SageMaker를 이용하여 이미지 분류 AI 웹 애플리케이션 구축과 운영하기

마이크로서비스 아키텍처(MSA)와 인공지능(AI)은 현대화 애플리케이션 구현에 가장 많이 언급되는 기술입니다. 애플리케이션은 규모가 커질 수록 하나의 모놀리식 서비스가 아닌 다양한 마이크로서비스의 조합이 필요합니다. 그리고 사용자에게 추세나 패턴을 식별할 수 있는 인공지능 기능을 제공하기 위해서는 학습된 기계 학습 모델이 필요합니다. 이렇게 마이크로서비스 아키텍처와 기계 학습 모델로 구성된 애플리케이션은 고객의 요구에 따라서 확장하고 민첩하게 업데이트 되어야 합니다.

이번 글에서는 Amazon ECS와 Amazon SageMaker를 이용해서 AI 웹 애플리케이션을 마이크로서비스 아키텍처(MSA)로 구축하는 방법을 소개합니다. 이를 통해서 컨테이너 기반 마이크로서비스 아키텍처를 구성하는 방법을 배우고 트래픽 수요에 따른 인프라 관리와 운영을 자동화할 수 있습니다. 그리고 기계 학습 모델을 학습하고 배포하는 방법을 통해서 이미지 분류를 위한 AI 기능을 제공하는 방법을 배울 수 있습니다. 여기에 더해서 AWS CodePipeline과 Amazon SageMaker Pipelines를 이용해서 CI/CD 구축 방법을 기술합니다. 이를 통해서 코드를 컨테이너로 빌드 및 배포하는 파이프라인을 구성하는 방법과 기계 학습 모델을 학습하고 배포하는 파이프라인을 구성하는 방법을 배울 수 있습니다.

전체 과정을 통해서 엔지니어는 인공지능 기능을 제공하는 웹 애플리케이션을 쉽고 빠르게 개발하고 소프트웨어의 품질 개선과 출시 주기를 단축하여 운영의 효율성을 가져오는 아키텍처를 구성할 수 있습니다.

AI 웹 애플리케이션과 운영을 위한 아키텍처

AI 웹 애플리케이션을 구성하는 아키텍처를 살펴보도록 하겠습니다.

AI 웹 애플리케이션은 두 개의 마이크로서비스(Web Service,  WAS Service)로 구성된 애플리케이션 부분과 기계 학습 모델을 통해 이미지 분류 기능을 제공하는 기계 학습 부분으로 구성되어 있습니다. 그리고 애플리케이션을 구성하는 코드를 관리 및 빌드하고 배포하는 애플리케이션 CI/CD 부분과 기계 학습 모델을 학습하고 배포하는 기계 학습 CI/CD 부분으로 구성되어 있습니다.

Amazon ECS와 Amazon SageMaker를 이용한 AI 웹 애플리케이션

Amazon ECS는 AWS Fargate를 사용해서 Web Service와 WAS(Web Application Server) Service로 구성된 애플리케이션을 운영합니다. Amazon SageMaker는 모델을 학습하고 학습된 모델을 Amazon SageMaker Endpoint를 통해서 API 형태로 WAS에 제공합니다. NAT gateway는 네트워크 주소 변환 서비스로 Private Subnet 에 위치한 WAS Service 가 외부의 서비스와 연결이 필요한 경우 사용됩니다.

사용자가 AI 웹 애플리케이션을 이용할 때 각 서비스가 호출되는 순서는 다음과 같습니다.

  • 단계1: 사용자가 애플리케이션 접속을 요청하면 Internet Gateway를 통과한 트래픽은 Web Service 앞에 있는 ALB로 트래픽을 전송합니다.
  • 단계2: ALB 는 트래픽을 분산해서 Web Service에 배포된 컨테이너 중 하나로 전송하고 컨테이너는 애플리케이션을 제공합니다.
  • 단계3: 이미지 분류와 같은 비즈니스 로직이 필요한 경우 Web Service의 컨테이너는 WAS Service 앞에 위치한 ALB로 트래픽을 전송합니다.
  • 단계4: ALB는 트래픽을 분산해서 WAS Service에 배포된 컨테이너 중 하나로 전송하고 컨테이너는 비즈니스 로직을 수행합니다.
  • 단계5: 이미지 분류가 필요한 경우 WAS Service의 컨테이너는 기계 학습 모델이 배포된 Amazon SageMaker Endpoint를 호출하고 분석 결과를 제공합니다.

AWS CodePipeline를 이용한 애플리케이션 CI/CD 구성

코드의 통합과 배포를 자동화할 수 있는 CI/CD 서비스를 제공합니다. 애플리케이션 개발자는 AWS CodePipeline를 통해서 빠르고 안정적으로 애플리케이션을 빌드하고 Amazon ECS로 구성된 인프라에 배포하는 과정을 자동화할 수 있습니다.

애플리케이션 CI/CD 파이프라인이 호출되는 순서는 다음과 같습니다.

  • 단계1: AWS CodeCommit을 통해서 개발 중인 코드를 업로드하고 관리합니다.
  • 단계2: AWS CodeBuild를 통해서 관리 중인 코드를 컨테이너 이미지로 빌드합니다.
  • 단계3: AWS CodeDeploy를 통해서 ECS 환경에 배포합니다.

Amazon SageMaker Pipelines를 이용한 기계 학습 CI/CD 구성

기계 학습 Model을 학습하고 배포할 수 있는 CI/CD 서비스를 제공합니다. 모델 엔지니어는 AWS SageMaker Pipelines을 통해서 학습과 배포를 자동화하고 워크플로를 시각화하고 관리할 수 있습니다.

기계 학습 CI/CD 파이프라인이 호출되는 순서는 다음과 같습니다.

  • 단계1: 학습 단계로 Amazon S3에서 학습 데이터를 다운로드하고 모델을 학습합니다. 학습이 완료된 모델은 Amazon S3에 저장됩니다.
  • 단계2: 모델 등록 단계로 Amazon S3에 저장된 모델을 Amazon SageMaker Models에 등록합니다.
  • 단계3: 배포 단계로 등록한 모델을 Amazon SageMaker Endpoint에 배포해서 API를 제공합니다.

구현 단계 요약

VPC, Amazon ECS, AWS Fargate를 이용한 인프라 구성

‘VPC 생성’, ‘Amazon ECS 클러스터 구성’, ’AWS Fargate 기반 Web Service 구성’ 그리고 ‘AWS Fargate 기반 WAS Service 구성’ 단계를 CDK 를 사용하여 구성할 수 있습니다. 자세한 내용은 CDK를 이용한 인프라 설치를 참고하세요.

VPC 생성

AWS가 전 세계에서 데이터 센터를 클러스터링하는 물리적 위치를 리전이라고 합니다. 각 리전은 가용 영역(Availability Zone)이라고 알려진 격리된 위치를 여러 개 가지고 있는데 한 가용 영역에서 장애가 발생하더라도 다른 가용 영역에서 서비스를 운영할 수 있도록 2개의 가용 영역으로 구성합니다. 자세한 내용은 샘플 프로젝트의 [VPC 생성] 을 참고하세요.

Amazon ECS 클러스터 구성

가용성을 위해서 2개의 Available Zone의 Private Subnet을 모두 사용합니다. 그리고 Infrastructure로는 AWS Fargate를 사용해서 구성합니다. 자세한 내용은 샘플 프로젝트의 [Amazon ECS 클러스터 구성] 을 참고하세요.

AWS Fargate 기반 Web Service 구성

AWS Fargate 기반 Web Service를 구성하기 위해서 몇 가지 단계를 진행합니다. Docker로 빌드한 Sample Web Application 프로젝트 이미지를 Amazon ECR에 등록하여 AWS ECS Service 에 배포할 준비를 합니다. 다음으로 Internet Gateway를 통해 들어오는 트래픽을 허용하기 위해서 로드 밸런서를 위한 Security Group을 생성합니다. 로드 밸런서를 생성하고 앞서 생성한 Security Group을 적용합니다. 그리고 로드 밸런서를 통해 들어오는 트래픽을 허용하기 위해서 Web Service를 위한 Security Group을 생성합니다. 마지막으로 Web Service 구성을 위한 태스크 정의를 하고 Web Service를 생성합니다. 앞서 생성한 Security Group을 적용합니다. 전체 과정을 완료하면 Web Service에 접속하여 확인할 수 있습니다. 자세한 내용은 샘플 프로젝트의 [AWS Fargate 기반 Web Service 구성] 을 참고하세요.

AWS Fargate 기반 WAS Service 구성

AWS Fargate 기반 Web Service 구성과 동일한 흐름으로 진행되지만, 다른 부분이 있습니다. WAS Service는 이미지 분류를 위해서 Amazon SageMaker Endpoint를 호출합니다. 이를 위해서 Task Role에 권한을 등록하고 AWS SDK인 boto3를 사용해서 자격증명(Credentials)을 확인하고 호출합니다. 전체 과정에 대한 자세한 내용은 샘플 프로젝트의 [AWS Fargate 기반 WAS Service 구성] 을 참고하세요.

WAS Service를 구성할 때 중요한 두 가지를 살펴보겠습니다.

Amazon SageMaker Endpoint 호출 권한

Amazon SageMaker Endpoint 호출을 위해서 역할을 생성하고 sagemaker:InvokeEndpoint API 사용을 허용합니다. 태스크 정의를 진행할 때 생성한 역할을 등록합니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sagemaker:InvokeEndpoint",
            "Resource": "*"
        }
    ]
}

Amazon SageMaker Endpoint 호출 코드

AWS SDK인 boto3를 이용해서 Amazon SageMaker Endpoint를 호출합니다. 샘플 코드는 다음과 같으며 샘플 프로젝트의 main.py에서 확인할 수 있습니다.

client = boto3.client("sagemaker-runtime")
endpoint_name = 'image-classifier'
response = client.invoke_endpoint(
    EndpointName=endpoint_name,
    Body=body,
    ContentType='application/json',
    Accept='Accept'
)

AWS CodePipeline을 이용한 CI/CD 구성

AWS CodeCommit 레파지토리를 생성하고 Web 과 WAS 프로젝트 코드를 각각 업로드합니다. 그리고 AWS CodePipeline으로 CI/CD를 구성을 시작합니다. 프로젝트 코드를 가져오기 위해서 Source provider에 생성한 레파지토리를 연결합니다. 빌드를 위해서 Buildspec을 작성해서 등록하고, 배포를 위해서 Deploy provider로 Amazon ECS를 선택합니다. Web과 WAS를 위한 Pipeline을 각각 구성합니다. 자세한 내용은 샘플 프로젝트의 [AWS CodePipeline을 이용한 CI/CD 구성] 을 참고하세요.

AWS CodeBuild 단계를 구성할 때 필요한 BuildSpec에 대해서 알아보겠습니다.

BuildSpec 구성

Buildspec을 구성해서 AWS CodeCommit 레파지토리에서 다운 받은 코드를 도커로 빌드하고 ECR 에 업로드하는 과정을 작성합니다. 작성된 파일은 AWS CodePipieline 에서 빌드하는 단계에서 사용됩니다.

version: 0.2

phases:
  pre_build:
    commands:
      - ECR_URI=933988069619.dkr.ecr.us-west-2.amazonaws.com/app-web
      - IMAGE_TAG=latest
      - echo Logging in to Amazon ECR...
      - aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin $ECR_URI
  build:
    commands:
      - echo Building the Docker image...
      - docker build -t app-web .
      - docker tag app-web:latest $ECR_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Pushing the Docker image...
      - docker push $ECR_URI:latest
      - printf '[{"name":"app-web","imageUri":"%s"}]' $ECR_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
    files: imagedefinitions.json

Amazon SageMaker Studio 생성

웹 기반 통합 개발 환경(IDE)인 Amazon SageMaker Studio를 생성해서 기계 학습 모델을 학습하고 배포하는 환경을 구성하는 데 사용합니다. Amazon SageMaker 콘솔에서 도메인 생성하면 Amazon SageMaker Studio에 접속할 수 있습니다. 자세한 내용은 샘플 프로젝트의  [Amazon SageMaker Studio 생성] 을 참고하세요.

Amazon SageMaker Pipelines을 이용한 모델 학습 및 배포 자동화

Amazon SageMaker Studio에서 모델을 학습, 등록 그리고 배포하는 파이프라인을 구성합니다. 배포된 모델은 엔드포인트를 제공하며 WAS 서버에서 호출할 수 있습니다. 자세한 내용은 샘플 프로젝트의 [Amazon SageMaker Pipelines을 이용한 모델 학습 및 배포 자동화] 을 참고하세요.

학습 단계 준비

Amazon SageMaker는 학습 데이터 저장소로 Amazon Elastic File System(Amazon EFS), Amazon FSx for Lustre 그리고 Amazon S3를 사용할 수 있습니다. 이번 글에서는 학습 데이터를 Amazon S3에서 다운로드해서 사용합니다. 그렇기 때문에 학습에 필요한 데이터를 Amazon S3에 업로드해 놓아야 합니다. Amazon S3에 버킷을 생성하고 학습에 사용할 flowers를 다운받아서 업로드합니다.

학습 코드 준비

Amazon SageMaker Studio에 학습 단계에 필요한 코드를 업로드합니다. train.py 파일에는 학습 데이터 로드, 모델 생성, 모델 학습 그리고 학습한 모델을 저장하는 코드가 있습니다. Amazon SageMaker는 학습을 시작하기 전에 S3에 있는 학습 데이터를 지정된 경로에 다운받기 때문에 코드에서 불러와서 사용할 수 있습니다. 그리고 Amazon SageMaker가 지정한 특정 경로에 학습이 완료된 모델을 저장하면 자동으로 S3에 업로드됩니다. 다음 코드는 모델을 생성하는 함수로 이미지 추론을 위해서 MobileNetV2 모델을 생성합니다.

def build_model(dropout=0.2, category_num=3):
    print(" --- BUILD MODEL --- ")
    mobile_net_layers = tf.keras.applications.MobileNetV2(include_top=False,
                                                          weights='imagenet',
                                                          pooling='avg',
                                                          input_shape=(224, 224, 3))
    mobile_net_layers.trainable = False
    model = tf.keras.Sequential([
        mobile_net_layers,
        tf.keras.layers.Dropout(dropout),
        tf.keras.layers.Dense(category_num, activation='softmax')
    ])
    model.summary()
    return model

생성된 모델과 학습 데이터를 이용해서 모델을 학습하는 코드입니다.

def train_model(model, x, y, learning_rate=0.0001, batch_size=32, epochs=50):
    print(" --- TRAIN MODEL --- ")
    adam = tf.keras.optimizers.Adam(learning_rate=learning_rate)
    model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
    history = model.fit(x, y,
                        shuffle=True,
                        batch_size=batch_size,
                        epochs=epochs,
                        validation_split=0.2)
    return history

마지막으로 학습이 완료된 모델을 특정 경로에 저장하는 코드입니다.

def store(model, model_path="/opt/ml/model"):
    print(" --- STORE --- ")
    print(model_path)
    
    # Store Keras
    model.save(model_path + "/1")

파이프라인 코드 생성

파이프라인은 노트북에서 코드로 구성할 수 있습니다. 노트북에서 앞서 올린 train.py을 이용해서 학습 단계를 생성하는 코드를 작성합니다.

From sagemaker.inputs import TrainingInput
from sagemaker.workflow.steps import TrainingStep
from sagemaker.workflow.properties import Properties

# estimator
tf_estimator=TensorFlow(
    source_dir='src',
    entry_point='train.py',

--- 생략 ---

step_train = TrainingStep(
    name="Train",
    estimator=tf_estimator,
    inputs={
        "train": TrainingInput(
            # s3_data=train_data.default_value,
            s3_data=train_data.to_string(),
            content_type="image/*"
        ),
        "test": TrainingInput(
            # s3_data=test_data.default_value,
            s3_data=test_data.to_string(),
            content_type="image/*"
        )
    },
)

모델을 배포하기 위해서 학습이 완료된 모델을 등록하는 단계를 코드로 작성합니다.

from sagemaker.model import Model
from sagemaker.inputs import CreateModelInput
from sagemaker.workflow.steps import CreateModelStep

model = Model(
    image_uri="763104351884.dkr.ecr.ap-northeast-2.amazonaws.com/tensorflow-inference:2.11.0-cpu", 
    model_data=step_train.properties.ModelArtifacts.S3ModelArtifacts,
    sagemaker_session=sagemaker_session,
    predictor_cls=sagemaker.predictor.RealTimePredictor,
    role=role
)

inputs = CreateModelInput(
    instance_type="ml.m5.large",
)

step_create_model = CreateModelStep(
    name="CreateModel",
    model=model,
    inputs=inputs,
)

등록한 모델을 SageMaker Endpoint에 배포하는 단계를 작성합니다. 먼저 배포 단계에 필요한 deploy.py 파일을 SageMaker Studio에 업로드합니다. 파일에서는 boto3를 이용해서 SageMaker Endpoint를 생성하는 코드가 포함되어 있습니다. deploy.py을 이용해서 배포하는 단계를 코드로 작성합니다

from sagemaker.workflow.steps import ProcessingStep
from sagemaker.sklearn.processing import SKLearnProcessor

sklearn_processor = SKLearnProcessor(
    framework_version="1.0-1",
    instance_type="ml.m5.large",
    instance_count=1,
    # base_job_name="comprehen",
    sagemaker_session=sagemaker_session,
    role=role,
)

step_create_model = ProcessingStep(
    name="CreateEndpoint",
    processor=sklearn_processor,
    job_arguments=[
        "--model-name",
        step_create_model.properties.ModelName,
    ],
    code="src/deploy.py",
)

파이프라인 생성 및 실행

지금까지 준비한 학습, 등록, 배포 단계를 이용해서 파이프라인을 생성하는 코드를 작성합니다. 전체 코드는 build-pipeline.ipynb 에서 확인할 수 있습니다.

rom sagemaker.workflow.pipeline import Pipeline

pipeline_name = f"AppMlPipeline-Deploy"
pipeline = Pipeline(
    name=pipeline_name,
    parameters=[
        train_data,
        test_data,
        epoch_data,
        batch_size_data,
        learning_rate_data
    ],
    steps=[step_train, step_create_model, step_deploy_model],
)

build-pipeline.ipynb 코드를 모두 실행해서 파이프라인을 생성하면 실행할 수 있습니다.

파이프라인 결과 보기

파이프라인을 실행하고 기다리면 다음과 같이 학습, 모델 등록, 배포까지 완료된 화면을 볼 수 있습니다.

AI 웹 애플리케이션 동작 확인

애플리케이션에 접속해서 정상적으로 동작하는지 확인합니다. 빨간 사진기 버튼을 눌러서 학습한 꽃 이미지 중 하나를 선택하고 노란 돋보기 버튼을 눌러서 분석을 요청합니다. 기다리면 분석과 함께 설명이 나오는 것을 확인할 수 있습니다.

리소스 정리하기

실습 후 추가 과금을 방지하기 위해서 사용한 리소스를 모두 삭제해야 합니다.

  • Amazon S3 콘솔로 이동해서 실습 과정에서 생긴 버킷을 모두 삭제합니다.
  • Amazon ECR 콘솔로 이동해서 생성한 Repository도 모두 삭제합니다.
  • CodePipeline 콘솔의 Repositories, Build projects, Pipelines에서 생성한 리소스를 모두 삭제합니다.
  • Amazon Elastic Container Service 콘솔로 이동해서 생성한 Cluster를 삭제합니다.
  • EC2 콘솔로 이동해서 왼쪽 메뉴의 Target Groups, Load Balancers, Security Groups에 들어가서 생성한 리소스를 모두 삭제합니다.
  • Amazon SageMaker 콘솔로 이동합니다. 생성한 도메인을 삭제합니다. 그리고 왼쪽 메뉴 Models, Endpoints, Endpoint configuration에 들어가서 파이프라인에서 생성한 리소스를 모두 삭제합니다.
  • VPC 콘솔로 이동해서 생성한 NAT Gateways, Subnets, Route Tables, Network ACLs, Internet Gateways, Security Groups을 삭제하고 VPC 를 삭제합니다.
  • 마지막으로 계정의 Billing Dashboard 에 접속해서 남은 리소스가 있는지 확인합니다.

결론

이 글에서는 AWS에서 제공하는 다양한 서비스를 이용하여 꽃 이미지 분류를 위한 AI 애플리케이션 구축하는 방법을 소개했습니다. 먼저 컨테이너화된 애플리케이션을 쉽게 배포, 관리, 확장할 수 있도록 도와주는 완전 관리형 컨테이너 오케스트레이션 서비스인 Amazon ECS와 기계 학습 모델을 학습하고 배포하여 운영할 수 있는 Amazon SageMaker를 이용하여 대규모 트래픽에도 유연하게 확장할 수 있도록 했습니다. 그리고 Amazon SageMaker Pipelines를 이용하여 기계 학습 모델 학습 및 배포를 자동화하고 AWS CodePipeline을 이용해서 컨테이너 통합 및 배포를 위한 CI/CD 파이프라인을 구축하는 방법을 소개했습니다.

모든 과정은 aws-samples 에 업로드된 ai-web-application-using-amazon-ecs-and-amazon-sagemaker 를 통해서 샘플 코드와 자세한 워크샵을 진행할 수 있습니다. 본 글과 워크샵을 통해서 애플리케이션 규모가 커지더라도 마이크로서비스 및 모델의 확장에 유연하고 민첩하게 운영할 수 있는 AI 웹 애플리케이션을 구현하는 데 참고가 될 수 있을 것으로 기대합니다.

Kichul Kim

Kichul Kim

김기철 솔루션즈 아키텍트는 고객의 요구사항을 도출하고 다양한 개발 경험과 모범사례를 바탕으로 효율적인 아키텍처를 제안하는 역할을 수행하고 있습니다.

Kyoung-Su Park

Kyoung-Su Park

박경수 솔루션즈 아키텍트는 다양한 워크로드에 대한 개발 경험을 바탕으로 고객이 최적의 솔루션을 선택하여 비즈니스 성과를 달성할 수 있도록 고객과 함께 효율적인 아키텍처를 구성하는 역할을 수행하고 있습니다. 현재 AWS의 Machine Learning, IoT, Analytics TFC에서 활동하고 있습니다.