본문으로 바로가기

[AWS] App Runner를 사용해보자.

category Architecture/AWS 2023. 1. 5. 22:25
728x90
반응형

 

AWS App Runner를 사용하면 컨테이너나 인프라를 배포하고 관리하는 경험이 없는 팀에서 조차도 작성된 언어에 관계없이 웹 앱과 API를 클라우드에 쉽게 배포할 수 있습니다.

이 서비스에는 AWS 운영 및 보안 모범 사례가 내장되어 있으며, 즉시 자동 확장 또는 축소되므로 완전 시작을 걱정할 필요가 없습니다.

...
https://aws.amazon.com/ko/blogs/korea/app-runner-from-code-to-scalable-secure-web-apps/ 

목차

     

    개요

    재미난 주제 없나 하고 구글링 하던 중 AWS App Runner에 대해 접하게 되었습니다.

    과거 ECS에서 Fargate랑 EC2를 이용해 컨테이너를 올려봤던 게 생각났는데 인용문에서도 언급되어있듯이 "보다 쉽고 간편하게 할 수 있다고?" 하는 생각에 "이거 안 써볼 수가 없겠는 걸?" 하고 사용해보게 되었네요.

    저는 Flask App + Github Action + AWS ECR + AWS AppRunner 형태로 구성하여 이 형태를 써보려고 이래저래 사용해보고 들었던 생각과 어떻게 시도했는지를 남기는 글입니다.

     

    App Runner는 AWS-ECR 혹은 Github Repository를 대상으로 설정이 가능합니다만 이 포스팅에서는 AWS-ECR을 대상으로 설정하는 것을 가정합니다

     

    1. IAM 설정하기

    우선은 AWS App Runner를 사용하기 위해 IAM에서 AWS App runner 권한을 추가해 줍시다.

    ...
    		"Action" : [
    				...
    				"apprunner:*",
    				...
    		]
    ...

     

    2. App Runner Service 생성

    App runner를 생성하는 과정이 복잡하지 않아 기술할 내용이 별로 없긴 합니다. Application의 스펙을 고려하여 App Runner Service를 만드는 과정에서 요구하는 정보를 채워 넣어주면 됩니다.

    주의할 점은 포트 설정 부분인데 프로젝트에서 Dockerfile에 설정했던 EXPOSE 포트랑 일치시켜 줍시다.

    이후 하단에 “다음”이라는 버튼을 통해 App Runner를 사용하면 됩니다. 몇 분 정도 거치면 “App Runner > 서비스”에서 App Rrunner가 실행 중인 것을 확인할 수 있습니다

     

    3. App Runner 대략적 흐름

    구성도 그리는 건 늘 어색합니다만 위와 같은 흐름으로 돌아가게끔 구성해 봤습니다. Github Repository에 Source를 Merge 하면 Github Repository에 걸어준 Github Actions에서 Project내의 Dockerfile을 보고 ECR에 Dockerfile을 빌드하여 업로드합니다. AWS App Runner는 ECR에 업로드된 Docker Image의 버전을 감지하여 자동으로 배포하게 됩니다.

    4. Demo: Simple Flask Project

    이제 Flask Project를 App Runner로 띄우는 것을 목표로 App Runner를 사용해볼 차례입니다. Flask를 실행할 때 `python app.py` 와 같은 형식이 아닌 flask run과 같은 flask command를 이용했습니다. 

    4.1 Structure

    ├── .github
    │   └── workflows
    │       └── aws.yml
    ├── Dockerfile
    ├── app.py
    ├── application
    │   ├── __init__.py
    │   └── api.py
    ├── requirements.txt

    위 프로젝트 구조에서  `aws.yml`, `Dockerfile`, `app.py`에 해당하는 내용만 작성해두겠습니다. aws.yml의 경우 Project Source 내에 존재하는 Dockerfile을 AWS ECR에 빌드하여 업로드해주는 Github Action입니다.

    4.2 app.py

    from flask import Flask
    
    def create_app():
        app = Flask(__name__)
    
        from application.api import bp as index_bp
        app.register_blueprint(index_bp)
    
        return app

    4.3 Dockerfile

    FROM python:3.8-slim-buster
    
    WORKDIR /usr/src/app
    
    COPY . .
    
    RUN pip3 install -r requirements.txt
    
    EXPOSE 8080
    
    CMD ["python3","-m","flask","run","--host=0.0.0.0","--port=8080"]

    DockerFile에서 실행되는 명령어는 python app.py 가 아닌 flask run입니다!

     

    4.4 github action

    ame: Deploy to Amazon ECR
    
    on:
      push:
        branches:
          - "main"
    
    env:
      AWS_REGION: "ap-northeast-1"                   # set this to your preferred AWS region, e.g. us-west-1
      ECR_REPOSITORY: "jako-test"           # set this to your Amazon ECR repository name
      IMAGE_TAG: latest
    
    permissions:
      contents: read
    
    jobs:
      deploy:
        name: Deploy
        runs-on: ubuntu-latest
        environment: production
    
        steps:
        - name: Checkout
          uses: actions/checkout@v3
    
        - name: Configure AWS credentials
          uses: aws-actions/configure-aws-credentials@v1
          with:
            aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
            aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
            aws-region: ${{ env.AWS_REGION }}
    
        - name: Login to Amazon ECR
          id: login-ecr
          uses: aws-actions/amazon-ecr-login@v1
    
        - name: Build, tag, and push image to Amazon ECR
          id: build-image
          env:
            ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          run: |
            
            docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:${{ env.IMAGE_TAG }} .
            docker push $ECR_REGISTRY/$ECR_REPOSITORY:${{ env.IMAGE_TAG }}
            echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:${{ env.IMAGE_TAG }}"

     

    5. 사실 이 글은 쓴 목적은..

    AWS App Runner는 AWS에서 제공하는 가이드나 구글링을 통해서 얻은 정보를 이용하면 위에 작성한 내용보다 이해도 쉽고 간단한 게 사용해볼 수 있을 것입니다. 사실 이 글을 쓴 목적은 간단한 Flask Project를 하나 배포하는데 드는 과정에서 겪은 AWS App Runner 사용 후기를 남기려고 작성한 글입니다.


    App Runner를 사용하는 동안 AWS App Runner 문서에서 의미하는 “간단한 배포”에는 많이 동감이 되었습니다. 제 좁은 식견상 EC2를 이용하여 배포하게 되면 여러 가지 신경 써야 하는 포인트(EC2 Image, EC2내부 설정, 기타 다른 인프라)가 있었기 때문입니다.


    App Runner를 써보니 이러한 설정 없이 Application을 간단한 게 배포하는 과정이 재밌었습니다. 간단한 서버를 올릴 때는 EC2보다 AppRunner를 고려해보는 건 어떨지 싶네요


    6. 배포 속도가 느리다고 본다.

    그런데 아직 궁금한 점이 남아있긴 합니다.


    App Runner의 배포 설정 옵션을 자동으로 설정했다면 Github-Action에 의해 ECR에 Docker Image가 업로드 완료된 시점에서 App Runner에서 이를 감지하고 배포를 시작하는데 App Runner 자체의 배포 시간이 오래 걸린다는 점입니다.


    처음엔 Docker Image를 Python:3.7로만 생성하여 시도했었는데 배포 과정이 10~12분 정도 걸렸습니다. EC2에 배포하면 Remote에서 배포 스크립트를 실행하여 5 ~15초 정도(소규모인 경우) 소요된 것에 비하면 굉장히 느린 속도입니다.


    해결 방법을 찾던 중 Docker Image를 축소하여 올리는 방법을 알게 되었습니다. Python:3.7은 Docker Image로 Build 하면 350Mb 정도 나오는 것을 확인했는데 Python:3.7-slim-buster로 설정하니 45 ~ 50mb 정도였고 App Runner 배포 시간이 5~6분 정도로 단축되는 것을 경험했습니다.


    그래도 여전히 5~6분 정도면 오래 걸린다고 생각합니다. 어쩌다가 2~3분 정도 걸리는 경우도 있었는데 차이는 잘 모르겠네요.

     

     

     


     

    728x90
    반응형