???? 뭐? ChatGPT 안들어가진다고?
F*** UP! 내 완벽한 업무 메이트인 gpt가 출근을 하지 않았다.
그 일로부터 며칠 후, OpenAPI에서 해당 이슈에 대한 리포트를 작성했다는 소식을 보았다. 지금 공부하고 있는 쿠버네티스와 관련된 이슈라는 소식에 흥분감을 감추지 못하고 원문을 말끔히 번역하여 정리해보겠다.
API, ChatGPT & Sora Facing Issues
Incident Report for OpenAI
2024년 12월 11일 OpenAI의 모든 서비스가 작동을 중지하였다. 본 글은 해당 사고에 대한 검시(post-mortem)이다. 이번 문제는 OpenAI가 도입한 새로운 Telemetry 서비스에 의해 발생했다.
우선, Telemetry 서비스가 무엇인지 짚고 넘어가자.
MSA에서는 여러 개의 마이크로 서비스가 분산 환경에서 운영되기 때문에 독립된 서비스들의 상태를 관리하고 따로따로 모니터링하는 것은 개발자의 업무 부담을 크게 늘린다. Telemetry는 이러한 분산 서비스의 이슈들을 한 번에 모니터링하고 빠르게 대응할 수 있도록 환경을 구성하는 역할을 한다.
세부적인 역할은 조금은 포괄적이다. Prometheus처럼 인프라, 애플리케이션의 성능이나 효율성을 확인하는 모니터링을 할 수도 있고, AWS Elastic Search처럼 실행 중인 프로세스에서 발생하는 Log를 수집하여 한번에 보여줄 수도 있고, Zipkin처럼 여러 서비스에서 발생한 Event를 순서대로 나열하여 서비스의 동작을 추적할 수도 있다.
이번 OpenAI 장애에서는 이 Telemetry 서비스를 새롭게 배포했다가 Kubernetes control plane에 의도치 않게 과부하를 주어 결과적으로 시스템 전체를 먹통으로 만들게 되었다. 이 글에서 그 근본 원인을 분석하고 수정을 위해 취한 단계를 설명하며 재발을 방지하기 위한 조치를 설명할 것이다.
Impact
우선 이번 사건이 OpenAI에게 끼친 영향 범위를 알아보자. OpenAI가 확인한 공식적인 “서버 불능 시간”은 태평양 표준시 기준(PST), 2024년 12월 11일 오후 3시 16분부터 오후 7시 38분까지이다. 이 시간 동안 Chat GPT를 비롯한 GPT API, Sora 등 모든 OpenAI 서비스가 심각한 서비스 성능 저하 내지는 완전한 사용 불가 상태를 경험했다.
이 사건은 새로운 Telemetry 서비스를 배포하면서 발생한 문제이지 보안 문제나 최근에 있었던 신제품 출시와 관련된 내용이 아님을 다시 한번 강조한다.
OpenAI의 서비스는 단계적으로 복구되었다. ChatGPT와 API는 오후 5시 40분경 상당 부분 복구되었고, 오후 7시경 완전히 복구되어 정상 운영되었다. Sora 또한 오후 7시 경 완벽히 복구되었다.
Root Cause
OpenAI는 전 세계적으로 수백 개의 Kubernetes 클러스터를 운영 중이다. Kubernetes에는 클러스터의 관리를 담당하는 control plane과 모델 추론과 같은 워크로드를 실제로 담당하는 data plane이 존재한다.
OpenAI는 조직 내 협업을 위한 신뢰성을 향상을 목적으로 시스템 상태를 시각화하여 보여주는 도구를 개선하기 위해 노력해 왔다. 이 도구는 Kubenetes 클러스터 전체를 아우르는 시각화 도구로 PST 기준 오후 3시 12분 새롭게 배포되어 Kubernetes의 control plane의 세부 사항을 수집하기 시작했다.
이 Telemetry 서비스는 그 역할 범위와 크기가 상당히 크기 때문에 의도치 않게 각 클러스터의 모든 노드가 클러스터 크기에 따라 실행 부담이 증가하는 리소스 집약적인 Kubernetes API 작업을 수행했다. 수 천 개의 노드가 이런 작업을 동시에 수행하면서 Kubenetes API 서버가 과부하되었고 대부분의 대규모 클러스터에서 control plane이 다운되었다.
불행하게도 이 문제는 규모가 큰 클러스터에서 더 심하게 나타났기 때문에 대규모 클러스터를 완벽히 모사하지 못한 테스트 단계에서는 해당 문제를 포착하지 못했다.
해당 장애는 엎친데 덮친 격으로 DNS 캐싱으로 인해 초기에는 문제를 인식하지 못하고 있다가 전체 Kubernetes 클러스터가 rollout(fleet-wide rollout, 전체 배포)되고 나서야 장애가 눈에 띄게 되었다.
OpenAI의 클러스터 아키텍처는 DNS 기반 서비스 검색에 의존하고 있다. 여러 서비스와 노드가 DNS 기반 서비스 검색을 통해서 서비스 이름을 도메인으로 변환해 통신을 가능하게 한다(예: service-name.namespace.svc.cluster.local). 이 때문에, 각 노드가 서비스의 위치를 확인하기 위해 DNS 서버를 자주 호출하게 된다.
새로운 Telemetry 서비스는 클러스터 내 모든 노드에서 API 서버로 상태 데이터를 수집하도록 설계되었다. 하지만 일부 노드에서 DNS 캐싱(DNS의 결과를 일정 시간 동안 저장하고 재사용) 덕분에 API 요청이 초기에는 DNS 서버로 전달되지 않아, 시스템의 부하가 잠시 동안 가려진 것이다. DNS 캐싱의 TTL(유효기간)이 만료되자 각 노드가 DNS 서버로 대규모 요청을 보내면서 API 서버와 클러스터에 심각한 과부하가 걸리게 되었다.
Kubernetes의 data plane은 control plane과 거의 독립적으로 동작하기 때문에 문제없이 작동할 수 있었지만 DNS는 control plane에 의존적이다. 서비스들이 Kubernetes의 control plane 없이는 서로의 위치를 알고 연락할 방법이 없다는 것이다.
요약하자면, 대규모 클러스터에서 엄청난 Kubernetes API 부하가 발생하여 control plane의 과부하를 일으키고 DNS 기반 서비스 검색을 중단시킨 새로운 Telemetry가 원인이다.
Testing & deployment
결과적으로 이번 장애 사태는 특정 크기를 초과하는 Kubernetes 클러스터에서 발생하였고 각 노드의 DNS 캐시는 클러스터 내부의 모든 노드가 충분히 rollout 될 수 있을 만큼의 시간 동안 장애를 숨겼다.
이번 새로운 Telemetry 서비스를 배포하면서 OpenAI의 가장 신경을 썼던 안정성 이슈는 Telemetry 서비스의 리소스 소비였다. 이미 배포 전에 모든 클러스터에서 CPU, 메모리 등의 리소스 사용률 메트릭을 평가하여 배포가 실행 중인 서비스를 방해하지 않는지는 확인하였다. 모든 클러스터 별로 리소스를 철저하게 관리하였다고 생각했지만 Kubernetes API 서버 부하를 평가하기 위한 테스트를 수행하지 않았었다. 서비스 상태에 대해서만 테스팅하고 클러스터 상태에 대한 대응은 놓친 것이다.
사용자 요청 처리를 담당하는 data plane은 control plane과 독립적으로 동작하도록 설계되어 control plane에 문제가 생겨도 data plane은 계속해서 요청을 처리할 수 있습니다. 하지만 Kubernetes API 서버는 DNS에 의존하며, 많은 서비스에 중요한 종속성을 가지고 있었다. DNS 해석은 Kubernetes API 서버를 통해 이루어지기 때문에, API 서버가 정상적으로 작동하지 않으면 DNS 해석이 실패하고 서비스 간의 통신이 막힐 수 있다.
캐시된 DNS 레코드는 최신 정보는 아니지만 여전히 기능적으로 사용이 가능했고 일시적으로 장애를 숨겨버렸다. 캐시된 레코드가 TTL이 지나 만료되면서 DNS 요청이 새롭게 들어오기 시작하고 이때부터 DNS 서버에 대한 부하가 증가했다. 이로 인해 여러 서비스들이 DNS 해석 실패로 인해 작동을 멈추기 시작했고 재앙이 시작되었다.
DNS 캐싱으로 장애가 완전히 드러나기 전에 시스템이 계속해서 배포되었기 때문에 문제를 빠르게 인지하고 대응하기 어려웠다. 결국 DNS 캐시가 비어버리고 새롭게 rollout 된 각 클러스터 노드들이 새로운 DNS 요청을 보내자마자 DNS 서버가 완전히 다운되어 버린 것이다. 뿐만 아니라 이 부하는 control plane에도 영향을 미쳐, 제어 플레인 자체의 과부하를 야기했고, 문제 해결을 위한 즉각적인 대응이 더 복잡하게 만들었다.
Remediation
사실 배포를 모니터링하고 문제가 있는 변경 사항을 롤백하는 것은 OpenAI에서는 배포 모니터링과 관련된 자동화된 툴을 활용하여 간단하게 처리할 수 있다. 이번 장애 사태에도 마찬가지로 모니터링 툴이 사용자들이 에러를 만나기 몇 분 전에 이미 문제를 감지했었다.
이 사태를 해결하기 위해서 문제의 Telemetry를 제거해야 했다. 이 작업을 control plane에 접근하여 수행해야 했지만 Kubernetes API 서버에 대한 부하 증가로 인하여 controle plane으로의 액세스가 불가능했다.
OpenAI는 문제를 파악하고 빠르게 클러스터를 복구하기 위해서 여러 작업을 동시에 진행했다.
- 클러스터의 크기를 축소하여 Kubernetes API에 가해지는 총 부하를 줄였다.
- Kubernetes 관리 API에 대한 네트워크를 차단하여 비용이 많이 드는 요청을 막아 API 서버가 회복할 시간을 벌었다.
- Kubernetes API 서버를 확장하여 보류 중인 요청을 처리할 수 있도록 추가 리소스를 제공하였다.
위 세 가지 노력 끝에 결국 문제가 되는 서비스를 제거할 수 있을 만큼 충분한 제어권을 회복하게 되었다.
일부 Kubenetes의 control plane 제어권을 되찾고 나서, 즉각적으로 복구에 나섰다. 가능하다면 다른 클러스터에 대한 수정 작업을 진행하는 동안 회복된 클러스터로 트래픽을 전환했다. 하지만 많은 서비스가 동시에 리소스를 다운로드하려고 시도하여 리소스 제한이 포화 상태에 이르고 그로 인해 또 추가적인 수동 개입이 필요해지면서 일부 클러스터는 다운된 상태로 유지하였다.
이번 장애 사태는 여러 시스템과 프로세스가 동시에 실패하고 예기치 않은 방식으로 상호작용하면서 발생했다.
- 주요한 변경이 Kubernetes control plnae에 미치는 영향을 테스트에서 포착하지 못했다.
- DNS 캐싱은 결과적으로 장애에 장애를 더하는 역할을 했다.
- control plane에 대한 접근이 막혀버려 복구 작업이 매우 느려졌다.
Prevention
동일한 이유로 사고가 재발하지 않도록, 다음과 같은 조치를 시행했다.
1. 강화된 단계적 배포(Robust phased rollouts)
OpenAI는 모든 인프라 변경에 대해서 단계적 배포를 강화하고 모니터링을 개선하여 장애가 발생하더라도 영향이 제한적이고 빠르게 탐지할 수 있도록 조치할 것이다. 모든 인프라 설정 변경은 단계적인 배포 프로세스를 따르도록 하며, 이는 서비스 워크로드와 Kubernetes control plane을 포함한 모든 클러스터의 상태를 주기적으로 확인하는 모니터링 시스템을 활용할 것이다.
2. 장애 주입 테스트(Fault injection testing)
Kubernetes data plane이 제어 플레인 없이도 더 오래 지속될 수 있도록 테스트를 진행하고, 잘못된 변경을 의도적으로 배포하여 시스템이 이를 감지하고 롤백할 수 있는지 확인할 것이다.
3. 긴급 Kubernetes control plane 접근(Emergency Kubernetes control plane access)
data plane이 control plane에 너무 많은 부하를 걸어 접근할 수 없을 때, API 서버에 접근할 수 있는 비상 경로를 마련할 것이다. 이를 위해 비상용 “break-glass” 매커니즘을 구현하여, 엔지니어가 어떤 상황에서도 Kubernetes API 서버에 접근할 수도 있도록 할 것이다.
4. data plane과 control plane의 분리(Decouple the Kubernetes data plane and control plane)
Kubernetes DNS가 서비스 발견에 사용되면서, 데이터 플레인과 제어 플레인 간의 의존성이 생겨버렸다. 이 의존성은 제어 플레인에 문제가 생기면 데이터 플레인에도 영향을 미칠 수 있는 위험을 초래하므로 data plane과 control plane을 분리하는 시스템을 투자하여, control plnae이 서비스 처리에 대한 부담을 줄이고 독립적으로 동작할 수 있도록 할 것이다.
5. 더 빠른 복구(Faster recovery)
클러스터 시작에 필요한 리소스를 빠르게 준비하기 위해 캐시와 동적 속도 제한기를 개선하여, 리소스가 부족해지는 상황을 예방하고 복구를 더 빠르게 진행할 것이다.
'IT 생태계' 카테고리의 다른 글
2023 IT 10대 트렌드 (0) | 2023.06.24 |
---|
댓글