IL-0231 Stytch · 2023-02-23kubernetesaws
EKS 클러스터의 워커 노드가 모두 꺼지고 새 노드가 뜨지 않아 Stytch API 가 14분 동안 완전히 멈췄다
Stytch 는 AWS EKS 위에서 서비스를 돌리고, 클러스터와 관리형 노드 그룹 같은 클라우드 리소스를 Crossplane 으로 코드로 관리한다. 2022년 상반기부터 Fargate 에서 EC2 노드로 옮겨, 크기가 고정된 관리형 노드 그룹과 Karpenter 가 그때그때 띄우는 자체 관리 노드를 함께 썼다. 1년쯤 지나 팀은 Karpenter 를 충분히 믿게 되자 데이터 플레인 애플리케이션용 관리형 노드 그룹을 없애기로 했다.
팀은 2023-02-23 14:21 UTC 에 쓰지 않는 관리형 노드 그룹을 지우는 변경을 반영했다. Crossplane 리소스는 orphan 삭제 정책이라 AWS 콘솔에서 직접 지워야 했다. 두 엔지니어가 스테이징부터 작업했다. 이때 콘솔은 워커 역할이 aws-auth ConfigMap 에서 빠져 자체 관리 노드 그룹에 영향이 갈 수 있다고 경고했다. 팀은 이 ConfigMap 도 Crossplane 이 곧바로 되살릴 것이라 보았고, 스테이징에서 문제가 없자 운영에도 같은 변경을 했다. 그런데 AWS API 는 AWS 문서에 없는 정리 호출을 뒤에서 했다. CloudTrail 로그를 보니 노드 그룹 삭제가 instance profile 삭제로 이어져 있었다. 스테이징은 14:24 UTC, 운영은 14:50 UTC 에 instance profile 이 지워졌다. Crossplane 이 역할은 다시 만들었지만, Cluster Composition 이 이전 이름 대신 무작위 이름을 정했다. Karpenter 설정은 이전 이름에 기대고 있었다. 그래서 Karpenter 는 새 노드를 띄울 권한이 없었다. Karpenter 노드와 노드 그룹이 같은 IAM 역할을 쓰고 있어서 이런 문제가 났다.
문제는 지워진 instance profile 을 다시 쓰려 할 때 드러났기 때문에 몇 시간 뒤에야 나타났다. 16:06 UTC 와 17:48 UTC 에 스테이징과 운영에서 낮은 긴급도 경고가 왔지만 급하지 않은 문제로 분류되었다. 19:54 UTC 에 스테이징 노드가 꺼지기 시작했고, 20:13 UTC 부터 운영 노드가 Ready:Unknown 이 되며 하나씩 종료되고 파드가 쫓겨났다. Karpenter 는 새 노드를 띄우지 못했다. 팀은 20:26 UTC 에 장애 대응을 시작했고, 21:00 UTC 에 노드 그룹 삭제를 되돌렸다. 하지만 새 노드가 뜨는 동안 파드가 빨리 스케줄되지 않아 21:10 UTC 에 API 가 내려갔다. 팀은 Live API 노드 그룹 하나를 훨씬 큰 노드로 늘리고 taint 와 애플리케이션의 node selector 를 차례로 지워 파드를 스케줄했다. 21:24 UTC 에 Live API, 21:34 UTC 에 Dashboard 와 Frontend SDK, 21:36 UTC 에 Test API 가 돌아왔다. Live API 는 14분, Frontend SDK 와 Dashboard 는 17분 동안 완전히 멈췄다.
사고 뒤 AWS 는 DeleteNodegroup 이 문서에 없는 연쇄 동작을 일으킨다고 확인했다. DeleteNodegroup 은 워커 노드를 drain 하고 파드를 쫓아낸다. 이어 서비스 역할이 노드 그룹과 엮인 역할, 정책, 보안 그룹 같은 리소스를 지우고, 마지막으로 워커 노드 인스턴스를 종료한다. AWS 는 원인과 결과 사이의 지연도 예상된 동작이라고 확인했다.
- 심각도
- –
- 영향 범위
- Full outage of the Live Stytch API for 14 minutes and of the Stytch Frontend SDKs and Dashboard for 17 minutes; the production Test API was down from 21:10 to 21:36 UTC
- 영향 사용자
- –
- 지역
- –
- 감지까지
- –
- 복구까지
- –
증상
2023-02-23 20:48 UTC 에 운영 환경에서 Deployment Replicas Unavailable 알림이 울리기 시작했다. 21:10 UTC 에 운영 Live API 와 Test API 가 내려가 Stytch API 호출이 모두 5XX 를 냈고, 21:17 UTC 에는 Dashboard 와 SDK 도 내려갔다.
첫 경고는 몇 시간 앞서 왔다. 16:06 UTC 에 스테이징에서 Karpenter 가 지정된 instance profile 을 찾지 못해 새 노드를 띄울 수 없다는 낮은 긴급도 경고가 왔고, 17:48 UTC 에 운영에서도 비슷한 경고가 왔다. 기존 배포가 정상이고 새 파드도 스케줄되고 있어서 당직 엔지니어는 그날 안에 고치면 되는 문제로 판단했다.
19:54 UTC 에 스테이징의 기존 노드가 꺼지기 시작했고 kube-proxy 상태 알림이 왔다. 이때 운영은 아직 정상으로 보여 팀은 스테이징 문제와 원인에 집중했다.
20:13 UTC 에 운영의 첫 노드가 쿠버네티스 컨트롤 플레인에서 Ready:Unknown 으로 표시되었다. 지워진 instance profile 을 쓰던 노드들이 그 profile 을 쓰려 할 때마다 하나씩 종료되었다. Unknown 상태로 5분이 지나면 taint controller 가 unreachable taint 를 걸어 그 노드의 파드를 모두 쫓아냈다. Karpenter 는 지워진 instance profile 로 새 노드를 띄우려다 실패했고, 스케줄되는 파드가 점점 줄었다.
20:26 UTC 에 노드 생성 실패로 Karpenter 오류율이 치솟아 팀은 장애 대응 절차를 시작하고 배포를 멈췄다. 이때까지 Stytch API 와 SDK 는 아직 동작했다. 20:44 UTC 에 운영의 쿠버네티스 모니터링 알림이 울렸다.
21:00 UTC 에 팀은 노드 그룹 변경을 원인으로 보고 노드 그룹 삭제를 되돌렸다. 노드 그룹은 금방 다시 만들어졌지만, 새 파드는 새 노드가 뜨기를 기다려야 해서 충분히 빨리 스케줄되지 않았다.
원인
- 촉발
- 14:21 UTC 에 팀은 쓰지 않는 관리형 노드 그룹을 지우는 변경을 반영했고, 두 엔지니어가 AWS 콘솔에서 스테이징과 운영의 노드 그룹을 지웠다. 노드 그룹을 지우자 AWS 가 뒤에서 그 노드 그룹과 엮인 리소스를 정리하면서 Karpenter 노드도 쓰던 instance profile 을 지웠다.
감지
운영에서는 20:48 UTC 에 Deployment Replicas Unavailable 알림이 울렸고, 21:14 UTC 에 지원팀이 장애를 알렸다. 그보다 앞서 16:06 UTC 에 스테이징, 17:48 UTC 에 운영에서 Karpenter 가 instance profile 을 찾지 못한다는 낮은 긴급도 경고가 왔지만 급하지 않은 문제로 분류되었다. 20:26 UTC 에 Karpenter 오류율이 치솟자 팀은 장애 대응을 시작했다.
조치
- 노드 그룹 삭제를 되돌려 노드 그룹을 다시 만들었다. 새 파드는 새 노드가 뜨기를 기다려야 해서 충분히 빨리 스케줄되지 않았다.
- Live API 노드 그룹 하나를 컴퓨팅 크기가 훨씬 큰 노드로 손으로 늘리고, 그 노드 그룹에서 taint 를 지웠다.
- 애플리케이션의 node selector 를 차례로 지워 파드가 그 노드에 스케줄되게 했다. 몇 분 안에 애플리케이션마다 필요한 수의 노드에 파드가 스케줄되었다.
후속 조치
- Karpenter 오류의 심각도를 올려 당직 호출기로 바로 가는 높은 긴급도 알림으로 다룬다.
- 클러스터 알림의 임계값을 조정해 높은 긴급도 호출이 더 일찍 가게 한다.
- 노드가 오랫동안 NotReady 나 Unknown 으로 표시되면 알림을 보내 기존 노드의 상태를 더 잘 지켜본다.
- 스케줄할 수 없는 파드, 사용할 수 없는 레플리카를 비롯한 다른 배포 관련 알림의 임계값을 올린다.
- Karpenter 가 쓰는 IAM instance profile 을 노드 그룹이 쓰는 IAM profile 과 다른 것으로 바꾼다.
- 여러 용도로 겹쳐 쓰던 다른 AWS 리소스, 특히 IAM 과 보안 그룹을 나눈다.
- EKS 와 Karpenter 설정을 크게 고쳐 복잡도를 줄인다. 새 시스템 instance profile 은 Karpenter 가 클러스터마다 고유하고 고정된 이름으로 만들게 한다.
- 개발팀이 인프라를 바꿀 때 쓸 수 있도록 클라우드 시각화 도구를 들인다.
- 상태 페이지에 실시간 시스템 지표와 제품 지표를 넣어 Stytch API 가 지금 어떻게 동작하는지 보여 준다.
- 문서에 없는 동작과 부작용을 AWS 에 문의해 확인한다.
- 인프라에서 IAM 역할과 보안 그룹을 여러 용도로 겹쳐 쓰던 것을 바로잡는다.
교훈
Karpenter 의 자체 관리 노드에 노드 그룹과 같은 IAM 역할을 쓰지 말았어야 했다. 한 IAM 역할을 여러 용도로 겹쳐 쓰면 이번 같은 문제가 그대로 난다. 팀은 Karpenter 를 처음 설정할 때 빠르고 단순하게 하려다 역할을 나누지 않았다. 원인과 결과 사이가 몇 시간 벌어져 있어 장애 전체를 판단하기 어려웠다. AWS 는 이 지연이 예상된 동작이라고 확인했고, 팀은 앞으로 IAM instance profile 을 바꿀 때 이를 고려한다.
출처
관련 사례
IL-0192Crossplane 컴포지션의 병합 정책 변경이 Service 타입을 ClusterIP 로 바꿔 클라우드 로드 밸런서가 지워지고 Grafana Cloud 서비스의 약 25%가 끊겼다.Grafana Labs · 2025같은 원인 · 공통 설정 템플릿
IL-0114클러스터 용량을 늘리던 중 버전이 고정되지 않은 VPC CNI 플러그인이 자동으로 업데이트돼 새 파드가 IP 를 받지 못하고 Pending 에 머물렀고, 메인넷 운영 환경의 정산이 약 3.5시간 멈췄다.CoW Protocol · 2024같은 원인 · 공통 노드 풀
IL-0019EKS 모듈 18 업그레이드로 새 노드의 디스크가 20Gb 로 줄어 이미지 풀이 no space left on device 로 실패했다UK Ministry of Justice · 2023같은 원인 · 공통 노드 풀
IL-0017live 클러스터 노드 6대에서 VPC CNI 가 IP 주소를 할당하지 못해 새 파드가 ContainerCreating 에 멈췄다UK Ministry of Justice · 2023같은 원인 · 공통 노드 풀
IL-0473Azure 공개 쿠버네티스 클러스터의 노드 풀이 모두 지워지고 다시 만들어지지 않아 Jenkins 인프라 서비스가 4시간 넘게 멈췄다Jenkins project · 2023같은 원인 · 공통 노드 풀
IL-0091Terraform 으로 노드 인스턴스 타입을 바꾸자 노드가 한꺼번에 교체되어 사용자 운영 파드가 모두 지워지고 서비스가 내려갔다UK Ministry of Justice · 2023같은 원인 · 공통 노드 풀
IL-0109로그 수집을 고치려던 EKS 노드 롤오버가 꼬이면서 Auto Scaling 그룹이 정상 워커 노드를 모두 종료해 클러스터에 노드가 하나도 남지 않았다.DFDS · 2023 · sev1같은 원인 · 공통 노드 풀
IL-0191Loki distributor 서비스에 레이블 셀렉터가 하나 더 들어가 롤아웃 중 새 파드 몇 개에만 쓰기 트래픽이 몰렸고, 그 파드들이 OOM으로 죽으면서 로그 쓰기 경로가 약 25분간 멈췄다.Grafana Labs · 2022같은 원인 · 공통 설정 템플릿
같은 원인 · 공통 설정 템플릿
같은 원인 · 공통 설정 템플릿
같은 원인 · 공통 노드 풀
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0231
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0231/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.