본문 바로가기

Trouble Shooting

롤링 업데이트 health check fail issue

개요

회사에서 본인이 개발 중인 프로덕트는 총 8대의 ec2 인스턴스를 관리하는 elastic beanstalk 리소스로 운영되고 있다. 무중단 배포를 위하여 4대씩 총 2개의 배치로 나누어 롤링 배포를 한다. 프레임워크는 next.js 를 사용하고 있다. 이때 정적파일들을 cdn을 통하여 제공하기 위해 assets_path를 새롭게 정의한 커밋을 포함한 배포가 실패하는 이슈가 발생하였다.

재현 과정 및 현상

  1. 배포 시작
  2. 1번째 배치 배포 시작
  3. 배포 완료
  4. 1번째 배치 health check fail
    4-1. 원인은 4xx 응답률 40%~50%
    4-2. cdn 적용전 즉, 기존에 was에서 제공하고 있던 경로로 정적파일을 브라우저에서 계속 요청 중인 현상 발생.
  5. 배포 실패
  6. 운영환경에서 간헐적으로 빈 화면이 계속 로드됨.
  7. 버전 롤백으로 장애 해소

원인

롤링 배포


배치를 처리할 때 Elastic Beanstalk는 (2)배치에 있는 모든 인스턴스를 로드 밸런서에서 분리하고 (3)새 애플리케이션 버전을 배포한 다음, 인스턴스를 다시 연결한다.
이때, Elastic Load Balancing 은 인스턴스가 최소한의 Elastic Load Balancing 상태 확인(health check)을 전달할 때까지 기다린 다음 그 인스턴스로 트래픽을 라우팅하기 시작한다.
Elastic Beanstalk 는 배치에 있는 모든 인스턴스가 정상 상태가 될 때까지 대기한 후 다음 배치로 이동한다. 기본 상태 보고를 사용할 경우 인스턴스 상태는 TCP 연결 수락 혹은 상태확인 url 로 http 200 OK를 응답하는지 검사하는 Elastic Load Balancing health check에 의존하지만,
확장 상태 보고가 활성화 된 경우 Elastic Beanstalk는 모든 인스턴스가 웹 서버 환경에 대해서 2분 내에 12회 연속으로 OK 상태의 상태 확인을 전달해야 하며, 작업자 환경에 대해서는 3분 내 18회의 상태 확인을 전달해야 한다.
Elastic Load Balancing health check은 통과하였지만 (새로 배포된 인스턴스에 라우팅이 되었으므로) 본 프로덕트는 확장 상태 보고가 활성화 되어 있어 별도로 확장 health check 이 필요하고, 이 단계에서 배포가 실패한 것으로 보인다.

  • ELB health check 성공 -> 배포 성공한 1번째 배치 라우팅 가능 -> 확장 health check -> fail

롤링 배포가 실패한 경우 완료된 배치는 새로운 버전을 실행하는 반면, 대기 중인 배치는 계속 기존 버전을 실행한다. 이런 버전 불일치가 배포 실패 이후 30분 가량 간헐적으로 빈 화면이 로드되는 현상이 지속되었던 이유일 것이다.

왜 확장 Health Check Fail?

그렇다면 왜 Elastic Load Balancing health check 이후 확장 health check 단계에서 4xx 응답률이 50% 가까이 나와 배포 실패가 되었을까?


배치 1(최신 버전), 배치 2(이전 버전) 이라고 가정하자.

  1. 둘다 로드밸런서에 연결되어있으므로 사용자는 배치 2로 연결될 수 있다.
  2. SSR 이 끝난 document 를 응답받는다.
  3. 이후 hydration 을 위해 브라우저에서 다시 js chunk 파일들에 대한 요청을 한다. 하지만 로드밸런서에서 해당 요청을 배치 1로 라우팅 되는 케이스가 발생한다

url로 접근시 배치 2로 라우팅된 사용자가 이전과 같이 was로 정적파일 요청을 보낼 때 로드 밸런서가 배치 1로 라우팅을 해준다면 404 에러가 발생하는 것이다. 이는 배치 1은 정적파일을 더 이상 was 에서 제공하지 않고, cdn 에서 제공하기 때문이다.

 

롤링 배포를 시도한다면 이전 버전과 최신 버전이 동시에 떠있는 step 이 항상 존재하므로 하위 버전과의 호환성을 고려해야한다.

 

이전에 하위 호환성을 고려하지 않고 배포가 가능했던 것은 변경사항에 대한 서버요청이 상태확인 임계치를 넘지 않아서일 것이다. 아무래도 페이지 접근시 항상 대량 요청하는 static 파일만큼의 요청은 없었을 것이다.
하지만 이전 버전과 최신 버전이 동시에 로드벨런서에 연결된 상태에서도 완벽한 무중단 배포를 위해선 분명히 고려를 해야할 부분이다.

해결 방법들

상태 확인 무시: True

배포 중 health check 을 무시하고 다음 배치를 진행하도록 하는 설정이다. 상태확인무시를 true 로 설정해도 명령 제한 시간 동안은 다음 배치가 진행되지 않으므로 이 옵션을 사용하고자한다면 명령 제한 시간도 10 정도의 낮은 값으로 수정하는 것을 권장한다.

S3에 정적파일 미리 업로드

was 에서 제공 중인 정적파일이 배치 1에선 더이상 제공하지 않는 것이 문제였으므로, 항상 정적파일을 제공할 수 있는 S3에 정적파일을 미리 업로드한다.

  • 빌드 파일을 접근가능한 s3 에 업로드한다.
  • ssh 로 인스턴스에 직접 접근하여 next 애플리케이션에서 사용 중인 ASSETS_PATH 를 직접 수정한다.

다만 임시로 파일을 업로드할 s3 설정이 사용하고자 하는 cdn 버킷과 설정이 동일한지 다시 확인해봐야 한다.
실제로 S3에 정적파일을 업로드하여 링크를 수정해주었는데, 해당 버킷은 CORS 설정이 되어있지 않았던 차이가 있었고 이는 다른 장애로 이어졌다.

기본상태보고 사용

기본상태보고 옵션을 사용할 경우 health check 을 elb 단계에서만 수행하기 때문에 다음 배치로 바로 넘어 갈 수 있다. (테스트는 안해봄)

Blue/Green 업데이트

blue/green 배포에서는 새 버전을 별도의 환경에 배포한 후 두 환경의 CNAME 을 바꿔 트래픽을 새 버전으로 즉시 리다이렉션한다.
실제로 AWS 에서도 호환되지 않은 버전을 새로 배포할 때는 blue/green 배포를 권장한다.

다른 런타임, 웹서버, 어플리케이션 서버 또는 운영체제를 포함하는 다른 플랫폼 브랜치의 플랫폼 버전 또는 다른 메이저 플랫폼 버전으로 업데이트할 때 이 방법을 사용하는 것이 좋습니다.
레거시 플랫폼 버전에서 마이그레이션하려면 블루/그린 배포가 필요합니다. 이러한 플랫폼 버전이 현재 지원되는 버전과 호환되지 않기 때문입니다.

다만 두 개의 환경이 별도로 필요하기 때문에 비용 부담이 발생한다.

참고

'Trouble Shooting' 카테고리의 다른 글

알고리즘, FE 실무에 적용하기  (0) 2024.03.31
내 블로그가 검색되지 않는다  (2) 2022.11.07