ECS 서비스 오토스케일링, 늘릴 때와 줄일 때가 다른 이유
ECS 서비스에 자동 확장을 걸면 태스크는 빨리 늘어나고 천천히 줄어든다.
목표 추적 정책이 늘릴 때는 서두르고 줄일 때는 보수적으로 움직이도록 만들어져 있고, 줄이는 순간에는 처리 중인 요청이 끊길 수 있기 때문이다.
이 글의 목차자동 확장은 지표를 보고 개수를 바꾼다6
ECS 서비스에 자동 확장을 켜면 최소 태스크 수와 최대 태스크 수, 그리고 정책을 정하는 칸이 나온다.
ECS에서 같은 컨테이너를 여러 개 띄워 두는 단위가 서비스이고, 띄운 하나하나가 태스크다.
정책에는 평균 CPU 사용률 50% 같은 목표를 하나 적는다.
켜 두고 부하가 오르내리는 것을 지켜보면 이상한 점이 하나 보인다.
부하가 오르면 태스크가 금방 늘어나는데, 부하가 내려간 뒤에는 한참 동안 그대로다.
설정을 잘못한 것처럼 보이지만 원래 그렇게 동작하도록 만들어져 있다.
자동 확장은 지표를 보고 개수를 바꾼다
ECS의 서비스 자동 확장은 서비스가 유지할 태스크 수를 자동으로 늘리고 줄이는 기능이다.
계산은 Application Auto Scaling이라는 별도 서비스가 맡는다.
판단 근거는 AWS의 지표 수집 서비스인 CloudWatch에 쌓이는 지표다.
ECS는 서비스의 평균 CPU와 메모리 사용률을 1분 간격으로 CloudWatch에 보낸다.
지표를 보고 개수를 바꾸면, 바뀐 개수가 다시 지표에 반영된다.
태스크를 늘려 요청을 나눠 받으면 평균 CPU 사용률이 내려가는 식이다.
AWS가 가장 쓰기 쉬운 방식으로 꼽는 것은 목표 추적(target tracking)이다.
지표 하나와 목표값을 정해 두면, 지표가 목표값 근처에 머물도록 태스크 수를 조정한다.
목표 추적 정책을 만들면 Application Auto Scaling이 필요한 CloudWatch 알람을 대신 만들고 관리한다.
지표가 목표보다 높으면 태스크를 더하고, 낮으면 뺀다.
늘릴 때와 줄일 때 속도가 다르다
목표 추적 정책은 두 방향을 같은 속도로 움직이지 않는다.
지표가 목표를 넘으면 이미 부하가 많이 걸렸다고 보고, 지표 값에 비례해 할 수 있는 한 빨리 늘린다.
줄일 때는 조심스럽다.
태스크 하나를 뺐을 때 지표가 다시 목표를 넘을 것 같으면 줄이지 않고, 대개 목표보다 10% 넘게 낮아졌을 때 줄인다.
부하가 확실히 내려간 뒤에만 줄이려는 설계다.
태스크는 1.5개처럼 나눌 수 없으니 계산 결과를 올리거나 내리는 것도 보수적으로 한다.
1.5개가 필요하면 2개를 더하고, 0.5개를 뺐을 때 목표를 넘을 것 같으면 빼지 않는다.
태스크 수가 적은 서비스에서 지표가 목표보다 꽤 낮게 머무는 것은 이 때문이다.
정책을 여러 개 걸었을 때도 같은 방향으로 기운다.
하나라도 늘리자고 하면 늘리고, 모든 정책이 줄일 준비가 됐을 때만 줄인다.
쿨다운이 있는 이유
늘린 태스크가 뜨고 요청을 받기 시작해서 그 효과가 지표에 나타나기까지는 시간이 걸린다.
그동안 지표는 여전히 목표 위에 있다.
그 값만 보고 또 늘리면, 효과가 다 나타난 뒤에는 필요보다 많은 태스크가 남는다.
그래서 정책에는 직전 조정이 효과를 낼 때까지 기다리는 쿨다운이 있다.
ECS 서비스의 기본 쿨다운은 300초다.
확대 쿨다운 동안에는 더 큰 확대가 필요할 때만 다시 늘리고, 그때도 직전에 늘린 태스크를 계산에 넣는다.
축소 쿨다운 동안에는 축소가 막히지만, 그사이 확대가 필요해지면 쿨다운을 멈추고 바로 늘린다.
목표 CPU 사용률은 50%이고, 지금은 태스크 4개가 75%로 일한다. 새 태스크가 지표에 반영되기 전에 평가가 두 번 더 돈다고 보고 두 방식을 비교한다.
지표가 읽은 값 75% · 태스크 4개 때 값
평가 ① · 원하는 태스크 6개
평가 ② · 원하는 태스크 6개
평가 ③ · 원하는 태스크 6개
부하가 나뉜 뒤 평균 사용률 50%
목표 50%에서 태스크 4개가 75%로 일하면 6개가 필요하다. 반영 전의 75%를 보고 매번 다시 계산하면 9개, 14개로 늘지만, 확대 쿨다운 동안 직전에 늘린 개수를 계산에 넣으면 6개에서 멈춘다.
직전에 늘린 2개를 다음 계산에 넣어 6개에서 멈춘다. 부하가 6개에 나뉘면 평균 사용률은 목표인 50%다.
부하가 태스크에 고르게 나뉘고 두 번의 평가 동안 지표가 바뀌지 않는다고 단순화한 예시다. AWS 정책의 실제 계산식이나 측정한 값이 아니다.
줄이는 순간 끊기는 요청
늘리는 쪽은 조금 늦어도 기존 태스크가 계속 일한다.
줄이는 쪽은 돌고 있는 태스크를 골라 멈추는데, 그 태스크가 그 순간 요청을 처리하고 있을 수 있다.
로드밸런서 뒤에 있는 태스크를 멈출 때 ECS는 먼저 대상 그룹에서 등록을 해제하고, 그다음 컨테이너에 종료 신호(SIGTERM)를 보낸다.
정해 둔 시간이 지나도 살아 있으면 강제로 종료한다.
등록을 해제하는 동안 로드밸런서는 새 요청을 보내지 않고 진행 중인 요청을 기다린다.
ALB 글에서 본 등록 해제 지연이다.
AWS는 기본 300초인 이 값을 응답이 빠른 서비스라면 줄이라고 권하면서도, 오래 걸리는 요청이 있으면 줄이지 말라고 한다.
종료 신호를 받은 앱이 쓸 수 있는 시간은 컨테이너 설정의 stopTimeout 값으로 정하고, Fargate에서는 기본 30초에 최대 120초다.
큐에서 꺼낸 작업처럼 요청 밖에서 하던 일은 이 시간 안에 끝내야 한다.
헷갈리기 쉬운 것이 쿨다운과 이 대기 시간이다.
쿨다운은 개수를 바꾼 뒤 다음 조정까지 기다리는 시간이고, 등록 해제 지연과 stopTimeout은 태스크 하나를 멈추면서 기다리는 시간이다.
지표가 늦거나 비면
판단 근거도 늦게 도착한다.
지표는 정해진 간격으로 모이고, 모인 뒤에 평가되고, 평가된 뒤에야 조정이 시작된다.
새 태스크가 떠서 요청을 받기까지도 시간이 든다.
그래서 결정은 늘 조금 전 상황을 보고 내려진다.
간격이 길면 반응도 통째로 밀린다.
EC2 지표는 기본적으로 5분 간격으로 보내지고, 1분 간격으로 바꾸려면 세부 모니터링을 켜야 한다.
지표가 아예 끊기기도 한다.
지표에 값이 비어 정책의 알람이 데이터 부족(INSUFFICIENT_DATA) 상태가 되면, 새 데이터가 들어올 때까지 확장이 이뤄지지 않는다.
알람의 이 세 번째 상태는 CloudWatch 글에서 자세히 다룬다.
배포 중에도 축소는 멈춘다.
ECS 배포가 진행되는 동안 Application Auto Scaling은 축소를 끄고 확대만 계속한다.
처음 설정할 때 정해 둘 것
지표는 대상이 얼마나 바쁜지를 나타내고, 태스크 수가 늘어난 만큼 값이 내려가는 것을 고른다.
평균 CPU 사용률이나 대상당 요청 수가 그런 지표다.
목표값은 비용을 생각해 되도록 높게 잡되, 갑자기 몰리는 트래픽을 받을 여유는 남겨 둔다.
쿨다운은 기본값으로 시작하고, 짧은 변화에 늘렸다 줄였다를 반복하면 그때 늘린다.
줄이는 쪽은 태스크가 멈추는 과정과 함께 맞춘다.
등록 해제 지연은 가장 오래 걸리는 정상 요청보다 길게 잡고, 앱은 SIGTERM을 받으면 새 일을 받지 않고 하던 일을 stopTimeout 안에 끝내도록 만들어 둔다.