Incident Library
  • 원인
  • 구성 요소
  • 증상
  • 기여 요인
  • 사례

사례2건

2건 중 1~2번째

  1. 증상

    2025년 2월 18일 08:41 UTC, Grafana Labs 의 애플리케이션 팀 여러 곳이 자기 엔드포인트 일부에 접속이 되지 않는 것을 알아챘다.

    촉발

    로드 밸런서의 TLS 정책 버전을 올리면서, 기본 TLS 정책을 덮어쓸 수 있도록 Crossplane 컴포지션의 병합 정책을 바꾼 변경이 개발, 스테이징, 운영 환경에 동시에 적용됐다.

    원인
    구성 요소
    기여 요인
    감지

    08:41 UTC 에 애플리케이션 팀 여러 곳이 자기 엔드포인트 일부에 접속이 되지 않는 것을 알아챘다. 조사해 보니 최근의 TLS 정책 설정 변경 때문에 그 엔드포인트의 로드 밸런서가 사라져 있었다.

    조치
    • 문제의 코드 변경을 롤백했다.
    • 영향받은 쿠버네티스 Service 를 다시 만들어 쿠버네티스가 로드 밸런서를 새로 만들게 했다.
    후속 조치
    • 한 번에 두 개 이상의 웨이브로 배포하는 것을 막는 CI 검사를 넣어, 개발에서 스테이징, 카나리, 운영으로 이어지는 순서를 벗어나는 배포를 잡아내게 했다.
    • 논의만 하던 더 정교한 웨이브 설계의 우선순위를 올려 개선안을 합의하고 구현한다.
    • 실수로 지워지지 않도록 로드 밸런서에 삭제 보호를 켜기 시작했다. Crossplane 수준의 삭제 보호보다 한 층 아래에서 막는다.
    • 로드 밸런서 말고도 중요한 클라우드 리소스를 하나씩 살펴 필요한 곳에 삭제 보호를 켠다.
    • 변경 검증과 가시성을 높이려고 만든 Crossplane Managed Resources exporter 를 플랫폼 엔지니어링 안에서 베타로 시험하고 있다. 이번 장애를 일으킨 변경에 적용해 보면 차이가 분명히 드러난다.
    • TLS 정책을 다시 설정하는 기능을 제대로 완성하고 시험해, 애플리케이션 팀이 배포할 수 있게 했다.
    교훈

    작은 변경이라 위험이 낮다고 가정하고 충분한 시험과 영향 범위 줄이기를 건너뛴 것이 장애로 이어졌다. 웨이브 배포는 절차로 기대하는 데 그치지 않고 시스템이 강제해야 한다. 비상 예외는 웨이브를 고르지 않았을 때의 기본 동작이 아니라 말 그대로 예외여야 한다. 이번 변경은 시험을 안 한 것이 아니라 시험한 범위가 충분하지 않았다. 클라우드 로드 밸런서 컨트롤러와 자체 도구까지 처음부터 끝까지 돌려 봐야 의도한 작은 변화만 일어나는지 알 수 있었다. 개발 웨이브부터만 적용하도록 강제했다면 제대로 시험할 수밖에 없었을 것이다.

  2. 증상

    어느 일요일, 클러스터 사용자 한 명이 지연 시간이 올라갔다며 쿠버네티스 업무 시간 외 지원 담당을 직접 호출했다. 특히 p90 과 최댓값 지연이 높았다.

    촉발

    HAProxy 인그레스 컨트롤러를 v0.6 으로 올렸다. v0.5 문서는 sort-backends 플래그의 기본값이 false 이고 백엔드 서버를 기본으로 무작위로 섞는다고 설명했다. 그러나 템플릿이 pod_ip:port 를 키로 하는 맵을 순회할 때 Go 의 text/template 이 키 순서대로 방문해, 파드는 늘 IP 오름차순으로 설정 파일에 들어갔다. 운영 클러스터처럼 변화가 잦은 곳에서는 설정이 자주 다시 쓰였고, HAProxy 가 무중단 리로드를 하지 못해 재시작하는 일이 잦았다. 그때마다 모든 HAProxy 인스턴스가 같은 목록의 처음부터 라운드 로빈을 시작했다.

    원인
    구성 요소
    기여 요인
    감지

    클러스터 사용자가 p90 과 최댓값 지연이 오른 것을 보고 업무 시간 외 쿠버네티스 지원 담당을 직접 호출했다. 그 전에도 한 사용자가 파드 사이 요청 분포가 고르지 않다고 알렸지만 팀은 우선순위를 낮게 두었다.

    조치
    • 내부 배포 도구 Slingshot 의 설정을 바꿔, 영향받은 서비스의 매니페스트가 파드 IP 대신 Service VIP 를 쓰게 했다.
    • 컨트롤러가 맵에 넣은 순서를 슬라이스에 보관하고 템플릿이 그 슬라이스를 순회하도록 컨트롤러 코드와 설정 템플릿을 패치했다.
    • 패치를 샌드박스 클러스터에서 테스트한 뒤 운영 클러스터에 배포했다.
    후속 조치
    • 컨트롤러 패치를 운영에서 돌리고, 백엔드 주소는 다시 파드 IP 를 기본으로 쓴다.
    • 업스트림 프로젝트에 GitHub 이슈와 PR 을 올려 문제를 알렸다.
    • 클러스터 컴포넌트를 바꿀 때는 구체적인 동작과 조건을 염두에 두고 테스트한다.
    교훈

    클러스터 컴포넌트를 바꿀 때는 특정 동작과 조건을 염두에 두고 테스트해야 한다. 팀은 백엔드 목록이 정렬되면 hot-podding 이 생긴다는 것을 이미 알았지만, 새 플래그가 기대대로 동작하는지 충분히 테스트하지 않았다. 같은 키워드라도 언어의 한 곳에서 동작하는 방식이 다른 곳에서도 같으리라고 기대하면 안 된다. Go 의 range 와 text/template 의 range 는 맵을 순회하는 순서가 달랐다. 쿠버네티스 클러스터의 작은 컴포넌트 하나만 바꿔도 클러스터 사용자와 고객에게 큰 피해를 줄 수 있다.

내 클러스터에도 있는지 확인하기

이 2건에서 가장 많이 나오는 구성 요소: 설정 템플릿, 클라우드 로드 밸런서. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.

원인별2