{"id":"IL-0004","org":"Grafana Labs","date":"2019-07-19","docs":["https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/"],"title":{"en":"A new default pod priority let a new Cortex cluster preempt every production ingester in a cascade, taking Grafana Cloud Hosted Prometheus down","ko":"새 Cortex 클러스터에서 기본 우선순위를 받은 파드가 우선순위가 없는 운영 Ingester 를 연쇄적으로 선점해 Hosted Prometheus 쓰기가 실패했다"},"domain":["kubernetes","observability"],"impact":{"scope":"Grafana Cloud Hosted Prometheus: writes to the production Cortex clusters; no data lost","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Medium should not have become the default priority until the production ingesters had the high priority, and that designation should have reached production sooner. The change was considered too minor for a design document and was only discussed in a GitHub issue; cluster-global configuration needs more scrutiny. On the positive side, once Cortex had enough capacity it recovered by itself, and Grafana Loki helped confirm that the ingesters exited gracefully.","ko":"운영 Ingester 에 high 우선순위를 지정하기 전에 medium 을 기본 우선순위로 만들지 말았어야 했다. 운영 Ingester 의 high 지정도 더 일찍 배포했어야 했다. 팀은 이 변경이 설계 문서를 쓸 만큼 크지 않다고 보고 GitHub 이슈에서만 논의했다.\n\n좋은 점도 있었다. Cortex 는 자원이 충분해지자 추가 조치 없이 스스로 회복했다. 팀은 새 로그 수집 시스템인 Grafana Loki 로 Ingester 가 정상적으로 종료됐는지 확인했다."},"related":["IL-0020"],"sources":[{"url":"https://grafana.com/blog/2019/07/24/how-a-production-outage-was-caused-using-kubernetes-pod-priorities/","kind":"blog","license":"unknown","archived":"http://web.archive.org/web/20251209070733/https://grafana.com/blog/2019/07/24/how-a-production-outage-was-caused-using-kubernetes-pod-priorities/"}],"summary":{"en":"To upgrade without downtime, Cortex needs one extra ingester during a rollout so the old ingesters can hand their in-progress data to new ones. Each ingester requests 4 cores and 15GB of RAM, 25% of one machine, and the clusters rarely have that much free on a single machine. To make room, Grafana Labs deployed four priority classes on Thursday 18 July: critical, high, medium and low. Medium became the default for pods without a priority, ingesters were to get high, and critical was reserved for monitoring jobs. The classes had run for about a week on an internal cluster without customer traffic, but the existing production Cortex ingesters had not yet been given the high priority.\n\nOn 19 July the new customer cluster's ingesters, at the default medium priority, preempted an ingester of the production Cortex cluster, whose pods had no priority. The production ReplicaSet created a replacement ingester, which also got the default medium priority and preempted another production ingester. The cascade went on until all production ingesters had been preempted. Cortex ingesters are stateful and hold up to the last 12 hours of data. Cortex does not write to ingesters that are shutting down, so with that many of them leaving it could not replicate writes, and writes failed.\n\nAbout 5 minutes after the page, the team had diagnosed the problem and scaled up the underlying Kubernetes cluster to fit both the new and the production Cortex clusters. About 5 minutes later the old ingesters had written out their data, the new ones had been scheduled, and Cortex was available again without further intervention. Fixing the out-of-memory errors in the authenticating proxies took about 10 more minutes. No data was lost: the ingesters flushed all in-memory data to long-term storage, and customers' Prometheus servers buffered failed remote writes with the new WAL-based remote write code and replayed them after the outage.","ko":"Grafana Cloud 의 Hosted Prometheus 는 CNCF 프로젝트인 Cortex 위에 만든 서비스다. Cortex 의 Ingester 서비스를 다운타임 없이 업그레이드하려면 업그레이드하는 동안 Ingester 레플리카가 하나 더 있어야 한다. Ingester 파드 하나는 CPU 4코어와 메모리 15GB 를 요청하고, 이는 쿠버네티스 노드 한 대의 CPU 와 메모리의 25% 다. 평소에는 노드 한 대에 그만큼의 빈자리가 없다. 그래서 Grafana Labs 는 파드 우선순위를 도입했다. Ingester 에 높은 우선순위를 주고, 필요할 때 다른 작은 파드를 잠시 선점해 자리를 만들려는 것이었다.\n\n7월 18일 목요일 팀은 critical, high, medium, low 네 가지 우선순위 클래스를 클러스터에 배포했다. 고객 트래픽이 없는 내부 클러스터에서 약 1주 돌려 본 설정이었다. medium 은 우선순위를 지정하지 않은 파드의 기본값이 되었고 Ingester 는 high 로 정했다. 그러나 운영 Cortex 클러스터의 Ingester 에는 아직 high 지정이 반영되지 않았다.\n\n다음 날 새 전용 Cortex 클러스터의 Ingester 가 기본값 medium 을 받았고, 우선순위가 없는 운영 Ingester 하나를 선점했다. 운영 ReplicaSet 이 새로 만든 Ingester 도 medium 을 받아 또 다른 운영 Ingester 를 선점했다. 이 연쇄로 운영 Cortex 클러스터의 Ingester 가 모두 선점됐다. Cortex 는 데이터를 시리즈 단위로 분산 해시 테이블에 샤딩하고 Ingester 세 개에 쿼럼 방식으로 복제한다. Ingester 가 대거 빠지자 쓰기를 충분히 복제하지 못해 쓰기가 실패했다.\n\n당직자는 약 5분 만에 원인을 찾고 쿠버네티스 클러스터를 늘렸다. 다시 약 5분 뒤 옛 Ingester 가 데이터를 모두 플러시하고 새 Ingester 가 스케줄링되어 Cortex 클러스터가 돌아왔다. 이어서 인증 리버스 프록시의 OOM 을 약 10분 걸려 찾고 고쳤다. 장애는 모두 26분이었고 데이터는 잃지 않았다. 고객 Prometheus 서버는 WAL 기반 remote write 로 쓰기를 버퍼에 담아 두었다가 장애 뒤 다시 보냈다."},"trigger":{"en":"An engineer created a new dedicated Cortex cluster for a large customer. Its configuration did not include the new pod priorities, so all its pods got the default medium priority, and the Kubernetes cluster did not have enough free resources to fit it.","ko":"7월 19일 한 엔지니어가 큰 고객을 위한 전용 Cortex 클러스터를 새로 띄웠다. 새 클러스터 설정에는 새로 도입한 파드 우선순위 지정이 없어서, 모든 파드가 기본값인 medium 우선순위를 받았다. 쿠버네티스 클러스터에는 새 Cortex 클러스터를 올릴 자원이 부족했다."},"severity":"unknown","symptoms":["pods-evicted","high-error-rate","service-unavailable","oom-killed"],"timeline":{"detected_after":"4m","resolved_after":"26m"},"date_kind":"incident","detection":{"en":"New error-budget-based Prometheus alerts paged the on-call engineer within 4 minutes of the start of the outage.","ko":"새로 도입한 오류 예산 기반 Prometheus 알림이 장애 시작 4분 안에 당직자를 호출했다."},"components":["pod-priority"],"root_cause":"config-change","remediation":[{"text":{"en":"Scaled up the underlying Kubernetes cluster to fit both the new and the production Cortex clusters","ko":"쿠버네티스 클러스터를 늘려 새 Cortex 클러스터와 기존 운영 Cortex 클러스터가 모두 들어가게 했다."}},{"text":{"en":"Diagnosed and fixed the out-of-memory errors in the authenticating reverse proxies in front of Cortex","ko":"Cortex 앞의 인증 리버스 프록시에서 난 OOM 을 찾아 고쳤다."}}],"action_items":[{"text":{"en":"Give the production ingesters the high priority class, which should have been done before medium became the default","ko":"운영 Ingester 에 high 우선순위 지정을 반영했다."}},{"text":{"en":"Have more people review changes to configuration that is global to the cluster","ko":"클러스터 전역 설정처럼 네임스페이스 밖에 있는 객체의 배포는 더 많은 사람이 리뷰한다."}},{"text":{"en":"Require a design document for every configuration change outside a namespace","ko":"네임스페이스 밖 설정 변경에는 모두 설계 문서를 요구한다."}},{"text":{"en":"Automate the sizing of the frontend authenticating reverse proxy so it does not run out of memory under overload","ko":"인증 리버스 프록시의 규모 조정을 자동화해 과부하 때 OOM 이 나지 않게 한다."}},{"text":{"en":"Investigate the default backoff and scaling behaviour of Prometheus to prevent a stampeding herd of retries","ko":"한꺼번에 몰려드는 재시도를 막으려고 Prometheus 의 기본 백오프와 확장 동작을 조사한다."}}],"contributing":["partial-rollout","automation-amplified","review-missed","no-spare-capacity","retry-storm"],"recurrence_of":null,"symptoms_text":{"en":"On Friday 19 July 2019 the Grafana Cloud Hosted Prometheus service, which is built on the Cortex project, was down for 26 minutes. New error-budget-based Prometheus alerts paged the on-call engineer within 4 minutes of the start.\n\nWrites to the production Cortex clusters failed. Ingester pods of the production clusters were being preempted one after another until none were left. Cortex replicates each series to three ingesters with quorum consistency and does not write to ingesters that are shutting down, so with many ingesters leaving its hash ring at once it could not replicate writes.\n\nAfter Cortex was available again, the authenticating reverse proxies in front of it ran out of memory. Their request rate had risen more than tenfold, which Grafana Labs believes came from overly aggressive retries by customers' Prometheus servers. Diagnosing and fixing these out-of-memory errors took about another 10 minutes.","ko":"2019년 7월 19일 금요일, Grafana Cloud 의 Hosted Prometheus 서비스가 장애를 겪었다. 오류 예산 기반 Prometheus 알림이 장애 시작 4분 안에 당직자를 호출했다.\n\n운영 Cortex 클러스터의 Ingester 파드가 선점되어 밀려났다. 밀려난 Ingester 를 대신하려고 ReplicaSet 이 새 파드를 만들었고, 이 파드가 다시 다른 운영 Ingester 를 선점했다. 이 연쇄로 운영 Cortex 클러스터의 Ingester 파드가 모두 선점됐다.\n\nCortex 는 종료 중인 Ingester 에는 데이터를 쓰지 않는다. 많은 Ingester 가 분산 해시 테이블에서 한꺼번에 빠지자 Cortex 는 쓰기를 충분히 복제하지 못했고 쓰기가 실패했다.\n\n클러스터를 늘려 Cortex 가 돌아온 뒤에도 Cortex 앞에 있는 인증 리버스 프록시가 OOM 으로 죽었다. QPS 가 10배 넘게 뛰었고, 팀은 고객 Prometheus 서버가 지나치게 공격적으로 재시도했기 때문이라고 본다."},"updated_at":"2026-11-10T00:00:31.398638Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0004","org_slug":"grafana-labs"}