Incident Library

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 에 팀은 노드 그룹 변경을 원인으로 보고 노드 그룹 삭제를 되돌렸다. 노드 그룹은 금방 다시 만들어졌지만, 새 파드는 새 노드가 뜨기를 기다려야 해서 충분히 빨리 스케줄되지 않았다.

증상 노드 NotReady노드 증설 실패파드 축출파드 Pending서비스 중단

원인

촉발
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 오류율이 치솟자 팀은 장애 대응을 시작했다.

조치

후속 조치

교훈

Karpenter 의 자체 관리 노드에 노드 그룹과 같은 IAM 역할을 쓰지 말았어야 했다. 한 IAM 역할을 여러 용도로 겹쳐 쓰면 이번 같은 문제가 그대로 난다. 팀은 Karpenter 를 처음 설정할 때 빠르고 단순하게 하려다 역할을 나누지 않았다. 원인과 결과 사이가 몇 시간 벌어져 있어 장애 전체를 판단하기 어려웠다. AWS 는 이 지연이 예상된 동작이라고 확인했고, 팀은 앞으로 IAM instance profile 을 바꿀 때 이를 고려한다.

출처

관련 사례

내 클러스터에도 있는지 확인하기

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: Karpenter, 노드 풀, 설정 템플릿. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.