안녕하세요. 오늘은 Amazon ECS를 이용해서 배포되고 있는 서비스의 무중단 배포를 이뤄냈던 방법에 대해서 설명드리려고 합니다.
여러분은 부디 장기 실행 태스크를 사용하지 마시고 행복한 개발을 하시기 바랍니다.
사용하더라도 장기 실행 태스크의 실행 환경을 서비스와 격리하고
서비스의 기능 시퀀스에 크게 영향을 주지 않도록 설계하셔야 합니다...! ㅜㅠ
1. 무중단 배포란
서비스를 운영하다보면 기능 추가 혹은 버그 수정을 위해서 서비스 업데이트가 필수적으로 진행되어야 합니다.
업데이트를 진행한다면 필연적으로 오래된 버전의 서비스는 종료되고, 새로운 버전의 서비스가 실행됩니다.
그러면 기존에 서비스를 이용하던 사용자들은 어떻게 될까요?
서비스와의 연결이 끊겨서 진행 중이던 작업이 끊기게 됩니다!
이러한 다운 타임은 사용자 경험을 저하시키고, 잠재적으로는 브랜드 평판을 저하시킬 수도 있습니다 😥
그래서 배포 중 다운타임을 없애거나 최소화하기 위해서 롤링 업데이트, 블루/그린 배포 등의 배포 전략이 있습니다.
- Amazon ECS 서비스는 직접적으로는 롤링 업데이트기능을 제공하고 있고, Code Deploy를 이용하여 블루/그린 배포를 진행할 수 있습니다.
2. 장기 실행 태스크란
"1에서 설명한 롤링 업데이트, 블루/그린 배포를 통해서 다운 타임을 없앨 수 있으니깐 끝인건가요?" 라고 생각하실 수 있지만 장기 실행 태스크라는 장애물이 남아있습니다.
장기 실행 태스크를 간단히 설명드리면 이미지 처리, 영상 처리 등의 장시간이 걸리는 작업들을 일컫습니다.
이런 장시간이 걸리는 작업들을 요청 받으면 쓰레드 혹은 프로세스로 따로 실행시키고 사용자에게 주기적으로 상태를 전달합니다.
온라인 동영상 인코딩 서비스를 예시로 들 수 있습니다.
사용자가 동영상 파일의 형식을 변환한다면 시간이 오래 걸릴 수 있죠?
이런 경우에는 동영상 변환 작업은 다른 워커( 쓰레드나 프로세스)로 실행시켜두고 작업이 완료되었을 때 완료 신호를 보내게끔 구현합니다.
그러면 이런 장기 실행 태스크가 왜 문제일까요?
제가 서비스를 이용하여 대용량의 wav 동영상 파일을 mp4 형식으로 변환하고 있고, 완료까지 1시간 남았다고 가정해봅시다.
만약 1시간이 다 지나지 않은 상태에서 서비스가 업데이트 되면 동영상 변환 작업 중인 워커가 작업을 완료하지 못한 상태로 종료되버립니다.
작업 상태가 저장되어 중단된 순간부터 재개할 수 있다면 다행이지만 그렇지 않다면 서비스에 대해 부정적인 평가를 내릴수 밖에 없겠죠...
그러면 Amazon ECS에서 장기 실행 태스크를 고려하면서 무중단 배포를 어떻게 이룰 수 있을까요?
3. ECS에서 제공해주는 배포 전략으로 해결되지 않나요?
정말 아쉽게도 ECS에서 제공해주는 배포 전략으로는 기존에 실행 중이던 장기 실행 태스크를 살릴 수 없습니다.
롤링 업데이트가 진행되면서 새로운 버전의 작업이 배포되면 자동으로 구버전의 작업이 종료되기 때문입니다.
구버전의 작업을 조금이라도 더 살릴 수 있는 방법은 없나 찾아봤지만 관련 설정값들이 없더라고요...
4. Task scale-in protection
어째서 ECS는 새 작업이 배포되었을 때 기존 작업을 자동으로 종료시켜버리는건지, 타임아웃을 지정할 수 없게한건지 한탄하고 있을 때...
가뭄의 단비같은 기능을 찾게 되었습니다!!!
Task scale-in protection(작업 종료 비활성화 기능)
실행되고 있는 작업들을 지정하여 scale-in을 비활성화 시킬 수 있는 것이죠!
이 기능을 이용하여 새로운 버전을 배포할 때 기존에 실행되고 있던 작업들의 scale-in을 비활성화시키면 장기 실행 태스크들을 지킬 수 있게 됩니다!
예시)
aws ecs update-task-protection --cluster CLUSTER_NAME --tasks TASK1_ID TASK2_ID --protection-enabled true --expires-in-minutes 300
그러면 scale-in이 비활성화 된 작업을 언제 종료시킬까요?
작업 속의 장기 실행 태스크가 전부 끝났을 때 종료시키면 됩니다!
5. 해치웠나...? - 라우팅 설정
장기 실행 태스크만 살리면 끝날줄 알았는데 라우팅 설정이 남아있습니다...
구버전 작업들의 scale-in을 비활성화 시켰더라도 한계가 존재합니다(최대 48시간).
결국 구버전의 작업들로 요청이 전달되지 않게끔 해야하는 것이죠!
5.1. 1차 시도
첫번째로 생각한 방법은 Route53에서 ECS의 서비스 디스커버리 기능으로 인해 생성된 라우팅 정책을 수정하는 것이었습니다.
하지만 ECS의 서비스 디스커버리 기능으로 인해 생성된 라우팅 정책은 수정이 불가능하더라고요 ㅜㅠ
5.2. 2차 시도
두번째로 생각한 방법은 작업 내부에서 업데이트 여부와 자신의 버전을 검사하여 만약 자신이 구버전 작업이란 것을 식별했다면 서비스 도메인으로 리다이렉션 시키는 것입니다.
꽤나 그럴싸한 방법이었고 동작하는 것도 확인할 수 있었습니다.
하지만 stopped after 10 redirection 이라는 에러가 뜨면서 API가 동작하지 않는다는 문제가 공유됩니다.
알고보니 라우팅 설정에는 TTL이라는 값이 있었고, 설정된 TTL 동안은 서비스 도메인으로 요청이 오더라도 이전에 라우팅되었던 작업으로 전달되는 것이었습니다.
그래서 구버전의 작업이 캐싱되어 있는 동안에는 리다이렉션을 하더라도 계속해서 구버전의 작업으로만 전달되는 것이었죠...
5.3. 3차 시도
마지막으로 라우팅 설정에서 TTL을 1초로 줄이고, 리다이렉션 할 때 0.1초의 지연시간을 주는 것으로 문제를 해결할 수 있었습니다.
6. 그건 제 잔상입니다만? - Keep Alive 옵션
라고 생각했지만 끝이 아니었습니다.
서버 프로그램에서 사용하고 있는 http 라이브러리가 기본적으로 Keep Alive 옵션을 활용하고 있어서 연결이 끊기지 않고 있었습니다!
진짜 진짜 마지막으로 구버전 작업들이 요청을 받으면 Keep Alive 옵션을 비활성화하도록 서버 코드를 수정했습니다.
- 어떤 서버 프레임워크 혹은 라이브러리를 쓰느냐에 따라 다르겠지만 Keep Alive 옵션을 비활성화하는 방법이 있을 거에요!
7. 네트워크 설정이 그렇게 빨리 완료될 거라고 생각하셨습니까? - Route53
2023.06.09
진짜 끝난줄 알았는데 Route53이 또 말썽을 부릴 줄은 몰랐네요...
ECS의 서비스에서 할당된 Domain Name으로 요청을 보내는데 계속해서 같은 태스크로 요청이 전달되더라고요.
지금은 새로운 태스크가 실행되고 Route53의 레코드가 추가되고 설정이 적용되기까지 시간이 소요되는 것으로 짐작하고 있습니다.
2023.06.23
클라우드 서비스 전문가분께 물어본 결과, 새롭게 실행된 태스크가 Route53의 레코드에 추가되기까지 1분 ~ 1분30초가 걸린 것을 확인하셨다고 하더라고요...
진짜 장기 실행 태스크는 만들지 마세요...
2023.07.09
문제가 해결된 줄 알았는데 한번씩 서버가 배포된 후에 502(Bad Gateway) 에러가 발생하더라고요!
이게 무슨 일이야 하고 로그를 분석하고 사례를 찾아보니 아뿔싸...
4. Task scale-in protection 에서 구버전의 작업에서 실행되고 있는 장기 실행 태스크가 전부 종료되면 작업을 종료한다고 했었는데,
구버전의 작업이 종료되고 어느 정도는 route 53의 레코드에는 해당 작업이 할당 받은 ENI의 IP가 남아있었던 것입니다.
저 말고도 이런 문제를 겪는 경우가 많더라고요 ㅋㅋㅋ ECS 이 놈들...
관련 사례 링크: https://github.com/aws/containers-roadmap/issues/708
ALB를 연동하여 ECS 서비스 간 통신을 지원하는 방법도 찾아봤지만 ALB 역시 라우팅 문제를 100% 해결해주지 못하는 것 같더라고요.
최종적으로는 http 통신을 사용하는 것이 아니라 다른 서비스를 통해서 pub/sub 방식을 이용하여 문제를 해결할 수 있었습니다.
여기까지가 장기 실행 태스크를 가지고 있는 서비스의 무중단 배포를 이뤄내기 위한 여정이었습니다!
저는 이번 경험으로 장기 실행 태스크를 어떻게 다뤄야 하는지 무중단 배포를 이루기 위해서 시스템을 어떻게 설계해야 하는지 공부할 수 있었습니다.
여러분에게도 유익하고 재밌는 사례가 되었으면 좋겠네요 ㅎㅎ
'aws' 카테고리의 다른 글
Amazon NAT Gateway - Network Address Translation이 왜 필요한 것일까요? (0) | 2023.09.01 |
---|---|
AWS 고정 IP 할당 방법 - egress 네트워크 트래픽편(EIP, NAT Gateway) (4) | 2023.08.24 |
Amazon ECS Graceful Shutdown - ECS를 안정적으로 사용하려면 SIGNAL은 처리해줘야죠! (0) | 2023.06.23 |
AWS 고정 IP 할당 방법 - ingress 네트워크 트래픽편(EIP, NLB, ALB[Global Accelerator]) (2) | 2023.05.28 |
Amazon Dynamodb global secondary index - 기간별 검색 최적화 (0) | 2022.10.22 |