Post

2023-03-08 Datadog 멀티리전 인프라 네트워크 장애 Postmortem 분석

회사에서 Observability 관련 업무를 진행할 때 Datadog을 사용하고 있는데, 작년 한바탕 크게 장애가 났었습니다. 그 때는 사내에 어떤 기능이 어디까지 복구가 되었고, 어떤 것은 안되고 있고, Datadog측에서 어떻게 대응하고 있는지 전파하느라 정신이 없었는데요. 장애 복구가 완료된 후에도 단순히 Datadog에서 어떻게 앞으로 대응할건지 물어보기만 하고, 세세하게 뜯어보지 못해 아쉬운 점이 있어 장애 Postmortem 글을 정리하며 실제 어떤 Root Cause가 있었는지, Postmortem 글은 어떻게 작성하는지 분석해보는것을 목적으로 글을 써 봤습니다.

일단 Postmortem 글의 전체적인 구성(목차, 제목)을 유지하며, 간략하게 번역/요약해보겠습니다.


Impact, chronology, and response(장애 범위, 시간순 배열, 대응)

incident and impact(사건과 범위)

2023년 3월 8일 UTC 06:03 경(이하 모든 시간은 UTC) 부터, Datadog US1, EU1, US3, US4, US5의 전체 Datadog 서비스에 영향을 준 장애가 발생했습니다. 사건 발생 시점부터, 유저들은 Datadog 플랫폼 및 Datadog내 다수 기능을 웹 브라우저 및 API 등으로 접근할 수 없었고, 모니터(Datadog 내 알람 서비스)와 알림이 작동하지 않았습니다. 다수 기능의 데이터 수집 역시 장애 시점부터 영향이 발생하였습니다.

시간 순 배열

바로 즉시 조사를 시작하였고, Status Page에 06:31분 경 이슈 표시하였습니다. 데이터 수집과 모니터에 영향이 있을 수 있음에 대한 첫 업데이트는 07:23분 업데이트하였습니다.

복구에 대한 첫 징후는 09:13에 확인 할 수 있었고,(웹 접근 복구) 16:44에 주요 서비스에 대한 작동 확인이 되었습니다. 모든 리전에서 모든 서비스에 대한 작동 확인은 2023년 3월 9일 08:58에 진행이 되었고, 장애에 대한 모든 문제 해결은 2023년 3월 10일 06:25에 장애 상황에 정상 처리되지 못한 과거 데이터를 채우는데 완료함으로 종료되었습니다.

대응

Datadog이 내부 모니터링으로 본 이슈에 대해 처음 알림받은 것은 문제가 되는 업데이트의 배포 3분 뒤었습니다. 조사 시작후 18분 뒤, 내부 중대(High-severity) Incident로 지정하고 잠시 뒤 공개적인 Incident로 공지하였습니다.

10명의 시니어 엔지니어링 리더, 약 70명의 지역별 사건 지휘관, 450~750명의 사건 대응 인력이 사건 해결 전까지 4교대로 대응을 진행했습니다.

4개 리전을 넘나드는 200번의 Status Page 업데이트, 수백명의 Support Engineer의 고객 대응이 꾸준히 이루어졌습니다.

장애 완화 및 해결은 다음과 같은 순서로 진행되었습니다.

  1. 초기 대응의 목표는 데이터의 정상 수집과 실시간 수치 데이터의 처리였습니다. 이로 인해 고객들이 제한적으로나마 플랫폼을 이용할수 있도록 하였습니다.
  2. 실시간 데이터가 가용하게 된 뒤, Datadog으로 수집이 되었지만 정상적으로 처리되지 않은 데이터를 복구하는데 집중했습니다.
  3. 동시에, Status Page에 주기적인 업데이트를 진행함으로써 고객이 현 상황에 대해 알 수 있도록 하였습니다.

Root Cause

장애의 원인을 확인(그리고 비활성화 진행)하였습니다; 2023년 3월 8일 06:00에, systemd에 대한 업데이트가 몇 VM으로 배포되었고, 이 업데이트가 Ubuntu 22.04 네트워크 스택의 숨겨져 있던 원치 않은 상호작용을 systemd-networkd 재시작 시에 발생시키는 것을 확인했습니다. systemd-networkd가 Container Network Interface(CNI) 플러그인이 관리하는 컨테이너 간 통신에 사용하는 경로들을 삭제해버려 영향을 받은 노드 들이 오프라인으로 빠져 버렸습니다.

더 문제가 되었던 점은, 새로 생성한 노드나 재부팅을 한 노드들이 이런 현상을 보이지 않는 점이었습니다. 일반 부팅 과정에서는 systemd-networkd가 CNI 플러그인이 경로 규칙을 설정하기 전에 시작되어 영향을 주지 않았고, 이 말은 systemd-networkd 업데이트가 일어나는 상황이 아닌 경우 문제를 확인하는 검사를 진행할 수 없었다는 것을 의미합니다.

해당 시점엔, 수만개의 노드가 06:00 ~ 07:00 간 영향을 받았습니다. 06:31경에는 고객이 장애를 인지할 수 있을 정도로 비활성화 된 노드들이 발생했습니다.

보통 Datadog에서는 기능 배포, 수정이 있을 때 리전별/클러스터별/노드별로 진행합니다. 진행시에는 In-place로 진행하지 않고 노드와 컨테이너를 Blue/Green 방식으로 배포합니다. 배포 시 문제가 있을 경우 언제든 롤백이 가능하도록요. 이런 변경/롤백을 하루에도 수도 없이 진행하고 있어 해당 프로세스에는 자신감이 있습니다.

하지만, 기반이 되는 OS이미지의 경우 레거시 업데이트 채널이 있었습니다. 이 채널이 자동적으로 업데이트를 트리거했습니다. 보통 기반 OS이미지는 최소화 된 패키지와 구성요소를 가지고 있어 이 업데이트는 자주 발생하지 않았고, 이 날 전까진 그렇게 파괴적이지 않았습니다.

자동 업데이트는, 모든 리전 및 클러스터를 구성하는 노드들에 걸쳐 06:00 ~ 07:00에 진행하도록 기본 값이 설정되어 있어 각 리전이 직접적으로 연관이 되어있지 않음에도 불구하고 영향이 크게 번졌습니다. 이 점은, 사건에 대한 영향이 아주 거대해지게 만들었을 뿐만 아니라 초기 대응 팀이 직접적이지 않은 리전 간 연결 등에 혼란을 주기 충분했습니다.

이런 일이 다시 발생하지는 않습니다. 레거시 업데이트 채널을 비활성화 하였습니다. 추가로, systemd-networkd의 설정을 변경하여 재시작 후에도 경로를 삭제하지 않도록 하였습니다. 마지막으로, 이번 사건의 원인괴 비슷한 레거시 업데이트 채널에 대한 인프라에 대한 감사를 진행했습니다.

레거시 업데이트 채널을 비활성화 하는것은 보안 관점에서 영향이 없습니다. 현재 보안 패치를 배포하는 것과 이미 중복되어 패치되고 있습니다.

Recovery

가용 컴퓨트 성능 하락의 폭을 검토했을 때, 복구 과정은 크게 두가지 단계로 쪼개져 순차적으로 진행되었어야 했습니다.

  1. 먼저 각 리전별로 가용 컴퓨트 자원을 늘려 인입 데이터를 정상적 속도로 처리할 수 있도록 하는게 선행되어야 했습니다. 실은, 각 CSP와의 협업을 통해 보통 서비스 수준보다 더 많은 양으로 스케일해 실시간 인입 데이터 처리와 과거에 수집된 데이터를 처리할 수 있도록 하였습니다.
  2. 가용 컴퓨트 자원을 복구한 뒤, 각 서비스의 복구를 병렬적으로 처리하여 모든 서비스를 최대한 빠른 시간 내 처리할 수 있도록 하였습니다.

Compute Capacity

여러 CSP에 걸쳐 네트워크 스택을 잃게 되었는데, 이 과정 중 각 CSP별로 느껴지는게 달라졌고 그에 따라 대응책도 달라져야 했습니다.

어떤 CSP들의 오토스케일링 로직은 영향을 받은 노드들이 제대로 unhealthy 하다고 판단하였지만, 바로 노드들을 제거하지는 않았습니다. 이 말은 단순하게 노드를 재부팅하는 것만으로 복구가 가능하였고 각 노드에 저장되어 있는 상태를 쓰는 워크로드들이 자신의 데이터를 그대로 가지고 있어 전체적인 복구가 빨라질 수 있었습니다.

어떤 CSP들의 오토스케일링 로직은 영향을 받은 노드들을 즉시 새로운 노드로 교체하였습니다. unhealty한 노드에 있던 데이터는 즉각 복구가 어려웠고, 복구 작업에 복잡도를 더했습니다. 수만개의 노드가 비슷한 시기에 교체되며, 각 CSP 리전의 rate limit을 시험에 들게 하기도 했습니다.

일단 날것의 컴퓨팅 자원을 얻게 된 뒤, 복구 순서에 유의했습니다. 각 리전의 전체 쿠버네티스 클러스터가 정상 작동하도록 관리하는 컨트롤 플레인이 가장 먼저 복구가 되어야 했고, 그 뒤에 실제 서비스가 구동되는 클러스터 복구를 진행할 수 있었습니다.

Service Recovery

Datadog의 각 서비스들은 Live Data(서비스에 따라 다르지만 최근 15분에서 24시간)와 Historical Data(Live Data 이전 데이터)를 처리하는 시스템으로 나뉩니다. 모든 서비스들의 복구 첫번째 목표는 Live Data의 수집/처리에 있었습니다. Live Data를 처리하는 시스템과 Historical Data를 처리하는 시스템을 나누어 구성한 것은, 각 서비스의 기능 복구에 큰 도움이 되었습니다.

서비스 복구를 진행하며 팀들이 직면한 공통점 서로 공유하는 데이터가 없는 분산 데이터 저장소가 정족수 기반 데이터 플레인을 가진 분산 데이터 저장소보다 장애 상황을 더 잘 처리한다는 점 입니다. 서로 공유하는 데이터가 없는 분산 데이터 저장소의 경우, 장애 상황에서 선형적으로 성능을 잃는 반면, 정족수 기반 데이터 플레인을 가진 분산 데이터 저장소는 정족수가 유지될때까지는 작동하지만, 그 이후부터는 아예 작동을 하지 않습니다. 물론 정족수 기반 Fleet의 경우 일상적으로 관리하기 훨씬 쉽기 때문에 어느 한쪽을 선택하는게 쉬운 결정은 아니지만, 이번 장애를 겪으며 과거의 결정을 다시 한번 검토해야 한다는 점을 상기시켰습니다.

일반적으로, 우리의 Telemetry 데이터 저장소(각 측정 값과 Raw Log 데이터)는 정적으로 샤딩되었고, 다양한 메타데이터(인덱스, 태그 들)은 정족수 기반 데이터 저장소에 저장되어 있습니다. 따라서 대부분의 복구 인력은 메타데이터 저장소를 복구하는데 집중하여 새로운 Live Data를 작성할 수 있도록 노력하였습니다. 그와 동시의 소규모의 팀은 독립적인 정적 샤딩 저장소를 복구하는데 집중하였습니다.

Lessons learned

장애 중 겪고 얻은 교훈들 중 중요한 것들을 정리해보자면;

이번 사건은 Datadog의 첫번째 글로벌 장애입니다. 우리는 Datadog을 만들때 명시적인 디자인 목표를 “자동화”, “로컬 장애에 대한 복원력”으로 두고 있습니다. 그렇기 때문에 각 독립적인 CSP 위 여러 Zone을 두고 서로 직접적으로 연결/연관성을 두려 하지 않습니다. 또, 이게 바로 우리가 글로벌, 공유된 컨트롤 플레인을 만들지 않는 이유이기도 합니다. 더해서, 각 서비스들은 각 리전별로 여러 AZ에 Active-Active 상태로 Failover되도록 구성되어 있고, 피크 트래픽을 대비해 추가적인 여유 컴퓨트 자원을 준비해두고 있습니다. 그럼에도 불구하고, 우리는 각 리전이 어떻게 간접적으로 연결되어 있을 수 있는지 생각하는데 실패했습니다. 하지만, 그 실패에서 우리의 기반 인프라를 어떻게 강화해야하는지 알 수 있었습니다.

이번 장애를 겪으며 고객들이 어떻게 각 서비스를 어떻게 계층하고 있는지 알 수 있었습니다. 하지만 무엇보다 중요한건, 과거 데이터보다 사용 가능한 Live Data가 고객 입장에서 가치 있다는 점 입니다. 이 명백한 데이터 간 계층성을 가지고, 앞으로 서비스가 정상 작동되지 않을 때 데이터를 어떻게 처리 및 접근할 수 있는지에 대해 검토할 예정입니다.

우리는 카오스 테스트를 진행합니다. 하지만 어느 정도로 테스트를 해야하는지에 대한 적절한 강도 검토에는 실패했습니다. 앞으로는 이번 장애 상황을 토대로, 인프라 장애 상황에서 완전한 Down 상태가 아닌 Degraded 상태로 운영 가능하도록 증명할 예정입니다.

Live Data와 Historical Data가 분리된 시스템으로 구성되어 있고, 시스템 중 일부가 고객들에게 각 시스템을 어떻게 접근하는지에 대한 가이드가 부족했습니다. 고객들에게 어떤 시스템 및 데이터가 사용 가능하고 어디서 접근 가능한지에 대한 접근 가이던스의 우선순위를 올릴 예정입니다.

상태 페이지 업데이트를 진행하며 계속 개선되었지만, 상태 페이지만으론 미묘한 서비스들의 상태를 전달하는데 부족함을 깨달았습니다.

In closing

이번 서비스 중단은 Datadog 직원들에게 겸허한 경험이었습니다. 중단 없는 서비스가 고객들에게 얼마나 중요한지 알고 있고, 이번 장애에서 배운 것을 토대로 서비스의 복원력을 확실히 개선하기 위해 노력하고 있습니다.


일단 제목부터 확인해 보면,

  • Impact, chronology, and response(장애 범위, 시간순 배열, 대응)
    • incident and impact(사건과 범위)
    • 시간 순 배열
    • 대응
  • Root Cause

  • Recovery
    • Compute Capacity
    • Service Recovery
  • Lessons learned

  • In Closing

장애가 완전히 복구 된 후 작성된 글이라 원인 분석까지 되어 있는 상황이라 원인이 아주 상세하게 나와있습니다. 보통 장애 보고를 읽는 사람이 궁금한 순서대로 배치되어 있다고 느껴집니다. 일단 장애가 언제 어떤 시간 순서로 발생했는지 독자에게 밝히고 나면, 독자와 작성자는 머릿속에 같은 타임라인을 공유하며 정보를 주고 받을 수 있어 정보 전달에 강점을 가질 것 같습니다. 대응 방법을 읽다 보면, 자연스럽게 원인이 궁금해지고, 원인을 읽다 보면 이걸 어떻게 복구했지…? 하며 복구 방법이 궁금해지는 글이었습니다.

Root Cause에서는 컨테이너 기반 서비스 관리 및 인프라 관련 전문 개념이 나와 많이 복잡하게 쓰여질 수 있지만, 단순히 “뭐가 바뀌어서, 어떤게 작동을 멈췄습니다”와 같은 사실 나열보다는 각 구성 요소가 전체 서비스에서 어떻게 사용되고 그게 작동이 하지 않음으로서 어떤 문제가 발생했는지 설명을 겯들여 독자들이 이해를 더 쉽게 할 수 있도록 도와주고 있습니다.

마지막 Lessons Learned에서는 장애 상황에서 어떤 것을 알게 되었는지 뿐만 아니라, 앞으로의 목표를 같이 서술하며 고객들에게 어떻게 재발 방지를 할 것인지 이야기하고 있습니다. 장애가 일어난 것은 일어난 것이고, 앞으로 어떻게 이와 같은 일이 발생하는것을 막을지 상세하게 언급하면서 신뢰를 다시 구성하는데 노력하는 것 같습니다.

장애 사후 리포트는 봐도봐도 재미있는 것 같습니다. 시시각각으로 발생하는 문제를 어떻게 해결하는지 따라가는게 아주 흥미로데다, 읽으며 몰랐던 것을 얻어가는 것도 많아, 앞으로도 재미있는 장애 사후 리포트가 있으면 분석 글을 써보려 합니다. 쓸일이 없는게 가장 좋지만, 만약 쓰게 된다면 제대로 잘 쓰고싶기 때문이죠. :)

This post is licensed under CC BY 4.0 by the author.