[Django] Elastic Beanstalk + ElastiCache + Celery 배포

요즘것들

요즘것들

2023년 08월 27일

백엔드의 특정 API 로직에서 처리 시간이 오래 걸릴 경우 Celery를 사용하는 것이 일반적입니다.

현재 EB(Elastic Beanstalk)로 배포하기 위해 awsebcli를 사용하는데, 실제 배포 환경에서 Celery worker를 실행시키는 데 관련한 문서가 찾기도 어렵고, 있어도 너무 구버전이고 (쉘 스크립트로 배포하는 과정도 있었음....) 심지어 그 마저도 동작하지도 않았습니다... ㅠㅠ
그래서 여러분들의 lifesaver가 되고자 기록합니다.

전제조건은 다음과 같습니다!
1. celery에 대한 기본적 이해
2. awsebcli 사용
3. ElastiCache Redis cluster 사용
4. EB와 redis가 연결되어 있음

만약 EB와 Redis를 연결하는 데 어려움을 겪고 있다면 이 글에서 보안그룹 설정까지 마쳐주시면 됩니다.

Django에서의 세팅

먼저 여러분들의 프로젝트 settings에서 다음 변수들을 추가해줍니다.

REDIS_SERVER_ENDPOINT = env("REDIS_SERVER_ENDPOINT")
CELERY_BROKER_URL = f"redis://{REDIS_SERVER_ENDPOINT}:6379/0"
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
CELERY_ACCEPT_CONTENT = ["json"]
CELERY_TASK_SERIALIZER = "json"

CELERY_RESULT_BACKEND는 비동기 작업 결과를 저장할 백엔드가 있는 경우 추가해주시면 됩니다.
env("REDIS_SERVER_ENDPOINT")는 .env에서 해당 변수의 값을 가져온다는 뜻입니다. 따라서 여러분의 EB 환경변수에 해당 변수의 값을 추가해주시면 됩니다.

awsebcli 설정

awsebcli를 사용하신다면 .ebextensions 디렉터리와 함께 운영하실 겁니다. 해당 디렉터리 내에 여러분의 xx-example.config과 같이 xx에 01, 02 등 번호로 config 파일들이 분리되어 있을텐데, 각자의 마지막 config 번호 +1로 새로운 파일을 생성해줍니다.

# 예시) 04-celery.config
packages:
  yum:
    gcc: []
    python3-devel: []
    libcurl-devel: []
    openssl-static.x86_64: []

관련하여 이 파일 없이 운영하는 케이스도 보긴 했으나 필자의 OS(Amazon Linux 2)에선 에러가 발생했습니다.

ImportError: The curl client requires the pycurl library.

그래서 xx-celery.config은 여러분의 OS에 따라 추가해도 되고, 안 해도 되는 케이스가 있을 겁니다.

다음으론 .ebextensions의 django.config에서 옵션 세팅을 추가해줄 겁니다.

option_settings:
  ...
  aws:elasticbeanstalk:application:environment:
    CELERY_BROKER_URL: redis://{여러분의 레디스 서버 엔드포인트}:6379//
    DJANGO_SETTINGS_MODULE: config.settings
    PYTHONPATH: /var/app/venv/*/bin
container_commands:
  ...

또 프로젝트의 루트 위치에서 Procfile 이름으로 파일 하나를 생성해줍시다. 이미 있는 경우 다음 명령어만 추가해줍시다.

celery: celery -A {여러분 celery가 있는 위치} worker -l INFO

eb deploy로 배포했을 때, Procfile을 통해 배포 전 동작해야 할 명령어를 확인하고 실행합니다. 즉, celery의 worker를 백그라운드에서 계속 실행하겠다는 의미입니다. celery의 브로커로 연결되는 URL은 django.config에 추가했던 CELERY_BROKER_URL을 참조합니다.

eb deploy를 하고 celery 작업이 있는 API 호출을 해보면 성공적으로 연결될 겁니다!
주의할 점은 EB에서 auto scaling에 의해 추가될 인스턴스들에도 worker가 실행되는 지 확인은 하지 않았습니다. 그래서 만약 새로운 인스턴스들에도 worker가 실행되지 않는 경우 해당 로직에 문제가 발생할 수 있으니 주의하셔야 합니다.

  • 2023.08.21
    Auto scaling에 의해 추가된 인스턴스들에도 정상적으로 worker가 실행되는 것을 확인했습니다.

마치며

메일 발송 함수를 비동기로 처리하기 위해 시작했던 일인데, 배포 과정에서 쉘 스크립트도 작성하기도 하고 상당한 애를 먹었는데 막상 쓰고나니 허무하게 짧아 머쓱합니다만 이 글이 다른 분들에게 도움이 조금이라도 되길 바랍니다..ㅎㅎ

개발