API 와 MCP
무엇이 있나
여러 회사가 공개한 장애 보고서를 한 건씩 읽고, 같은 틀에 맞춰 정리한 사례 모음입니다. 지금 겪는 장애와 비슷한 사례를 찾아 보려는 엔지니어와, 그런 엔지니어를 돕는 AI 도구가 씁니다.
사례
사례 하나는 보고서 한 건입니다. 모든 사례에 같은 항목이 있습니다. 엔지니어가 본 증상, 장애를 촉발한 일, 원인, 문제가 난 구성 요소, 장애를 키운 기여 요인, 장애를 끝내려고 한 조치, 그 뒤에 조직이 하기로 한 일, 교훈, 원문 주소와 보관본 주소입니다.
모든 사례는 영어로 썼습니다. 한국어로도 쓴 사례가 있고, 그런 사례는 한국어로 받을 수 있습니다.
분류
사례마다 네 가지 분류가 있습니다. 원인, 구성 요소, 증상, 기여 요인입니다. 분류의 값은 정해진 목록에서 고릅니다. 예를 들어 원인에는 용량 한계, 설정 변경, 인증서 만료 같은 값이 있고, 구성 요소에는 CoreDNS, kubelet, VPC CNI 같은 값이 있습니다.
분류 값에는 이름이 두 가지 있습니다. 화면에 보이는 이름과, API 와 MCP 에서 쓰는 영문 식별자입니다. 인증서·자격 증명 만료라는 원인의 식별자는 certificate-expiry 이고, CoreDNS 라는 구성 요소의 식별자는 coredns 입니다. 식별자를 모를 때는 생각나는 단어로 찾을 수 있습니다. 방법은 아래에 적었습니다.
할 수 있는 일
- 증상으로 찾기. 지금 보이는 증상을 한 문장으로 적으면 가장 비슷한 사례부터 차례로 나옵니다. 찾은 사례를 원인, 구성 요소, 증상, 기여 요인별로 몇 건인지 세어서 함께 보여 줍니다. 그 숫자를 보면 이런 증상이 무엇 때문에 자주 나는지 알 수 있습니다.
- 사례 한 건 읽기. 사례 번호로 전체 내용을 받습니다. 같은 원인에 같은 구성 요소를 가진 다른 사례도 함께 받습니다.
- 분류로 거르기. 원인, 구성 요소, 증상, 기여 요인, 영역, 조직으로 사례 목록을 거릅니다.
- 분류 하나를 들여다보기. 분류 값 하나를 고르면 그 값을 가진 사례가 전부 나옵니다. 그 사례들에 다른 분류 값이 몇 건씩 있는지도 나옵니다. 예를 들어 DNS 조회 실패라는 증상을 고르면 그 증상이 어떤 원인에서 몇 번 나왔는지 보입니다. 증상 문장을 함께 주면 그 문장과 비슷한 사례만 남깁니다.
- 식별자 찾기. 생각나는 단어 몇 개를 주면 뜻이 가장 가까운 분류 값을 찾아 줍니다. cert ran out 이라고 주면 certificate-expiry 가 나옵니다.
AI 도구에 붙이기
MCP 서버 주소는 https://incidentlib-mcp.benchlet.com/mcp 입니다. 연결 방식은 Streamable HTTP 이고 주소만 등록하면 됩니다. 인증은 없습니다.
Claude Code 에서는 아래 명령 한 줄이면 됩니다.
claude mcp add --transport http incidentlib https://incidentlib-mcp.benchlet.com/mcpCursor 에서는 프로젝트의 .cursor/mcp.json 에 아래 내용을 넣습니다. MCP 서버를 주소로 등록하는 다른 도구에도 같은 주소를 넣으면 됩니다.
{
"mcpServers": {
"incidentlib": { "url": "https://incidentlib-mcp.benchlet.com/mcp" }
}
}Claude Desktop 에서는 설정의 Connectors 에서 사용자 지정 커넥터를 추가하고 위 주소를 넣습니다.
이렇게 물어보면 됩니다
Our pods stopped resolving DNS after CoreDNS restarted. Which public incidents look like this, and what caused them?
AI 는 아래처럼 도구를 부르고, 사례 번호와 원문 주소를 인용해서 답합니다.
search_incidents(symptoms="pods cannot resolve dns after coredns restarts", limit=5)
→ results: [{ id, url, title, org, date, root_cause, symptoms, components, contributing, summary, snippet, source }, …]
facets: { root_causes: [{ slug, en, ko, count, cases }], components: [...], symptoms: [...], factors: [...] }
get_incident(id="IL-0001")
→ symptoms_text, trigger, root_cause, components, contributing, summary, detection, remediation, action_items, lessons, sources, similar_cases도구 다섯
search_incidents- 누군가 장애 증상을 말하면 가장 먼저 쓰는 도구입니다. 증상 문장을 넣으면 가장 비슷한 사례부터 차례로 나오고, 찾은 사례를 분류별로 센 숫자도 함께 옵니다.
get_incident- 사례 번호를 알 때 전체 내용을 읽는 도구입니다. 같은 원인과 구성 요소를 가진 다른 사례도 함께 옵니다.
list_incidents- 특정 원인이나 구성 요소의 사례를 전부 보고 싶을 때 쓰는 도구입니다. 식별자로 거릅니다. 조건을 여럿 주면 모두 만족하는 사례만 나옵니다. 한 번에 한 페이지가 오고, 다음 페이지가 있으면 그 페이지 주소가 함께 옵니다.
get_topic- 분류 값 하나를 들여다보는 도구입니다. 그 값의 사례와, 그 사례들에 다른 분류 값이 몇 건씩 있는지가 옵니다. 증상 문장을 주면 비슷한 사례만 남깁니다.
vocab- 식별자를 찾는 도구입니다. 단어를 주면 뜻이 가까운 분류 값이 나오고, 단어 없이 부르면 모든 분류 값과 이름이 나옵니다.
한도
같은 주소에서는 1분에 60번까지 부를 수 있습니다. 넘으면 429 응답이 오고, 응답의 Retry-After 헤더에 몇 초 뒤에 다시 보내면 되는지 적혀 있습니다.
프로그램에서 부르기
기본 주소는 https://incidentlib-api.benchlet.com 입니다. 모든 호출은 GET 이고, 인증도 꼭 넣어야 하는 헤더도 없습니다. 응답은 JSON 이고 필드 이름은 소문자와 밑줄로 씁니다. 사례와 분류 값에는 늘 url 필드가 있고, 사람이 읽는 페이지 주소가 들어 있습니다.
증상으로 찾기
curl 'https://incidentlib-api.benchlet.com/search?q=pods+cannot+resolve+dns+after+coredns+restarts&limit=3'아래는 실제 응답을 줄여서 보인 예시입니다. 가장 비슷한 사례부터 차례로 results 에 오고, 찾은 사례를 분류별로 센 결과가 facets 에 옵니다. 비슷한 사례가 없으면 results 는 비어 있습니다.
{
"query": "pods cannot resolve dns after coredns restarts",
"results": [
{
"id": "IL-0001",
"title": {
"en": "Cluster-wide DNS outage after CoreDNS ran out of memory",
"ko": "CoreDNS 가 메모리 한도에 걸려 죽으면서 클러스터 전체 DNS 가 멈춘 장애"
},
"org": "Zalando",
"date": "2019-01-07",
"root_cause": "capacity",
"contributing": [
"limit-unknown",
"no-caching",
"… 2 more"
],
"symptoms": [
"high-error-rate",
"dns-resolution-failures",
"… 2 more"
],
"components": [
"coredns",
"memory-limit",
"… 1 more"
],
"domain": [
"kubernetes",
"aws"
],
"severity": "unknown",
"symptoms_text": {
"en": "Product pages on the storefront returned errors for more than an hour. Every DNS lookup in…",
"ko": "상품 페이지가 한 시간 넘게 오류를 냈어요. 클러스터 안의 DNS 조회가 전부 실패했고, 클러스터 안에 있던 모니터링도 같이 죽어서 아무도 자동으로 호출되지 않았…"
},
"trigger": {
"en": "Calls from the aggregation layer to one downstream service timed out; clients retried, and…",
"ko": "집계 계층이 뒤쪽 서비스 하나를 부르다 타임아웃이 났어요. 클라이언트들이 재시도하면서 요청이 몰렸고, 그 요청이 그대로 CoreDNS 로 가는 DNS 조회 폭증으…"
},
"summary": {
"en": "CoreDNS pods ran with a 100Mi memory limit set from old usage figures. A spike of DNS quer…",
"ko": "CoreDNS 파드의 메모리 한도가 예전 사용량 기준으로 100Mi 였어요. DNS 조회가 몰리자 한도를 넘어 OOM 으로 죽었고, 부하가 계속되니 살아나자마자 …"
},
"detection": {
"en": "An on-call engineer from the aggregation layer phoned the Kubernetes on-call engineer; aut…",
"ko": "집계 계층 당직자가 쿠버네티스 당직자에게 전화했어요. 자동 호출은 클러스터 안 모니터링에 기대고 있었는데 그게 죽어 있었어요."
},
"remediation": [
"raised CoreDNS memory requests and limits from 100Mi to 2000Mi by hand"
],
"action_items": [
{
"text": {
"en": "Run CoreDNS behind a per-node dnsmasq to contain the blast radius",
"ko": "노드마다 dnsmasq 를 두고 CoreDNS 를 그 뒤에 둬서 영향 범위를 줄이기"
},
"status": "planned"
},
{
"text": {
"en": "Alert from outside the clusters",
"ko": "클러스터 바깥에서 경보 보내기"
},
"status": "planned"
},
"… 1 more"
],
"lessons": {
"en": "DNS in the cluster was not resilient enough: one application could take it down for everyo…",
"ko": "클러스터 안 DNS 가 너무 약했어요. 애플리케이션 하나가 모두의 DNS 를 무너뜨릴 수 있었어요. 클러스터 안에서 도는 모니터링은 클러스터와 함께 죽어요."
},
"sources": [
{
"url": "https://github.com/zalando-incubator/kubernetes-on-aws/blob/dev/docs/postmortems/jan-2019-…",
"kind": "github",
"license": "unknown",
"archived": "http://web.archive.org/web/20261004005813/https://github.com/zalando-incubator/kubernetes-…"
}
],
"matched_symptoms": [
"dns-resolution-failures"
],
"matched_components": [
"coredns",
"dns-resolver"
],
"snippet": {
"ko": "클러스터 안의 DNS 조회가 전부 실패했고, 클러스터 안에 있던 모니터링도 같이 죽어서 아무도 자동으로 호출되지 않았어요.",
"en": "Every DNS lookup inside the cluster failed, and because the cluster's own monitoring was a…"
},
"url": "https://incidentlib.benchlet.com/cases/IL-0001"
}
],
"facets": {
"root_causes": [
{
"slug": "capacity",
"en": "Capacity exhaustion",
"ko": "용량 한계",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/root-causes/capacity"
}
],
"components": [
{
"slug": "coredns",
"en": "CoreDNS",
"ko": "CoreDNS",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/components/coredns"
},
{
"slug": "dns-resolver",
"en": "Client-side DNS resolver and cache",
"ko": "클라이언트 쪽 DNS 리졸버와 캐시",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/components/dns-resolver"
},
"… 1 more"
],
"symptoms": [
{
"slug": "dns-resolution-failures",
"en": "DNS resolution failures",
"ko": "DNS 조회 실패",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/symptoms/dns-resolution-failures"
},
{
"slug": "high-error-rate",
"en": "High error rate",
"ko": "오류율 상승",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/symptoms/high-error-rate"
},
"… 2 more"
],
"factors": [
{
"slug": "limit-unknown",
"en": "Unknown limit",
"ko": "한계 미인지",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/factors/limit-unknown"
},
{
"slug": "monitoring-blind-spot",
"en": "Monitoring blind spot",
"ko": "모니터링 사각지대",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/factors/monitoring-blind-spot"
},
"… 2 more"
]
}
}매개변수는 셋입니다. q 는 증상 문장이고 꼭 있어야 합니다. limit 은 최대 몇 건을 받을지 정합니다. 기본은 10건이고 최대 50건입니다. lang=ko 를 붙이면 한국어가 있는 글은 한국어로 옵니다.
사례 한 건과 비슷한 사례
curl 'https://incidentlib-api.benchlet.com/cases/IL-0001'{
"id": "IL-0001",
"org": "Zalando",
"date": "2019-01-07",
"docs": [
"https://github.com/kubernetes/dns/issues/159#issuecomment-336449931",
"https://nodejs.org/docs/latest/api/dns.html#dns_implementation_considerations",
"… 1 more"
],
"title": {
"en": "Cluster-wide DNS outage after CoreDNS ran out of memory",
"ko": "CoreDNS 가 메모리 한도에 걸려 죽으면서 클러스터 전체 DNS 가 멈춘 장애"
},
"domain": [
"kubernetes",
"aws"
],
"impact": {
"scope": "whole cluster DNS; customer-facing product pages",
"users": "unknown",
"region": "unknown"
},
"review": {
"written_by": "session",
"reviewed_at": null,
"reviewed_by": null
},
"lessons": {
"en": "DNS in the cluster was not resilient enough: one application could take it down for everyo…",
"ko": "클러스터 안 DNS 가 너무 약했어요. 애플리케이션 하나가 모두의 DNS 를 무너뜨릴 수 있었어요. 클러스터 안에서 도는 모니터링은 클러스터와 함께 죽어요."
},
"related": [
"IL-0005"
],
"sources": [
{
"url": "https://github.com/zalando-incubator/kubernetes-on-aws/blob/dev/docs/postmortems/jan-2019-…",
"kind": "github",
"license": "unknown",
"archived": "http://web.archive.org/web/20261004005813/https://github.com/zalando-incubator/kubernetes-…"
}
],
"summary": {
"en": "CoreDNS pods ran with a 100Mi memory limit set from old usage figures. A spike of DNS quer…",
"ko": "CoreDNS 파드의 메모리 한도가 예전 사용량 기준으로 100Mi 였어요. DNS 조회가 몰리자 한도를 넘어 OOM 으로 죽었고, 부하가 계속되니 살아나자마자 …"
},
"trigger": {
"en": "Calls from the aggregation layer to one downstream service timed out; clients retried, and…",
"ko": "집계 계층이 뒤쪽 서비스 하나를 부르다 타임아웃이 났어요. 클라이언트들이 재시도하면서 요청이 몰렸고, 그 요청이 그대로 CoreDNS 로 가는 DNS 조회 폭증으…"
},
"severity": "unknown",
"symptoms": [
"high-error-rate",
"dns-resolution-failures",
"… 2 more"
],
"timeline": {
"detected_after": null,
"resolved_after": null
},
"date_kind": "incident",
"detection": {
"en": "An on-call engineer from the aggregation layer phoned the Kubernetes on-call engineer; aut…",
"ko": "집계 계층 당직자가 쿠버네티스 당직자에게 전화했어요. 자동 호출은 클러스터 안 모니터링에 기대고 있었는데 그게 죽어 있었어요."
},
"components": [
"coredns",
"memory-limit",
"… 1 more"
],
"root_cause": "capacity",
"remediation": [
"raised CoreDNS memory requests and limits from 100Mi to 2000Mi by hand"
],
"action_items": [
{
"text": {
"en": "Run CoreDNS behind a per-node dnsmasq to contain the blast radius",
"ko": "노드마다 dnsmasq 를 두고 CoreDNS 를 그 뒤에 둬서 영향 범위를 줄이기"
},
"status": "planned"
},
{
"text": {
"en": "Alert from outside the clusters",
"ko": "클러스터 바깥에서 경보 보내기"
},
"status": "planned"
},
"… 1 more"
],
"contributing": [
"limit-unknown",
"no-caching",
"… 2 more"
],
"recurrence_of": null,
"symptoms_text": {
"en": "Product pages on the storefront returned errors for more than an hour. Every DNS lookup in…",
"ko": "상품 페이지가 한 시간 넘게 오류를 냈어요. 클러스터 안의 DNS 조회가 전부 실패했고, 클러스터 안에 있던 모니터링도 같이 죽어서 아무도 자동으로 호출되지 않았…"
},
"updated_at": "2026-11-08T06:09:02.994198Z",
"url": "https://incidentlib.benchlet.com/cases/IL-0001"
}curl 'https://incidentlib-api.benchlet.com/cases/IL-0001/similar'같은 원인이면서 구성 요소를 하나 이상 공유하는 사례입니다. 공유하는 구성 요소가 많은 사례부터 옵니다.
[
{
"id": "IL-0016",
"title": {
"en": "Prometheus on the live cluster killed by memory exhaustion",
"ko": "메모리 소진으로 죽은 운영 클러스터의 Prometheus"
},
"org": "UK Ministry of Justice",
"date": "2023-07-25",
"severity": "sev3",
"root_cause": "capacity",
"url": "https://incidentlib.benchlet.com/cases/IL-0016",
"shared_components": [
"memory-limit"
]
}
]분류로 거르기
curl 'https://incidentlib-api.benchlet.com/cases?root_cause=capacity&limit=2'거르는 매개변수는 root_cause, component, symptom, factor, domain, org 이고 값은 식별자입니다. 여러 개를 주면 모두 만족하는 사례만 옵니다. 최근 사례가 먼저 옵니다.
목록은 페이지로 나뉘어 옵니다. items 에 이번 페이지의 사례가 있고, 다음 페이지가 있으면 next 에 그 페이지의 전체 주소가 있습니다. next 가 없으면 마지막 페이지입니다. 한 페이지는 기본 50건, 최대 200건입니다. 다음 페이지 주소는 직접 만들지 말고 next 를 그대로 쓰면 됩니다.
{
"items": [
{
"id": "IL-0006",
"org": "Neon",
"date": "2025-05-16",
"docs": [
"https://github.com/aws/amazon-vpc-cni-k8s/blob/v1.18.6/docs/eni-and-ip-target.md",
"https://docs.aws.amazon.com/eks/latest/userguide/cni-increase-ip-addresses.html"
],
"title": {
"en": "IP exhaustion with the AWS VPC CNI, then a warm-pool setting cascade",
"ko": "AWS VPC CNI 의 IP 소진, 그리고 웜 풀 설정이 부른 연쇄 장애"
},
"domain": [
"kubernetes",
"aws"
],
"impact": {
"scope": "one region's cluster, about 10% of pod starts failing",
"users": "unknown",
"region": "us-east-1"
},
"review": {
"written_by": "session",
"reviewed_at": null,
"reviewed_by": null
},
"lessons": {
"en": "Defaults and documentation need verifying under real pod churn, a revert does not necessar…",
"ko": "기본값과 문서는 실제 파드 생성 삭제 부하에서 확인해야 해요. 되돌린다고 건강한 상태로 돌아오는 건 아니에요. 부하 테스트에서 나온 용량 가정은 성장이 앞지르면 …"
},
"related": [
"IL-0007",
"IL-0015",
"… 1 more"
],
"sources": [
{
"url": "https://neon.com/blog/aws-cni-lessons-from-a-production-outage",
"kind": "blog",
"license": "unknown",
"archived": "http://web.archive.org/web/20260508092749/https://neon.com/blog/aws-cni-lessons-from-a-pro…"
}
],
"summary": {
"en": "The region's subnets were half the size used elsewhere, and growth pushed them to their li…",
"ko": "그 리전의 서브넷은 다른 곳의 절반 크기였고 성장이 한계를 밀어붙였어요. VPC CNI 가 파드를 더 받을 수 없는 노드에도 주소를 많이 쥐고 있어서 풀이 실제보…"
},
"trigger": {
"en": "A control-plane job that terminates idle computes started failing, so active computes doub…",
"ko": "쉬는 컴퓨트를 종료하는 컨트롤 플레인 작업이 실패하기 시작해서 주말 사이 활성 컴퓨트가 두 배로 늘었어요. 사흘 뒤 CNI 설정을 되돌리자 같은 증상이 다시 나타…"
},
"severity": "unknown",
"symptoms": [
"pod-pending",
"no-available-ip"
],
"timeline": {
"detected_after": null,
"resolved_after": null
},
"date_kind": "incident",
"detection": {
"en": "IP assignment errors and a falling pod-start rate in metrics and logs.",
"ko": "메트릭과 로그에서 IP 할당 오류와 떨어지는 파드 시작률이 보였어요."
},
"components": [
"vpc-cni",
"subnet",
"… 1 more"
],
"root_cause": "capacity",
"remediation": [
"set WARM_IP_TARGET to 1, later all warm targets to 0",
"enlarged pre-created compute pools",
"… 1 more"
],
"action_items": [
{
"text": {
"en": "Upstream improvement to aws-vpc-cni (PR 3300)",
"ko": "aws-vpc-cni 에 개선 PR 올리기"
},
"status": "done"
},
{
"text": {
"en": "Follow up with AWS support on unaccounted addresses",
"ko": "집계되지 않은 주소를 AWS 지원과 확인하기"
},
"status": "planned"
},
"… 1 more"
],
"contributing": [
"default-config-unchanged",
"revert-did-not-restore",
"… 1 more"
],
"recurrence_of": null,
"symptoms_text": {
"en": "New compute pods were scheduled but could not start, failing with IP allocation errors. Th…",
"ko": "새 컴퓨트 파드가 스케줄은 됐는데 IP 할당 오류로 시작하지 못했어요. 서브넷은 다 찬 것처럼 보이는데 쓰이지 않는 주소가 많아 보였고, 쉬고 있던 고객 데이터베…"
},
"updated_at": "2026-11-08T06:09:03.901278Z",
"url": "https://incidentlib.benchlet.com/cases/IL-0006"
},
{
"id": "IL-0007",
"org": "Adevinta",
"date": "2024-10-22",
"docs": [
"https://aws.amazon.com/blogs/containers/addressing-ipv4-address-exhaustion-in-amazon-eks-c…"
],
"title": {
"en": "Running out of IPv4 addresses in EKS before it became an outage",
"ko": "EKS 에서 IPv4 주소가 바닥나기 전에 막은 사례"
},
"domain": [
"kubernetes",
"aws"
],
"impact": {
"scope": "one small cluster; a fleet-wide outage was avoided",
"users": "unknown",
"region": "unknown"
},
"review": {
"written_by": "session",
"reviewed_at": null,
"reviewed_by": null
},
"lessons": {
"en": "The VPC CNI needs capacity planning before it is ready for a large fleet; what works in a …",
"ko": "VPC CNI 는 큰 규모에서 쓰기 전에 용량 계획이 필요해요. 작은 클러스터에서 되던 것이 커지면 안 돼요."
},
"related": [
"IL-0015",
"IL-0019"
],
"sources": [
{
"url": "https://adevinta.com/techblog/how-we-avoided-an-outage-caused-by-running-out-of-ips-in-eks…",
"kind": "blog",
"license": "unknown",
"archived": "http://web.archive.org/web/20260826124239/https://adevinta.com/techblog/how-we-avoided-an-…"
}
],
"summary": {
"en": "The VPC CNI gives every pod an address from the VPC, so pod growth consumes IPv4 space dir…",
"ko": "VPC CNI 는 파드마다 VPC 주소를 하나씩 주기 때문에 파드가 늘면 IPv4 공간이 그만큼 줄어요. 첫 장애는 거의 쓰지 않는 작은 클러스터에서 났고 영향은…"
},
"trigger": {
"en": "unknown; growing pod counts during a large EKS migration pushed one cluster's subnets to t…",
"ko": "알 수 없음. 큰 EKS 이전 중에 파드 수가 늘면서 클러스터 하나의 서브넷이 한계에 닿았어요."
},
"severity": "sev4",
"symptoms": [
"no-available-ip",
"pod-pending"
],
"timeline": {
"detected_after": null,
"resolved_after": null
},
"date_kind": "published",
"detection": {
"en": "A pager alert on failing DaemonSets, then pod status on the node.",
"ko": "DaemonSet 실패 호출이 왔고, 노드의 파드 상태로 확인했어요."
},
"components": [
"vpc-cni",
"subnet",
"… 1 more"
],
"root_cause": "capacity",
"remediation": [
"custom networking with a secondary CIDR, first on small clusters then fleet-wide",
"reserved-ENI setting for Karpenter"
],
"action_items": [
{
"text": {
"en": "Custom networking across the fleet",
"ko": "전체 클러스터에 커스텀 네트워킹 적용"
},
"status": "done"
},
{
"text": {
"en": "Karpenter honours custom networking",
"ko": "Karpenter 가 커스텀 네트워킹을 따르게 하기"
},
"status": "done"
},
"… 1 more"
],
"contributing": [
"default-config-unchanged",
"no-capacity-planning"
],
"recurrence_of": null,
"symptoms_text": {
"en": "A pager alert reported DaemonSets failing on a small cluster. Pod status showed the CNI co…",
"ko": "작은 클러스터에서 DaemonSet 이 실패한다는 호출이 왔어요. 파드 상태를 보니 CNI 가 새 컨테이너에 주소를 못 주고 있었어요."
},
"updated_at": "2026-11-08T06:09:04.059881Z",
"url": "https://incidentlib.benchlet.com/cases/IL-0007"
}
],
"next": "https://incidentlib-api.benchlet.com/cases?root_cause=capacity&limit=2&after=MjAyNC0xMC0yM…"
}분류 하나를 들여다보기
curl 'https://incidentlib-api.benchlet.com/symptoms/dns-resolution-failures'원인은 /root-causes/식별자, 구성 요소는 /components/식별자, 증상은 /symptoms/식별자, 기여 요인은 /factors/식별자 입니다. 네 가지 모두 같은 모양으로 옵니다. 식별자 없이 부르면 그 분류의 모든 값과 사례 수가 옵니다. 아래는 DNS 조회 실패라는 증상의 예시입니다. related.root_causes 가 이 증상을 낸 원인과 건수입니다.
{
"kind": "symptom",
"slug": "dns-resolution-failures",
"en": "DNS resolution failures",
"ko": "DNS 조회 실패",
"url": "https://incidentlib.benchlet.com/symptoms/dns-resolution-failures",
"count": 2,
"first_date": "2019-01-07",
"last_date": "2024-12-11",
"cases": [
{
"id": "IL-0005",
"title": {
"en": "Telemetry rollout overloaded the control planes and broke service discovery",
"ko": "텔레메트리 서비스 배포가 컨트롤 플레인을 과부하시켜 서비스 디스커버리를 끊은 장애"
},
"org": "OpenAI",
"date": "2024-12-11",
"severity": "sev1",
"root_cause": "config-change",
"url": "https://incidentlib.benchlet.com/cases/IL-0005"
},
{
"id": "IL-0001",
"title": {
"en": "Cluster-wide DNS outage after CoreDNS ran out of memory",
"ko": "CoreDNS 가 메모리 한도에 걸려 죽으면서 클러스터 전체 DNS 가 멈춘 장애"
},
"org": "Zalando",
"date": "2019-01-07",
"severity": "unknown",
"root_cause": "capacity",
"url": "https://incidentlib.benchlet.com/cases/IL-0001"
}
],
"related": {
"root_causes": [
{
"slug": "capacity",
"en": "Capacity exhaustion",
"ko": "용량 한계",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/root-causes/capacity"
},
{
"slug": "config-change",
"en": "Configuration change",
"ko": "설정 변경",
"count": 1,
"cases": [
"IL-0005"
],
"url": "https://incidentlib.benchlet.com/root-causes/config-change"
}
],
"components": [
{
"slug": "dns-resolver",
"en": "Client-side DNS resolver and cache",
"ko": "클라이언트 쪽 DNS 리졸버와 캐시",
"count": 2,
"cases": [
"IL-0005",
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/components/dns-resolver"
},
{
"slug": "coredns",
"en": "CoreDNS",
"ko": "CoreDNS",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/components/coredns"
},
"… 3 more"
],
"factors": [
{
"slug": "failure-delayed-by-cache",
"en": "Cache-masked failure",
"ko": "캐시로 가려진 장애",
"count": 1,
"cases": [
"IL-0005"
],
"url": "https://incidentlib.benchlet.com/factors/failure-delayed-by-cache"
},
{
"slug": "limit-unknown",
"en": "Unknown limit",
"ko": "한계 미인지",
"count": 1,
"cases": [
"IL-0001"
],
"url": "https://incidentlib.benchlet.com/factors/limit-unknown"
},
"… 5 more"
]
}
}q 에 증상 문장을 주면 그 문장과 비슷한 사례만 남고, 다른 분류의 건수도 그 사례들만 셉니다.
curl 'https://incidentlib-api.benchlet.com/root-causes/capacity?q=dns+lookups+fail'식별자 찾기
curl 'https://incidentlib-api.benchlet.com/vocab?q=cert+ran+out&kind=root_causes&limit=3'q 에 생각나는 단어를 주면 뜻이 가까운 순서로 분류 값이 옵니다. kind 로 한 분류만 볼 수 있고, 값은 root_causes, components, symptoms, factors 중 하나입니다. q 없이 부르면 모든 분류 값과 영어·한국어 이름이 옵니다.
{
"matches": [
{
"kind": "root_cause",
"slug": "certificate-expiry",
"en": "Certificate or credential expiry",
"ko": "인증서·자격 증명 만료",
"url": "https://incidentlib.benchlet.com/root-causes/certificate-expiry"
},
{
"kind": "root_cause",
"slug": "credential-exposure",
"en": "Credential exposure",
"ko": "자격 증명 유출",
"url": "https://incidentlib.benchlet.com/root-causes/credential-exposure"
},
"… 1 more"
],
"query": "cert ran out"
}사례의 필드
id | 사례 번호입니다. IL-0001 처럼 생겼고 바뀌지 않습니다. |
url | 이 사례를 사람이 읽는 페이지 주소입니다. |
title | 제목입니다. 영어와 한국어가 각각 들어 있습니다. |
org | 장애를 겪은 조직입니다. |
date | 장애가 난 날 또는 보고서가 공개된 날입니다. |
severity | 심각도입니다. sev1 부터 sev4 까지이고, 보고서에 없으면 unknown 입니다. |
domain | 영역입니다. kubernetes 또는 ai-infra 입니다. |
root_cause | 원인 분류의 영문 식별자입니다. 예를 들어 certificate-expiry 입니다. |
components | 문제가 난 구성 요소 분류의 식별자 목록입니다. |
symptoms | 증상 분류의 식별자 목록입니다. |
contributing | 기여 요인 분류의 식별자 목록입니다. |
symptoms_text | 엔지니어가 본 증상을 문장으로 적은 글입니다. |
trigger | 장애를 촉발한 일입니다. |
summary | 무슨 일이 어떻게 일어났는지 요약한 글입니다. |
detection | 장애를 어떻게 알아차렸는지 적은 글입니다. |
remediation | 장애를 끝내려고 한 조치 목록입니다. |
action_items | 그 뒤에 조직이 하기로 한 일과 진행 상태입니다. |
lessons | 보고서가 남긴 교훈입니다. |
sources | 원문 주소, 보관본 주소, 자료 종류, 라이선스입니다. |
impact | 영향 범위, 영향 받은 사용자, 지역입니다. |
timeline | 알아차리기까지 걸린 시간과 복구까지 걸린 시간입니다. |
recurrence_of | 같은 장애가 전에도 있었다면 그 사례 번호입니다. |
related | 편집자가 관련 있다고 연결한 사례 번호 목록입니다. |
updated_at | 이 사례가 마지막으로 바뀐 시각입니다. |
영어와 한국어가 함께 있는 글 필드는 en 과 ko 두 항목으로 옵니다. 한국어가 없는 사례는 en 만 있습니다.
오류 응답
모든 오류는 같은 모양입니다. 응답 형식은 application/problem+json 이고, status 에 상태 코드, title 에 그 코드의 이름, detail 에 무엇이 잘못됐는지 한 문장, instance 에 요청한 경로가 들어 있습니다. 없는 사례를 부르면 이렇게 옵니다.
curl -i 'https://incidentlib-api.benchlet.com/cases/IL-9999'{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "no approved case IL-9999",
"instance": "/cases/IL-9999"
}400 | 매개변수가 빠졌거나 범위를 벗어났습니다. 무엇이 문제인지 detail 에 있습니다. |
404 | 그 번호의 사례나 그 식별자의 분류 값이 없습니다. |
429 | 같은 주소에서 1분에 부를 수 있는 횟수를 넘겼습니다. Retry-After 헤더에 몇 초 뒤에 다시 보내면 되는지 적혀 있습니다. |
503 | 잠시 뒤 다시 보내면 됩니다. |
500 | 서버 안에서 예상 못 한 오류가 났습니다. 잠시 뒤 다시 보내고, 계속되면 아래 제보처에 알려 주세요. |
한도
같은 주소에서는 1분에 검색 30번, 그 밖의 호출 120번까지 부를 수 있습니다. 넘으면 429 응답이 오고, 1분 뒤에 다시 부를 수 있습니다. 더 많이 필요하면 아래 제보처로 알려 주세요.
헤더
| 요청 | 필요한 헤더가 없습니다. |
Content-Type | 정상 응답은 application/json; charset=utf-8, 오류 응답은 application/problem+json 입니다. |
Access-Control-Allow-Origin | 항상 * 입니다. 어느 사이트의 브라우저 코드에서든 이 API 를 읽을 수 있습니다. |
Retry-After | 429 응답에만 있고, 몇 초 뒤에 다시 보내면 되는지 적혀 있습니다. |
프로그램이 읽는 명세는 OpenAPI 문서에 있습니다.
데이터는 어디서 왔나
사례는 전부 공개된 장애 보고서에서 왔습니다. 회사의 기술 블로그, 상태 페이지, 발표 자료, 논문, 코드 저장소입니다. 사례 글은 보고서가 말한 사실을 우리 말로 다시 쓴 요약이고, 보고서에 없는 사실은 비워 둡니다. 원문을 보관본으로 남길 수 있으면 보관본 주소도 함께 둡니다.
사례 글, 분류 목록, API 응답은 출처만 밝히면 자유롭게 쓸 수 있는 CC BY 4.0 라이선스입니다. 원문 보고서는 각자의 라이선스를 따르고, 그 라이선스는 사례의 출처 항목에 적혀 있습니다. 틀린 곳을 알리거나 사례를 제안하려면 GitHub 이슈를 열어 주세요.