{"id":"IL-0240","org":"Cloudflare","date":"2020-11-02","docs":[],"title":{"en":"Cloudflare API requests failed and the dashboard slowed for hours after the authentication database lost its replicas","ko":"인증 데이터베이스가 과부하에 걸려 Cloudflare API 와 대시보드가 6시간 33분 동안 실패하고 느려졌다"},"domain":["database","networking"],"impact":{"scope":"Cloudflare control plane: the API, whose query success rate dipped as low as 75%, and the dashboard, up to 80 times slower than normal; the edge kept working","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Every system in the chain had redundancy and none failed completely; each only degraded, which made the chain of events much harder to model and foresee. Automating replica promotion so that it could trigger on a minute's notice had been a point of pride, but for at least one database a fast promotion can do more harm than the failure it answers. Most general-purpose cluster managers use Raft or Paxos rather than Byzantine fault tolerant protocols, accepting a rare failure mode in exchange for a protocol that is simpler to implement correctly and debug.","ko":"모든 시스템에 이중화가 있었지만, 고장 난 시스템들은 완전히 멈추지 않고 성능이 떨어진 채로 동작했다. 그래서 뒤이어 일어난 일들을 미리 모델링하고 예상하기가 훨씬 어려웠다. 1분 만에 복제본을 승격하는 자동 조치는 Cloudflare 가 자랑하던 기능이었지만, 적어도 데이터베이스 하나에서는 그 조치가 원래 문제보다 더 큰 피해를 낼 수 있었다. 대부분의 범용 클러스터 관리 시스템은 비잔틴 장애를 견디는 프로토콜을 쓰지 않고 RAFT 처럼 단순한 프로토콜을 쓴다. 드문 장애 유형에 약하다고 알려진 단순한 프로토콜이 구현과 디버깅이 어려운 복잡한 프로토콜보다 안전한 경우가 많다고 Cloudflare 는 보았다."},"related":[],"sources":[{"url":"https://blog.cloudflare.com/a-byzantine-failure-in-the-real-world/","kind":"blog","archived":"https://web.archive.org/web/20260808034208/https://blog.cloudflare.com/a-byzantine-failure-in-the-real-world/"}],"summary":{"en":"Cloudflare's control plane, the API and dashboard, is made of many microservices that are redundant across two regions, and most of their databases can be written in only one region at a time. Each rack in the control plane data centers has a pair of switches that are both normally active. On 2 November 2020 at 14:43 UTC one switch went into a partly working state in which some of its control protocols kept running, vPC did not, and its data plane dropped part of the traffic. Because the links stayed up, the servers did not fail over to the peer switch.\n\nOne server of the etcd cluster was in that rack. Traffic between node 1 and the leader, node 3, passed through the bad switch, while node 1 could still reach node 2 and node 2 could reach node 3. Node 1 kept starting elections and voting for itself while node 2 kept voting for node 3, so the elections tied, and because Raft blocks writes during an election, etcd was read-only until the switch recovered. Cloudflare's database cluster management system uses etcd for member discovery and coordination, so two clusters could not report a healthy primary, and the system automatically promoted their synchronous replicas, without error or data loss. A defect in the cluster management system required every replica to be rebuilt after a promotion. One cluster recovered quickly. The other handles authentication for API calls and the dashboard, takes heavy reads and relied on one replica to spare the primary; with no replica available, the primary took all the load and was overloaded, which is when the main impact began.\n\nEngineers shed load from the authentication database by slowing the push of SSL certificates to the edge, email sending and other features, and moved API read traffic by hand to the replicas in the secondary data center, which are not part of local failover and stayed online. This improved the API but hurt the dashboard, whose sessions could not cross data centers, so authentication calls were sent fully back to the primary data center. Because of the database's size, rebuilding a replica took hours; at 21:20 UTC the first rebuilt replica put itself into service and performance returned to normal. The services that had been turned down were ramped back up so asynchronous work could catch up. In a postscript Cloudflare noted that the distributed systems community saw the switch failure as an omission fault rather than a Byzantine fault.","ko":"2020년 11월 2일 Cloudflare 의 API 와 대시보드가 6시간 33분 동안 제대로 동작하지 않았다. API 와 대시보드는 Cloudflare 의 제어 플레인이고, 두 지역에 이중화한 많은 마이크로서비스로 이루어져 있다. 대부분 서비스의 데이터베이스는 한 번에 한 지역에서만 쓰기를 받을 수 있다. 전 세계에 퍼진 엣지는 영향 없이 동작했다. 14:43 UTC 에 한 랙의 스위치가 LACP 와 BGP 는 유지한 채 vPC 와 패킷 전달 일부를 잃었다. 스위치가 완전히 죽었다면 트래픽이 같은 쌍의 다른 스위치로 넘어갔겠지만, 일부만 망가져서 그런 전환이 일어나지 않았다. 이 랙에 있던 etcd 노드 하나는 리더와 연결이 끊겼지만 다른 노드와는 연결돼 있었다. 그래서 노드마다 클러스터 상태를 다르게 보게 됐고, 분산 시스템 이론에서는 이런 상태를 비잔틴 장애라고 부른다. RAFT 리더 선출에서 표가 갈려 리더가 뽑히지 않는 일이 거듭됐다. 선출 중에는 쓰기가 막히므로 etcd 는 스위치가 회복할 때까지 읽기 전용이 됐다. 스위치는 6분 뒤 스스로 회복했다.\n\n데이터베이스 클러스터 관리 시스템은 etcd 로 구성원을 찾고 서로 조율한다. 각 클러스터는 primary, 동기 복제본, 하나 이상의 비동기 복제본으로 이루어진다. etcd 가 읽기 전용이 되자 클러스터 두 개가 primary 가 정상이라고 알리지 못했고, 동기 복제본이 자동으로 새 primary 로 승격됐다. 승격은 오류나 데이터 손실 없이 끝났다. 하지만 클러스터 관리 시스템에는 새 primary 를 승격하면 복제본을 모두 다시 만들어야 하는 결함이 있었다. 한 클러스터는 복제본이 금방 다시 만들어져 영향이 작았다. 다른 클러스터는 API 호출과 대시보드의 인증을 맡은 데이터베이스였고, 읽기가 많아 복제본 하나가 부하를 나눠 받고 있었다. 복제본이 없어지자 primary 가 모든 부하를 받아 과부하에 걸렸다. 이 데이터베이스는 커서 복제본을 다시 만드는 데 몇 시간이 걸릴 것으로 보였다.\n\nCloudflare 는 SSL 인증서를 엣지로 보내는 속도와 메일 발송 같은 기능을 줄여 primary 의 부하를 덜었다. 주 데이터 센터의 모든 데이터베이스 클러스터는 보조 데이터 센터에도 복제본이 있었고, 이 복제본은 장애 내내 살아 있었다. 읽기 쿼리를 그쪽으로 보내는 일은 아직 자동화되지 않아 손으로 API 트래픽을 돌렸고, API 가용성이 크게 나아졌다. 하지만 대시보드의 사용자 세션은 데이터 센터를 넘나들면 끊겨서 대시보드는 더 나빠졌다. 결국 인증 호출을 모두 주 데이터 센터로 되돌렸다. 21:20 UTC 에 첫 복제본이 다시 만들어져 자동으로 서비스에 투입되자 성능이 정상으로 돌아왔다. 줄였던 서비스를 다시 올려 밀린 비동기 처리를 따라잡게 했고, 한동안 지켜본 뒤 장애 종료를 선언했다. 글 끝에 덧붙인 글에서 Cloudflare 는 분산 시스템 커뮤니티의 지적을 받아들여, 이 고장은 비잔틴 장애보다 omission fault 로 보는 편이 맞다고 밝혔다. omission fault 는 비잔틴 장애보다 훨씬 좁은 장애 유형이고, 비잔틴 장애를 견디는 프로토콜 없이도 견딜 수 있다."},"trigger":{"en":"At 14:43 UTC a network switch in a control plane data center partly failed: it kept LACP and BGP running but stopped forwarding some packets, and it recovered on its own six minutes later.","ko":"14:43 UTC 에 제어 플레인 데이터 센터의 네트워크 스위치 하나가 일부만 동작하는 상태에 빠졌다. LACP 와 BGP 는 계속 돌았지만 받은 패킷 일부를 전달하지 못했고, 스위치는 6분 뒤 스스로 회복했다."},"severity":"unknown","symptoms":["high-error-rate","high-latency","database-overloaded","writes-rejected","packet-loss"],"timeline":{"detected_after":"0m","resolved_after":"6h 33m"},"date_kind":"incident","detection":{"en":"At 14:43 UTC alerts fired because the misbehaving switch was unreachable to pings. Engineers then saw that the primary authentication database was overwhelmed.","ko":"14:43 UTC 에 스위치가 ping 에 응답하지 않는다는 알림이 울리기 시작했다. 그 뒤 엔지니어들이 주 인증 데이터베이스가 과부하에 걸린 것을 확인했다."},"components":["network-link","coordination-store","failover-manager","database","database-replication"],"root_cause":"dns-network","remediation":[{"text":{"en":"Shed load from the primary authentication database by slowing SSL certificate pushes to the edge, emails and other features","ko":"SSL 인증서를 엣지로 보내는 속도와 메일 발송 같은 기능을 줄여 주 인증 데이터베이스가 늘어난 부하를 감당할 여유를 만들었다."}},{"text":{"en":"Moved API traffic that could use read replicas to the secondary data center by hand","ko":"읽기 복제본으로 처리할 수 있는 API 트래픽을 손으로 보조 데이터 센터로 돌렸다. API 가용성이 크게 나아졌다."}},{"text":{"en":"Sent authentication calls fully back to the primary data center when the dashboard got worse","ko":"대시보드 사용자의 불편이 커지자 인증 호출을 모두 주 데이터 센터로 되돌렸고, 성능이 떨어진 상태에서도 최대한 버티도록 주 데이터베이스를 계속 손봤다."}},{"text":{"en":"Rebuilt the first database replica, which put itself back into service at 21:20 UTC and returned performance to normal","ko":"21:20 UTC 에 첫 데이터베이스 복제본이 다시 만들어지자마자 자동으로 서비스에 투입됐고, 성능이 정상으로 돌아왔다."}},{"text":{"en":"Ramped the turned-down services back up so asynchronous processing could catch up","ko":"줄였던 서비스를 모두 다시 올려 밀린 비동기 처리가 따라잡게 했고, 한동안 지켜본 뒤 장애 종료를 선언했다."}}],"action_items":[{"text":{"en":"Remove the cluster management limitation that requires rebuilding all replicas after a primary is promoted","ko":"새 primary 를 승격하면 데이터베이스 복제본을 모두 다시 만들어야 하는 클러스터 관리 시스템의 제약을 고친다. Cloudflare 는 글을 쓸 무렵 이 결함을 이미 고쳤다고 밝혔다."}},{"text":{"en":"Redesign the user sessions system so dashboard traffic can be steered between data centers","ko":"트래픽을 다른 데이터 센터로 돌려야 할 때 유연하게 대응하지 못하는 사용자 세션 시스템을 다시 설계한다."}},{"text":{"en":"Change the auto-remediation configuration so a database replica is not promoted so quickly","ko":"자동 복구 조치의 설정 값을 다시 검토한다. 적어도 데이터베이스 하나에서는 복제본을 primary 로 승격하는 절차를 그렇게 빨리 시작하지 않도록 장애 직후 설정을 바꿨다."}},{"text":{"en":"Tune each system involved to be more resilient to failures of its dependencies","ko":"이 장애에 얽힌 시스템마다 자기가 의존하는 시스템의 고장을 더 잘 견디도록 계속 조정한다."}}],"contributing":["automation-amplified","no-spare-capacity","manual-action-worsened"],"recurrence_of":null,"symptoms_text":{"en":"On 2 November 2020 the Cloudflare API and dashboard were degraded for six hours and 33 minutes. The success rate of API queries dropped at times to 75%, and the dashboard was up to 80 times slower than normal, while Cloudflare's edge network kept working.\n\nThe first signal came at 14:43 UTC, when alerts fired because a network switch in one rack of a control plane data center stopped answering pings. The switch had only partly failed: LACP and BGP kept running while vPC, which keeps the ports of a switch pair in step, did not, and its data plane forwarded only some of the packets it received. Because LACP spreads traffic over the links, each connected server saw trouble on only part of its traffic, and since the links never went down, traffic did not move to the peer switch. The switch recovered by itself six minutes later.\n\nFrom 14:44 UTC the etcd cluster, which had one server in that rack, kept holding leader elections that never produced a leader every member could reach, so etcd stayed read-only until the switch recovered. At 14:45 UTC two database clusters could no longer report a healthy primary through etcd, and the cluster management system promoted a synchronous replica in each. In the cluster that handles authentication for API calls and dashboard activity, no replica was left online after the promotion, and the new primary was overwhelmed by the read load a replica had carried before.\n\nMoving API reads to replicas in the secondary data center improved API availability but made the dashboard worse, because dashboard user sessions, kept in a Redis cluster, could not move between data centers without disruption. Performance returned to normal only at 21:20 UTC, when the first rebuilt replica came back into service.","ko":"14:43 UTC 에 네트워크 스위치 하나가 ping 에 응답하지 않는다는 알림이 울리기 시작했다. 장애 동안 API 쿼리 성공률이 한때 75%까지 떨어졌고, 대시보드는 평소보다 최대 80배 느려졌다.\n\n스위치는 일부만 동작하는 상태였다. LACP 와 BGP 같은 제어 프로토콜은 살아 있었지만 vPC 는 동작하지 않았고, 데이터 플레인은 받은 패킷을 전부 전달하지 못했다. LACP 가 트래픽을 여러 링크에 나눠 보내기 때문에 연결된 서버는 트래픽 일부에서만 문제를 겪었고, 서버 쪽에서는 이 고장이 보이지 않았다. 스위치는 6분 뒤 사람이 손대지 않았는데도 회복했다.\n\n14:44 에 etcd 오류가 시작됐다. 고장 난 랙에 있던 etcd 노드 1은 리더인 노드 3에 닿지 못했지만, 노드 2는 노드 1과 노드 3 모두에 닿았다. 노드 1은 자기에게 투표하며 리더 선출을 거듭 시작했고 노드 2는 계속 노드 3에 투표해 표가 갈렸다. 선출이 끝나지 않는 동안 모든 쓰기가 막혀 etcd 클러스터가 읽기 전용이 됐다.\n\n14:45 에 데이터베이스 클러스터 두 개가 etcd 를 통해 primary 가 정상이라고 알리지 못했고, 동기 복제본이 자동으로 새 primary 로 승격됐다. 승격 뒤에는 복제본을 모두 다시 만들어야 했다. API 호출과 대시보드의 인증을 맡은 데이터베이스는 읽기가 많아 복제본 하나가 부하를 덜어 주고 있었는데, 그 복제본이 사라지자 primary 가 모든 부하를 받아 과부하에 걸렸다. 본격적인 영향은 이때 시작됐다.\n\nAPI 가용성을 높이려고 읽기 트래픽을 보조 데이터 센터로 돌리자 대시보드 사용 경험은 오히려 나빠졌다. 대시보드의 사용자 세션은 바다 건너 데이터 센터로 옮기면 끊기기 때문이었다."},"updated_at":"2026-11-14T12:33:02.780374Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0240","org_slug":"cloudflare"}