{"id":"IL-0458","org":"Wikimedia Foundation","date":"2019-09-10","docs":["https://wikitech.wikimedia.org/wiki/Portal:Toolforge/Admin/Kubernetes","https://phabricator.wikimedia.org/T148929#2817428"],"title":{"en":"Toolforge Kubernetes API server failed to start after a restart, logging \"etcd cluster is unavailable or misconfigured\"","ko":"Toolforge 쿠버네티스 API 서버가 재시작 뒤 올라오지 못해 몇 시간 동안 클러스터 전체가 멈췄다"},"domain":["kubernetes"],"impact":{"scope":"Toolforge Kubernetes API server down for several hours: tools could not be launched or managed with webservice or kubectl, and Kubernetes webservices were offline at the proxy level after kube2proxy crashed","users":"Toolforge users and the tools running on the Kubernetes backend","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Components that often misbehave, such as etcd, drew the responders to the wrong fix, and working on etcd instead of the CA certificates made the outage worse. Puppet-managed certificates are risky, and very old Kubernetes versions log errors that are hard to read. The failure was hard to find because it surfaced at an API server restart rather than at the Puppet change, because the etcd cluster had long-standing undocumented quirks, and because no disaster recovery or node replacement procedure was written down for etcd.","ko":"etcd 처럼 원래 말썽이 잦은 구성 요소가 해법 찾기를 헷갈리게 했다. 퍼핏 인증서는 위험하다. 아주 오래된 쿠버네티스 버전은 로그에 남기는 오류 메시지가 형편없다. 팀은 CA 인증서가 아니라 etcd 를 고치려다 상황을 더 나쁘게 만들었다. 문제는 API 서버를 재시작할 때에야 드러났다. etcd 클러스터에는 문서화되지 않은 오래된 특이점이 있었고, etcd 재해 복구와 노드 교체 절차는 문서로 남아 있지 않았다. 이 셋이 겹쳐 해법을 찾는 데 오래 걸렸다. 교차 교육이 있었다면 도움이 됐을 수 있지만, 이번 일은 어차피 여럿이 함께 풀어야 했다."},"related":[],"sources":[{"url":"https://wikitech.wikimedia.org/wiki/Incidents/2019-09-10_toolforge-kubernetes","kind":"runbook","archived":"https://web.archive.org/web/20260718055107/https://wikitech.wikimedia.org/wiki/Incidents/2019-09-10_toolforge-kubernetes"}],"summary":{"en":"Puppet changes made the night before left the Toolforge Kubernetes API server with a CA certificate that did not match the one used by the etcd servers. Nothing broke until 18:30 on 10 September 2019, when maintain-kubeusers restarted the API server and it had to reconnect to etcd. The API server failed to start, kube2proxy lost its watch on Kubernetes and crashed, and Kubernetes webservices on Toolforge went offline at the proxy for several hours.\n\nBecause the change and the failure were hours apart, the responders first looked at etcd. Quirks of the old etcd cluster, such as etcdctl timing out after 1 second and frequent raft elections, sent the team down that path; the etcd cluster was rebooted, reduced to one node and, after a mistake while adding a node back to the two-node cluster, collapsed and was recovered from a backup. Around 01:00 the team turned back to the API server, found that the CA certificate had changed, and reproduced a CA trust error with curl.\n\nAt 01:28 swapping the API server's CA for the one from the etcd servers restored communication and services, but Puppet reverted the change and broke things again at 01:33. Following a pointer to an earlier Phabricator task, the etcd Puppet CA certificate was placed in /var/lib/puppet/client/ssl/certs/ca.pem, which Puppet picked up, and the outage was over at 01:43. Four SREs, a team manager and a technical volunteer took part.","ko":"2019-09-10 18:30 에 maintain-kubeusers 프로세스가 Toolforge 쿠버네티스 API 서버를 재시작했고, API 서버는 다시 올라오지 못했다. 전날 밤 퍼핏 변경으로 API 서버가 쓰는 CA 인증서가 etcd 서버의 것과 어긋났는데, 재시작으로 etcd 에 다시 연결하기 전까지는 드러나지 않았다. API 서버가 멈춘 동안 webservice 와 kubectl 로 도구를 띄우거나 관리할 수 없었고, kube2proxy 가 죽어 쿠버네티스 webservice 전부가 프록시 단계에서 내려갔다.\n\n로그에 etcd 오류가 찍히고 옛 etcdctl 이 1초 만에 타임아웃을 내자 팀은 etcd 를 원인으로 보았다. 쿠버네티스 마스터와 etcd 클러스터를 재부팅하고, 백업을 뜬 뒤 잦은 raft 선출을 원인에서 빼려고 etcd 를 노드 하나로 줄였다. 21:24 에 etcd 가 느렸을 뿐 떨어진 것이 아님을 알고 클러스터를 원래 크기로 되돌리기 시작했다. 그런데 첫 노드를 다시 넣을 때 실수가 있어 노드 두 개짜리 etcd 클러스터가 무너졌다. 노드 두 개짜리 etcd 클러스터는 두 노드가 모두 살아 있어야 동작한다. 결국 백업에서 전체 재해 복구를 해 00:25 쯤 etcd 를 원래 용량으로 되돌렸다.\n\n01:02 에 CA 인증서가 전날 밤 바뀌었다는 것을 찾았고, 01:05 에 curl 로 kube API 서버에서 나가는 SSL 호출에서만 CA 신뢰 오류가 나고 etcd 서버끼리는 나지 않는 것을 재현했다. 01:28 에 CA 를 etcd 서버의 것으로 바꾸자 통신과 서비스가 돌아왔지만, 01:33 에 퍼핏이 그 변경을 되돌려 다시 깨졌다. 01:43 에 etcd 퍼핏 CA 인증서를 /var/lib/puppet/client/ssl/certs/ca.pem 에 두자 퍼핏이 그 인증서를 가져가 안정적으로 복구됐다. 복구에는 SRE 4명, 팀 관리자 1명, 기술 자원봉사자 1명이 참여했다."},"trigger":{"en":"At 18:30 the maintain-kubeusers process restarted the Kubernetes API server, which forced it to reconnect to etcd with a CA certificate that Puppet changes the night before had left mismatched with the etcd servers.","ko":"18:30 에 maintain-kubeusers 프로세스가 쿠버네티스 API 서버를 재시작했다. 재시작한 API 서버는 etcd 에 다시 연결해야 했는데, 전날 밤 퍼핏 변경으로 CA 인증서가 etcd 서버의 것과 어긋나 있어 연결하지 못했다."},"severity":"unknown","symptoms":["control-plane-unresponsive","service-unavailable","tls-certificate-errors"],"timeline":{"detected_after":"15m","resolved_after":"7h 13m"},"date_kind":"incident","detection":{"en":"Automated monitoring: an Icinga alert on the toolschecker check http://checker.tools.wmflabs.org/k8s/nodes/ready, about \"All k8s nodes healthy\", fired at 18:45.","ko":"처음 울린 것은 http://checker.tools.wmflabs.org/k8s/nodes/ready 를 검사하는 icinga 알림이었다. 18:45 에 toolschecker 의 \"All k8s nodes healthy\" 검사가 울렸다."},"components":["kube-apiserver","etcd","config-management"],"root_cause":"config-change","remediation":[{"text":{"en":"Rebooted the Kubernetes master and the etcd cluster, which did not help","ko":"19:10 과 20:30 에 쿠버네티스 마스터를, 20:18 에 etcd 클러스터를 재부팅했지만 도움이 되지 않았다."}},{"text":{"en":"Took a backup of etcd and reduced the etcd cluster to one node to rule out raft election flaps","ko":"21:06 에 백업을 떠 둔 뒤 잦은 raft 선출을 원인에서 빼려고 etcd 클러스터를 노드 하나로 줄였다."}},{"text":{"en":"Brought etcd back to full capacity through a full disaster recovery from the backup","ko":"노드를 다시 넣다 클러스터가 무너진 뒤 여러 시도 끝에 백업에서 etcd 전체 재해 복구를 해 00:25 쯤 etcd 를 원래 용량으로 되돌렸다."}},{"text":{"en":"Swapped the API server's CA certificate for the one from the etcd servers, which restored services until Puppet reverted it","ko":"01:28 에 API 서버가 쓰는 CA 를 etcd 서버의 CA 로 바꿨고, 통신과 서비스가 돌아왔다. 퍼핏이 곧 이 변경을 되돌렸다."}},{"text":{"en":"Placed the etcd Puppet CA certificate in /var/lib/puppet/client/ssl/certs/ca.pem so Puppet kept the right CA","ko":"01:43 에 etcd 퍼핏 CA 인증서를 /var/lib/puppet/client/ssl/certs/ca.pem 에 두었고, 퍼핏이 이 인증서를 가져가 장애가 안정적으로 끝났다."}}],"action_items":[{"text":{"en":"Document the etcd cluster processes","ko":"etcd 클러스터 운영 절차를 문서로 남긴다. 작업 번호는 T232769 다."}},{"text":{"en":"Upgrade Toolforge Kubernetes to improve etcd and Kubernetes error reporting and stop needing an API server restart to add a tool","ko":"Toolforge 쿠버네티스 업그레이드로 etcd 와 쿠버네티스의 오류 보고를 개선하고, 도구를 추가할 때 API 서버를 재시작하지 않아도 되게 한다. 작업 번호는 T214513 이다."}},{"text":{"en":"Make kube2proxy more resilient to API server failures","ko":"kube2proxy 가 API 서버 장애를 더 잘 견디게 만들어 본다. 작업 번호는 T232770 이다."}},{"text":{"en":"Audit the Puppet CA certificates so the tools project has no more than one","ko":"퍼핏 CA 인증서를 점검한다. tools 프로젝트 안에 CA 인증서가 둘 이상 있어서는 안 된다. 작업 번호는 T232772 다."}},{"text":{"en":"Make the Kubernetes control plane highly available","ko":"쿠버네티스 컨트롤 플레인을 고가용성으로 만든다. 작업 번호는 T142862 다."}}],"contributing":["delayed-effect-change","manual-action-worsened","no-runbook"],"recurrence_of":null,"symptoms_text":{"en":"On 10 September 2019 the Kubernetes API server of Wikimedia's Toolforge cluster did not come back after the maintain-kubeusers process restarted it at 18:30. To monitoring and to users the whole cluster looked down: Toolforge users could not launch tools with the webservice command on the Kubernetes backend or use kubectl, and an Icinga check against the \"All k8s nodes healthy\" endpoint started alerting at 18:45.\n\nThe API server log showed the failure as \"Failed to list *storage.StorageClass: client: etcd cluster is unavailable or misconfigured\". kube2proxy could not watch for Kubernetes changes, started from scratch and crashed. Prometheus showed the tool containers themselves still running, so the webservices on Kubernetes appear to have gone offline at the proxy level. The Toolforge homepage alerted as down at 19:48.\n\nPuppet certificates were suspected within the first half hour but set aside, because the Puppet changes had been made the night before and the etcd and Kubernetes certificates turned out not to have changed. The team then worked on etcd for hours: an etcd health check reported success, the same error could be reproduced against etcd, the etcd logs showed timeouts and frequent raft elections, and the old etcdctl on the tools-k8s-etcd servers timed out after 1 second, which made etcd look as if it were flapping when it was only slower than that timeout. The etcd cluster was rebooted, cut down to one node and, after a mistake while adding a node back, collapsed and had to be restored from a backup.\n\nAt 01:02 the responders noticed that the CA certificate had changed the night before in a way that was hard to pin down, and at 01:05 curl reproduced a CA trust error on SSL calls from the API server that did not occur between the etcd servers.","ko":"18:45 에 toolschecker 의 icinga 검사 \"All k8s nodes healthy\" 가 알림을 울렸다. 쿠버네티스 API 서버가 응답하지 않아 모니터링에서도 사용자 쪽에서도 클러스터가 완전히 내려간 것처럼 보였다. 사용자는 webservice 명령으로 도구를 띄울 수 없었고 kubectl 로 상태를 보거나 도구를 다룰 수도 없었다.\n\nkube-apiserver 로그의 마지막 실패 메시지는 \"Failed to list *storage.StorageClass: client: etcd cluster is unavailable or misconfigured\" 였다. kube-apiserver 프로세스를 다시 시작해도 실패했고, 쿠버네티스 마스터를 재부팅해도 같았다.\n\nAPI 서버가 멈춘 직후 kube2proxy 도 쿠버네티스 변경을 watch 하지 못했다. kube2proxy 는 처음부터 다시 시작했다가 죽었다. prometheus 로 보면 컨테이너와 도구 자체는 영향이 없었지만, 쿠버네티스 webservice 전부가 프록시 단계에서 내려간 것으로 보였다. 19:48 에는 Toolforge 홈페이지 다운 알림도 울렸다.\n\n18:55 에 퍼핏 인증서를 의심했다. 그러나 이 클러스터는 프로젝트 내부 인증서를 쓰고 퍼핏 인증서는 전날 밤에 바뀌었으므로, 장애 시점과 맞지 않는다고 보고 제쳤다. 방화벽 변경도 확인했지만 새 퍼핏 마스터를 위한 변경이어서 시점이 맞지 않았다.\n\netcd 헬스체크는 정상으로 나왔다. 그런데 etcd 에서도 같은 오류 메시지가 재현됐고 etcd 로그에 타임아웃과 잦은 raft 선출이 보였다. 그래서 팀은 etcd 를 원인으로 잘못 짚었다. tools-k8s-etcd 서버의 옛 etcdctl 은 1초 만에 타임아웃이 났다. 이 때문에 etcd 가 죽었다 살아나기를 되풀이하거나 점점 무너지는 중인 것처럼 보였다. 21:24 에야 etcd 가 떨어진 것이 아니라 etcdctl 기본 타임아웃보다 느렸을 뿐이라는 것을 알았다."},"updated_at":"2026-11-14T12:34:10.698631Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0458","org_slug":"wikimedia-foundation"}