{"id":"IL-0032","org":"Airbnb","date":"2020-12-04","docs":[],"title":{"en":"Mutating admission controller generated broken JSON patches, silently blocking deploys for a week until a production service ran down to two pods","ko":"mutating admission controller 의 JSON 패치 버그로 일주일 동안 새 코드가 배포되지 않았고, 운영 서비스 하나는 파드가 두 개만 남아 오류율이 치솟았다"},"domain":["kubernetes"],"impact":{"scope":"one production service failing and other deployments in the cluster silently not deploying new code for seven days","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Keep in mind that a mutating admission controller exists in the cluster; a recently added one is easy to forget during an incident. Search for the exact error message early instead of working on the visible symptoms. Page a teammate when progress stalls.","ko":"클러스터에 mutating admission controller 가 있다는 사실을 늘 염두에 둔다. 최근에 도입한 것이라 장애가 났을 때 팀원 대부분이 이를 먼저 떠올리지 못했다.\n\n막히면 도움을 청한다. 동료를 호출한 뒤에야 조사가 진척됐다.\n\n오류 문구를 검색한다. 처음 보고된 오류 문구를 바로 검색했다면 이미 알려진 문제라는 것을 훨씬 일찍 알았을 것이다.\n\n알림을 만든다. 문제를 일찍 잡을 수 있는 지표가 있었지만 알림이 없었다."},"related":[],"sources":[{"url":"https://www.youtube.com/watch?v=4CT0cI62YHk","kind":"talk","license":"unknown","archived":null}],"summary":{"en":"Airbnb's compute infrastructure team had rolled out a mutating admission controller within the previous month. When it needed to delete two items from an array in a spec, it generated two remove operations in ascending order, index 2 and then index 3. After the first removal the array no longer had an index 3, so the patch failed. The correct patch removes the higher index first. The bug was already well known once the team searched for the error message.\n\nBecause the patch failed, some deployments could no longer create new pods. The change had gone in seven days earlier, and during that time some deployments had not actually shipped new code: services kept running on their old replica sets, and as those older pods died one by one the services degraded slowly until one of them reached two pods and started failing. Deleting the mutating admission controller from the cluster stopped the outage immediately, and new pods came up.\n\nIn the postmortem the team found that metrics which could have revealed the problem earlier already existed, but no alert was built on them.","ko":"Airbnb 컴퓨트 인프라팀이 발표에서 소개한 장애다. 운영 서비스 하나에서 오류율이 높아졌고 배포도 되지 않았다. HPA 가 정한 레플리카 수는 9개였지만 파드는 2개만 남아 있었고, 디플로이먼트 하나에 레플리카셋이 세 개 있었다. 팀은 HPA 와 오래된 레플리카셋을 의심해 여러 조치를 해 봤지만 모두 효과가 없었다.\n\n원인은 최근 도입한 mutating admission controller 가 만든 JSON 패치였다. 스펙의 배열에서 항목 두 개를 지워야 할 때, 컨트롤러는 인덱스 2를 지우고 이어서 인덱스 3을 지우는 패치를 만들었다. 첫 번째 작업이 끝나면 배열에 인덱스 3이 더는 없으므로 패치가 실패한다. 올바른 패치는 인덱스 3을 먼저 지우고 인덱스 2를 지우는 것이다. 이 문제는 이미 널리 알려져 있었다.\n\n팀은 해당 클러스터에서 mutating admission controller 를 지웠고, 곧바로 파드가 정상적으로 뜨기 시작했다. 그런데 더 들여다보니 컨트롤러 변경은 7일 전에 적용되어 있었다. 지난 7일 동안 일부 디플로이먼트는 새 코드가 아예 배포되지 않았다. 이 서비스들은 기존 레플리카셋 덕분에 살아 있었지만 파드가 하나씩 죽으면서 조금씩 성능이 떨어지고 있었다. 사후 분석에서 보니 이 문제를 더 일찍 잡을 수 있는 지표가 이미 있었다."},"trigger":{"en":"A change to the mutating admission controller, which had been rolled out within the previous month, had gone in seven days before the incident surfaced; when it had to delete two items from an array in a spec, it generated an invalid JSON patch that removed index 2 and then index 3.","ko":"지난 한 달 사이에 도입한 mutating admission controller 에 변경이 들어갔고, 그 뒤로 컨트롤러가 배열에서 항목 두 개를 지우는 JSON 패치를 잘못된 순서로 만들었다. 이 변경은 장애가 드러나기 7일 전에 적용되어 있었다."},"severity":"unknown","symptoms":["high-error-rate","throughput-degraded","deploys-failing"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"published","detection":{"en":"The affected service reported a high error rate and its deploy failed; the slow degradation of other services over the previous seven days had gone unnoticed.","ko":"운영 서비스의 오류율이 높아지고 배포가 실패하면서 드러났다. 지표는 이미 있었지만 그 지표에 걸린 알림이 없어, 7일 동안 배포가 실패하는 것을 아무도 알아채지 못했다."},"components":["admission-webhook","hpa"],"root_cause":"software-bug","remediation":[{"text":{"en":"deleted the mutating admission controller from the affected cluster","ko":"해당 클러스터에서 mutating admission controller 를 지워 파드가 다시 정상적으로 뜨게 했다."}}],"action_items":[{"text":{"en":"Create alerts from the existing metrics that would have shown the problem earlier","ko":"이 문제를 더 일찍 잡을 수 있었던 기존 지표에 알림을 건다."}}],"contributing":["delayed-effect-change","monitoring-blind-spot","early-signal-ignored"],"recurrence_of":null,"symptoms_text":{"en":"A production service at Airbnb showed a high error rate and could not be deployed. The deploy failed with a cryptic Kubernetes error about being unable to access invalid index 5.\n\nThe service had only two pods running while its horizontal pod autoscaler wanted nine replicas, and the service was struggling on what was left. The namespace held one deployment but three replica sets, and the replica sets that still had pods were 16 days old.\n\nFor about an hour the responders worked on the autoscaling and replica set state: they deleted the horizontal pod autoscaler and scaled up by hand, deleted the old replica sets while keeping the one with the last two pods, and created a fresh deployment object to force an update. None of this helped. Recreating the namespace was ruled out because it would have deleted the last two production pods. A second engineer was paged, and about an hour later the team went back to the error message from the first page, searched for it, and found that it came from JSON patching.","ko":"운영 서비스 하나에서 오류율이 높아졌고 그 서비스는 배포도 되지 않았다. 배포할 때 인덱스 5에 접근할 수 없다는 뜻의 unable to access invalid index 오류가 났는데, 처음에는 무슨 뜻인지 알기 어려웠다.\n\n상태를 보니 HPA 는 레플리카가 9개여야 한다고 판단했지만 실제로 실행 중인 파드는 2개뿐이었다. 서비스는 남은 파드 두 개로 부하를 감당하지 못하고 있었다. 디플로이먼트는 하나인데 레플리카셋이 세 개였고, 실제로 파드를 가진 레플리카셋은 16일 전에 만든 것이었다.\n\n팀은 HPA 에 문제가 있다고 보고 HPA 를 지운 뒤 손으로 스케일을 올려 봤지만 효과가 없었다. 오래된 레플리카셋이 새 배포를 막는다고 보고 그것들을 지웠지만, 이것도 원인이 아니었다. 다만 남은 파드 두 개를 가진 레플리카셋은 지우지 않았다. 디플로이먼트 객체를 새로 만들어 갱신을 유도해 봐도 해결되지 않았다. 네임스페이스를 다시 만드는 방법도 생각했지만, 그러면 운영 중인 마지막 파드 두 개까지 지워지므로 하지 않았다.\n\n한 시간 넘게 진척이 없자 동료를 호출했다. 다시 처음 보고된 오류 문구로 돌아가 검색해 보니, 지난 한 달 사이에 배포한 mutating admission controller 의 JSON 패치 문제였다."},"updated_at":"2026-11-10T00:00:38.001182Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0032","org_slug":"airbnb"}