IL-0467 Kubernetes project · 2019-03-26kubernetesgcp
Boskos crash-looped after a node drain started it from a buggy StatefulSet image, failing Kubernetes PR jobs for 9 hours
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.
At 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.
An 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.
- Severity
- –
- 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 affected
- Contributors to kubernetes/kubernetes and other projects whose test jobs used Boskos
- Region
- –
- Time to detect
- 3h 46m
- Time to resolve
- 9h 6m
Symptoms
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.
The 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]".
The 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.
The 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.
Root cause
Root cause Faulty deployment
- Trigger
- 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.
Detection
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.
Remediation
- Built and deployed a new Boskos image with the bug fixed
- Cleaned up the GCP projects that had been left open
Action items
- Change the Boskos configuration so that deployments actually take effect (#11956)
- Automate Boskos deploys (#11957)
- Improve alerting on Boskos status (#11953)
Lessons
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.
Sources
References
- 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
Related cases
IL-0356Every domain hosted on Railway returned HTTP 404 to new connections for five minutes because route lookups failedRailway · 2026same root cause · shared CI system
IL-0237A Kubernetes patch upgrade evicted every Ray Serve head and worker pod at once, and Lucidworks hosted LLMs went downLucidworks · 2026 · sev1same root cause · shared Node pool
IL-0166A compute host update removed the credential parser used to decode StackScripts, so new Linodes and every new LKE and LKE-E node failed to boot and autoscaling and node recycling failed in all regionsLinode · 2026same root cause · shared Node pool
IL-0234An onboarding operator deployed without its scope file installed dev applications on other IONOS Kubernetes clustersIONOS Cloud · 2026same root cause · shared CI system
IL-0020During an EKS 1.30 upgrade the descheduler tried to reschedule every pod on the cordoned nodes at once and production workloads went downUK Ministry of Justice · 2025same root cause · shared Node pool
IL-0324Three MediaWiki deployments lost Memcached after a PHP 8.1 rollout and overloaded the External Storage database clusterWikimedia Foundation · 2025same root cause · shared CI system
IL-0552CircleCI's archival database ran out of storage, slowing workflow and job starts and the display of workflows in the UICircleCI · 2025same root cause · shared CI system
IL-0163An API change that slipped through a gap in automated testing made LKE clusters resize to the wrong number of nodes and added billable worker nodes to customer accountsLinode · 2023same root cause · shared Node pool
IL-0164An incremental Linode Kubernetes Engine production update that was missing changes from the previous release made cluster upgrades and node additions fail silentlyLinode · 2022same root cause · shared Node pool
IL-0328A field type change in the database of CircleCI's job distribution service left all jobs stuck in "not running"CircleCI · 2021same root cause · shared Node pool
IL-0149Upgrades of AKS clusters on Virtual Machine Scale Sets failed with a 'platform image is not available' error after a service update left a backend service unhealthyMicrosoft Azure · 2019same root cause · shared Node pool
IL-0466Prow scheduled test job pods onto its service cluster, leaving hundreds Pending and starving Prow's own servicesKubernetes project · 2019same root cause · shared CI system
Check your cluster for this
For AI tools and scripts
- This case as JSON: https://incidentlib-api.benchlet.com/cases/IL-0467
- The cases most like it: https://incidentlib-api.benchlet.com/cases/IL-0467/similar
- MCP server (Streamable HTTP, no key):
https://incidentlib-mcp.benchlet.com/mcp
The API needs no key. The MCP server offers search_incidents, get_incident, list_incidents, get_topic and vocab; both are explained on API and MCP.