두 개의 존, 열여덟 시간, 하나의 원인
드론 공격으로 AWS me-central-1 리전이 수개월 복구에 들어갔고, DR 권고는 유럽으로 복원하라였다. AZ 이름을 실제 ID로 매핑하는 랩 포함.

3월 1일, AWS me-central-1 리전의 한 가용 영역 mec1-az2가 AWS의 표현으로 "objects that struck the data center, creating sparks and fire"에 맞았다. 약 18시간 뒤, 두 번째 존 mec1-az3도 전원을 잃었다. 세 번째 mec1-az1은 내내 살아 있었다. 세 개 중 두 개의 존이 손상되자 S3와 DynamoDB가 리전 전체에서 실패하기 시작했고, Health Dashboard에 실린 AWS의 고객 권고는 그들 자신의 말로 "enact their disaster recovery plans and recover from remote backups into alternate AWS Regions, ideally in Europe"였다. 가용 영역 독립성은 전원 고장, 냉각 고장, 네트워크 고장을 상대로 설계된다. 3월에 그것은 애초에 설계된 적 없는 원인을 만났고, 그 원인은 그 설계에 아랑곳하지 않았다.
이 글은 Nothing Fails Alone의 2부다. 1부는 5월 us-east-1 사건을 살펴보며 존 경계가 버텼다고 주장했고, 실제로 그랬다. 한 데이터 홀의 냉각 장애는 설계된 그대로 한 존 안에 머물렀고, 뒤이은 장애는 고객이 스스로 만든 것이었다. 그 주장은 옳았고, 특정한 질문에 답했다. AZ 격리는 그것이 설계된 대상인 장애 모드를 봉쇄하는가? 3월 me-central-1 이벤트는 다른 질문을 던진다. 이 사건은 1부가 쓰이기 전에 일어났고, 당시에는 전시의 특수 사례, 즉 정상 아키텍처에 교훈이 없는 전쟁 각주로 치부하기 쉬웠다. 5월 사건이 그 일반적 형태를 드러냈다. 1부는 존 경계가 무엇을 보호하는지에 관한 것이었고, 이 부는 그것이 보호할 수 없는 것, 즉 둘 이상의 존에 닿는 모든 원인에 관한 것이다. 그런 원인은 평시에도 존재한다. 전쟁은 그 시연을 이틀로 압축했을 뿐이다.
me-central-1에서 실제로 일어난 일
이 이벤트는 3월 1일 PST 오전 4시 51분, "issues with AWS services in the ME-CENTRAL-1 Region"에 대한 조사로 AWS Health Dashboard에 열렸고, 곧 단일 가용 영역 mec1-az2의 "localized power issue"로 좁혀졌다. 대시보드 로그는 이례적으로 솔직했고, PST 오전 9시 41분에 전원이 왜 나갔는지 설명했다. "At around 4:30 AM PST, one of our Availability Zones (mec1-az2) was impacted by objects that struck the data center, creating sparks and fire. The fire department shut off power to the facility and generators as they worked to put out the fire." 다음 날 AWS는 The Register가 같은 날 다룬 업데이트에서 원인을 지목했다. 드론 공격, 중동 분쟁의 일부였다. "In the UAE, two of our facilities were directly struck"였고, 그 공격은 "caused structural damage, disrupted power delivery to our infrastructure, and in some cases required fire suppression activities that resulted in additional water damage"였다.
첫째 날 내내 이 사건은 교과서적인 단일 존 이벤트처럼 보였고, AWS도 같은 오전 9시 41분 업데이트에서 그렇게 말했다. "Customers who were running their applications redundantly across the AZs are not impacted by this event." 그 시각에 멀티 AZ는 옳고 충분한 답이었으며, 한 시간도 채 안 되기 전의 업데이트에는 1부를 읽었다면 이미 본 적 있는 단서가 실려 있었다. 영향받지 않은 존들의 수요 증가로 인해 "customers may experience longer than usual provisioning times". AWS가 1부가 2주 전 다룬 5월 us-east-1 이벤트 중에 게시하게 될 바로 그 문구다. 달력상으로는 3월이 먼저였는데도 말이다. 살아남은 존으로의 대규모 페일오버는 어느 리전에서든, 어느 사건에서든, 어디서나 썬더링 허드다.
그러다 PST 오후 10시 46분, 첫 타격으로부터 약 18시간 뒤. "a localized power issue has affected another Availability Zone in the ME-CENTRAL-1 Region (mec1-az3) ... At this point it is not possible to launch new instances in the region ... Other AWS Services, such as DynamoDB and S3 are also experiencing significant error rates and latencies." 세 개 중 두 개의 존이 다운됐고, 장애는 존 계층에서 완전히 기어 나왔다.
18시간은 동시가 아니며, 그것이 핵심이다
두 존은 함께 쓰러지지 않았다. 그들은 같은 원인에 약 18시간 간격을 두고 쓰러졌다. 그 구분이 이 글의 논지 전체이므로 정확히 짚을 가치가 있다. 존 독립성은 확률 주장이다. AWS는 한 시설의 내부 고장, 즉 실패한 냉각기, 실패한 변압기, 불량 스위치 패브릭이 그 안에 머물고 다른 시설의 내부 고장과 동시에 일어나지 않도록, 존들을 분리된 전원, 분리된 냉각, 분리된 침수 지역, 분리된 네트워크 경로 위에 설계한다. 그 주장 자체의 기준으로 보면 3월은 아무것도 바꾸지 않았다. 어느 존도 다른 존을 무너뜨리지 않았다. 공유 변압기도, 연쇄 의존성도 없었다. 격리 엔지니어링은 끝까지 작동했다.
실패한 것은 그 확률 계산 밑에 깔린 가정, 즉 존 장애가 독립 사건이라는 가정이었다. 그것들은 원인이 시설 내부에서 발생할 때에만 독립적이다. 시설 밖에서 발생하는 원인, 즉 폭풍, 전력망 붕괴, 산불, 무력 분쟁은 한 번 표집되어 그 도달 범위 안의 모든 존에 적용된다. 그 존들은 대도시권, 전력망, 영공, 그리고 전쟁을 공유했다. 상관 장애는 두 존이 같은 순간에 죽는다는 뜻이 아니다. 하나의 원인이 자신의 일정에 따라 둘 모두에 닿는다는 뜻이다. 18시간의 간격이 대시보드에서 상관관계가 실제로 보이는 모습이다. 동기화된 충돌이 아니라, 같은 손이 두 번 두드리는 것.
그래서 전시-특수-사례 프레이밍은 실패한다. 드론은 이국적이지만, 공유된 대도시 인프라는 그렇지 않다. 모든 멀티 AZ 리전은 존들을 서로 한 자릿수 밀리초 안에 집중시키는데, 이는 실무적으로 기상, 유틸리티, 정치에 대해 같은 도시 규모의 blast radius를 뜻한다. 3월 이벤트는 그것이 일어난 도시의 이름을 딸 만큼 큰 모든 사건을 포함하는 원인군의 극단이다. InfoQ가 그달 말 "War in Iran Damages Multiple AWS Data Centers, Challenging Multi-AZ Assumptions"라는 제목으로 이 사건을 분석했을 때, 그것이 요약한 커뮤니티 논의는 이미 드론을 지나 일반적 경우로 넘어가 있었다. 존은 같은 도시에 있는 건물들의 무리이고, 도전할 가치가 있는 가정은 도시에 닿을 수 있는 모든 것에 관한 것이다.
리전 자체가 장애 도메인일 때
로그 전체에서 가장 교훈적인 업데이트는 3월 2일 PST 오전 2시 53분에 나왔다. AWS가 두 존의 상실이 S3에 무엇을 하는지 설명한 때다. "Amazon S3 is a regional service and designed to withstand the total loss of a single Availability Zone ... As the second AZ became impaired, S3 error rates increased. With two Availability Zones significantly impacted, customers are seeing high failure rates for data ingest and egress."
그 문장을 아키텍처 문서로 읽어라. 실제로 그런 문서이기 때문이다. S3와 DynamoDB는 당신이 존 장애를 대비해 아키텍처를 짜지 않는 서비스다. AWS가 대신 해 주며, 존들에 걸쳐 복제해 한 존의 상실이 보이지 않도록 하기 때문이다. 그 설계에는 명시된 허용치가 있다. 한 존. 두 번째 존이 그것을 초과했고, 리전의 모든 "복원력 있는" 아키텍처가 상태를 위해, 백업을 위해, 페일오버 자체의 조정 데이터를 위해 기댔던 서비스들이 리전 전체에서 읽기와 쓰기를 거부하기 시작했다. 당신의 멀티 AZ 애플리케이션은 인스턴스만 잃은 것이 아니다. 그것이 복구하려고 계획했던 리전 기반 자체를 잃었다. mec1-az1은 건강했고, 그것은 중요하지 않았다. 손상된 리전 컨트롤 플레인에 붙은 건강한 존은 배관이 없는 건물에서 불만 켜진 방이기 때문이다. 이것이 멀티 AZ가 답할 수 없는 부분이다. 리전 서비스들은 당신과 같은 세 개의 존 위에 지어졌고, 상관 존 상실에 대한 그들의 허용치는 당신이 고른 숫자가 아니라 AWS가 고른 숫자다.
"ideally in Europe"
3월 2일 PST 오전 6시 22분까지 AWS의 안내는 가장 무뚝뚝한 문장에 이르렀다. "We recommend customers enact their disaster recovery plans and recover from remote backups into alternate AWS Regions, ideally in Europe."
그 문장은 3월에 받은 것보다 더 천천히 읽을 가치가 있다. 첫째, 그 리전을 소유한 공급자가 고객들에게 그곳을 떠나라고 말했다. 그것은 벤더가 명시한 인 리전 이중화의 천장이다. 복구 계획에서 me-central-1의 올바른 분량이 0인 사건의 부류가 존재하고, 당신이 어느 부류에 속하는지는 사건 도중에, 대시보드에서 알게 된다. 둘째, "ideally in Europe"은 조용하고 신중한 일을 하고 있다. 가장 가까운 대안인 바레인의 me-south-1은 지척이라 지연 관점에서 반사적인 DR 선택이 됐을 텐데, 그곳의 한 시설이 같은 작전에서 인근 타격의 영향을 받았다. AWS는 명시하지 않은 채 고객들에게, 상관 원인에는 지리가 있으며, 유용한 복구 리전은 단지 리전 ARN 밖이 아니라 그 지리 밖에 있는 리전이라고 말하고 있었다. 주 리전으로부터의 거리는 컴플라이언스 체크박스가 아니다. 그것은 당신의 상관 원인이 얼마나 멀리 이동하는지에 대한 베팅이다. DR 리전을 고를 때는 무엇이 복제 지연을 예쁘게 유지하는지가 아니라, 무엇이 둘 다에 그럴듯하게 닿을 수 있는지를 물어라.
셋째, 그 조언은 그것을 따를 수 있었던 고객에게만 통한다. "Recover from remote backups"는 원격 백업이 존재한다고 전제한다. 3월 1일 이전에, 즉 사건 전에 만들어진 것으로. 같은 업데이트 로그가 이벤트 중 S3 "data ingest and egress"가 리전 전체에서 실패하고 있음을 보여 주기 때문이다. 데이터를 리전 밖으로 복사하는 것은 평시의 활동이다. 공급자가 그것을 권하는 시점이면 시작할 창은 이미 닫힌 것이다.
수개월
이 이벤트의 마지막 업데이트는 4월 30일 자로 한 문단 길이이며, 이야기를 끝내지 않으면서 끝낸다. 그 리전은 "has suffered damage as a result of the conflict in the Middle East and is currently unable to reliably support customer applications" 상태이고, 고객은 "migrate all accessible resources to other Regions and restore inaccessible resources from remote backups as soon as possible" 해야 하며, 결제 운영은 중단됐고, 복구는 "is expected to take several months"였다.
그것을 표준 DR 문서와 대조해 보라. RTO는 기간으로 쓰이고, 내가 검토한 거의 모든 RTO는 복구 대상이 이미 당신이 있는 곳이라고 조용히 가정한다. 스냅샷을 복원하고, 플릿을 다시 띄우고, 같은 리전, 최악이라도 몇 시간. "Several months"는 그 숫자를 압박하는 것이 아니라, 그것이 쓰인 축 자체를 삭제한다. 리전이 이번 분기에 돌아오지 않는다면, 당신의 실제 복구 시간은 콜드 크로스 리전 재구축이 걸리는 기간 전부다. 아무도 리허설하지 않은 부분까지 포함해서. 바라건대 당신에게 있는 코드로부터 재생성한 IAM과 네트워킹, 바라건대 당신이 만든 복제본으로부터 복원한 데이터, 전환된 DNS, 그리고 모두의 탈출을 한꺼번에 흡수하는 목적지 리전에서 찾아낸 용량. 크로스 리전 복제가 이미 흐르고 있던 팀에게 3월은 나쁜 한 주였다. DR 계획이 인 리전 스냅샷이었던 팀에게 그것은 포격으로 통보된 마이그레이션 프로젝트였다.
랩: 당신은 실제로 어느 물리적 존에 있는가?
1부는 랩 섹션을 마치며 AWS 사건 보고가 존을 ID로 지칭한다는 점, 즉 use1-az4를 언급했고, ID 대 이름 매핑 없이는 그것이 당신의 us-east-1a였는지 알 수 없다고 짚었다. 3월은 그것이 사소하기를 멈추는 사건이다. 대시보드는 mec1-az2, 그다음 mec1-az3라고 말했다. 당신의 워크로드가 타격받은 존에 있었는지 살아남은 존에 있었는지 알려면, 그 ID들을 당신의 계정에 대해, 사건 도중에 해석해야 했다. me-central-1a 같은 존 이름은 계정 범위의 별칭이기 때문이다. AWS는 물리적 존에 계정마다 독립적으로 문자를 할당하므로, 두 계정의 me-central-1a는 대개 서로 다른 물리적 존이다. "우리는 a, b, c에 분산돼 있다"는 물리적 배치가 아니라 당신 계정의 이름 짓기에 관한 진술이다.
이 부의 랩 02-az-id-truth는 의도적으로 시리즈에서 가장 작다. 유일한 API 호출이 DescribeAvailabilityZones와, 출력 라벨링용일 뿐인 GetCallerIdentity인 단일 read-only 스크립트다. 현재 계정과 리전의 이름 대 ID 매핑을 출력한다. 이것은 내 계정 중 하나의 실제 출력이다.
$ python3 az_ids.py --region us-east-1
Region: us-east-1
ZONE NAME | ZONE ID | STATE
---------------------------------
us-east-1a | use1-az1 | available
us-east-1b | use1-az2 | available
us-east-1c | use1-az4 | available
us-east-1d | use1-az6 | available
us-east-1e | use1-az3 | available
us-east-1f | use1-az5 | available
...이 계정에서 5월 사건 보고서의 존인 use1-az4는 us-east-1c다. 여기서 5월에 "use1-az4"를 읽고 "us-east-1a"라고 라벨된 다이어그램을 흘긋 본 엔지니어라면, 엉뚱한 존에 대해 안심하고 건강한 존을 걱정했을 것이다. 스크립트는 --compare <profile>도 받는데, 같은 리전에서 두 번째 계정의 매핑을 읽어 둘을 나란히 출력하고, 같은 물리적 존으로 해석되는지 이름별 판정을 붙인 뒤 불일치 개수를 센다. 같은 이름이 계정 간에 다른 ID로 해석되는 것이 예외가 아니라 정상이다. "us-east-1a를 대피시켜라"라고 말하는 공유 런북은 계정마다 다른 일을 한다. 런북, 배치 결정, 사건 조회는 존 ID에 속해야 한다. 매핑을 인벤토리 도구에 넣기 위한 --json 플래그가 있고, 종료 코드는 실행이 완료되면 언제나 0이며, 아예 일어날 수 없는 실행에는 2를 예약한다. boto3 없음, 자격 증명 없음, 리전 없음, 알 수 없는 프로필, 또는 describe 호출 자체의 실패.
실패 모드와 주시할 것
먼저 한계에 대해 정직하자. 고객은 me-central-1을 전쟁 밖으로 아키텍처할 수 없다. 당신의 Terraform 어디에도 상관 원인을 막는 것은 없다. 당신이 통제하는 것은 그것이 당신을 찾아왔을 때 당신의 데이터가 이미 다른 곳에 있느냐다. 3월에서 따라 나오는 관찰 목록은 짧다. 당신의 모든 존에 한꺼번에 닿는 원인들을 열거하라. 공유 대도시권, 공유 전력망, 공유 기상, 공유 관할권. 그리고 그 답을 당신의 진짜 리전 상실 확률로 취급하라. 낮지만, 존 계산이 조용히 가정한 0은 아니다. 재생성할 수 없는 모든 것에 대해, 상관 지리 밖이라는 이유로 고른 리전에 크로스 리전 백업을 보유하고, 복원을 테스트하라. 3월판 그 테스트에는 소방서가 끼어 있었기 때문이다. RTO를 두 번 써라. 한 번은 인 리전 복구용, 한 번은 리전이 한 분기 동안 사라졌다고 가정하고. 그리고 두 번째 숫자를 리스크를 책임지는 사람 앞에 놓아라. 그리고 계정마다 물리적 존 ID의 인벤토리를 유지하라. 다음 보고서가 존 ID를 말할 때, 당신의 매핑을 배울 시간은 사건 도중이 아니기 때문이다. 존 경계는 실재하고, 1부는 그것이 버티는 것을 보여 줬다. 3월은 그 위의 것을 보여 줬다. 존들은 서로 완벽하게 격리되면서도 여전히 세계로부터 격리되지 않을 수 있다.
다음으로 읽을 글
- 이 시리즈의 1부: AZ 격리는 버텼다. 당신의 아키텍처는 아니었다., 경계가 작동했고 장애가 그 위에 구축됐던 5월 us-east-1 사건.
- 이 시리즈의 3부: 수정은 장애와 운명을 공유한다, 당신의 복구 계획이 다른 모두의 것과 무엇을 공유하는지에 관하여.
- ercan.ai의 크로스 리전 추론: 값싼 복원력인가, 레지던시 함정인가?: 한 계층 위의 같은 트레이드오프. 리전을 살아남아야 하는 것이 AI 워크로드이고 제약이 데이터가 갈 수 있는 곳일 때.
- 동반 저장소: nothing-fails-alone, 이 시리즈의 모든 랩, 설계상 read-only.
AWS, 클라우드 아키텍처, 복원력 리뷰, 플랫폼 작업에 대한 컨설팅은 ercanermis.com에서 시작하라.
참고 자료
Ercan의 다른 글
같은 저자, 다른 영역의 사이트 두 개.