{"id":"IL-0076","org":"Fullstaq","date":"2019-06-01","docs":["https://github.com/ctron/kill-kube-ns"],"title":{"en":"Kubernetes masters went down after Dex filled etcd with AuthRequest objects and deleting its namespace started an endless list-and-timeout loop","ko":"dex의 AuthRequest 리소스가 끝없이 쌓였고, 이를 치우려고 네임스페이스를 지우자 목록 조회 타임아웃과 재시도가 반복되며 쿠버네티스 마스터가 내려갔다"},"domain":["kubernetes"],"impact":{"scope":"Kubernetes masters down; cluster authentication and access to monitoring lost; no business applications affected","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Dex with Kubernetes as its storage keeps every AuthRequest as an API object, and with a long TTL they pile up until the API cannot list them. Deleting a namespace that holds that many objects makes Kubernetes list them in a loop and can overload the masters. Monitoring that is reached through cluster authentication is lost when authentication is what broke.","ko":"외부 도구의 기본값을 그대로 믿지 않는다. 목록 조회도 안 될 만큼 쌓인 리소스를 네임스페이스 삭제로 치우면 정리 루프가 타임아웃과 재시도를 반복해 마스터를 내릴 수 있다. 클러스터 인증이 클러스터 안에 있으면 클러스터가 죽었을 때 모니터링에도 들어갈 수 없다. API로 finalizer를 직접 지우는 방법은 발표자도 절대 하지 말라고 한 마지막 수단이다."},"related":[],"sources":[{"url":"https://pieterlange.github.io/failure-stories/2019-06.dex.html","kind":"talk","license":"unknown","archived":null}],"summary":{"en":"This is a meetup talk by Pieter Lange of Fullstaq, given as slides without notes. Dex ran with what the speaker calls bad defaults, an insane TTL, together with refreshing dashboards and an actual security bug. AuthRequest objects piled up in etcd until listing them timed out, and the speaker had seen hints of this earlier. The options he weighed were tuning etcd and API server timeouts, deleting the namespace and letting Kubernetes clean up, or deleting the objects directly in etcd.\n\nHe deleted the namespace. The reconciliation loops then listed all AuthRequests, timed out and started over, which drove master load to 60 and brought the masters down. He removed the kubernetes finalizer from the dex namespace by calling the API directly, with the kill-kube-ns tool, a step he marks NEVER DO THIS. That ended the outage, but about 0.5G of AuthRequests stayed in etcd, and he was fairly sure that creating a namespace named dex again would kill the cluster, so Dex was deployed to a new namespace with sane defaults. No business applications were affected.","ko":"Fullstaq의 Pieter Lange가 NMBRS에서 열린 k8s 밋업에서 발표한 사례다. 이 클러스터는 쿠버네티스 인증에 OIDC 프록시인 dex를 썼고, dex는 저장소로 클러스터 자체를 쓰도록 type: kubernetes, inCluster: true로 설정돼 있었다. 잘못된 기본값 탓에 AuthRequest가 쌓였고, 목록 조회조차 타임아웃이 나서 지울 수 없었다. 발표자가 든 선택지는 etcd와 API 서버의 타임아웃을 조정하는 것, 네임스페이스를 지워 쿠버네티스가 정리하게 두는 것, 쿠버네티스를 거치지 않고 etcd에서 직접 지우는 것이었다. 발표자는 두 번째를 골랐다.\n\n네임스페이스 정리 루프는 지우기 위해 모든 요청을 나열하다 타임아웃이 나고 다시 시도하기를 반복했다. 마스터 부하가 60까지 오르며 마스터가 내려갔다. 네임스페이스는 finalizers에 kubernetes가 남은 채 Active 상태로 멈춰 있었고, 이 finalizer는 kubectl로 지울 수 없었다. 발표자는 kill-kube-ns 도구로 API를 직접 호출해 finalizer를 지웠다. 그러면서 이 방법은 절대 쓰지 말라고 두 번 강조했다. 이것으로 일단 풀렸지만 etcd에는 AuthRequest가 0.5G 남았다. 발표자는 kubectl create namespace dex를 실행하면 클러스터가 죽을 것이라고 봤다. dex를 적절한 기본값으로 설정해 새 네임스페이스에 다시 배포했다. 업무 애플리케이션은 이 장애로 피해를 입지 않았다."},"trigger":{"en":"The dex namespace was deleted so that Kubernetes would clean up the accumulated AuthRequest objects itself.","ko":"dex의 잘못된 기본값 때문에 AuthRequest 리소스가 쌓였다. 발표는 원인으로 지나치게 긴 TTL, 계속 새로고침되는 대시보드, 실제 보안 버그를 꼽았다. 그리고 쌓인 리소스를 치우려고 dex 네임스페이스를 지우자 마스터가 내려갔다."},"severity":"unknown","symptoms":["control-plane-unresponsive","monitoring-down"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"published","detection":{"en":"The speaker says he had got hints of the problem earlier. While the masters were down, plenty of alerts arrived in Slack, but monitoring could not be reached because authentication and port-forwarding no longer worked.","ko":"발표자는 그 전부터 이미 징후가 있었다고 했다. 마스터가 내려간 뒤에는 Slack에 경보가 많이 들어왔지만, 인증도 port-forward도 되지 않아 모니터링에는 들어갈 수 없었다."},"components":["kube-apiserver","etcd","oidc-provider"],"root_cause":"capacity","remediation":[{"text":{"en":"removed the kubernetes finalizer from the dex namespace by calling the API directly (kill-kube-ns)","ko":"kill-kube-ns 도구로 API를 직접 호출해 dex 네임스페이스에 남은 kubernetes finalizer를 지웠다."}},{"text":{"en":"deployed Dex to a new namespace with sane defaults","ko":"dex를 적절한 기본값으로 설정해 새 네임스페이스에 다시 배포했다."}}],"action_items":[],"contributing":["default-config-unchanged","manual-action-worsened","retry-storm","limited-debug-access","early-signal-ignored"],"recurrence_of":null,"symptoms_text":{"en":"Dex, the OIDC proxy that handled Kubernetes authentication, stored its data in the Kubernetes API (storage type kubernetes, inCluster: true) and had built up a huge number of AuthRequest objects. Listing all AuthRequests timed out, and without the list they could not be deleted.\n\nAfter the dex namespace was deleted, the reconciliation loops kept listing all AuthRequests in order to delete them, timing out and repeating. Load on the masters rose to 60 and the masters went down. Monitoring could not be reached because authentication and port-forwarding no longer worked, while alerts kept arriving in Slack.","ko":"dex의 AuthRequest 리소스가 엄청난 수로 쌓여 있었다. 발표자는 그 전부터 이미 징후가 있었다고 했다.\n\nAuthRequest 전체 목록을 조회하면 타임아웃이 났다. 리소스를 지우려면 목록이 필요했기 때문에 쌓인 리소스를 정리할 수 없었다.\n\ndex 네임스페이스를 지우자 쿠버네티스의 정리 루프가 모든 요청을 나열하려다 타임아웃이 나고 다시 시도하기를 반복했다. 마스터 부하가 60까지 치솟았고 마스터가 내려갔다. 인증이 되지 않고 port-forward도 할 수 없어 모니터링에 들어갈 수 없었다. Slack에는 경보가 많이 들어왔다."},"updated_at":"2026-11-08T19:10:32.601757Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0076","org_slug":"fullstaq"}