gcp cloud run jobs을 이용해 배치 작업을 해보자(feat. cloud scheduler)
안녕하세요 😉
유유자적한 개발자 유로띠 입니다 😀
회사에서
프로젝트를 통해 배우고 성장하며
이것을 토대로 그로스 해커(Growth Hacker)가 되기 위한 포스팅입니다.
👏👏👏👏
두 번째 그로스 해커
오늘의 이야기는
특정 시간대에 실행되어 반복적으로
처리하는 작업(배치)을 GCP환경에서
구성하는 방법에 대해 고민했던 내용입니다. 😏
특정 시간에 작업이 실행되어야 한다.
이번에 작업한 기능은 수강생에게 특정 메일을 보내는 기능입니다.
특정 메일은 강의가 오픈했거나, 강의 종료 며칠 전, 혹은 특정 수강률을 달성 시에 메일을 보내는 기능입니다.
기능은 수월하게 만들었으나
문제는 매일매일 해당 정보를 확인해서 메일을 보내는 일이였습니다.
✅ 매일매일 작업을 해야 한다?
매일 특정 시간에 작업이 진행된 후 메일을 보내야 하는 수강생을 구별하여 보내는 작업이 필요합니다.
즉 배치 작업이 필요하게 된 것입니다.
💡배치란 무엇일까요?
컴퓨터가 주기적으로 대량의 반복적인 데이터 작업을 완료하는 데 사용하는 방법.
데이터를 실시간으로 처리하는 것이 아닌, 일괄적으로 모아서 처리하는 작업.
✅ 배치의 고민
기존 AP서버에 해당 기능을 처리하는 route를 별도로 만들어 사용하는 방법을 생각했습니다.
그다음 cron을 이용하여 특정 시간에 api를 호출하여 작업을 처리하는 방식인 거죠.
하지만 해당 방식은 다음과 같은 문제가 있었습니다. 🥲
🛑 기존 api 서버를 사용하기 때문에 해당 작업이 발생하는 시점은 대용량 처리를 진행하기 때문에 기존 api 서버에 부담을 줄 수 있다.
🛑 배치 작업과 기존 api 작업이 분리되지 않아 로그를 분석하는데 어려움이 존재한다.
🛑 배치의 시간대를 변경할 때 서버에 설치된 cron에 대해 설정을 수정해야 하는 번거로움이 있다.
🛑 특정 문제로 실행되지 않은 경우 재시도 방법이 어렵다.
특히나 배치의 특정 상 한번 실행하고 나면 더 이상의 자원을 소비하지 않기에 굳이 기존 api에 같이 있을 필요는 없습니다.
그리고 api 서버 특성상 route로 호출할 수 있기 때문에 외부에서도 호출 가능 할 수 있어 보안의 위험도 존재합니다.
그래서 배치만의 별도의 서비스 분리가 필요했습니다.
✅ 서비스 분리 및 스케쥴러 도입
배치 서비스를 분리하여 별도의 cloud run 서버로 생성하여 진행하였습니다.
🙆♂️ 분리에 따른 장점
🔵 기존 api 서버에 부담이 없다.
🔵 별도의 서버로 분리하였기 때문에 로그 검색이나 이슈에 대해 각각 확인이 가능하다.
🙅♂️ 해결되지 않은 문제
🛑 여전히 배치의 시간대를 설정할 때에는 어려움이 있다.
🛑 문제가 발생할 때 재시도의 방법이 어렵다.
그래서 gcp에 있는 cloud scheduler을 확인하게 되었습니다.
Cloud Scheduler 란?
Cloud Scheduler는 엔터프라이즈 수준의 완전 관리형 크론 작업 스케쥴러로서 일괄 및 빅데이터 작업, 클라우드 인프라 작업 등을 비롯한 거의 모든 작업의 예약을 돕습니다. 장애 발생 시 재시도를 포함하여 모든 작업을 자동화할 수 있으므로 수작업이나 사용자의 개입 필요성을 줄일 수 있습니다.
바로 cloud Scheduler 작업을 만들어서 테스트를 진행하였습니다.
빈도는 cron 형식을 사용하기 때문에 기존에 했던 방식으로 하면 됩니다.
또한 시간대도 정할 수 있어서 기존에 서버에서 했을 때 서버의 시간대가 잘못되었을 때 발생되는 문제도 최소화할 수 있었습니다.
스케쥴러 목록에서도 확인 가능하고 실행 상태와 최종, 다음 실행 시간을 알 수 있습니다.
또한 작업을 선택하면 강제로 즉시 실행이 가능합니다. (문제가 발생 시 바로 작업을 처리할 수 있는 장점 👍 )
하지만 cloud Scheduler의 실행 구성에서 잠시 문제를 마주하였습니다. 😇
실행 구성 방식에 세 가지 방법이 있습니다. (현재 저의 환경에서는 두 가지 방식 뿐이라 두가지만 설명드리겠습니다.)
🟡 HTTP 방식
🟡 게시/구독(cloud Pub/Sub) 방식
🟡 App Engine HTTP
App Engine HTTP은 제외하고 두가지 방법 중에서 cloud run과 같이 사용하려면 게시/구독(cloud Pub/Sub) 방식이어야 합니다.
그러면 다음과 같은 프로세스가 됩니다.
Scheduler를 사용하기 위해 불필요한 pub/sub을 사용해야 하는 상황이 되었습니다.
✅ cloud run jobs 도입
🙋♂️ 불필요한 작업을 줄이고 cloud scheduler의 장점을 살리면서 사용할 수 있는 방식에 대해 알아보던 중 cloud run jobs에 대해서 알게 되었습니다.
cloud run jobs이란?
요청을 리슨하고 제공하는 Cloud Run 서비스와 달리 Cloud Run 작업은 태스크만 실행하고 완료 시 종료됩니다.
작업을 만들거나 업데이트한 후에는 일회성으로, 일정에 따라 또는 워크 플로의 일부로 작업을 실행할 수 있습니다.
개별 작업 실행을 관리하고 실행 로그를 볼 수 있습니다.
cloud run jobs는 저희가 필요한 모든 장점을 포함하는 기능이었습니다. 😏
배치에 최적화되어있나? yes
스케쥴러와 사용 가능한가? yes
개별 작업으로 실행하고 태스크별로 로그를 확인할 수 있나? yes
또한 cloud run은 요청을 수신 대기하고 이벤트를 받으면 해당 작업을 실행하는 Event-Driven 방식이지만, cloud run jobs은 요청을 수신하는 것이 아닌 Job을 직접 호출해야 하고 호출되면 해당 작업만 실행하고 완료되면 종료되는 형태를 가지고 있습니다.
병렬처리하기 때문에 cloud run 보다 효율적이고 태스크 별로 로그도 확인할 수 있는 장점이 있습니다.
다만, cloud run job은 현재(2023.05) beta 버전으로 되어있습니다.
cloud run과 cloud run jobs의 비교는 다음 영상에서 확인 할 수 있습니다.
cloud run jobs을 생성하면 cloud run에서 작업(job) 탭에서 확인이 가능합니다.
상세 정보로 이동하면 트리거(스케쥴러)를 확인 할 수 있습니다.
✅ cloud run jobs 생성하기
cloud run jobs 생성의 기본적인 명령어는 아래의 링크를 참고하면 됩니다.
저희는 git workflows를 통해서 생성 및 배포하도록 하고 있기 때문에 gcloud 명령을 통해 생성하고 배포하는 방법을 소개합니다.
gcloud run jobs 명령어를 사용하기 전에 cloud run jobs은 beta 버전이기 때문에 관련 beta components를 설치해야 합니다.
# use cloud run jobs beta
$ gcloud components install beta -q
$ gcloud components list
create 명령어 대신 deploy를 하면 생성(create)과 동시에 deploy를 진행합니다.
$ gcloud beta run jobs deploy ${JOB_SERVICE_NAME} -q \
--image=${DOCKER_IMAGE} \
--tasks 1 \
--task-timeout 60 \
--max-retries 1 \
--region=${GCP_REGION}
tasks: 작업이 완료된 것으로 간주되기 위해 완료될 때까지 실행해야 하는 작업 수입니다.
task-timeout : 작업 시도를 실행할 수 있는 최대 시간을 설정합니다.
max-retries : 작업이 영구적으로 실패하기 전에 실패한 경우 다시 시작할 수 있는 횟수입니다.
cloud run jobs을 deploy 한 후에 스케쥴러도 같이 생성해야 합니다.
$ gcloud scheduler jobs create http \
${SCHEDULER_NAME} \
--location=${GCP_REGION} \
--schedule=${CRON} \
--uri ${RUN_JOB_URL} \
--http-method=POST \
--oauth-service-account-email=${ACCOUNT_EMAIL} \
--oauth-token-scope="https://www.googleapis.com/auth/cloud-platform"
schedule: cron 형식으로 작성합니다. ex) 0 9 * * *
uri: 요청이 전송될 전체 URI 경로입니다. 다음과 같은 형식으로 작성합니다.
https://${GCP_REGION}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${GCP_PROJECT}/jobs/${JOB_SERVICE_NAME}:run
oauth-service-account-email : 작업을 실행할 때 대상으로 전송되는 요청에 포함할 OAuth2 액세스 토큰을 생성하는 데 사용할 서비스 계정 이메일입니다.
oauth-token-scope : 작업 실행 시 대상에게 보내는 요청에 포함될 OAuth2 액세스 토큰을 생성할 때 사용할 범위입니다. 지정하지 않으면 'https://www.googleapis.com/auth/cloud-platform'이 사용됩니다.
이번 프로젝트를 통해 개선하거나 변경된 점
배치 작업을 하려면 어떻게 해야 할까?
🔜 배치 작업은 일괄적으로 모아서 작업해야 하기 때문에 기존 서비스에 영향을 미쳐서는 안 되도록 서비스 분리를 생각했습니다.
gcp 환경에서 어떻게 배치 작업을 할 수 있을까?
🔜 cloud run jobs과 cloud scheduler를 이용해 배치 작업을 할 수 있도록 환경을 구성하였습니다.
👀 마무리
프로젝트를 하면서 한 번쯤 만나게 될 배치 작업에 대해서
어떻게 환경을 구성해야 하는지 배울 수 있었습니다.
또한 gcp를 사용하면서 조금 더 효율적으로
사용할 수 있는 방법을 찾아서 적용하기 위해 많은 공부가 되었습니다.
참고
https://cloud.google.com/sdk/gcloud/reference/beta/run/jobs/deploy
https://cloud.google.com/sdk/gcloud/reference/scheduler/jobs/create/http