{"id":"IL-0467","org":"Kubernetes project","date":"2019-03-26","docs":["https://github.com/kubernetes/test-infra/commit/02110870507abdeb93dfd6205c70f82145f8993c#r32917192","https://github.com/kubernetes/test-infra/issues/11956","https://github.com/kubernetes/test-infra/issues/11957","https://github.com/kubernetes/test-infra/issues/11953","https://github.com/kubernetes/test-infra/pull/11947","https://github.com/kubernetes/test-infra/pull/11949","https://github.com/kubernetes/test-infra/pull/11576"],"title":{"en":"Boskos crash-looped after a node drain started it from a buggy StatefulSet image, failing Kubernetes PR jobs for 9 hours","ko":"Prow 빌드 클러스터의 노드 업그레이드 중 Boskos 파드가 크래시 루프에 빠져 GCP 프로젝트가 필요한 테스트 작업이 9시간 넘게 모두 실패했다"},"domain":["kubernetes","gcp"],"impact":{"scope":"All Prow test jobs that needed a GCP project from Boskos failed for just over nine hours, including the required pull-kubernetes-e2e-gce job, so no kubernetes/kubernetes pull request could be merged; 70 failures on pull-kubernetes-e2e-gce alone, with similar effects on other projects","users":"Contributors to kubernetes/kubernetes and other projects whose test jobs used Boskos","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"The write-up lists what went poorly: a ten-hour upgrade was started shortly after 17:00 when on-call coverage ended at 18:00; deployments were not checked to confirm that something had actually rolled out; the Boskos StatefulSet was not set up to perform updates, so changing its spec left the old pod running; the December change appears never to have been tested; and Boskos was deployed by hand, unlike most of Prow, which left more room for error. Once people were available, the problem was fixed quickly.","ko":"팀은 당직자가 오후 6시까지만 있는 날 오후 5시가 넘어 10시간짜리 배포를 시작하지 말았어야 했다고 보았다. 배포는 실제로 무언가가 바뀌었는지 확인할 수 있게 지켜봐야 하고, 그럴 수 없으면 아예 하지 않아야 한다고 정리했다. Boskos 의 StatefulSet 은 업데이트하도록 설정되어 있지 않아서 배포해도 아무것도 바뀌지 않았다. 12월의 변경은 한 번도 시험되지 않은 것으로 보였다. Prow 의 다른 부분과 달리 Boskos 는 손으로 배포해서 실수할 여지가 컸다. 담당자가 대응을 시작한 뒤로는 문제를 비교적 빨리 풀었다."},"related":[],"sources":[{"url":"https://github.com/kubernetes/test-infra/blob/master/docs/post-mortems/2019-03-26.md","kind":"github","archived":null}],"summary":{"en":"Boskos is the service in the Kubernetes project's Prow test infrastructure that hands out GCP projects to test jobs. A commit that landed in December 2018 (the timeline gives 12-05 16:21) contained a bug that kept Boskos from starting: it tried to create its resources.boskos.k8s.io CRD with a definition that could never be valid. On 2019-03-20 the Boskos StatefulSet spec was updated to an image with this bug, but the running pod was not replaced, because the StatefulSet had no configuration that rolled out updates, and nobody noticed that the deploy had changed nothing. Unlike most of Prow, Boskos was deployed by hand.\n\nAt around 17:20, several hours before the outage, the team began upgrading the Prow clusters from Kubernetes 1.11 to 1.13 from the GKE console. The build cluster has 150 nodes and each node update takes five minutes, so the whole upgrade would take about ten hours. Nothing looked wrong several hours in, and the team went to bed. At 23:04 the node holding the only Boskos pod was drained to be replaced with a 1.13 node. The new pod was created from the StatefulSet's spec with the buggy image and crash-looped. Every job that needed a Boskos project failed for just over nine hours while on-call was asleep. Users reported the failure from 02:50, and the monitoring dashboard showed it, but no alert caught it.\n\nAn engineer woke at 07:16 and saw the Slack reports, and at 07:37 another engineer traced the failure to the December commit. A new image was built and deployed, and the timeline records a fixed Boskos running at 08:10 as the end of the outage. Boskos recovered at once, the projects left open were cleaned up over the next few minutes, and tests passed again shortly after. The audit logs then confirmed that the pod had run gcr.io/k8s-testimages/boskos:v20180405-12e892d69 until the drain and that the update of the week before had had no effect.","ko":"Boskos 는 테스트 작업에 GCP 프로젝트를 나눠 주는 서비스이고, StatefulSet 이 띄운 파드 하나로 돌았다. 지난해 12월에 들어간 커밋에 Boskos 가 시작하지 못하게 만드는 버그가 있었다. 아무도 이 버전을 배포하지 않다가 2019-03-20 에 처음 배포를 시도했다. StatefulSet 스펙은 새 이미지로 바뀌었지만 파드를 교체하게 하는 설정이 없었다. 그래서 파드는 옛 이미지 gcr.io/k8s-testimages/boskos:v20180405-12e892d69 로 계속 돌았고, 아무것도 바뀌지 않았다는 사실을 아무도 알아채지 못했다.\n\n장애 당일 오후 5시가 넘어 Prow 클러스터를 1.11 에서 1.13 으로 올리기 시작했다. 빌드 클러스터는 노드가 150개이고 노드 하나에 5분이 걸려서, 전체가 10시간쯤 걸리는 작업이었다. 그런데 당직자가 대응하는 시간은 오후 6시까지였다. 몇 시간 동안 이상이 없어 팀은 잠자리에 들었다. 23:04 PDT 에 Boskos 파드가 돌던 노드가 drain 됐다. 새 노드에서 다시 만들어진 파드는 StatefulSet 스펙에 적힌 버그 있는 이미지로 떴고, CRD 클라이언트를 만들지 못해 크래시 루프에 빠졌다. 그 뒤로 Boskos 에서 프로젝트를 받아야 하는 작업은 모두 실패했다.\n\n사용자들이 GitHub 와 Slack 으로 알렸지만 아침까지 아무도 대응하지 못했다. 07:16 에 담당자가 Slack 의 보고를 보았고, 07:37 에 원인 커밋을 찾았다. 고친 이미지를 빌드해 배포하자 Boskos 는 곧바로 살아났고, 08:10 에 장애가 끝났다. 장애는 9시간을 조금 넘게 이어졌고, pull-kubernetes-e2e-gce 에서만 실패가 70번 났다. 감사 로그를 보니 파드는 StatefulSet 이 바뀐 뒤에도 전날까지 옛 이미지로 돌고 있었다. 지난주에 업데이트를 시도했을 때도 아무 일도 일어나지 않았다."},"trigger":{"en":"At 23:04 PDT the node running the only Boskos pod was drained to be replaced with a 1.13 node during the upgrade of the Prow clusters from Kubernetes 1.11 to 1.13. The replacement pod started from the StatefulSet's current spec, which named a newer Boskos image containing the bug.","ko":"Prow 클러스터를 쿠버네티스 1.11 에서 1.13 으로 올리는 노드 업그레이드 중 23:04 에 Boskos 파드 하나가 돌던 노드가 drain 됐다. 새 노드에서 다시 만들어진 Boskos 파드는 StatefulSet 스펙에 적힌 새 이미지로 시작했는데, 이 이미지에 버그가 있었다."},"severity":"unknown","symptoms":["crash-loop","service-unavailable"],"timeline":{"detected_after":"3h 46m","resolved_after":"9h 6m"},"date_kind":"incident","detection":{"en":"Users reported the failure on GitHub at 02:50 and on Slack at 05:16 and 06:27, and an engineer saw the Slack reports on waking at 07:16. The Boskos monitoring dashboard showed the failure, but no alert caught it.","ko":"알림은 울리지 않았다. Boskos 대시보드에는 실패가 뚜렷하게 보였지만 이를 잡는 알림이 없었다. 사용자들이 02:50 에 GitHub 로, 05:16 과 06:27 에 Slack 으로 장애를 알렸고, 담당자는 07:16 에 일어나 Slack 의 보고를 보고서야 알았다."},"components":["ci-system","node-pool"],"root_cause":"deploy-rollout","remediation":[{"text":{"en":"Built and deployed a new Boskos image with the bug fixed","ko":"버그를 찾은 뒤 고친 Boskos 이미지를 새로 빌드해 배포했고, Boskos 는 곧바로 살아났다."}},{"text":{"en":"Cleaned up the GCP projects that had been left open","ko":"장애 동안 반납되지 않고 열린 채로 남은 GCP 프로젝트들을 그 뒤 몇 분에 걸쳐 정리했다."}}],"action_items":[{"text":{"en":"Change the Boskos configuration so that deployments actually take effect (#11956)","ko":"Boskos 설정을 고쳐 배포하면 실제로 파드가 교체되게 한다."}},{"text":{"en":"Automate Boskos deploys (#11957)","ko":"Boskos 배포를 자동화한다."}},{"text":{"en":"Improve alerting on Boskos status (#11953)","ko":"Boskos 상태를 지켜보는 알림을 개선한다."}}],"contributing":["delayed-effect-change","assumption-unverified","single-point-of-failure","no-alert-on-limit","change-before-off-hours"],"recurrence_of":null,"symptoms_text":{"en":"Overnight into 26 March 2019 (PDT), every Prow test job that needed a GCP project from Boskos, the Kubernetes test-infra service that hands out GCP projects to test jobs, failed. The required job pull-kubernetes-e2e-gce failed on every run, so no pull request could be merged in kubernetes/kubernetes for just over nine hours, and other projects saw similar failures.\n\nThe jobs failed with \"Something went wrong: failed to prepare test environment: --provider=gce boskos failed to acquire project: Post http://boskos.test-pods.svc.cluster.local./acquire?type=gce-project&state=free&dest=busy&owner=pull-kubernetes-e2e-gce\", and the request itself ended in \"dial tcp 10.63.250.132:80: i/o timeout\". The only Boskos pod was in a crash loop, logging the fatal error \"unable to create a CRD client\" with \"CustomResourceDefinition.apiextensions.k8s.io \\\"resources.boskos.k8s.io\\\" is invalid: [spec.versions: Invalid value: []apiextensions.CustomResourceDefinitionVersion(nil): must have exactly one version marked as storage version, status.storedVersions: Invalid value: []string(nil): must have at least one stored version]\".\n\nThe failures began at 23:04, when the node running Boskos was drained during an upgrade of the Prow clusters from Kubernetes 1.11 to 1.13 that had been started that evening, and on-call was asleep. Users reported it on GitHub at 02:50 and on Slack at 05:16 and 06:27. The Boskos monitoring dashboard showed the failure, but no alert fired. The pull-kubernetes-e2e-gce job alone recorded 70 failures from the outage.\n\nThe engineers first suspected the Kubernetes upgrade, perhaps a change between 1.11 and 1.13 in how an invalid CRD is handled, although the timing did not quite match. The CRD that Boskos tried to create would never have been valid in any version. The cause was a Boskos code change, and the audit logs showed that the pod had kept running the old image gcr.io/k8s-testimages/boskos:v20180405-12e892d69 until the drain, even though the StatefulSet had been changed the week before.","ko":"Boskos 에서 GCP 프로젝트를 받아야 하는 Prow 테스트 작업이 밤사이 전부 실패했다. kubernetes/kubernetes 의 모든 PR 에 필수인 pull-kubernetes-e2e-gce 가 계속 실패해서 PR 을 하나도 병합할 수 없었다.\n\ne2e-gce 작업마다 \"Something went wrong: failed to prepare test environment: --provider=gce boskos failed to acquire project: Post http://boskos.test-pods.svc.cluster.local./acquire?type=gce-project&state=free&dest=busy&owner=pull-kubernetes-e2e-gce\" 오류가 났다. 같은 요청은 \"dial tcp 10.63.250.132:80: i/o timeout\" 로 끝났다.\n\nBoskos 파드는 시작하자마자 다음 로그를 남기고 죽기를 되풀이했다. {\"error\":\"CustomResourceDefinition.apiextensions.k8s.io \\\"resources.boskos.k8s.io\\\" is invalid: [spec.versions: Invalid value: []apiextensions.CustomResourceDefinitionVersion(nil): must have exactly one version marked as storage version, status.storedVersions: Invalid value: []string(nil): must have at least one stored version]\",\"level\":\"fatal\",\"msg\":\"unable to create a CRD client\",\"time\":\"2019-03-26T09:44:13Z\"}\n\n장애는 23:04 PDT 에 시작했다. 사용자들이 02:50 에 GitHub 로, 05:16 과 06:27 에 Slack 으로 장애를 알렸지만 당직자가 자고 있었다. Boskos 대시보드에는 실패가 뚜렷하게 보였지만 이를 잡은 알림은 없었다. 07:16 에 담당자가 일어나 Slack 의 보고를 보았다.\n\n처음에는 다른 원인을 의심했다. 한 엔지니어는 최근의 snowflake ID 변경과 관계가 있는지 물었지만 그 변경은 아직 하지 않은 상태였다. 담당자는 전날 저녁의 쿠버네티스 업그레이드를 의심했지만 시각이 맞지 않았고, 1.11 과 1.13 사이에 잘못된 CRD 를 다루는 방식이 바뀌었는지도 따져 보았다. 그러나 Boskos 가 만들려던 CRD 는 어느 버전에서도 유효하지 않았다. 07:37 에 원인이 된 커밋을 찾았다."},"updated_at":"2026-11-14T12:34:11.487395Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0467","org_slug":"kubernetes-project"}