본문 바로가기
카테고리 없음

MLOps note(2)

by 볼록티 2023. 10. 22.
728x90
반응형

 

 이번에는 전에 만들어둔 Makefile, hello.py, test_hello.py, requirements.txt 네가지 scaffold를 도커라이징하고, 이미지를 AWS의 레지스트리인 ECR에 푸시할 계획이다. 그런 다음 ECS에서 해당 이미지를 실행하는 컨테이너를 띄워볼 것이다. 트리거는 깃헙 저장소에 main브랜치로 코드를 푸시하는거고, 깃헙액션이 이를 확인할거다.

 

 docker와 aws와의 연결을 위해서는 로컬에서 권한에 대한 이슈가 발생한다. 그리고 포트 등에 대해서 마음대로 할 수 없다. 이미지도 갈수록 늘어날테고.. 회사 서버로 작게 작게 연습중이었는데, 아쉽지만 로컬로 갈아타게 되었다.  🥲

 우분투로 잘 하고 있었는데, 맥북에서 진행해야하니 운영체제 때문에 초기에 설정을 좀 해주었다. 


docker도 새로 설치.

brew install --cask docker

"Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?" 의 에러가 발생했는데, 위에서 --cask 로 도커를 설치해서 앱도 같이 설치되었는데, 로그인을 굳이 하지 않아서 앱을 실행해서 작업 화면까지만 가준뒤 터미널을 껐다키면 실행된 데몬과 연결이 된다.

 

ssh를 새로 생성해 깃헙에 새로운 ssh키도 등록했다.

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
cat ~/.ssh/id_rsa.pub

 

앞전에 구성해 놓은 스캐폴드 파일들을 가상환경에서 make 명령어도 잘 되는걸 확인했다. 당장 사용을 더 할 것같지는 않다.

source test_mlops/bin/activate

 

작업 순서는 하는 것은 아래와 같다.

 

1. scaffold의 파일에 대해 도커라이징 하기.

  Dockfile은 아래와 같다. app.py를 실행하는데, 실습하던 도중에 플라스크를 사용해야해서 중간에 플라스크를 활용한 간단한 파이썬 파일을 하나 추가했다.

FROM python:3.8-slim

# 작업경로
WORKDIR /app

# 컨테이너 작업경로인 /app에 현재 파일들을 다 복사한다.
COPY . /app

# 패키지 설치
RUN pip install -r requirements.txt

# 컨테이너 밖에서 80포트로 연결할 수 있도록 포트를 뚫어 준다.
EXPOSE 80

# World라는 변수명으로 환경변수 하나 설정하기.
ENV NAME World

# 이미지에 의해 컨테이너가 실행되면 아래의 커맨드가 실행된다.
CMD ["python", "app.py"]

 

app.py

from flask import Flask

# Flask 애플리케이션을 생성합니다.
app = Flask(__name__)

# 루트 경로 ("/")에 대한 요청을 처리하는 뷰 함수를 정의합니다.
@app.route('/')
def hello_world():
    return 'Hello, World!'

# 애플리케이션을 실행합니다.
if __name__ == '__main__':
    app.run(port=5000)

 

 

 

2. AWS ECR에 이미지 푸시하기.

    컨테이너 레지스트리는 AWS의 ECR을 사용한다. ECR은 Elastic Container Resistry로 AWS의 도커허브 같은거다. 먼저 Elastic Container Resistry을 검색해서 기본 설정으로 테스트로 아무거나 이름 적고 하나 생성해주기만 하면 된다. 그리고 IAM에서 CLI사용을 위한 계정을 하나 만들어준다. 권한은 ECR에 관한 full access권한으로 만들어 준다.

 

  - Actions에 셋팅에 들어가 시크릿에 aws 콘솔에서 발급받은 각각 액세스키와 시크릿 액세스키에 대해 환경변수를 입력한다.

  - 도커 Actions에서 새로운 워크플로우를 수동으로 만들어준다. 아래와 같이 yml 을 만들어준다.

name: Deploy to ECR

on:
 
  push:
    branches: [ main ]

jobs:

  build:

    name: Build Image
    runs-on: ubuntu-latest

    steps:

    - name: Check out code
      uses: actions/checkout@v2

    - 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: ap-northeast-2
 
    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1
      
    - name: Build, tag, and push image to Amazon ECR
      run: |
        docker build -t test_mlops .
        docker tag test_mlops:latest 434404663272.dkr.ecr.ap-northeast-2.amazonaws.com/test_mlops:latest
        docker push 434404663272.dkr.ecr.ap-northeast-2.amazonaws.com/test_mlops:latest

  >> 가운데 secrets를 볼 수 있고, 가장 아래에 run 부분은 aws 콘솔에서 실행할 수 있도록 했다.

 

 

>> 푸시 명령 보기를 클릭.

 

 

  >> 1번은 커널에서 실행해서 aws ecr과 docker를 서로 연결한다. 그리고 2,3,4를 깃헙 액션에서 만들던 yml 파일의 실행부분에 복붙한다. 레지스트리와 리포지토리는 환경변수를 사용하는게 좋을 듯하다. 

 

 

  >> yml 파일을 커밋하고 나면 바로 main으로 푸시가되기 때문에 Actions에서 자동으로 ECR에 이미지가 푸시된다.

 

 


 

3. AWS ECS에서 컨테이너 실행하기.

  (1) ECS 에서 새로 클러스터를 생성한다. 

  >>  EC2는 인스턴스 자체로 우선 돈을 내야해서 덜 유연하지만 아직 작업이 복잡하지 않은 관계로 Fargate로 생성했다.

 

(2) Task 를 설정한다.

  >> 새로운 태스크를 생성한다.

 

  >> 역할의 경우에는 아래와 같은 절차를 거쳐서 생성해줘야한다.

 

  >> IAM에 역할로 들어간다.

 

  >> AWSServiceRoleForECS에 대한 역할 만들기

 

  >> ECS에서 ECS Task를 클릭한다.

 

 

  >> 이름을 지정해주고.

 

 

  >> AmazonECSTaskExecutionRoelPolicy로 생성한다.

 

 

  >> 이름을 지어주고, ECR에 저장했던 이미지 URI를 가져와서 넣어준다. 포트는 도커파일에서 80포트를 지정했는데 디폴트에 있어 그대로 둔다.

  >> Task 생성 완료.

 

3. 로드밸런서를 생성한다.

  >> EC2로 넘어가서 로드 밸러서를 생성한다. 로드밸러서는 트래픽을 분산처리할 수 있게 해주는건데, 지금 그렇게 필요하진 않지만 공부니까 생성한다.

 



  >> 가장 왼쪽에 있는걸로 선택함.

 

  >> 이름을 지어주고, 

 

  >> 2개 이상의 리전을 설정해줬다.

 

 

  >> 대상그룹을 생성해본다.

 

  >> 복잡해서 2단계는 그냥 스킵했다.

 

  >> 대상그룹 생성완료 했으니 추가해주고 로드밸런서를 마무리하자.

 

  >> 생성될 때까지 시간이 조금 걸린다.

 

 

4. 서비스를 생성한다.

 

  만들던 Task에서 서비스생성으로 들어간다.

 

  >> 만들어 놓은 클러스터를 선택했다.

 

  >> 서비스 이름을 지어준다.

 

 

  >> 기존에 로드밸런서를 사용하고, 컨테이너에 리스너도 대상 그룹도 모두 기존에 만들었던 것을 사용한다.

 

  >> 서비스까지 하고 나면 클러스터에서 배포를 진행한다.

 

 

  여기서 배포가 잘 이뤄진다면 url에 포트 5000로 붙으면 hello world! 가 떠야할텐데, 쉽게 서비스가 생성이 안된다.. 그래서 지금 IAM 사용자의 EC2, ECS 권한을 모두 full로 부여하고 다시 해보려 한다.

 

 


 

머신러닝 프로젝트를 좀 더 단순화하여 배포를 진행해봐야겠다. 홀로서기가 힘드네 힘들어...

 


 

ref)

-Practical MLOps by Noah Gift, Alfredo Deza

-https://github.com/paiml/practical-mlops-book

-https://velog.io/@dnflekf2748/AWS-ECS%EB%A5%BC-ECR%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0

-https://tempodivalse.tistory.com/49

728x90
반응형

댓글