homelab89 Docs Logs Legacy Files ☰ TOC 🌓
guideistio 2026-06-09egressmulti-gatewaymtlstls-passthroughnamespace-isolation

이중 egress gateway — passthrough와 mTLS를 별도 ns·별도 pod로 나란히

ABSTRACT

단일 egress gateway를 멀티-gateway 토폴로지로 일반화하면서, 두 egress 패턴(① TLS PASSTHROUGH, ② outer 메시 mTLS + inner 앱 TLS)을 서로 다른 namespace의 서로 다른 gateway pod로 동시에 띄워 직접 비교한 homelab 검증 랩. 결론: 진짜 격리는 물리 분리(pod/ns/label)와 논리 스코핑(exportTo/sourceLabels)을 함께 갖춰야 성립한다 — 둘 중 하나라도 빠지면 “분리된 것처럼 보이는” 상태에 그친다. 본 문서는 그 둘을 어떻게 맞물리는지에 집중한다(패턴 자체의 구조·운영은 기존 문서로 링크).

대상 환경: homelab (kubespray bare-metal, k8s v1.30.6, CNI Calico, 3노드), Istio 1.30.0 (Helm gateway chart) 대상 독자: 단일 egress gateway는 띄워봤고, 이제 패턴/tier별로 gateway를 쪼개려는 SRE/DevOps 범위: “왜 쪼개나” → 격리의 두 축(물리·논리) → 경로별 Istio 객체 → 트래픽·Envoy 검증 → 실측 함정 2건 선행 개념: egress route 스코핑 (멀티-gateway의 전제) · egress CRD 멘탈모델


1. 배경 — 왜 egress gateway를 둘로 쪼개나

단일 egress gateway면 메시의 모든 외부 호출이 한 pod를 통과한다. 처음엔 단순해서 좋지만, 운영이 커지면 그 한 pod가 여러 책임을 한 몸에 떠안는 구조가 문제가 된다:

  • 장애 격리 부재 — 한 tier의 graceful drain·재시작·crashloop이 모든 외부 트래픽을 흔든다.
  • SNAT 포트 고갈 공유 — 한 워크로드가 source port를 다 써버리면 무관한 다른 트래픽도 외부 연결을 못 연다.
  • 정책 충돌 — passthrough(SNI만 보고 통과)와 mTLS 종단(client cert 검증)은 listener의 TLS 동작이 정반대다. 한 pod에 얹으면 포트를 갈라야 하고, 한쪽 정책 변경이 다른 쪽 listener를 건드릴 위험이 상존한다.

그래서 패턴/tier별로 gateway pod를 분리한다. 그런데 “Deployment를 둘로 나눴다"만으로 격리가 끝나지 않는다는 게 이 문서의 핵심 교훈이다. Istio에서 한 메시 안의 리소스는 기본적으로 전역 가시성을 갖기 때문에, 물리적으로 떨어진 두 pod라도 잘못된 전역 리소스 하나가 양쪽 config를 동시에 망가뜨릴 수 있다(함정 ②, 단 아래 §5·검증 기록 참고 — 2026-07-05 재현에서는 이 현상 자체가 재현되지 않았다). 진짜 격리에는 두 번째 축이 필요하다.

선행 개념인 egress route 스코핑을 먼저 잡아두면 이 문서의 exportTo/ client-VS·gateway-VS 분리가 자연스럽게 읽힌다. 멀티-gateway는 그 스코핑 규칙을 gateway 개수만큼 곱한 것에 가깝다.

2. 멘탈모델 — 격리는 두 축의 곱(物理 × 論理)

머릿속에 담을 한 장면: 두 gateway는 pod·ns·label로 물리적으로 분리돼 있지만 여전히 하나의 메시다. 그래서 격리는 다음 두 축이 둘 다 채워질 때만 성립한다 — 하나라도 비면 “분리된 척"에 그친다.

isolation = PHYSICAL  ×  LOGICAL
            (분리)        (가시성·적용대상)

  PHYSICAL axis                    LOGICAL axis
  +--------------------+           +---------------------------+
  | label (selector)   |           | exportTo  (누가 이 리소스를  |
  |   Gateway가 자기      |           |            볼 수 있나)      |
  |   pod만 잡음         |           | sourceLabels (어떤 client에 |
  | ns    (소유권 경계)   |           |            라우트가 붙나)    |
  | pod   (장애·SNAT 경계)|           +---------------------------+
  +--------------------+
        |                                   |
        v                                   v
  "딴 pod의 변경이                    "전역 리소스 하나가
   내 listener를 안 건드림"            모든 gateway를 못 얼리게"
  • PHYSICAL — 각 ns의 Gateway 리소스가 자기 label만 selector로 잡으므로 한쪽 변경이 다른 pod로 새지 않는다. ns는 소유권/RBAC 경계, pod는 장애·SNAT 경계. PILOT_SCOPE_GATEWAY_TO_NAMESPACE=true 환경에서도 Gateway 리소스와 workload가 같은 ns라 안전하다.
  • LOGICALexportTo: ["."]로 SE/VS의 가시성을 자기 ns에 닫아, 전역 push에 끼어 남의 config를 얼리지 않게 한다 (함정 ②). sourceLabels는 “어떤 client가 어느 gateway로 가나"를 명시한다(현재 랩은 host로 분기, §다음 작업 참고).

이 한 장면에서 나머지가 따라 나온다. 아래 토폴로지가 그 물리 축을 그림으로 보인 것이다 — 같은 client(sleep)가 두 외부 host를 호출하지만, host에 따라 다른 ns의 다른 gateway pod로 갈린다.

flowchart TB
  subgraph mesh["mesh-test ns — client sleep (injection ON)"]
    C1["curl https://example.org"]
    C2["curl https://www.wikipedia.org"]
  end

  subgraph pt["ns: egress-pt"]
    GPT["pod egw-pt (label istio=egw-pt)<br/>Gateway :443 → :8443<br/>tls PASSTHROUGH<br/>SNI route, no decrypt"]
  end
  subgraph mt["ns: egress-mtls"]
    GMT["pod egw-mtls (label istio=egw-mtls)<br/>Gateway :443 → :8443<br/>tls ISTIO_MUTUAL<br/>terminate OUTER mTLS (verify client cert/SPIFFE)<br/>tcp_proxy INNER app TLS"]
  end

  EX1["example.org:443"]
  EX2["www.wikipedia.org:443"]

  C1 -->|"tls/sniHosts route (sidecar no terminate)"| GPT
  C2 -->|"DR ISTIO_MUTUAL + sni (sidecar wraps mesh mTLS)"| GMT
  GPT --> EX1
  GMT --> EX2

왼쪽 경로는 gateway가 복호화하지 않는 passthrough, 오른쪽은 gateway가 outer mesh mTLS를 종단하고 inner 앱 TLS만 흘려보내는 패턴이다. inner 앱 TLS는 두 경로 모두 client↔external 간 end-to-end로 유지된다 — passthrough는 애초에 건드리지 않고, mTLS 경로는 outer mesh 레이어만 벗기고 inner는 tcp_proxy로 통과시키므로.

두 패턴의 본질 차이 (각 상세는 링크)

측면 PASSTHROUGH outer mTLS + inner TLS
in-mesh leg 평문 TCP(앱 TLS만) 메시 mTLS(SPIFFE 신원 검증)
gateway가 보는 것 SNI만 outer 종단 후 inner는 불투명 통과
L7 정책 불가 불가(inner 미복호)
호출자 식별 gateway단 불가(→ Calico 등) SPIFFE로 가능
상세 구조·실측 passthrough 가이드, 필드 매뉴얼 HTTPS over mTLS 구조, mTLS 테스트 리포트
패턴 선택 근거 이중 TLS 없이(decision)
운영(모니터링·SNAT·graceful) egress 운영 가이드 동일

두 패턴 모두 inner는 gateway가 못 보므로 L7 정책은 어느 쪽도 불가다. 차이는 in-mesh leg에 있다 — mTLS 경로만 SPIFFE 신원으로 호출자를 식별할 수 있고, passthrough는 gateway단에서 호출자를 못 가린다(Calico 등 외부 수단 필요).

3. 구성 따라하기 — 두 축을 어떻게 코드로 채우나

3-1. 물리 축: gateway 2개를 별도 ns·pod로

# (repo) scenarios/20-egress/dual-gateway/00-namespaces.yaml — egress-pt / egress-mtls (둘 다 injection ON)
kubectl apply -f scenarios/20-egress/dual-gateway/00-namespaces.yaml

# Helm gateway chart 2 release — label로만 구분(egw-pt / egw-mtls), 둘 다 ClusterIP
helm upgrade --install egw-pt   istio/gateway -n egress-pt   --version 1.30.0 -f install/helm/values-egw-pt.yaml   --wait
helm upgrade --install egw-mtls istio/gateway -n egress-mtls --version 1.30.0 -f install/helm/values-egw-mtls.yaml --wait

두 release의 차이는 label과 ns뿐이다 — 나머지(svc 포트, ClusterIP)는 의도적으로 동일하게 둬서 “차이 = 격리의 근거"가 label/ns 단 두 곳임을 드러낸다.

# egw-pt   svc 포트: 443 -> targetPort 8443   (PASSTHROUGH listener)
# egw-mtls svc 포트: 443 -> targetPort 8443   (ISTIO_MUTUAL listener)  <- egw-pt와 동일
#   둘 다 443으로 통일: 다른 pod·다른 ns라 충돌 없음. (한 pod에 두 모드를 얹을 때만 포트 분리 필요.)

→ 포트를 같이 443으로 둘 수 있는 이유 자체가 물리 격리의 증거다. 단일 pod였다면 두 모드가 같은 listener 포트를 다툴 테니 갈라야 했다. 별도 pod라 충돌이 원천적으로 없다.

3-2. 논리 축: 경로별 Istio 객체

passthrough (scenarios/20-egress/dual-gateway/10-passthrough.yaml): SE(example.org, protocol: TLS, exportTo: [".", "egress-pt"]) + Gateway(egress-pt, :443 PASSTHROUGH) + DR(subset만) + client-VS(mesh, tls) + gateway-VS(egress-pt, tls). gateway는 복호화 안 함.

mTLS (scenarios/20-egress/dual-gateway/20-mtls.yaml): SE(www.wikipedia.org) + Gateway(egress-mtls, :443 ISTIO_MUTUAL) + DR(portLevelSettings 443 ISTIO_MUTUAL + sni: www.wikipedia.org) + client-VS(mesh, tls → gw:443) + gateway-VS(egress-mtls, tcp :443 → wikipedia:443).

여기서 route 타입(tls vs tcp)이 왜 갈리는가가 이 랩의 가장 비자명한 지점이다. 규칙은 단순하다: gateway가 종단(decrypt)하면 SNI가 이미 소비돼 사라지므로 SNI 매칭(tls/sniHosts)을 더는 쓸 수 없다 → tcp route(포트 매칭)로 가야 한다. passthrough는 종단을 안 하니 SNI가 그대로 살아 있어 tls route로 라우팅한다. gateway-VS(2단)는 이 규칙과 직결되므로 정확한 필드 구조를 보인다 — ISTIO_MUTUAL 종단 listener는 tcp route다:

# (2) egress-mtls gateway -> external (inner 앱 TLS passthrough). ISTIO_MUTUAL listener는 tcp route.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata: { name: wiki-gateway, namespace: egress-mtls }
spec:
  exportTo: ["."]                 # 가시성을 egress-mtls ns로 닫음(함정 ② 방지) — LOGICAL 축
  hosts: [www.wikipedia.org]
  gateways: [egw-mtls-gateway]    # mesh가 아니라 egress-mtls gateway에만 적용
  tcp:                            # ← tls/sniHosts가 아님. outer mTLS가 이미 종단돼 SNI는 소비됨
    - match:
        - gateways: [egw-mtls-gateway]
          port: 443               # 포트 매칭만으로 충분 → inner 앱 TLS를 tcp_proxy로 그대로 흘림
      route:
        - destination: { host: www.wikipedia.org, port: { number: 443 } }
          weight: 100

전체 필드(client-VS의 tls.match.sniHosts, DR portLevelSettings.sni, Gateway ISTIO_MUTUAL 서버)는 HTTPS over mTLS 구조의 CRD 해부와 첨부 manifest를 참조.

스코핑은 전제 문서대로 client-VS / gateway-VS를 분리하고 각자 exportTo: ["."]로 닫았다 — 이게 위 멘탈모델의 LOGICAL 축을 코드로 채우는 부분이다.

4. 검증 (기대 vs 실제)

SLEEP=$(kubectl -n mesh-test get pod -l app=sleep -o jsonpath='{.items[0].metadata.name}')
# A) passthrough
kubectl -n mesh-test exec $SLEEP -c sleep -- curl -sS -o /dev/null -w "%{http_code} %{remote_ip}\n" https://example.org
#  -> 200 104.20.26.136     egw-pt access log: outbound|443||example.org (egw-pt pod :8443 경유)
# B) mTLS
kubectl -n mesh-test exec $SLEEP -c sleep -- curl -sS -o /dev/null -w "%{http_code} %{remote_ip}\n" https://www.wikipedia.org
#  -> 200 103.102.166.224   egw-mtls access log: outbound|443||www.wikipedia.org (egw-mtls pod :8443 경유)

cluster 이름 outbound|443||example.org(direction|port|subset|fqdn)이 각자의 gateway pod access log에 찍히는 게 경로가 실제로 갈렸다는 직접 증거다 — 둘 다 200이어도 같은 pod로 샜다면 격리가 깨진 것이다.

Envoy 증거 — listener/cluster 레벨에서 “종단 vs 미종단"을 못 박는다:

# egw-mtls 8443 listener = outer mTLS 강제됨
istioctl proxy-config listener deploy/egw-mtls.egress-mtls --port 8443 -o json | grep requireClientCertificate
#  "requireClientCertificate": true        ← client cert 요구 + ROOTCA 검증(SPIFFE)
# egw-pt 클러스터에 originate-TLS 없음 = 순수 passthrough
istioctl proxy-config cluster deploy/egw-pt.egress-pt --fqdn example.org -o json | grep -c transportSocket
#  0                                        ← TLS transport socket 없음
istioctl analyze -A                          # 충돌 0 (default-ns Info 무관)

합격 판정: 두 경로 모두 200 + 각자의 gateway pod 경유(access log) + egw-mtls는 outer mTLS 강제 (requireClientCertificate: true) + egw-pt는 미복호 passthrough(transportSocket 0개) + analyze 청정.

5. 실측 함정 2건 (검증 중 실제로 막힌 곳)

함정 ① 종단 listener에 tls route → 0 chains

mTLS gateway-VS(2단)를 처음에 tls/sniHosts로 작성했더니 egw-mtls의 listener가 아예 안 떴다. (당시 포트는 15443 — 이후 §3처럼 443→8443으로 통일했고, 아래 로그의 15443은 그 시점 값이다.) istiod 로그:

gateway egress-mtls/egw-mtls-gateway:15443 listener missed network filter
omitting listener "0.0.0.0_15443" due to: must have more than 0 chains

메커니즘: ISTIO_MUTUAL은 gateway가 outer mTLS를 종단하므로 그 시점에 SNI는 이미 소비됐다. 그런데 tls/ sniHosts route는 SNI로 filter chain을 매칭하려 한다 → 매칭할 SNI가 없어 유효 chain이 0개 → Envoy가 빈 listener를 거부(must have more than 0 chains). tlstcp(포트 매칭)로 바꾸자 listener가 SNI: www.wikipedia.org / Cluster: outbound|443||www.wikipedia.org로 떴다. 이것이 §3의 “종단하면 tcp” 규칙의 실증이다.

함정 ② exportTo 누락 SE가 mesh 전체 gateway를 NACK (당시 관찰 — 정정 있음, 아래 참고)

전역 export된 데모 SE(example-logicaldns, LOGICAL_DNS)가 multi-IP가 된 example.com 때문에 Envoy에서 거부됐고, 그 push에 실린 listener까지 모든 gateway에서 드롭되는 것으로 당시 관측했다(기존 egress gateway 포함). 즉 물리적으로 멀쩡히 분리된 두 gateway가 전역 리소스 하나에 동반 사망한 사건으로 기록했다 — 이게 §1·§2에서 말한 “물리 분리만으론 부족, LOGICAL 축이 필요"의 근거로 삼았던 사건이다. exportTo: ["."]로 가시성을 좁혀 해소했다. 메커니즘 상세는 스코핑 §5.

2026-07-05 정정

원 서술은 이 현상의 원인을 xDS의 트랜잭션성(한 push는 all-or-nothing) 이라고 설명했으나, Envoy 공식 xDS 프로토콜 문서는 “a NACK does not necessarily mean that none of the resources were accepted"라고 명시해 이 표현과 정확히 일치하지 않는다. 더 정합적인 설명은 exportTo 기본값이 전역 가시성이라, 무관한 gateway의 config 생성 로직에도 같은 깨진 리소스가 섞여 들어간다는 쪽이다(xDS 레벨의 전역 원자성이 아니라 istiod가 전역 노출된 SE를 모든 관련 proxy의 config snapshot에 포함시키는 로직 문제일 가능성이 큼).

또한 homelab에서 동일 시나리오(전역 노출 SE + 서로 무관한 두 물리적 분리 gateway)를 Istio 1.30.0으로 재현했을 때는(T03) egw-a/egw-b의 CDS configStatus가 계속 SYNCED로 유지됐고 istiod 로그에도 NACK·거부 흔적이 전혀 없어 — “물리 분리만으론 불충분, 전역 리소스 하나가 무관한 gateway까지 동반 파괴한다"는 blast-radius 현상 자체가 이 조건에서는 재현되지 않았다. 다만 원 사건은 LOGICAL_DNS SE가 실제 DNS 응답으로 multi-IP가 되며 깨진 경우였고, 재현은 DNS_ROUND_ROBIN + 고정 2-IP static endpoint로 근사한 것이라 완전히 같은 조건은 아니다. 즉 이 사건이 원천적으로 “일어날 수 없다"는 뜻이 아니라, 이 조건에서는 실증되지 않았고 “xDS 트랜잭션성"이라는 인과 설명은 부정확하다는 뜻으로 정정한다. 상세는 문서 끝 검증 기록(C1/C6) 참고.

핵심 정리

  • 멀티-gateway egress의 격리는 물리 축 × 논리 축의 곱이다: label 분리(selector) + ns 분리(소유권) + exportTo(가시성) + sourceLabels(적용대상). 한 축만으론 “분리된 척"에 그친다.
  • 종단 여부가 2단 route 타입을 결정한다: PASSTHROUGH=tls(SNI 살아있음), ISTIO_MUTUAL 종단 후=tcp(SNI 소비됨). 거꾸로 쓰면 0-chains로 listener가 안 뜬다(함정 ①).
  • 별도 ns·pod로 나누면 장애·정책·소스 IP가 tier별 격리되지만, 같은 메시인 이상 전역 리소스(exportTo 누락 SE)가 exportTo 기본값(전역 가시성) 때문에 무관한 gateway의 config 생성에도 섞여 들어갈 수 있다는 것이 §5 함정 ②의 원래 관측이었다 — 다만 2026-07-05 homelab 재현(T03)에서는 이 blast-radius 현상 자체가 재현되지 않았으므로, 실제 영향 범위는 조건(SE의 resolution 모드, 실패 양상 등)에 따라 달라질 수 있다는 점을 함께 기록해둔다.
  • 검증의 핵심 증거는 “200” 자체가 아니라 각자의 gateway pod access log에 찍힌 cluster 이름(경로가 실제 갈렸는지)
    • listener의 requireClientCertificate/transportSocket(종단/미종단)이다.

다음 작업

  • tier별 client를 sourceLabels로 각 gateway에 강제 매핑(현재는 host로 분기) → LOGICAL 축의 sourceLabels 절반을 채워 egress 거버넌스 강화.

What you might be missing

“별도 gateway pod"의 실익은 장애·정책·소스 IP의 격리다(한 tier의 graceful drain·SNAT 고갈·정책 변경이 다른 tier에 안 번짐). 그러나 격리는 배포만으로 완성되지 않는다 — 같은 메시 안에 사는 이상, 잘못된 전역 리소스(exportTo 누락 SE)가 exportTo 기본값(전역 가시성)으로 인해 무관한 gateway의 config 생성에도 섞여 들어갈 수 있다는 것이 이 문서 §5 함정 ②의 원래 교훈이다(단, 2026-07-05 homelab 재검증에서는 이 현상 자체가 재현되지 않았다 — 위 정정과 문서 끝 검증 기록 참고). 즉 멀티-gateway는 물리적 분리(pod/ns)와 논리적 스코핑 (exportTo/sourceLabels)을 함께 갖춰야 비로소 격리다. 한쪽만으로는 “분리된 것처럼 보이는” 상태에 그친다. 그리고 이 함정은 gateway를 늘릴수록 잠재적으로 더 위험해진다 — exportTo를 기본값(전역)으로 방치하면 무관한 gateway 개수만큼 노출 대상이 늘어나기 때문이다(다만 실제 xDS push 실패가 gateway 수에 비례해 함께 늘어나는지는 이번 재현에서 직접 확인되지 않았다). 그래서 멀티-gateway 환경일수록 exportTo 위생이 선택이 아니라 전제라는 결론 자체는 유효하다.

덧붙여, 두 패턴의 공존에는 pod 분리가 아닌 다른 축도 있다: mode는 Deployment 속성이 아니라 Gateway CR server(=리스너/포트) 속성이라, 같은 Deployment 하나에서 8443=ISTIO_MUTUAL, 9443=PASSTHROUGH로 포트 단위 공존이 가능하다. 클라이언트·인프라 무변경으로 목적지별 점진 전환이 되는 게 이 축의 실익이고, 장애·소스IP 격리가 필요하면 이 문서의 pod 분리 축을 택한다 — 프로덕션 채택 맥락은 도입 가이드 (사내 공유본) §3 참고.


관련 파일 · 참조

선행/전제: egress route 스코핑 · egress CRD 멘탈모델 · 패턴 상세: passthrough 가이드 · HTTPS over mTLS 구조 · mTLS 테스트 리포트


검증 기록 (2026-07-05 · Istio 1.30.0 / k8s 1.30.6)

검증 방법 요약: 공식 문서(istio.io/envoyproxy.io/GitHub 이슈) 대조 + homelab 클러스터 실측(T03 — 물리적으로 분리된 두 egress gateway + 전역 노출 ServiceEntry의 blast-radius 재현 시도, T07 — ISTIO_MUTUAL 종단 리스너의 tls/tcp route 전환 재현).

주장 판정 근거
C1. 멀티-gateway egress의 진짜 격리는 물리 축(label/ns/pod)과 논리 축(exportTo/sourceLabels)이 둘 다 채워져야 성립 ✅ 실측 확인 (기본 메커니즘) istio.io/…/sidecar/ · T03 실측 — 물리 분리된 두 gateway의 독립 동작 자체는 확인됨(blast-radius 세부 주장은 C6 참고)
C2. Gateway tls.mode: PASSTHROUGH는 SNI만으로 라우팅하며 페이로드를 복호화하지 않음 ✅ 문헌 확인 istio.io/latest/docs/reference/config/networking/gateway/
C3. ISTIO_MUTUAL은 outer mesh mTLS를 종단·client cert(SPIFFE) 검증 후 inner 앱 TLS는 tcp_proxy로 통과 ✅ 문헌 확인 istio.io/latest/docs/reference/config/networking/gateway/
C4. 종단 시 SNI 소비 → tcp route 필요, PASSTHROUGH는 SNI 생존 → tls route ✅ 실측 확인 istio.io/…/virtual-service/ · T07 실측
C5. 종단 listener에 tls/sniHosts route 사용 시 0 chains로 Envoy가 리스너 거부, “must have more than 0 chains” 로그 ✅ 문헌 확인 github.com/istio/istio/issues/17517 (재현은 C4의 T07로 커버)
C6. exportTo 누락 SE가 xDS “트랜잭션성(all-or-nothing)“으로 무관한 gateway까지 동반 파괴 🔬 실측 반증 — 본문 교정 envoyproxy.io/…/xds_protocol · T03 실측
C7. exportTo: ["."]로 가시성을 자기 ns로 닫으면 전역 push에 안 끼어듦 ✅ 문헌 확인 istio.io/…/sidecar/
C8. PILOT_SCOPE_GATEWAY_TO_NAMESPACE=true면 gateway workload가 같은 ns의 Gateway만 선택(기본값 false) ✅ 문헌 확인 pkg.go.dev/istio.io/istio/pilot/pkg/features
C9. TLS mode는 Deployment가 아닌 Gateway CR server(포트) 속성 — 한 Deployment 내 포트별 공존 가능 ✅ 문헌 확인 istio.io/latest/docs/reference/config/networking/gateway/
C10. requireClientCertificate: true는 client cert 요구 + root CA(SPIFFE) 검증을 의미 ✅ 문헌 확인 envoyproxy.io/…/tls.proto
C11. transportSocket 개수 0은 해당 클러스터에 TLS origination이 없다는(순수 passthrough) 증거 ✅ 문헌 확인 istio.io/…/egress-gateway-tls-origination/
C12. Envoy/Istio 클러스터 이름 포맷은 direction|port|subset|fqdn ✅ 문헌 확인 istio.io/latest/docs/ops/diagnostic-tools/proxy-cmd/
C13. PASSTHROUGH·outer mTLS+inner TLS 모두 gateway가 inner를 복호화 못 해 L7 정책 적용 불가 ✅ 문헌 확인 istio.io/…/egress-gateway/
C14. passthrough는 gateway단에서 호출자 identity 식별 불가, ISTIO_MUTUAL은 SPIFFE로 식별 가능 ✅ 문헌 확인 istio.io/latest/docs/concepts/security/
C15. DestinationRule portLevelSettings로 포트별 ClientTLSSettings 적용, 상위 설정을 오버라이드 ✅ 문헌 확인 istio.io/…/destination-rule/

Files