IL-0188 Yonghyun Kim · 2025-11-09 (게시일)kubernetesaws
작성자의 팀은 EKS 에서 ALB 를 앞에 두고 Service 와 파드를 뒤에 둔 마이크로서비스를 운영했다. 롤링 업데이트를 할 때마다 배포는 성공으로 끝났지만 사용자는 502 를 받았다.
원인은 Kubernetes 와 ALB 가 준비 상태를 판단하는 시점이 다르다는 데 있었다. Kubernetes 는 컨테이너가 실행 중이고 readinessProbe 가 성공하면 파드를 Ready 로 보고 EndpointSlice 에 넣은 뒤 옛 파드를 지운다. ALB 는 새 파드 IP 를 대상 그룹에 등록한 뒤 initial 상태로 두고, 헬스 체크를 두 번 연속 통과해야 healthy 로 바꿔 트래픽을 보낸다. 이 과정에 최소 30초에서 40초가 걸린다. 그 사이 옛 파드는 이미 사라지거나 draining 중이고 새 파드는 아직 healthy 가 아니어서, ALB 가 트래픽을 보낼 곳이 없었다.
작성자는 파드가 종료될 때도 502 가 날 수 있다고 설명한다. 파드에 SIGTERM 이 가는 시점과 EndpointSlice 에서 빠지는 시점이 같은데, ALB 가 대상을 빼기까지는 몇 초가 더 걸려 그동안 종료 중인 파드로 트래픽이 갈 수 있다.
작성자는 사흘 동안 디버깅한 끝에 네임스페이스에 elbv2.k8s.aws/pod-readiness-gate-inject=enabled 레이블을 붙였다. AWS Load Balancer Controller 의 웹훅이 파드에 ReadinessGate 를 넣고, 파드는 ALB 대상이 healthy 가 된 뒤에야 Ready 가 됐다. 적용 뒤 배포 10번 동안 502 는 한 번도 나지 않았다. 대신 파드가 Ready 가 되기까지 10초에서 45초로 늘었다. 작성자는 종료 쪽을 다듬는 설정으로 preStop 의 sleep 15 와 terminationGracePeriodSeconds 30, 대상 그룹 deregistration_delay 30초, ALB 헬스 체크 주기 15초를 함께 권한다.
새벽 3시에 "배포는 성공했는데, 서비스는 죽었다"는 Slack 메시지가 왔다. 모든 파드는 Ready 였고 Datadog 도 초록불이었지만, 사용자는 계속 오류 화면을 보고 있었다.
롤링 업데이트 중에 새 파드가 Running 과 Ready 가 되고 옛 파드가 Terminating 으로 바뀌는 바로 그때, 사용자는 HTTP/1.1 502 Bad Gateway 를 받았다. Datadog 로그에는 [02:34:11] ALB HealthCheck: 10.0.1.50:8080 → initial 다음에 Request → 502 Bad Gateway (no healthy targets) 가 이어졌고, [02:34:41] 에 대상이 healthy 가 된 뒤에야 200 OK 가 돌아왔다.
이 현상은 롤링 업데이트마다 났다. 배포 10번 중 10번 모두 오류가 났다. 오류는 평균 28초 이어졌고, 배포 한 번에 502 가 평균 156개 났으며, 영향받은 사용자는 약 50명에서 100명이었다. 새벽 호출도 한 달에 3번 있었다. 서비스는 EKS 에서 ALB 뒤에 Service 와 파드를 둔 구조였다.
처음에는 terminationGracePeriodSeconds 를 300초로 늘려 보았다. 오류는 줄었지만 레플리카 3개 배포가 15분으로 늘었고, 애플리케이션은 정상 종료되지 않고 기다리다 SIGKILL 로 죽었다. 무엇보다 새 파드가 뜰 때 생기는 공백은 그대로 남았다.
새벽 3시에 "배포는 성공했는데, 서비스는 죽었다"는 Slack 메시지로 알았다. 파드 상태와 Datadog 대시보드는 모두 정상이었고, 장애는 사용자가 보는 화면에만 나타났다.
–
Kubernetes 의 Ready 와 ALB 의 healthy 는 서로 다른 시점에 정해지므로, 둘을 잇는 장치가 없으면 롤링 업데이트 때 502 가 날 수 있다. 파드 상태와 대시보드가 모두 정상이어도 사용자는 오류를 볼 수 있다. terminationGracePeriodSeconds 를 늘려 시간을 버는 방식은 배포만 느리게 하고 새 파드가 뜰 때의 공백은 막지 못한다. ReadinessGate 는 ALB 대상 유형이 ip 일 때만 의미가 있고, instance 모드에서는 노드가 대상이라 쓸 수 없다. ReadinessGate 를 쓰면 파드가 Ready 가 되기까지 30초에서 40초가 더 걸리므로 급한 스케일 아웃에 대비해 레플리카나 HPA 를 넉넉히 잡는다. 웹훅의 failurePolicy 를 Ignore 로 두면 컨트롤러가 죽어도 배포가 막히지 않는다.
같은 원인 · 공통 인그레스 컨트롤러
같은 원인 · 공통 인그레스 컨트롤러