{"id":"IL-0187","org":"Yonghyun Kim","date":"2025-10-11","docs":[],"title":{"en":"A brief Spring Cloud Config Server downtime failed every client application's liveness probe, because the actuator health check included the config server, and Kubernetes restarted the pods in a kill loop","ko":"Spring Cloud Config Server 가 잠깐 내려가자 이를 헬스 체크에 포함한 모든 앱의 Liveness Probe 가 실패해 쿠버네티스가 파드를 계속 죽이고 다시 띄우면서 한 계열사 서비스가 마비됐다."},"domain":["kubernetes"],"impact":{"scope":"The services of one affiliate company went down while their pods were restarted in a loop","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"A liveness probe that includes an external dependency turns a short outage of that dependency into a restart loop of every client. Keep external dependencies out of liveness checks and handle temporary problems with readiness probes.\n\nLibraries can add health indicators to Spring Boot's actuator health endpoint automatically, so check what the probe path actually reports. The author ran another Kubernetes environment for two years without liveness probes, relying on strict readiness probes and on the application terminating itself on unrecoverable faults.","ko":"Liveness Probe 가 앱 자신이 아니라 외부 의존성의 상태까지 판단하면, 잠깐의 외부 장애나 네트워크 문제에도 쿠버네티스가 멀쩡한 앱을 죽인다. 일시적인 부하나 외부 서버 다운은 앱을 죽일 이유가 아니며, Readiness Probe 로 잠시 트래픽만 막으면 된다. 글쓴이는 특별한 이유가 없으면 Liveness Probe 를 끄라고 권한다. 꼭 써야 한다면 헬스 체크 경로에서 DataSourceHealthIndicator, ConfigServerHealthIndicator 같은 외부 Health Indicator 를 빼거나 /healthz 같은 별도 경로를 만들어야 한다. initialDelaySeconds 는 앱이 뜨는 데 걸리는 최대 시간보다 길게, failureThreshold 와 periodSeconds 는 넉넉하게 잡는다. 예를 들어 failureThreshold: 10, periodSeconds: 6 이면 60초 동안 연속으로 실패해야 재시작된다. 글쓴이가 운영한 레브잇 환경은 Liveness Probe 없이 2년 동안 안정적으로 서비스했다."},"related":[],"sources":[{"url":"https://medium.com/@baramboys0615/liveness-probe%EB%8A%94-%EC%96%91%EB%82%A0%EC%9D%98-%EA%B2%80%EC%9D%98-%EC%9C%84%ED%97%98%EC%84%B1-%EA%B2%BD%ED%97%98-%EA%B8%B0%EB%B0%98-%EC%8B%AC%EC%B8%B5-%EB%B6%84%EC%84%9D-12123be6e310","kind":"blog","license":"unknown","archived":null}],"summary":{"en":"At the author's previous company, business applications on Kubernetes embedded the Spring Cloud Config Client library to load configuration from a Spring Cloud Config Server, and in one Kubernetes environment a liveness probe was configured by default. The Spring Boot actuator health endpoint used by the probe automatically included the config server's state once the Config Client library was present.\n\nWhen the config server was taken down briefly for an upgrade, every client's health check failed because of that external dependency. Kubernetes restarted the pods, they failed again, and the applications fell into a restart loop that took down an affiliate's services, although nothing was wrong with the applications.\n\nThe author's conclusion is that a liveness probe must check only the application itself. Readiness probes should handle temporary problems such as load, network loss or an unavailable config server by taking the pod out of traffic. If a liveness probe is needed, external health indicators such as DataSourceHealthIndicator and ConfigServerHealthIndicator should be excluded or a separate path such as /healthz used, with a generous initialDelaySeconds and a long failure window, for example failureThreshold: 10 and periodSeconds: 6 for 60 seconds of continuous failure.","ko":"글쓴이가 이전 회사에서 겪은 장애다. 회사는 Spring Cloud Config Server 를 운영했고, 업무용 애플리케이션은 모두 Spring Cloud Config Client 라이브러리를 넣어 설정을 동적으로 받아 왔다. 한 쿠버네티스 환경의 앱에는 Liveness Probe 가 기본으로 설정돼 있었다.\n\nSpring Boot 앱은 보통 actuator 로 Health Indicator 를 켠다. Config Client 라이브러리가 들어 있으면 외부 Config Server 의 상태도 자동으로 헬스 체크에 포함된다. 그래서 Config Server 업그레이드 중 짧은 다운타임이 생기자 모든 클라이언트 앱의 헬스 체크가 실패했다. 쿠버네티스는 외부 의존성 때문에 실패한 헬스 체크를 보고 멀쩡한 파드를 죽이고 다시 띄웠고, 파드는 재시작 루프에 빠졌다. 그 결과 한 계열사의 서비스가 마비됐다."},"trigger":{"en":"A downtime upgrade of the Spring Cloud Config Server made it stop responding for a short time.","ko":"Config Server 를 다운타임이 있는 방식으로 업그레이드하면서 서버가 잠깐 응답하지 않았다."},"severity":"unknown","symptoms":["readiness-probe-failures","crash-loop","service-unavailable"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"published","detection":null,"components":["health-probe"],"root_cause":"dependency-failure","remediation":[],"action_items":[],"contributing":["default-config-unchanged","automation-amplified","blast-radius-too-wide"],"recurrence_of":null,"symptoms_text":{"en":"While the Spring Cloud Config Server was briefly down for an upgrade, every client application began to answer its liveness probe with a failure saying it could not reach the config server.\n\nKubernetes treated the failed health check as a dead application and killed and restarted the pods. The applications themselves were fine, and the config server was about to come back, but the pods kept being killed and restarted without a chance to recover, and the services of one affiliate company went down.","ko":"Config Server 업그레이드로 서버가 잠깐 응답하지 않는 동안, 클라이언트 앱 전부가 Liveness Probe 요청에 Config Server 와 연결되지 않는다며 실패로 응답했다.\n\n쿠버네티스는 이 실패만 보고 파드를 비정상으로 판단해 강제로 종료하고 다시 띄웠다. 앱 자체에는 아무 문제가 없었고 Config Server 도 곧 돌아올 예정이었다. 그런데도 파드는 다시 뜨자마자 또 죽는 재시작 루프에 빠졌고, 회복할 틈이 없었다. 결국 한 계열사의 서비스가 마비됐다."},"updated_at":"2026-11-09T11:55:57.611330Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0187","org_slug":"yonghyun-kim"}