당신은 돈을 내기 위해 태어난 사람 ~(...)
EBS도 돈이 나가는구먼. 로드밸런서.. 거 kinesis도 메세지 몇 개 던지지도 않았는데 저렇게 나왔다. 쩝..서울 리전이어서 더 비싼 것도 있는 듯하고.
이래저래 서버 띄울 일이 생겨서 aws의 elasticbeanstalk를 써보게 되었다. 어디서는 lambda로 띄우는 법도 있던데 aws 문서를 대충 보니 사이트 패키지를 람다와 연결된 ec에 설치하는 것 같다.
EBS도 완전 관리형이라 한데 최소한의 설정방법은 알고 해야 안 헤맨다. nginx 502에러가 진짜 복병이었다....이 에러는 nginx 설정을 잘못해서 날 수도 있고, app에서 나는 에러때문에 생길 수도 있다. 에러엔 역시 콘솔로 접속해서 로그를 봐야 함; EB 브라우저에서 로그를 보는 것도 web로그랑 다 모아서 보여주니 좋을 때도 있는데 그래도 고르라면 콘솔로 로그 보는게..속 덜 터짐.
elasticbeanstalk로 서버 띄우기
스텝:
- app파일 작성
- app파일에 .ebextensions Procfile, .platform 폴더구조 만들고 환경설정 파일 작성. (아니면 aws elasticbeanstalk 브라우저에서도 설정 가능)
- aws, eb cli설치
- eb cli를 통해 app 환경 생성 → 배포
- 새로운 코드로 변경 후에
eb deploy
로 새 코드 배포함
프레임워크: FastAPI
main.py 파일에 함수 작성. 라우터가 몇 개 안 되는 정말 간단한 api여서 그냥 vim으로 작성했다.
from typing import Optional
from fastapi import FastAPI, Header
from pydantic import BaseModel
import uvicorn
from mangum import Mangum
app = FastAPI()
@app.get("/")
def hello():
return "hello"
... 생략 ...
handler = Mangum(app)
if __name__=="__main__":
uvicorn.run(app, host="0.0.0.0", port=5000, reload=True)
requirements.txt 생성.
이렇게 만들어놓고도 deploy할 때 패키지간 conflict나는 경우가 있으니 유의. (web.stdout.log 봐야함)
freeze로 생성 안 하고 그냥 수동으로 적어서 만들었을 때 virtualenv가 안 만들어지기도 함.
둘 다 경험..
pip freeze > requirements.txt # + gunicorn도 추가
.ebignore 생성.
배포시에 무시할 폴더, 파일들 작성 .gitignore 같은 것
env # ex. 가상환경 폴더
test_codes.py # ex 테스트 파일
elasticbeanstal에 올릴 app 폴더 구조는 다음처럼 이루어진다.
잘 봐야 하는 건 nginx 커스텀 conf 위치 (.platform폴더) 와 Procfile, .ebextensions 폴더.
여기서는 Procfile과 .platform 폴더, .ebextensions 폴더에 앱 환경 설정을 넣는다.
이부분을 몰라서 많이 해맸다..aws 자습서는 이런 거 자세히 안 말해줘서..ㅠ 그냥 환경구성(고오급)으로 빼놨음.
Procfile
web: gunicorn --bind 0.0.0.0:1234 -k uvicorn.workers.UvicornWorker main:app
.ebextensions/my_option.config
- 참조: 옵션 설정
option_settings:
aws:elasticbeanstalk:application:environment:
PORT: 1234
aws:elasticbeanstalk:container:python:
WSGIPath: main (내 실행 어플리케이션 파일 이름)
NumProcesses: 1
NumThreads: 14
- 위의 내용들은 aws 브라우저 설치 환경 선택 > 구성 > 소프트웨어 편집 에서도 설정 가능하다.
nginx구성
- 에러 찾느라고 진짜 다 뒤지다가 nginx도 들여다 봤다. 내 커스텀 설정은 .platform 폴더의 저~ 밑의 하위 폴더인 conf.d 안에 넣어야 한다. (위의 app구조 참조)
elasticbeanstalk의 nginx 기본 설정은 다음과 같다. 인스턴스에서 확인.
내용에서 include를 보면 중간 http 안에 include conf.d/*.conf;
가 보인다. 내가 작성한 커스텀 파일이 들어가는 부분임.
#Elastic Beanstalk Nginx Configuration File
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 32804;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include conf.d/*.conf;
map $http_upgrade $connection_upgrade {
default "upgrade";
}
server {
listen 80 default_server;
access_log /var/log/nginx/access.log main;
client_header_timeout 60;
client_body_timeout 60;
keepalive_timeout 60;
gzip off;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Include the Elastic Beanstalk generated locations
include conf.d/elasticbeanstalk/*.conf;
}
}[
eb CLI 설치
pip install awsebcli eb --version
AWS CLI 설치 (LINUX2) 후 작업을 위한 계정 설정
aws configure
#elasticbeanstalk fullaccess 권한을 가진 사용자의
#access key와 secret 등록
#원하면 리전도 등록
EB 인스턴스 생성
# 인스턴스 환경 초기화
eb init
#여기까지만 쳐도 알아서 환경 언어와 리전 설정, 앱환경이름 물어봄
#아니면 전체 입력
# eb init --platform python-3.8 --region us-east-1 my-app
# 인스턴스 생성. 시간 걸림
eb create --region us-east-1 my-app
# 서버 브라우저 띄우기
eb open
NGINX 502 에러
app 자체의 문제로 날 수도 있고, nginx에러로 날 수도 있음. 로그 시간은 UTC. 브라우저 콘솔에서 로그 100줄 추출해서 볼 때 로그 시간 잘 보고 판단. 이전 에러 난 것도 지금 난 걸로 헷갈릴 수 있다.
- PORT 설정 확인. 내 app의 port는 5000인데 EB에 아무 환경 설정도 안 넣어서 디폴트인 8000로 돌고 있을 수 있다. nginx.error 로그 확인
- nginx 커스텀 conf 넣었을 때 잘못 넣어서. server{ ... } 안에 기술해야 할 거임.
- option_setting 제대로 값 설정했는지 브라우저 콘솔에 찍힌 값과 비교해보기.
- app 자체의 문제. 모듈이 뭐가 없거나(가상환경 설치에 문제가 있을 때), 코드 에러. web.stdout.log 살펴보기.
참조
elasticbeanstalk
- elastic beanstalk Amazon Linux2 python 환경 마이그레이션 후기
- [Hands On] Elastic Beanstalk를 사용한 웹 애플리케이션 배포 – Django
- call () missing 1 required positional argument: 'send' FastAPI on App Engine
- TypeError: call () missing 1 required positional argument: 'send'
- AWS Elastic Beanstalk Java SE 플랫폼 환경으로 애플리케이션 배포하기
- AWS Elastic Beanstalk 으로 flask app 배포하기(+무료 도메인 route53, freenom)
- FastAPI 및 AWS Elastic Bean Stalk로 날씨 API 엔드 포인트 구축
nginx
- FastAPI 개발환경 셋팅으로 배우는 nginx와 웹서버의 관계
- Nginx로 FastAPI 배포하기 (Feat. Gunicorn)
- node.js의 리버스 프록시 설정하기
- NGINX Proxy 502 Bad Gateway 오류 해결하기 ~ upstream sent too big header while reading response header from upstream
- nginx 리버스 프록시 긴 도메인으로 인한 에러 해결
- Nginx 서버 재시작 하는 방법 Restart / Reload
- include를 사용해서 NginX의 설정을 나누기
lambda
- Simple Serverless FastAPI with AWS Lambda
- Python에서 Lambda 코드를 실행할 때 발생하는 ‘모듈을 가져올 수 없음’ 오류를 해결하려면 어떻게 해야 합니까?