{"id":"IL-0102","org":"Buildkite","date":"2026-08-25","docs":[],"title":{"en":"CoreDNS pods on a production EKS cluster ran out of memory under a burst of new pods, endpoints and nodes, taking down the Buildkite web UI, APIs and job dispatch","ko":"배포와 워커 오토스케일링 폭주가 겹치자 크기를 고정해 둔 CoreDNS 가 메모리 한도를 넘겨 재시작된 뒤 회복하지 못했고, Buildkite 사이트 전체가 약 30분 멈췄다."},"domain":["kubernetes","aws"],"impact":{"scope":"Buildkite web interface, REST API (including the Remote MCP Server), Agent API, job queue and notifications; new builds could not be created and job dispatch was delayed; under 1.5% of requests returned errors","users":"All customers","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"A CoreDNS deployment sized once and left at a fixed size can carry a growing cluster for months and then fail on the first burst of churn it cannot absorb. When query processing slows, pending queries take up memory, the pods hit their limits and restart, and client retries keep the service down after the restart.\n\nServer-side DNS query duration and volume need their own alerts: here client-side latency was masked by unrelated application speed-ups, and a broken monitoring query hid the server-side trend. Maximum replica counts raised as a temporary measure remove the cap that normally stops runaway scaling when new nodes are slow to arrive.","ko":"크기를 고정해 둔 CoreDNS 는 클러스터가 커지고 변경 속도가 빨라지면 한순간에 무너질 수 있다. 나중에 낮출 생각으로 높게 잡아 둔 워커의 최대 레플리카 수는 노드 공급이 늦어질 때 오토스케일링 폭주를 막지 못했다. 모니터링 쿼리에 결함이 있고 쿼리량을 제대로 감시하지 않아 장기 추세가 보이지 않았다. 클러스터 핵심 서비스는 급격한 저하와 여유분 감소를 둘 다 직접 감시해야 한다."},"related":[],"sources":[{"url":"https://www.buildkitestatus.com/incidents/tm6746k61p73","kind":"official-status","license":"unknown","archived":null}],"summary":{"en":"Buildkite had spent four months moving its production workloads from AWS ECS to an AWS EKS cluster, and the cluster had grown steadily throughout. Services in it locate databases, queues and other components through CoreDNS, which ran as a fixed set of three pods and did not scale with the size or rate of change of the cluster. Buildkite had also recently moved time-sensitive notification jobs from the general background worker pool into a new low-latency pool, and had given both pools the same high maximum replica count as the original shared pool, planning to lower both later.\n\nAt 22:44 UTC an application deploy consumed the headroom on the deployed nodes. Background workers, including the notification workers, were trying to scale out at the same moment. Their new compute was delayed while the cluster scaled, and since the metrics that had made them scale had not changed, they requested still more pods. The services' maximums would normally have capped this runaway scaling, but they had been set higher than usual. The flood of new pods, endpoints and nodes drove CoreDNS query time from under 1 ms to about 780 ms; queued queries filled memory, all three pods exceeded their memory limits and were restarted, and retries kept them from recovering. With DNS failing, APIs, job dispatch and notifications failed for all customers from 22:47 to 23:16 UTC.\n\nThe post-incident analysis found that a defect in a key monitoring query had hidden an upward trend in CoreDNS query duration that tracked the growing cluster size, and that DNS query volume, which had been rising as more workloads moved to EKS, was not monitored well enough. On the client side, recent application performance gains offset the slower DNS answers, so the trend drew no attention, and the planned work to autoscale CoreDNS had not been given priority. Engineers paused deploys, added CoreDNS replicas with more memory and enlarged the node pool that runs them. The new CoreDNS pods were serving by 23:12 UTC, DNS errors dropped quickly, and the accumulated backlog was processed by 23:16 UTC.","ko":"Buildkite 는 넉 달째 운영 워크로드를 AWS ECS 에서 AWS EKS 클러스터로 옮기고 있었고, 그동안 클러스터는 꾸준히 커졌다. 이 클러스터의 서비스들은 데이터베이스와 큐 같은 구성 요소의 위치를 CoreDNS 로 찾는다. CoreDNS 는 크기가 고정돼 있어 클러스터 크기나 변경 속도에 맞춰 늘어나지 않았다. Buildkite 는 얼마 전 시간에 민감한 알림 작업을 범용 백그라운드 워커 풀에서 새 저지연 워커 풀로 옮기면서, 두 풀 모두에 원래 공용 풀과 같은 높은 maxReplica 값을 주었다. 이 값은 나중에 낮출 생각이었다.\n\n22:44 UTC 배포로 파드가 급증하자 클러스터가 확장을 시작했고, 기존 노드의 여유 용량이 바닥나 다른 서비스의 오토스케일링이 제때 되지 않았다. 노드를 기다리는 동안 확장 지표가 바뀌지 않으니 워커들은 파드를 더 요청했고, 높게 잡아 둔 최대치가 이 폭주를 막지 못했다. 배포와 오토스케일링 폭주가 겹쳐 애플리케이션, 네트워크 엔드포인트, 노드가 유난히 빠르게 바뀌었고, 그 결과 CoreDNS 에 갑자기 부하가 몰렸다.\n\nCoreDNS 쿼리 처리 시간이 약 780ms 까지 늘면서 대기 요청이 메모리에 쌓였고, 파드 세 개가 모두 메모리 한도를 넘어 재시작됐다. 재시작 뒤에도 수요와 DNS 재시도가 이어져 CoreDNS 는 회복하지 못했다. CoreDNS 가 멈추자 모든 고객의 API, 작업 배정, 알림이 실패했고, 재시도와 밀린 작업이 복구 중 부하를 더 키웠다. 팀은 배포를 멈추고 CoreDNS 를 늘렸다. 새 빌드 처리는 23:10 UTC 에 다시 시작됐다. 새 CoreDNS 파드가 23:12 UTC 에 서비스에 들어오자 DNS 오류가 빠르게 줄었고, 밀린 작업은 23:16 UTC 까지 모두 처리됐다.\n\n사후 분석에서 CoreDNS 모니터링의 결함이 드러났다. 핵심 모니터링 쿼리 하나에 결함이 있어 클러스터 크기와 함께 늘던 쿼리 처리 시간이 보이지 않았고, DNS 쿼리량은 충분히 모니터링되지 않았다. 그래서 계획해 둔 CoreDNS 오토스케일링 도입의 우선순위가 제대로 잡히지 않았다."},"trigger":{"en":"At 22:44 UTC an application deploy created a surge of new pods, which used up the free capacity on the existing nodes and made the EKS cluster scale out. Background worker pools with unusually high maximum replica counts were scaling out at the same time and kept asking for more pods while new nodes were still being provisioned. Together they produced an unusually high rate of change in applications, network endpoints and nodes, and with it a sudden rise in demand on CoreDNS.","ko":"22:44 UTC 에 애플리케이션을 배포하면서 파드가 한꺼번에 늘어 이미 떠 있던 노드의 여유 용량이 바닥났다. 같은 시각 알림 워커를 비롯한 백그라운드 워커들도 확장하려 했고, 노드 공급이 늦어지자 확장 지표가 그대로인 채 파드를 계속 더 요청했다. 이 워커들의 최대 레플리카 수는 평소보다 높게 잡혀 있었다."},"severity":"unknown","symptoms":["service-unavailable","dns-resolution-failures","oom-killed","autoscaler-misbehaving"],"timeline":{"detected_after":"8m","resolved_after":"29m"},"date_kind":"incident","detection":{"en":"The first status post, at 22:55 UTC, eight minutes after the outage began, said something had gone wrong, and at 23:05 UTC the status page said a sitewide outage was being investigated. CoreDNS query duration had been rising as the cluster grew, but a defect in a key monitoring query and too little monitoring of query volume meant this went unnoticed before the outage.","ko":"장애는 22:47 UTC 에 시작됐고, Buildkite 는 22:55 UTC 에 문제를 조사 중이라고 상태 페이지에 처음 알렸다. 23:05 UTC 에는 사이트 전체 장애를 조사 중이라고 올렸다. CoreDNS 쿼리 처리 시간은 클러스터가 커지면서 늘고 있었지만, 핵심 모니터링 쿼리의 결함과 쿼리량 모니터링 부족 때문에 장애 전에는 이를 알아채지 못했다."},"components":["coredns","memory-limit","hpa","node-pool"],"root_cause":"capacity","remediation":[{"text":{"en":"paused further application deploys","ko":"추가 애플리케이션 배포를 멈췄다."}},{"text":{"en":"scaled CoreDNS from three to twelve pods","ko":"CoreDNS 파드를 3개에서 12개로 늘렸다."}},{"text":{"en":"raised each CoreDNS pod's memory limit from 512 MiB to 2 GiB","ko":"CoreDNS 파드마다 메모리 한도를 512 MiB 에서 2 GiB 로 올렸다."}},{"text":{"en":"expanded the system node pool that runs CoreDNS","ko":"CoreDNS 를 돌리는 시스템 노드 풀을 늘렸다."}}],"action_items":[{"text":{"en":"Increase immediate CoreDNS headroom: twelve pods instead of three, a 2 GiB memory limit instead of 512 MiB, and a larger system node pool","ko":"CoreDNS 파드를 3개에서 12개로 늘리고, 파드당 메모리 한도를 512 MiB 에서 2 GiB 로 올리고, 이 파드들을 돌릴 시스템 노드 풀을 넓혔다."}},{"text":{"en":"Enable EKS-managed CoreDNS autoscaling with a tested minimum replica count and enough capacity to spread the replicas across nodes and availability zones","ko":"EKS 관리형 CoreDNS 오토스케일링을 켠다. 검증한 최소 레플리카 수를 정하고, 레플리카를 여러 노드와 가용 영역에 나눠 둘 만큼 용량을 확보한다."}},{"text":{"en":"Add direct alerts on CoreDNS query duration, query volume, goroutine growth, memory pressure, OOM restarts and available replicas, and track longer-term trends in capacity planning","ko":"CoreDNS 쿼리 처리 시간, 쿼리량, 고루틴 증가, 메모리 압박, OOM 재시작, 사용 가능한 레플리카 수에 직접 알림을 건다. 장기 추세도 용량 계획에 넣어 지켜본다."}},{"text":{"en":"Find other cluster-critical services that lack tested capacity, direct alerting, spread across failure domains, and either safe autoscaling or documented static headroom, and fix them","ko":"클러스터에 꼭 필요한 다른 서비스도 살핀다. 검증된 용량, 직접 알림, 장애 도메인 분산이 없는 서비스, 그리고 안전한 오토스케일링도 문서로 정한 고정 여유분도 없는 서비스를 찾아 고친다."}}],"contributing":["no-spare-capacity","automation-amplified","retry-storm","monitoring-blind-spot"],"recurrence_of":null,"symptoms_text":{"en":"From 22:47 UTC on 25 August 2026 the Buildkite web interface, REST API, Agent API, job queue and notifications stopped working for every customer. No one could create a build from the UI or the REST API, job dispatch was delayed, and some builds that were already running when the outage began stayed stuck until the services recovered.\n\nWebhooks from source control providers kept arriving, but their processing fell behind. A subset of customers whose database queries went through PgBouncer instances inside the EKS cluster got error responses from the web UI and on webhook delivery; these errors were less than 1.5% of all requests during the outage. A status post at 23:38 UTC put the failure down to Buildkite's internal DNS services.\n\nInside the cluster, CoreDNS kept completing queries at a steady rate, but the time to process each query rose from under 1 ms to about 780 ms. Pending queries piled up in memory until all three CoreDNS pods went over their memory limits and Kubernetes restarted them. Continued demand and DNS retries kept CoreDNS from recovering after the restarts.","ko":"22:47 UTC 부터 Buildkite 웹 화면, REST API, Agent API, 작업 큐, 알림이 한꺼번에 장애를 겪었다. 모든 고객이 웹 화면이나 REST API 로 새 빌드를 만들 수 없었고, 작업 배정이 늦어졌다.\n\n소스 관리 서비스에서 오는 웹훅은 계속 받았지만 처리가 밀렸다. 장애가 시작될 때 이미 돌고 있던 빌드 일부는 서비스가 회복될 때까지 멈춰 있었다. EKS 클러스터 안의 PgBouncer 를 거쳐 데이터베이스에 붙던 일부 고객은 웹 화면과 웹훅 수신에서 오류 응답을 받았고, 이런 오류는 전체 요청의 1.5% 미만이었다.\n\nCoreDNS 에서는 처리를 마친 쿼리 수가 그대로였지만 쿼리 처리 시간이 1ms 미만에서 약 780ms 로 늘었다. 처리되지 못한 요청이 메모리에 쌓이면서 원래 있던 CoreDNS 파드 세 개가 모두 메모리 한도를 넘었고, 쿠버네티스가 이 파드들을 재시작했다. 재시작 뒤에도 요청과 DNS 재시도가 계속 몰려 CoreDNS 는 회복하지 못했다.\n\n징후는 장애 전부터 있었다. CoreDNS 쿼리 처리 시간은 클러스터가 커지면서 계속 늘고 있었고, DNS 쿼리량도 EKS 로 워크로드를 옮길수록 늘고 있었다. 핵심 모니터링 쿼리에 결함이 있어 처리 시간이 느는 것이 보이지 않았고, 쿼리량은 제대로 모니터링되지 않았다. 클라이언트 쪽 지연 증가는 최근 애플리케이션 성능 개선에 묻혀 눈에 띄지 않았다."},"updated_at":"2026-11-10T00:00:33.275373Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0102","org_slug":"buildkite"}