IL-0194 Palark · 2023-03-23kubernetes
고객사 운영 클러스터에서 kube-apiserver 를 재시작한 뒤 etcd 메모리가 거의 세 배로 늘었고 모든 마스터 노드가 연쇄적으로 재시작했다. 감사 로그로 찾은 원인은 로그에 파드 메타데이터를 덧붙이려고 파드 정보를 읽는 Vector 로그 수집기 DaemonSet 이었다. 이 파드들은 client-go 인포머의 기본 동작처럼 kube-apiserver 가 재시작하면 캐시를 다시 채우려고 list 요청을 보낸다. 파드 하나가 시작하면서 list 요청을 60번 보냈고 노드는 약 80개였다.
요청은 /api/v1/pods?fieldSelector=spec.nodeName=$NODE_NAME 모양으로, 자기 노드에 있는 파드만 달라는 것이었다. 하지만 etcd 는 /registry/<kind>/<namespace>/<name> 꼴의 키로 값을 저장하는 단순한 키-값 저장소라서 필드 셀렉터나 레이블 셀렉터를 모른다. 그래서 kube-apiserver 는 파드 110개로 응답하려고 etcd 에서 파드 전부, 이 클러스터에서는 7130개를 읽어야 했다. resourceVersion 을 지정하지 않은 요청은 기본값인 MostRecent 로 처리돼 매번 etcd 까지 간다.
요청에 resourceVersion=0 과 resourceVersionMatch=NotOlderThan 을 넣으면 kube-apiserver 가 자기 캐시에서 답해 응답 시간이 337 밀리초에서 117 밀리초로 줄었다. 하지만 이 애플리케이션은 Rust 로 짜여 있었고 쿠버네티스 Rust 라이브러리에는 resourceVersion 설정이 없었다. 대신 API Priority and Fairness 로 이 DaemonSet 서비스 어카운트의 파드 list 와 get 요청을 대기열에 줄 세웠다. 그 뒤 etcd 메모리 그래프는 스파이크가 일부 남았지만 대체로 정상이었고, 팀은 장애 등급을 낮췄다.
일상적인 kube-apiserver 재시작 직후 etcd 메모리 사용량이 거의 세 배로 치솟았고, 그 여파로 모든 마스터 노드가 연쇄적으로 재시작했다. 고객사의 운영 클러스터였다.
etcd 로그에는 "apply request took too long" 경고가 찍혔다. took 는 130.768157ms, expected-duration 은 100ms 였고, 요청은 key:"/registry/pods/" range_end:"/registry/pods0" 인 read-only range 였다. 응답은 range_response_count:7130 size:13313287 이었다. 노드 하나의 파드만 묻는 요청이라 110개를 넘지 않아야 했는데 etcd 는 파드 7130개를 읽고 있었다.
감사 로그를 보니 DaemonSet 하나가 원인이었다. kube-apiserver 가 재시작하면 이 DaemonSet 의 파드들이 캐시를 채우려고 list 요청을 새로 보냈다. 파드 하나가 시작하면서 list 요청을 60번 보냈고 클러스터 노드는 약 80개였다. 파드를 하나씩 차례로 재배포할 때는 메모리 그래프에 변화가 없었고, 한꺼번에 재배포할 때만 메모리가 치솟았다.
kube-apiserver 재시작 직후 마스터 노드 전체 메모리와 etcd 메모리 그래프가 치솟고 마스터 노드가 연쇄적으로 재시작하면서 알았다. 원인이 된 DaemonSet 은 감사 로그를 보고 찾았다.
etcd 는 필드 셀렉터와 레이블 셀렉터를 모르기 때문에, kube-apiserver 에는 가벼워 보이는, 필터를 건 list 요청도 etcd 에서는 그 종류의 객체 전체를 읽는 일이 된다. 데이터가 꼭 최신이어야 하는 컨트롤러가 아니라면 resourceVersion=0 으로 kube-apiserver 캐시에서 읽게 할 수 있다. 다만 kube-apiserver 가 여러 대면 인스턴스마다 다른 데이터를 받을 수 있다. 여러 파드가 한꺼번에 보내는 요청은 Priority and Fairness 로 대기열에 넣어 kube-apiserver 와 etcd 를 지킬 수 있다. 위험한 것은 파드 요청만이 아니어서 Cilium CNI 에서도 비슷한 문제가 나왔다.
IL-0075 클러스터가 EC2 인스턴스 약 290대로 커지자 노드마다 도는 Datadog 에이전트가 쿠버네티스 API 를 폴링하면서 API 서버가 CPU 와 메모리를 다 써 쿠버네티스 컨트롤 플레인을 쓸 수 없게 됐다.Civis Analytics · 2019같은 원인 · 공통 쿠버네티스 API 서버, 텔레메트리 에이전트, etcd
IL-0204 Render 프랑크푸르트 클러스터에서 etcd 메모리 급증으로 컨트롤 플레인이 과부하에 걸렸고, 컨트롤 플레인 노드를 재부팅하자 그 위의 CoreDNS 가 다시 뜨지 못해 DNS 가 멈췄다.Render · 2024같은 원인 · 공통 쿠버네티스 API 서버, etcd
IL-0076 dex의 AuthRequest 리소스가 끝없이 쌓였고, 이를 치우려고 네임스페이스를 지우자 목록 조회 타임아웃과 재시도가 반복되며 쿠버네티스 마스터가 내려갔다Fullstaq · 2019같은 원인 · 공통 쿠버네티스 API 서버, etcd
IL-0042 OpenSearch 디스크가 가득 찬 동안 fluent-bit 가 로그를 처리하지 못해 Elasticsearch 와 OpenSearch 에 애플리케이션 로그가 들어오지 않았다.UK Ministry of Justice · 2024같은 원인 · 공통 텔레메트리 에이전트
https://incidentlib-mcp.benchlet.com/mcpAPI 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.
같은 원인 · 공통 텔레메트리 에이전트
IL-0168 새 쿠버네티스 릴리스 뒤 많은 Kapsule 클러스터가 동시에 자동 업그레이드되면서 Kubernetes API 가 과부하로 OOM 이 났고, 새 노드 인증 방식의 재시도가 혼잡을 키워 노드가 Not Ready 가 됐다.Scaleway · 2024같은 원인 · 공통 쿠버네티스 API 서버
같은 원인 · 공통 텔레메트리 에이전트
IL-0195 200개가 넘는 노드의 고객 클러스터에서 Cilium 파드가 LIST 요청을 한꺼번에 쏟아내 kube-apiserver 가 메모리를 다 쓰고 죽기를 되풀이했다.Palark · 2023같은 원인 · 공통 쿠버네티스 API 서버
같은 원인 · 공통 쿠버네티스 API 서버
IL-0026 메모리 제한이 없는 fluentd-sumologic 파드가 메모리를 다 써서 운영 쿠버네티스 노드 두 대에 이틀 연속 SystemOOM 이 났다Blue Matador · 2019같은 원인 · 공통 텔레메트리 에이전트
IL-0002 빌더 파드가 노드 한 대에 몰리자 kubelet 이 기본 API QPS 한도에 막혀 파드 상태를 늦게 갱신했고, CI 빌드가 AWS IAM 자격 증명을 받지 못해 실패했다Zalando · 2019같은 원인 · 공통 쿠버네티스 API 서버
같은 원인 · 공통 쿠버네티스 API 서버