ALB Ingress Controller를 사용하는데 부하가 늘어나서 노드가 늘면 전체 Pods가 트래픽을 1분 정도 못 받습니다
주말에 이런 질문을 받아서 생각나는대로 두서없이 설명했는데 이번에 내부 교육자료겸 글로 정리한다.
미흡한 헬스체크
기본적으로 502 계열이 나면 헬스체크가 충분히 제대로 구현 안 됐을 가능성이 높습니다. 애플리케이션 서버가 준비가 안 됐는데 트래픽을 받아서 문제가 발생하는 게 대부분입니다. liveness
와 readiness
그리고 initialdelayseconds
등이 주요 설정값이니 신중하게 설정하시기 바랍니다.
미들웨어 연결제한
반대 경우도 있는데 대부분 Spring Boot 로 구현한 경우입니다. 스프링부트의 actuator 헬스체크는 구현이 잘 되어 있어서 데이터베이스 등 미들웨어의 상태를 계속 들여다봅니다. 보통 애플케이션 헬스체크를 구현하라 하면 그냥 에코 API 정도로 구현하는 것과 많이 다르죠. 이런 상황에서 흔한 문제 패턴은
오토스케일링 발동 -> 파드 증가 -> 데이터베이스 등 미들웨어의 연결 증가 -> 연결제한도달 -> 새/기존 파드의 헬스체크 실패 -> 파드의 전면적인 재기동 (전체 셧다운)
입니다.
후자라면 당연히 오토스케일링 가능한 애플리케이션 개수를 측량해서 한계를 둬야 합니다. 그리고 안전책으로 deployment를 두 개쯤 두고 헬스체크 주기 등 설정 값을 바꿔서 모든 파드가 일시에 내려가지 않게 방어하면 됩니다. Pod Distruption Budget을 활용하는 방법도 있습니다.
그리고 Pods가 전면 재기동했다면 Restart 회수가 기록됐을 겁니다. kubectl get pod
로 재기동 회수를 확인하면 됩니다.
ALB HealthCheck 트래픽의 증폭
ALB Ingress Contoller는 NodePort 서비스를 이용해 Pods와 통합니다. 노드포트 서비스의 기본 ExternalTrafficPolicy
값은 cluster
입니다. 이 경우에 전체 노드가 ALB에 붙는데 예를 들어 백 대의 서버가 있고 파드는 셋인 경우라면 ALB 헬스체크가 본인들이 생각하는 것보다 33배 더 들어옵니다. 파드는 셋이지만 ALB는 백 대로 봐서 주기적으로 각 노드에 헬스체크를 보내기 때문이죠.
앞서 서술한 경우에 평소에 노드가 100대인데 오토스케일링이 발동했을 때 200대가 된다면 문제는 증폭됩니다. Pod가 세 대이니 ALB 헬스체크는 3대 분량이 아닌 200대 분량이 들어옵니다. 이 트래픽을 제대로 받아내질 못하면 3대의 파드는 먹통이 됩니다. EC2와 함께 Pods를 오토스케일링하더라도 신규 파드가 초기화를 끝내기 전에 앞서 초기화를 끝낸 파드가 트래픽을 먼저 받고 쓰러지기 때문에 전체 서비스가 다운되는 효과가 발생합니다.
CPU Credit 소진
AWS의 Tx 타입의 인스턴스를 사용한다면 초기화에 CPU를 상당히 요구하는 스프링 애플리케이션은 조심해서 다뤄야 합니다. 짧은 시간 내에 다수의 애플리케이션 서버를 배포하는 경우에 다음과 같은 시나리오에 걸릴 수 있습니다.
애플리케이션 배포 -> CPU 크레딧 소진 -> 평소보다 초기화 지연 -> Readiness 체크 실패 -> 실패한 파드 재기동 -> CPU 크레딧 소진
의 고리에 빠져서 망합니다. 이 고리에서 빠져나오는 방법은 전면적인 인스턴스 termination과 교체밖에 없습니다.