주뇽's 저장소

AWS Lambda + API Gateway를 이용해서 Fast API와 LangChain 서비스 배포 본문

클라우드서비스

AWS Lambda + API Gateway를 이용해서 Fast API와 LangChain 서비스 배포

뎁쭌 2024. 7. 7. 13:16
728x90
반응형

0. 사전 준비

- AWS 액세스 키와 시크릿 키 발급

- AWS CLI 설치

1. 프로젝트 구조 설정

먼저, 다음과 같은 디렉토리 구조를 설정한다:

my-fastapi-app/
├── app
│	├── controller
│	│	├── __init__.py
│	│	└── NickController.py
│	├── dto
│	│	├── __init__.py
│	│	├── NicknameProfileRes.py
│	│	├── NicknameReq.py
│	│	├── NicknameRes.py
│	│	└── ProfileImageReq.py
│	├── generation
│	│	├── __init__.py
│	│	├── makeNickname.py
│	│	└── makeProfile.py
│	├── service
│	│	├── __init__.py
│	│	└── NickService.py
│	├── __init__.py
│	├── .env
│   └── main.py
├── Dockerfile
└── requirements.txt

2. 코드 작성

1. app/main.py

from app.controller import NickController
from fastapi import FastAPI
from mangum import Mangum

app = FastAPI()
lambda_handler = Mangum(app)
app.include_router(NickController.router)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

2. requirements.txt(FastAPI, LangChain)

requirements.txt
0.00MB

3. Dockerfile

#-- aws 람다 python 3.9
FROM public.ecr.aws/lambda/python:3.9

#-- requirements.txt를 람다 디렉토리에 복사
COPY requirements.txt ./

#-- 필요 의존성 설치
RUN pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt

#-- app에 관련된 모든 파일 복사
COPY app ${LAMBDA_TASK_ROOT}/app

#-- 람다 핸들러 설정
CMD ["app.main.lambda_handler"]

 

3. Docker 이미지 빌드

프로젝트 루트 디렉토리에서 Docker 이미지를 빌드한다:

docker build -t my-fastapi-app .

1. 로컬에서 확인

docker run -p 9000:8080 my-fastapi-app

 

로컬에서 람다를 실행하려면 아래와 같은 경로에 요청을 보내면 된다.

  • 컨트롤러에 "/health"라는 경로에 GET 메서드로 함수를 정의
  • requestContext -> method와 path를 알맞게 설정
curl -X POST "http://localhost:9000/2015-03-31/functions/function/invocations" \
-H "Content-Type: application/json" \
-d '{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/health",
  "rawQueryString": "",
  "headers": {
    "Content-Type": "application/json"
  },
  "requestContext": {
    "http": {
      "method": "GET",
      "path": "/health",
      "protocol": "HTTP/1.1",
      "sourceIp": "127.0.0.1",
      "userAgent": "curl/7.64.1"
    }
  },
  "body": "",
  "isBase64Encoded": false
}'

200 상태코드를 반환받으면 성공

 

4. AWS ECR에 이미지 빌드

1. 지역과 AWS계정 ID만 변경

  • 아래 코드에서 자신의_AWS_계정_ID 부분에 AWS 계정 ID로 대체 한다.
  • 지역은 서울 같은 경우 ap-northeast-2로 설정
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 자신의_AWS_계정_ID.dkr.ecr.ap-northeast-2.amazonaws.com

2. create-repository 명령을 사용하여 Amazon ECR에 리포지토리를 생성

  • repository_name : 자신의 도커 이미지 파일을 올릴 리포지토리 이름
  • region : 서울 같은 경우 ap-northeast-2로 설정
aws ecr create-repository --repository-name nickname-generate --region ap-northeast-2 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE

 

성공적으로 생성이 된다면 아래와 같이 나온다.

{
    "repository": {
        "repositoryArn": "arn:aws:ecr:ap-northeast-2:자신의_AWS_계정_ID:repository/nickname-generate",
        "registryId": "자신의_AWS_계정_ID",
        "repositoryName": "nickname-generate",
        "repositoryUri": "자신의_AWS_계정_ID.dkr.ecr.ap-northeast-2.amazonaws.com/nickname-generate",
        "createdAt": "2024-07-05T16:12:38.310000+09:00",
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": true
        },
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }
    }
}

 

3. 도커 이미지 태그 후 ECR로 푸시

docker tag my-fastapi-app:latest 자신의_AWS_계정_ID.dkr.ecr.ap-northeast-2.amazonaws.com/my-fastapi-app:latest
 docker push 자신의_AWS_계정_ID.dkr.ecr.ap-northeast-2.amazonaws.com/my-fastapi-app:latest

5. 람다 함수 생성

  • ImageUri의 경우 이전의 리포지토리 URI를 지정

1. IAM역할 설정

1. AWS 관리 콘솔에 로그인합니다.
2. IAM 서비스로 이동합니다.
3. 왼쪽 메뉴에서 '역할'을 클릭합니다.
4. '역할 만들기' 버튼을 클릭합니다.
5. '신뢰할 수 있는 엔티티 선택' 페이지에서:
   - 'AWS 서비스'를 선택합니다.
   - 'Lambda'를 선택합니다.
6. '다음'을 클릭합니다.
7. '권한 추가' 페이지에서:
   - 'AWSLambdaBasicExecutionRole' 정책을 검색하여 선택합니다.
8. '다음'을 클릭합니다.
9. '이름 지정, 검토 및 생성' 페이지에서:
   - 역할 이름을 'lambda-basic-role'로 입력합니다.
10. '역할 생성'을 클릭합니다.

2. 람다 함수 생성

aws lambda create-function \\
  --function-name nickname-generate \\
  --package-type Image \\
  --code ImageUri=915540485491.dkr.ecr.ap-northeast-2.amazonaws.com/nickname-generate:latest \\
  --role arn:aws:iam::915540485491:role/lambda-basic-role
{
    "FunctionName": "nickname-generate",
    "FunctionArn": "arn:aws:lambda:ap-northeast-2:915540485491:function:nickname-generate",
    "Role": "arn:aws:iam::915540485491:role/lambda-basic-role",
    "CodeSize": 0,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2024-07-05T07:28:46.233+0000",
    "CodeSha256": "0eeeeee0ad13d4646fc0767b3030f915fe8b492a5462f376234ec01e3e9b4795",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "ffaa1e28-7aa3-4f4c-b978-f468805a0531",
    "State": "Pending",
    "StateReason": "The function is being created.",
    "StateReasonCode": "Creating",
    "PackageType": "Image",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": {
        "ApplyOn": "None",
        "OptimizationStatus": "Off"
    },
    "LoggingConfig": {
        "LogFormat": "Text",

성공 메시지

*참고 AWS Lambda 함수 업데이트

  • 업데이트
aws lambda update-function-code --function-name nickname-generate --image-uri 자신의_IAM_ID.dkr.ecr.ap-northeast-2.amazonaws.com/my-fastapi-app:latest
{
    "FunctionName": "nickname-generate",
    "FunctionArn": "arn:aws:lambda:ap-northeast-2:자신의_IAM_ID:function:nickname-generate",
    "Role": "arn:aws:iam::자신의_IAM_ID:role/lambda-basic-role",
    "CodeSize": 0,
    "Description": "",
    "Timeout": 480,
    "MemorySize": 1024,
    "LastModified": "2024-07-13T09:50:49.000+0000",
    "CodeSha256": "fd689ceba2007b9abd9213ae8baa38a8ad39172d99f16c822fedb67b5487e303",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "7d5832c8-5baa-4ee9-82d6-3bf8da6c4e26",
    "State": "Active",
    "LastUpdateStatus": "InProgress",
    "LastUpdateStatusReason": "The function is being created.",
    "LastUpdateStatusReasonCode": "Creating",
    "PackageType": "Image",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": { ...

 

 

6. API Gateway 설정

1. API 생성(REST API)

 

2. 리소스 생성(엔드포인트 설정)

2-1. 리소스 메소드 생성(GET, POST, PUT, DELETE)

3. API 배포

- 자신의 url만큼 생성 이후 API 배포

 

람다 콘솔창에서 확인해보면 잘 연결되어 있다. 이제 자신의 API게이트웨이 url로 요청을 보내면 된다.

 

 

7. 결과 확인

 

정상 작동한다!