목차
SQS와 Kubernetes로 만든 차량 파손 탐지 모델 서빙 (2020-03)
원문 정보
- 원문: 딥러닝 모델 Serving 간단 구축기
- 매체 · 게시일: 쏘카 기술 블로그 · 2020-03-10
- 저자: 토마스
- 원문 내용을 바탕으로 재구성한 요약입니다.
사람 눈으로 보던 8만 장
쏘카는 차량을 운행하기 전에 사용자가 각 부분의 사진을 찍어 올리게 합니다. 약 3개월 전까지는 차량 검수팀이 이 사진을 눈으로 확인했습니다. 하루 업로드가 8만 장 정도여서 전수조사가 어려웠고, 다른 업무에 밀려 표본 조사도 쉽지 않았습니다. 그래서 딥러닝으로 파손을 판정하는 모델을 만들고 이를 운영하는 시스템을 짓는 프로젝트가 시작됐습니다.
Kubeflow, SageMaker, AutoML 같은 종합 플랫폼도 검토했습니다. 쓰는 법을 익혀 입맛에 맞추기까지 허들이 있고 일부는 빠르게 바뀌어 서비스에 쓰기엔 불안하다고 봤습니다. 데이터 엔지니어링팀은 모델을 안정적으로 서빙하는 데 집중해, 짧은 기간에 만들어 사내 시스템과 붙이는 쪽을 택했습니다.
큐로 분리한 사내 시스템과 모델
사용자가 올린 사진은 S3에 저장되고 개발본부가 관리하며, CloudFront를 거쳐 인증 후 접근합니다. 사내 시스템과 모델 사이 인터페이스는 AWS SQS로 정했습니다. 이유는 세 가지입니다. 만들고 쓰기 쉽고, 검수 시스템이나 모델이 바뀌어도 서로 영향이 작고, 처리량 변화에 맞춰 유연하게 늘릴 수 있습니다.
사내 시스템은 판정할 이미지의 URL과 기타 정보를 메시지로 묶어 큐에 넣습니다. 모델 쪽은 큐를 폴링해 받아 와 판정하고 결과를 갱신합니다. 메시지는 단순한 JSON입니다. 초당 수십에서 수백 건으로 늘면 Protocol Buffers를 고려할 만하다고 적었습니다. SQS는 처리량 제한이 없지만 메시지 보관 기간이 있어서 그 안에 꺼내 가야 합니다.
Agent와 자동 확장
모델이 판정에 집중하는 동안 사내 시스템과의 연동을 맡는 서빙 프로그램을 Agent라고 부릅니다. Python으로 작성해 Docker 이미지로 만들었고, 모델은 PyTorch로 개발됐습니다. Agent의 일은 네 가지입니다.
- 시작할 때 S3에서 모델 가중치를 내려받아 초기화한다
- SQS에서 메시지를 한 건씩 받아 이미지 URL을 모델에 넘긴다
- 판정 결과 이미지는 S3에, 관련 정보는 데이터베이스에 저장한다
- 로그는 Fluentd로 모아 S3에 저장한다
네트워크 레이어가 7개라 가중치가 커서 이미지에 넣지 않았습니다. 재학습으로 가중치가 바뀔 때마다 이미지를 다시 빌드하는 불편도 피하려는 선택입니다. 이미지 한 장을 분석하는 데는 3~10초가 걸립니다.
판정 작업끼리 의존성이 없고 큐 순서도 중요하지 않아 Agent를 늘리면 처리량이 그만큼 늘어납니다. 평일과 주말, 낮과 밤의 업로드 편차가 커서 Kubernetes에 올리고 노드는 Spot Instance로 지정했습니다. Pod에 리소스 한도를 두어 작업량에 따라 확장되게 했습니다. 작업이 없을 때는 노드 1대에 Pod 2개가 대기하고, 메시지가 쌓이면 노드 5대에 Pod 14개까지 늘었다가 큐가 비면 원래대로 돌아옵니다.
Agent가 응답 없이 떠 있는 좀비 상태를 잡으려고 livenessProbe를 썼습니다. Agent가 SQS를 폴링할 때마다 heartbeat 파일을 갱신하고, 일정 시간 갱신이 멈추면 Kubernetes가 Pod를 지우고 새로 띄웁니다. 오류는 슬랙 채널로 알립니다.
Git과 Rancher로 단순화한 배포
배포와 모니터링에는 Rancher를 썼습니다. 개발본부가 이미 쓰고 있어 고민 없이 채택했다고 합니다. 브랜치는 master, release, develop으로 나뉩니다. release 브랜치에 머지하면 이미지를 빌드해 검증 환경에 배포하고, 시험을 통과하면 master에 머지합니다. 새 버전 Tag를 달 때만 그 Tag로 빌드해 운영 환경에 배포합니다. master에 실수로 머지되더라도 운영 배포가 일어나지 않게 하려는 장치입니다.
Tag가 바뀌지 않으면 Rancher Pipeline이 배포를 건너뜁니다. latest 같은 Tag를 쓴다면 Rancher UI에서 직접 Redeploy해야 합니다. 모니터링은 Rancher 기본 기능만 씁니다. Spot 노드라 수가 계속 변하고 현재 상태만 보면 충분해서 Prometheus와 Grafana는 쓰지 않았습니다. Pod의 stdout 로그는 Rancher UI에서 실시간으로 볼 수 있습니다.
원문은 약 한 달 안에 만드는 것이 목표여서 깊은 고려를 못 한 부분이 있다고 인정했습니다. 앞으로는 모델 성능을 모니터링하고 새 이미지로 재학습하는 체계로 넓힐 계획입니다.