Cloudflare, DNS 부분 빌드로 메모리 피크 85% 낮추고 변경 기록 중앙값 절반으로
Cloudflare는 DNS 변경 이벤트가 영향을 주는 레코드와 메타데이터만 다시 만드는 planner와 같은 zone의 작업을 합치는 scheduler를 도입했습니다. 회사가 공개한 24시간 집계에서 빌드의 92.95%가 전체 zone 재빌드를 피했고, working-set 메모리 피크는 79 GiB에서 12 GiB로 감소했습니다. 변경부터 Quicksilver 기록까지의 중앙값은 약 7.7초에서 3.3초로 줄었으며, 전 세계 네트워크로 배포하는 시간은 이 측정에 포함되지 않습니다.
본문
Cloudflare 블로그에 Alex Fattouche가 2026년 11월 2일 게시한 기술 해설은 회사 DNS 배포 파이프라인의 Zone Builder를 부분 빌드 중심으로 바꾼 과정과 자체 측정 결과를 설명합니다. 고객이 DNS Records API나 대시보드에서 레코드를 바꾸거나 Cloudflare 서비스가 zone 설정을 바꾸면 변경이 데이터베이스와 Kafka 이벤트를 거칩니다. DNS Kafka Aggregator가 여러 이벤트 흐름을 모아 Zone Builder에 전달하고, Builder는 권한 DNS 서버가 읽을 형식의 키를 만들어 Cloudflare의 분산 key-value 저장소 Quicksilver에 씁니다. Quicksilver가 이 변경을 Cloudflare 네트워크로 전파합니다.
기존 Zone Builder는 어떤 항목이 바뀌었는지 몰라도 현재 데이터베이스 상태에서 원하는 결과를 다시 만들 수 있었습니다. 대신 zone의 설정과 모든 DNS 레코드를 읽고 변환해 Quicksilver의 기존 키와 비교했습니다. 최종 기록에서는 바뀐 키만 쓰더라도, 처리 중에는 전체 레코드를 읽고 메모리에 보관해야 했습니다. Cloudflare는 수천만 개 레코드를 담은 zone이 생겼고 더 커질 것으로 예상해 이 방식이 큰 zone에서 부담이 된다고 설명했습니다.
새 planner는 이벤트에 바뀐 설정 항목과 가능한 경우 이전 값·새 값을 담도록 한 뒤, 해당 변경이 DNS 출력의 어느 부분에 영향을 주는지 분류합니다. 일반적인 A, AAAA, TXT, CNAME 변경은 보통 해당 이름의 레코드만 다시 만듭니다. Nameserver나 wildcard 변경은 여러 zone이 함께 쓰는 메타데이터도 갱신하고, Universal SSL 같은 설정은 zone 정점과 메타데이터를 다시 계산할 수 있습니다. 게시를 중단할 zone은 purge로 처리합니다. 변경 범위를 안전하게 특정할 수 없으면 모든 레코드를 다시 읽는 전체 빌드를 택합니다. 부분 빌드가 기록하는 키는 전체 빌드 결과와 바이트 단위로 같아야 한다는 기준을 뒀습니다.
같은 공개 도메인에 고객의 가입·해지 과정 등으로 여러 Cloudflare zone 객체가 잠시 존재할 수 있습니다. 이때 Quicksilver는 zone별 레코드 키와, 그 도메인 이름에 속한 zone 가운데 DNS 응답에 사용할 내부 ID 목록을 담는 공유 메타데이터 키를 따로 둡니다. 예를 들어 한 zone의 www 이름에 있는 TXT 레코드만 바뀌면 그 zone의 레코드 키만 바꾸면 됩니다. Nameserver나 wildcard 변경은 공유 메타데이터에도 영향을 주므로 두 종류의 키를 함께 갱신합니다.
이벤트는 과거에 일어난 변경을 알리므로, 작업이 시작될 때는 데이터베이스 상태가 이미 달라졌을 수 있습니다. 그래서 Builder는 이벤트를 받았을 때 보수적인 작업 목록을 만들고, 실행 직전에 최신 zone 설정과 해당 네트워크에서 게시할 zone 목록을 다시 읽습니다. 최신 상태에 따라 부분 빌드를 전체 빌드나 purge로 바꾸거나 작업을 건너뛰며, 공유 메타데이터는 현재 게시 후보 목록으로 다시 구성합니다. 데이터베이스 복제본이 Kafka 이벤트보다 늦게 갱신됐으면 마지막 검사에서 읽기를 거부합니다.
통합 scheduler는 같은 zone의 작업이 시작되기 전에 도착하면 합칩니다. 예를 들어 일반 레코드 이름과 wildcard가 함께 바뀌면 두 이름의 작업과 메타데이터 갱신을 한 번의 빌드에 넣습니다. 합쳐진 작업 중 하나라도 전체 빌드가 필요하면 전체 빌드가 되고, 게시 중단을 뜻하는 purge는 재빌드보다 우선합니다. Scheduler는 실제 DNS 작업과 Kafka 메시지의 확인 상태를 따로 추적해 재시도 중에도 메시지를 결과가 안전하게 기록될 때까지 붙들어 둡니다. Kafka 파티션에서는 앞선 메시지가 끝나기 전에 뒤의 오프셋을 확정하지 않아, 재시작 때 작업을 다시 하더라도 변경이 빠지지 않게 합니다.
Cloudflare는 부분 빌드와 전체 빌드가 같은 데이터베이스 상태에서 만든 Quicksilver 키를 바이트 단위로 비교하는 테스트를 추가했습니다. 배포 전에는 운영 Kafka 스트림과 운영 데이터베이스를 읽지만 고객 트래픽과 분리된 Quicksilver에 쓰는 미러 Zone Builder도 운용했습니다. 비교기는 zone의 20% 표본에서 누락·추가 키와 값 차이를 찾았고, 두 환경의 빌드 시점 차이로 생긴 일시적 불일치와 파이프라인이 따라잡은 뒤에도 남는 새로운 차이를 나눠 살폈습니다. 같은 도메인의 zone들이 서로 다른 scheduler에서 공유 키를 동시에 쓰지 않도록 배포도 zone 이름의 해시를 기준으로 진행했습니다.
Cloudflare가 공개한 24시간 집계에서 전체 빌드를 피한 빌드는 92.95%였습니다. 배포 전체의 평균 working-set 메모리는 49 GiB에서 7 GiB로, 피크는 79 GiB에서 12 GiB로 줄었습니다. 변경부터 Zone Builder가 Quicksilver에 쓰기를 끝낼 때까지의 중앙값은 약 7.7초에서 3.3초로 낮아졌습니다. 이 시간에는 Quicksilver가 변경을 전 세계 네트워크에 배포하는 과정이 들어 있지 않습니다. 빌드 작업량이 줄어든 뒤 Cloudflare는 대부분 요금제의 zone별 재빌드 대기 간격을 단축했고, 데이터베이스가 뒤처진 복제본의 읽기를 거부하게 되면서 이벤트를 기다리는 시간도 줄였습니다. 이 두 변경이 반영 시간 단축에 함께 기여했습니다.
자료: Cloudflare 블로그 / 정리·해설: Trawling