--- type: runbook tags: [istio, egress, dns, serviceentry, envoy] created: 2026-06-07 --- # Runbook — ServiceEntry `resolution: DNS` 동작과 진단 (STRICT_DNS) > [!abstract] > 외부 도메인(`httpbin.org`)을 `ServiceEntry(resolution: DNS)`로 등록하면 istiod가 이를 Envoy의 > **STRICT_DNS cluster**로 변환한다. 이 문서는 그 변환·DNS 갱신 메커니즘, "죽은 IP" 처리, ambient DNS > 질의 경로를 홈랩 실측·재현 명령과 함께 한 줄의 멘탈모델로 꿴다. > **결론 한 문장: DNS refresh는 health check가 아니다** — DNS는 "목록"만 줄 뿐 IP의 생사를 모르므로, > 죽은 IP 회피는 outlier detection으로 *명시*해야 한다. **환경:** cluster `homelab`(k8s v1.30.6, **istiod 1.30.0** / istioctl 1.27.0 client·skew) / egress gateway 경유 / 관련: [ingress·egress 통합 리포트](rpt__report-2026-06-07_ingress-egress.html) --- ## 1. 배경 — 왜 mesh가 외부 도메인의 IP를 직접 들어야 하나 mesh 안 트래픽은 전부 Envoy가 가로채 라우팅한다(sidecar/gateway). 그런데 Envoy는 "IP:port의 묶음"인 **cluster** 단위로만 upstream을 안다 — Envoy의 세계에는 호스트네임이 없고 endpoint 집합만 있다. mesh 내부 서비스는 istiod가 k8s `Endpoints`/`EndpointSlice`를 watch해서 cluster를 자동으로 채워준다. 하지만 `httpbin.org` 같은 **mesh 밖 외부 도메인**은 k8s에 Endpoints가 없다. istiod가 그 IP를 알 길이 없다. `ServiceEntry`는 바로 이 공백을 메우는 CRD다 — "이 호스트는 mesh의 일부로 취급하라, IP는 *이렇게* 알아내라"를 선언한다. 그 "IP를 알아내는 방식"이 `spec.resolution` 필드이고, **이 한 필드가 Envoy cluster의 종류를 결정**한다. 즉 외부 도메인 한 줄을 등록할 때 진짜로 고르는 것은 "Envoy가 IP를 들고 LB하는 전략"이다. 여기서 자연스럽게 따라오는 질문 4개가 이 문서의 뼈대다 — 이 순서대로 읽으면 길을 잃지 않는다: ``` resolution -> cluster type -> 갱신 주기 -> 죽은 IP -> 회피 구성 (어떻게 (STRICT_DNS (DNS TTL을 (DNS는 (outlier IP를 안다) / LOGICAL) 따라 재질의) 생사 모름) detection+retry) ``` **선행 개념:** Envoy cluster = endpoint(IP:port) 집합 + LB 정책 / cluster 이름 규칙 `direction|port|subset|fqdn` (예: `outbound|443||httpbin.org`) / egress gateway = mesh 밖으로 나가는 트래픽을 한 노드로 모으는 전용 Envoy. cluster 구조 자체는 [Cluster 해부](../istio/xds__src-cluster-anatomy.html) 참조. --- ## 2. 머릿속에 둘 그림 — DNS는 "목록", 생사는 별도 책임 이 문서 전체를 꿰는 **앵커 한 문장**: > **`resolution`이 Envoy cluster type을 정하고, cluster type이 "IP를 어떻게 들고 LB할지"를 정한다. > 그러나 어느 type이든 DNS는 IP "목록"만 줄 뿐 그 IP가 살아있는지는 모른다 — liveness는 outlier > detection의 별도 책임이다.** 이 한 문장에서 나머지가 전부 파생된다. resolution을 STRICT_DNS로 두면 A record의 모든 IP를 펼쳐 Envoy가 직접 LB하고(§3), 갱신 주기는 DNS TTL을 따른다(§4). 하지만 TTL 만료 전에 IP가 죽으면 Envoy는 그 IP를 여전히 HEALTHY로 들고 있어 연결이 실패한다(§5) — **DNS refresh는 단지 "목록 다시 받기"이지 "이 IP 살아있냐"를 묻는 게 아니기 때문**이다. 그래서 죽은 IP 회피는 outlier detection + retry로 *명시*해야 하고(§7), GSLB 뒤라면 LB 권한을 DNS에 위임하는 LOGICAL_DNS가 더 맞는다(§6). 마지막으로 "그 DNS 질의를 실제로 누가 쏘는가"가 진단의 출발점이다 — egress 경유 시 그 주체는 egress gateway의 Envoy(c-ares)다(§8). 왜 이렇게 책임을 쪼갰는가? **DNS와 health는 원래 다른 시스템**이기 때문이다. DNS 서버는 "이 이름에 어떤 IP들이 매핑되는가"의 권위자일 뿐, 그 IP 뒤 프로세스가 지금 요청을 받을 수 있는지는 모른다(특히 같은 A record 안에서 일부만 죽은 경우). Envoy는 이 둘을 의도적으로 분리한다 — DNS는 endpoint *발견(discovery)*, outlier detection은 endpoint *축출(ejection)*. 이 분리를 모르면 "DNS만 믿으면 알아서 죽은 IP 빠지겠지"라는 가장 흔한 오해에 빠진다. --- ## 3. 변환 구조 — `resolution`이 cluster type을 결정한다 `ServiceEntry.spec.resolution` 필드가 Envoy cluster type을 결정한다. 이 매핑을 먼저 확립해야 이후 갱신 주기(§4)·죽은 IP(§5)를 STRICT/LOGICAL 대비로 읽을 수 있다. | `resolution` | Envoy type | endpoint 적재 | 적합 대상 | |---|---|---|---| | `DNS` | **STRICT_DNS** | A record **모든 IP**를 펼침 | 개별 IP를 Envoy가 직접 LB하고 싶을 때 | | `DNS_ROUND_ROBIN` | **LOGICAL_DNS** | **첫 IP 1개**만, 연결 재사용 | CDN/GSLB/대형 LB 뒤 "논리적 단일 endpoint" | 차이의 본질은 "endpoint를 펼치느냐(STRICT) vs 한 점으로 접느냐(LOGICAL)" 한 곳이다 — 나머지(갱신·LB·연결 재사용)는 전부 이 한 델타에서 따라온다. `resolution: DNS`(STRICT_DNS) 변환 결과: ``` ServiceEntry(resolution: DNS, hosts: httpbin.org) | istiod 변환 v Envoy cluster "outbound|443||httpbin.org" type: STRICT_DNS <- Envoy가 직접 DNS 질의 respect_dns_ttl: true <- 갱신 주기 = DNS 응답의 TTL dns_refresh_rate: 60s <- TTL이 0/없을 때만 쓰는 fallback endpoints: [8 IPs] <- A record 전체를 펼쳐서 보관 ``` > 경유 구성 주의: 트래픽 경로가 `sleep → egress gateway → httpbin.org`이므로 > **실제 외부 DNS를 도는 주체는 egress gateway의 Envoy**다. sleep proxy에도 같은 cluster가 > 보이지만 라우팅이 egress gateway로 향하므로 실질 사용처가 아니다. 진단은 egress gateway 기준. **STRICT_DNS vs LOGICAL_DNS 실측** (`example.com`을 `DNS_ROUND_ROBIN`으로 별도 등록): ``` SERVICE FQDN TYPE endpoints(proxy-config) httpbin.org STRICT_DNS 다수 (A record 전체) example.com LOGICAL_DNS 1 ``` → `istioctl proxy-config endpoints --cluster "outbound|443||"`의 endpoint 개수가 **STRICT=다수 / LOGICAL=1**로 갈리는 것이 Envoy 반영의 결정적 증거다. LOGICAL_DNS의 핵심은 "DNS 레코드가 자주 바뀌어도 기존 연결을 유지(connection draining/cycling 제거)"라서, 공식 문서가 "large web scale services accessed via DNS"에 권장한다(상세 권장 근거는 §6). --- ## 4. 갱신 주기 결정 규칙 — 왜 60s가 함정값인가 | 필드 | 현재 값 | 의미 | |---|---|---| | `respect_dns_ttl` | `true` | DNS 응답 TTL을 갱신 주기로 사용 | | `dns_refresh_rate` | `60s` | TTL이 0/없을 때만 쓰는 fallback | | `httpbin.org` 실제 TTL | `10s` (dig) | → **실제 갱신 ≈ 10초** | `dns_refresh_rate: 60s`는 함정값이다 — config_dump에 60s가 박혀 있어도 `respect_dns_ttl: true`면 거의 안 쓰인다(TTL=0이거나 응답에 TTL이 없을 때만 fallback으로 등판). 즉 **실제 갱신 주기를 알려면 cluster 설정이 아니라 권위 DNS의 TTL을 봐야 한다** — config만 읽고 "60초마다 갱신되겠지"라고 단정하면 틀린다(실측은 10초). mesh 전역 기본은 **`meshConfig.dnsRefreshRate`** 필드(`configmap/istio`의 `.data.mesh`)로 조정한다. 단 효력 범위는 좁다: `respect_dns_ttl=true`인 외부 DNS cluster에서는 **TTL이 우선**이라 거의 무효이고, TTL을 무시하는 cluster나 NDS(DNS auto-allocation) 경로에 실질 영향을 준다. 확인: ```bash kubectl --context homelab -n istio-system get cm istio -o jsonpath='{.data.mesh}' | grep -i dnsRefreshRate # 미설정이면 출력 없음 = Envoy 기본 fallback(위 60s) ``` --- ## 5. "죽은 IP" 처리 — 이 문서의 심장 §2 앵커의 핵심이 여기서 구체화된다. DNS refresh는 liveness 체크가 아니므로, TTL 만료 전에 IP가 죽으면 Envoy는 그 IP를 HEALTHY로 들고 있다가 LB가 고르면 연결 실패한다. **갱신 주기를 아무리 줄여도 이 창은 닫히지 않는다** — TTL이 10초여도, 죽고 나서 다음 재질의 전까지(그리고 권위 DNS가 그 IP를 빼줄 때까지)는 무방비다. ``` [갱신 전, IP 죽음] client --> egress GW --> [죽은 IP 선택] --X TCP connect 실패 +-- retry O --> 다른 IP 재시도 --> 성공 +-- retry X --> 요청 실패 (503/connect error) ``` IP가 LB 목록에서 빠지는 경로는 3가지이고 서로 **독립적**이다 — 어느 것을 켜느냐가 죽은 IP 회피의 설계다: | 메커니즘 | 트리거 | 기본 구성 | |---|---|---| | DNS refresh | TTL 만료 → 재질의 시 DNS가 해당 IP 제외 | O (수동적) | | **Outlier detection** (passive HC) | 연속 5xx/connect 실패 → 일시 ejection | **X (DestinationRule 미설정)** | | Active health check | Envoy가 직접 주기적 probe | X | 세 경로를 갈라 보는 이유: DNS refresh는 *권위 DNS가 빼주길 기다리는* 수동적 경로라 내 통제 밖이다. outlier detection은 *내가 본 실패*로 즉시 빼는 능동적 경로라 통제 안에 있다. 그래서 — → **프로덕션 결론**: 죽은 IP 회피는 DNS TTL에 기대지 말고 `DestinationRule.trafficPolicy.outlierDetection` + `VirtualService.http.retries`로 명시 설정한다. **구체 구성(YAML)·passthrough 함정은 §7**, outlier 필드 의미의 정본은 [circuit-breaking 메커니즘 note](../istio/gw__note-circuit-breaking-mechanisms.html) 참조. --- ## 6. GSLB 환경 권장 — LOGICAL_DNS GSLB(DNS가 클라이언트 위치·health로 최적 IP를 고르는 모델) 뒤 호스트는 **LOGICAL_DNS** 권장. 이유를 한 축으로 압축하면 **"LB 권한을 누구에게 둘 것인가"** — GSLB가 이미 최적 IP를 골라 주는데 STRICT_DNS로 전체 IP를 펼치면 Envoy가 그 위에서 또 LB하며 GSLB 결정을 덮어쓴다. 근거: 1. **GSLB 결정 존중**: STRICT_DNS는 A record 전부를 펼쳐 Envoy가 자체 LB → GSLB가 고른 IP 외 원격 리전까지 섞어 **GSLB 의도 무력화**. LOGICAL_DNS는 DNS가 준 첫 IP만 써 결정을 따른다. 2. **동적 변경 + 짧은 TTL 친화**: LOGICAL_DNS는 새 연결 시 재해석해 최신 GSLB 결정 반영. STRICT_DNS는 전체 IP에 conn pool 유지 → stale·원격 연결 부담. 3. **자원 낭비 방지**: GSLB 뒤는 사실상 "하나의 논리적 endpoint" → 전체 IP에 사전 연결은 낭비. **Trade-off**: LOGICAL_DNS는 endpoint가 1개라 Envoy outlier/세밀 LB 효력이 약화 → "장애 판정을 GSLB에 위임"하는 셈. GSLB health가 느슨하면 STRICT_DNS + outlier가 나을 수도. **본질은 "LB 권한을 DNS(GSLB)에 둘 것인가 Envoy에 둘 것인가"의 선택.** --- ## 7. 죽은 IP 회피 구성 — outlier detection + retry DNS refresh는 liveness를 모르므로(§5), 죽은 IP 회피는 아래로 명시한다. outlier detection 필드 자체의 일반 의미(`consecutive5xxErrors`/`baseEjectionTime` 배수 증가 등)는 [circuit-breaking 메커니즘 note](../istio/gw__note-circuit-breaking-mechanisms.html)가 정본이고, 여기서는 **egress passthrough(L4) 특수성**에 집중한다. 이 특수성 한 줄이 §7 전체를 지배한다: **egress gateway가 TLS PASSTHROUGH면 HTTP/5xx를 못 보므로, L7에 기대는 회피 장치는 전부 무력화된다.** **outlier detection** (`DestinationRule.trafficPolicy.outlierDetection` — 적용 후 Envoy 반영 확인됨): ```yaml trafficPolicy: connectionPool: { tcp: { connectTimeout: 2s } } # connect 실패 빨리 판정 outlierDetection: consecutiveLocalOriginFailures: 3 # ★ connect 실패(L4) 3회 → eject (passthrough 핵심) splitExternalLocalOriginErrors: true consecutive5xxErrors: 5 # 5xx(L7) 5회 → eject interval: 10s baseEjectionTime: 30s maxEjectionPercent: 50 # 전멸 방지 minHealthPercent: 40 ``` > **egress 특화 포인트**: TLS PASSTHROUGH(L4)에서 egress gateway는 HTTP/5xx를 볼 수 없으므로 > `consecutive5xxErrors`는 발화하지 않는다. **`consecutiveLocalOriginFailures`(connect 실패 기반)가 > 유일한 자동 회피 경로**다. 따라서 짧은 `connectTimeout`과 함께 써야 빠르게 eject된다. **retry** (`VirtualService.http.retries`) — **L7 HTTP route에서만** 동작: ```yaml http: - route: [...] retries: attempts: 3 perTryTimeout: 2s retryOn: connect-failure,refused-stream,5xx,gateway-error ``` > ⚠️ **함정**: 현재 egress는 **TLS PASSTHROUGH(L4)** 라 egress gateway가 HTTP를 못 본다 → > `http.retries`는 **조용히 무시**된다. retry를 쓰려면 **TLS origination(L7)** 구성으로 전환해야 한다. > - passthrough(L4): `outlierDetection(consecutiveLocalOriginFailures)` + 짧은 `connectTimeout` 이 유일한 자동 회피 > - TLS origination(L7): 위 + `http.retries(retryOn: connect-failure)` --- ## 8. 적용·검증 (재현 가능) ### 8.1 진단 명령 — cluster가 어떻게 IP를 들고 있나 ```bash CTX=homelab GW=deploy/istio-egressgateway.istio-system CL="outbound|443||httpbin.org" # (1) 현재 endpoint IP 목록 + outlier 상태 istioctl --context $CTX proxy-config endpoints $GW --cluster "$CL" # (2) cluster DNS 설정 (type / refresh_rate / respect_dns_ttl) kubectl --context $CTX -n istio-system exec deploy/istio-egressgateway -c istio-proxy -- \ curl -s "localhost:15000/config_dump?resource=dynamic_active_clusters" \ | grep -A10 '"'"$CL"'"' # (3) 런타임 endpoint 상태(success_rate, healthy flags) kubectl --context $CTX -n istio-system exec deploy/istio-egressgateway -c istio-proxy -- \ curl -s "localhost:15000/clusters" | grep "httpbin.org" # (4) DNS 원천 데이터(IP + TTL) dig +noall +answer httpbin.org # TTL = 첫 컬럼 숫자 # (5) DNS 갱신 카운터를 보려면 sidecar stats 필터를 풀어야 함(기본 미노출): # pod annotation proxy.istio.io/config 의 proxyStatsMatcher.inclusionRegexps 에 ".*httpbin\.org.*" 추가 ``` **검증 실험 — "DNS 주기 = endpoint 갱신 주기"**: `dig` IP 집합과 `proxy-config endpoints`를 ~10초 간격 2회씩 떠서, IP 변동 시 endpoint도 따라 바뀌면 둘이 동기임이 확인된다. 이게 §4의 "실제 갱신 ≈ TTL(10s)"의 실측 근거다. ### 8.2 retry가 정말 무시됨을 입증 (gap finding: 기대 vs 실제) §7의 "L4에서 `http.retries`는 조용히 무시"라는 주장은 추정이 아니라 두 관측으로 *입증*된다 — HTTP route가 없으면 retry 정책이 붙을 곳이 없고, 붙을 곳이 없으면 retry 카운터가 영영 0이다: ```bash # (a) egress gateway에 HTTP route가 없음 = retry 정책이 붙을 곳이 없음을 확인. # passthrough는 TCP/SNI 매칭만 존재 → routes 출력이 비거나 TCP proxy만 보임. istioctl --context homelab proxy-config routes deploy/istio-egressgateway.istio-system \ | grep -i httpbin # 기대: 매칭 없음(HTTP route 부재) # (b) retry 카운터가 0으로 고정 = 재시도가 한 번도 발생하지 않음. kubectl --context homelab -n istio-system exec deploy/istio-egressgateway -c istio-proxy -- \ curl -s localhost:15000/stats | grep 'httpbin.*upstream_rq_retry' # 기대: upstream_rq_retry: 0 (혹은 카운터 자체 부재) — L4라 retry 경로 미존재 ``` --- ## 9. "ambient DNS" — 도메인 질의는 어디로 가나 (실측) §2 앵커의 마지막 가닥: "그 DNS 질의를 *누가* 쏘는가"가 진단의 출발점이다. config_dump의 cluster를 아무리 들여다봐도, 실제 질의를 누가/어디로 보내는지를 모르면 "왜 stale IP가 안 빠지나"를 추적할 수 없다. 공식 문서의 "querying the ambient DNS"에서 **ambient는 Istio ambient mesh가 아니라** "그 프록시 환경에 깔린 기본 resolver(`/etc/resolv.conf`)"라는 영어 일반어다. STRICT/LOGICAL 둘 다 동일. 측정 결과 질의 경로(실선 = DNS capture OFF 실측 경로, 점선 = capture ON 시 분기): ```mermaid flowchart LR GW["egress GW Envoy
(c-ares; no dns_resolver)"] RC["/etc/resolv.conf
nameserver 169.254.25.10"] NL["nodelocaldns
169.254.25.10 (link-local)"] CD["CoreDNS
(cluster DNS)"] UP["upstream DNS
(recursive)"] AU["authoritative
A record"] AG["istio-agent
DNS proxy :53"] GW --> RC --> NL --> CD CD -->|"not cluster domain"| UP --> AU AU -. "A record back" .-> GW GW -. "capture ON" .-> AG AG -. "internal: NDS local / external: forward" .-> UP ``` 핵심: **질의 주체는 egress gateway의 Envoy(c-ares)**이며, capture OFF에서는 istio-agent를 거치지 않고 `resolv.conf`의 nodelocaldns → CoreDNS → upstream으로 직접 나간다. 확인된 사실: - 질의 주체 = **Envoy의 c-ares** (`typed_dns_resolver_config: envoy.network.dns_resolver.cares`). resolver 주소 미지정 → c-ares가 `resolv.conf`를 그대로 읽음. - sleep/egress gateway pod의 nameserver = `169.254.25.10` (nodelocaldns) → CoreDNS → 외부 upstream. - **Istio DNS capture(`ISTIO_META_DNS_CAPTURE`)는 비활성** (meshConfig·pod env 모두 미주입) → istio-agent DNS proxy를 안 거치고 Envoy가 직접 나간다. > DNS capture를 켜면: istio-agent가 53을 가로채(DNS proxy), 메시 내부 호스트는 NDS로 로컬 응답, > 외부만 upstream 포워딩 → "질의 위치"가 istio-agent로 바뀐다. 진단 전에 capture 여부를 먼저 봐야 하는 이유. 진단 명령: ```bash # resolver(=ambient DNS) 확인 kubectl -n mesh-test exec deploy/sleep -c istio-proxy -- cat /etc/resolv.conf # Envoy가 쓰는 resolver 종류 kubectl -n istio-system exec deploy/istio-egressgateway -c istio-proxy -- \ curl -s "localhost:15000/config_dump?resource=dynamic_active_clusters" \ | grep -A60 '"outbound|443||httpbin.org"' | grep -i dns_resolver # DNS capture 활성 여부 kubectl -n istio-system get cm istio -o jsonpath='{.data.mesh}' | grep -i DNS_CAPTURE ``` --- ## 핵심 정리 - **`resolution`이 cluster type을 결정**: `DNS`→STRICT_DNS(A record 전 IP 펼침, Envoy 자체 LB), `DNS_ROUND_ROBIN`→LOGICAL_DNS(첫 IP 1개, 연결 재사용). endpoint 개수가 결정적 증거. - **DNS refresh ≠ health check**. DNS는 endpoint *발견*, outlier detection은 endpoint *축출* — liveness는 outlier detection / active HC의 몫이지 DNS TTL이 아니다. - **`respect_dns_ttl=true`면 실제 갱신 주기는 권위 DNS TTL**(실측 10s)이지 `dns_refresh_rate`(60s)가 아니다. - **egress gateway 경유 시 DNS 질의 주체는 gateway의 Envoy(c-ares)**, 클라이언트 sidecar가 아니다. - **passthrough(L4)에서는 `consecutiveLocalOriginFailures`가 유일한 자동 회피** — `http.retries`·`consecutive5xxErrors`는 HTTP를 못 봐서 무효(§7). - **GSLB 뒤 호스트는 LOGICAL_DNS** — LB 권한을 DNS에 위임. STRICT_DNS는 GSLB 의도를 무력화. ## What you might be missing - **갱신 주기를 줄여도 죽은 IP 창은 안 닫힌다**: TTL을 10초로 줘도, IP가 죽고 다음 재질의 + 권위 DNS가 빼줄 때까지는 무방비. 능동 축출(outlier)이 없으면 DNS 주기 튜닝은 근본 해법이 아니다(§5). - **`dnsRefreshRate`의 좁은 효력**: meshConfig 필드지만 `respect_dns_ttl=true` 외부 cluster에선 TTL이 우선이라 거의 무효다. 실제로는 TTL을 무시하는 cluster나 NDS auto-allocation 경로에만 작동(§4). - **"silent" 함정**: `http.retries`는 passthrough에서 에러 없이 그냥 무시된다. proxy-config에 HTTP route가 없고 retry 카운터가 0인지로만 확인 가능(§8.2 (a)(b)). - **"ambient DNS"는 Istio ambient mesh가 아니다** — 프록시 환경의 기본 resolver(`resolv.conf`)를 뜻하는 일반어. - **DNS capture 토글이 질의 위치를 바꾼다**: capture ON이면 istio-agent가 53을 가로채 질의 주체가 바뀌므로, 진단 시 capture 활성 여부를 먼저 확인해야 경로 추론이 어긋나지 않는다(§9). ## 참조 - [ingress·egress 통합 리포트](rpt__report-2026-06-07_ingress-egress.html) - [circuit-breaking 메커니즘 (outlier detection 정본)](../istio/gw__note-circuit-breaking-mechanisms.html) - [Cluster 해부 (STRICT_DNS/LOGICAL_DNS cluster 구조)](../istio/xds__src-cluster-anatomy.html) - [east-west gateway SNI](../istio/gw__note-eastwest-gateway-sni.html) - 시연 manifest: `scenarios/20-egress/{serviceentry-example-logicaldns,destinationrule-httpbin-outlier}.yaml` --- ## 관련 파일 · 참조 - 📎 [serviceentry-example-logicaldns.yaml](../istio/attachment/scenarios/20-egress/serviceentry-example-logicaldns.yaml) · 📎 [destinationrule-httpbin-outlier.yaml](../istio/attachment/scenarios/20-egress/destinationrule-httpbin-outlier.yaml) - 📎 [proxy-dump.sh](../istio/attachment/scripts/proxy-dump.sh) · 📎 [원본 runbook](../istio/attachment/docs/runbooks/2026-06-07_serviceentry-dns-resolution.md) - ↗ [Istio ServiceEntry reference (resolution: DNS/STATIC)](https://istio.io/latest/docs/reference/config/networking/service-entry/)