🏠 목록 Egress "HTTPS over mTLS" (ISTIO_MUTUAL) — 구조·CRD·장단점·활용·운영 📄 MD 원본 🌓 테마
istioegressmtlsistio-mutualspiffedouble-tlsgateway

Egress "HTTPS over mTLS" (ISTIO_MUTUAL) — 구조·CRD·장단점·활용·운영

NOTE

머릿속에 넣을 한 장의 그림: 이 패턴은 "end-to-end 암호화 보존"과 "egress에서 호출자 신원 식별"이라는 서로 독립인 두 축의 교집합 칸이다 — 둘 다 Yes일 때만 정답인 좁은 셀. 구현은 이중 TLS: 앱은 그대로 https://(inner end-to-end TLS)로 호출하고, sidecar↔egress 구간만 Istio 메시 mTLS(ISTIO_MUTUAL)로 한 겹 더 감싸(outer) gateway가 그 outer를 종단하며 호출 워크로드의 SPIFFE 신원을 암호학적으로 검증하되, 안쪽 앱 TLS는 풀지 않고 tcp_proxy로 외부까지 그대로 흘린다. passthrough(신원 없음)와 TLS origination(앱 평문화)의 사각지대를 메우는 패턴이며, 실측 검증은 Egress mTLS 리포트, 운영 정본은 Egress 운영, 개념 정본은 Egress Gateway 정본, 이 신원 위에 올라가는 통제(AuthorizationPolicy·테스트 매트릭스)는 Egress 신원 기반 통제 가이드 참조.

대상 환경: homelab (kubespray bare-metal, k8s v1.30.6, CNI Calico), Istio 1.30.0 검증 도메인: edition.cnn.com(외부 HTTPS) — 기존 httpbin.org passthrough를 control로 보존하고 직접 비교 전제 지식: sidecar/Gateway/VirtualService/DestinationRule 기본 + egress 2-leg 라우팅(정본 §04)


1. 배경 — 왜 이 패턴이 존재하나 (passthrough와 origination 사이의 빈칸)

egress gateway로 외부 HTTPS를 내보내는 방식은, 단 두 개의 독립된 질문으로 완전히 좌표가 잡힌다. 이 두 질문이 이 문서 전체의 출발점이다.

  1. gateway가 앱 payload를 복호화해도 되는가? (= end-to-end 암호화를 포기할 수 있나)
  2. egress에서 "누가 나가는지"를 식별해야 하는가? (= 호출 워크로드 신원이 필요한가)

표준 egress 패턴 두 개는 이 좌표의 대각선 두 칸만 채운다.

여기서 빈 칸이 하나 남는다: "payload는 절대 못 보게 하면서(end-to-end) + 그래도 누가 나가는지는 알아야 한다." passthrough는 신원이 없어서, origination은 복호화를 해서 둘 다 이 칸을 못 채운다. 그 빈 칸을 메우려고 등장한 게 바로 이 "HTTPS over mTLS" 패턴이다. 이 한 문장이 이 패턴이 존재하는 유일한 이유이고, 이후 모든 설계 결정(이중 TLS, ISTIO_MUTUAL, leg-2가 tcp인 것)은 전부 이 칸을 채우기 위한 귀결이다.

            end-to-end 암호화 보존?
                  Yes              No
              +----------------+----------------+
   egress  No | PASSTHROUGH     | (의미 없음)     |
   신원        | 가장 흔함        |                |
   식별?      +----------------+----------------+
          Yes | HTTPS over mTLS | TLS origination|
              | <-- 본 문서      | gw L7+cert중앙  |
              +----------------+----------------+
Q1. gateway가 앱 payload를 복호화해도 되는가? 됨 (gw L7 정책/감사) 안 됨 (end-to-end 유지) TLS origination 앱 평문 HTTP, gw가 새 TLS 시작 L7 가시·인증서 중앙관리 Q2. egress에서 호출 워크로드 신원을 식별해야 하는가? 필요 없음 필요함 (SPIFFE) PASSTHROUGH 단일 TLS, SNI 라우팅 가장 흔함 HTTPS over mTLS (ISTIO_MUTUAL) 이중 TLS — end-to-end + 신원 본 문서
그림 1. egress 패턴 선택 결정 트리 — payload 복호화 허용/egress 신원 필요 두 축으로 세 패턴이 갈린다(본 문서는 HTTPS over mTLS).

세 패턴을 한 표로 정렬하면 "무엇을 누가 푸느냐"가 한눈에 보인다.

                    gateway가 앱 TLS를     in-mesh leg(sidecar->gw)가     gateway가 본
  패턴              복호화하는가           암호+신원검증인가              L7(method/path/status)
  ---------------   -------------------   --------------------------    ---------------------
  PASSTHROUGH       No (SNI만 봄)          No (평문 TCP, 앱 TLS만)        No (L4 only)
  HTTPS over mTLS   No (이중 TLS)          Yes (메시 mTLS 종단+SPIFFE)    No (L4 only)   <-- 본 문서
  TLS origination   Yes (gw가 종단)        선택(메시 mTLS는 별개)         Yes (L7 visible)

여기서 이 패턴이 niche인 이유까지 미리 못 박아두자 — 뒤의 모든 설계 함정을 받아들이는 마음가짐이 된다. 본 패턴은 위 좌표의 한 칸일 뿐이고, 그 칸에 드는 시나리오 자체가 드물다. 대부분의 "단순 외부 HTTPS"는 passthrough로 충분하고(신원 불필요·cert 관리 없음·4객체 중 최단순), 신원·정책이 필요한 조직은 보통 origination을 택한다(egress gateway를 두는 주된 이유인 L7 감사/per-URL 정책/중앙 cert를 다 주므로). 본 패턴은 payload는 절대 노출 불가 + 신원은 필요라는 교집합에서만 최적이고, 결정타로 이 패턴을 써도 L7 egress 정책은 여전히 불가하다(이중 TLS라 gateway가 L7을 못 봄). 추가 복잡성으로 얻는 건 오직 "신원" 하나뿐이라, 많은 조직은 그 신원을 source IP / NetworkPolicy / namespace로 더 싸게 근사한다.

드문 건 구조가 나빠서가 아니라, 그 효익(end-to-end + 신원)을 동시에 요구하는 시나리오가 드물어서다. 그 시나리오에 정확히 들면 이건 유일하게 맞는 패턴이다(구체 사례는 §5).


2. 아키텍처 — 이중 TLS의 데이터 경로 (앵커: "outer는 풀고, inner는 흘린다")

이 패턴 전체를 한 문장으로 압축하면 이렇다: gateway는 바깥 봉투(outer mesh mTLS)만 열어 "누가 보냈는지"를 확인하고, 안쪽 편지(inner 앱 TLS)는 봉인된 채로 외부까지 그대로 부친다. 이 한 그림에서 나머지가 전부 따라 나온다 — outer를 종단하니까 신원을 볼 수 있고, inner를 못 푸니까 L7도 못 보고, 종단된 listener에선 SNI가 이미 소비됐으니까 leg-2가 tcp여야 한다.

  sleep(app)              sleep sidecar               egress-gw (:15443)            edition.cnn.com:443
  ----------              -------------               ------------------            -------------------
  curl https://  ──(A)──> [생성한 앱 TLS를            ───(terminate outer)───>     [inner 앱 TLS를
  (inner TLS 생성)         outer mesh mTLS로 래핑]      verify client SPIFFE          서버가 종단]
                          ── outer: ISTIO_MUTUAL ──>   re-emit inner via tcp_proxy
                          \________ inner: app TLS (end-to-end, gw가 못 봄) ________/

  outer (sidecar<->gw) : Istio 메시 mTLS. gw가 client cert 강제 + mesh CA로 SPIFFE 검증 후 *종단*.
  inner (app<->cnn)    : 앱 HTTPS. gw는 복호화 안 함 — 종단 직후 tcp_proxy로 opaque bytes 그대로 전달.

봉투가 어떻게 열리고 닫히는지 단계별로 — 각 단계가 위 앵커의 어느 부분인지 의식하며 읽으면 된다.

  1. (A) 앱 — inner 봉인: curl https://edition.cnn.com/. 앱이 직접 TLS handshake를 시작한다(inner TLS). 이 시점의 ciphertext는 끝까지 누구도 풀지 않는다 — 이게 "end-to-end 보존"의 물리적 실체다.
  2. sidecar (leg-1, outer 봉투 생성): VirtualService leg-1이 이 트래픽을 egress gateway로 라우팅하고, DestinationRule이 그 leg를 메시 mTLS(ISTIO_MUTUAL)로 래핑한다. sidecar는 자기 SPIFFE client cert를 제시하며 outer TLS를 만든다. outer의 SNI는 DR이 지정한 edition.cnn.com — 이게 gateway가 filter chain을 고르는 키.
  3. egress gateway (outer 봉투 개봉 + 신원 확정): :15443 listener가 tls.mode: ISTIO_MUTUALclient cert를 강제(requireClientCertificate: true) 하고 mesh CA(validationContext)로 sidecar의 SPIFFE ID를 검증한 뒤 outer mTLS를 종단한다. 여기서 "누가 나가는가"가 암호학적으로 확정된다 — 이게 이 패턴이 passthrough 대비 유일하게 더 얻는 것.
  4. egress gateway (leg-2, inner 봉인 그대로 발송): outer를 벗기고 나면 손에 남는 건 앱의 inner TLS ciphertext다. gateway는 이걸 풀 수 없고(앱↔cnn end-to-end), VirtualService leg-2의 tcp 라우트(tcp_proxy) 가 이 opaque 바이트를 outbound|443||edition.cnn.com으로 그대로 흘린다.
  5. 외부 — inner 봉인 개봉: edition.cnn.com:443가 inner TLS를 종단. 앱이 본 ssl_verify=0앱↔cnn end-to-end 검증 결과 — gateway가 inner에 전혀 관여하지 않았음의 증거다.

왜 leg-2는 tls가 아니라 tcp인가 (앵커에서 직접 따라 나오는, 이 패턴의 가장 큰 함정) outer를 종단하면 SNI는 그 자리에서 소비된다 — 더는 라우팅 키로 남아 있지 않다. 그런데 종단된 listener에 tls/sniHosts 라우트를 걸면 Envoy는 매칭할 SNI가 없어 network filter를 생성하지 못하고, listener가 통째로 누락된다(must have more than 0 chains로 omit). 종단 후 남은 inner 바이트를 흘리려면 SNI를 다시 보지 않는 L4 tcp_proxy가 필요 → leg-2는 반드시 tcp 라우트. passthrough는 종단을 안 하므로 SNI가 끝까지 살아 있어 양쪽 leg 모두 tls/sniHosts — 정반대다. (filter chain 생성 원리: Envoy filter chain)

2.1 CRD 4종 — 각 객체가 "봉투 메커니즘의 어느 부분"을 책임지나

scenarios/20-egress/*-cnn-mtls.yaml. 4개 객체는 위 데이터 경로의 서로 다른 부분을 맡는다. PASSTHROUGH 대비 무엇이 달라지는지(델타)만 좁혀 본다 — 차이가 곧 이 패턴의 본질이다.

CRD 답하는 질문 (봉투 경로의 역할) passthrough 대비 델타
ServiceEntry "이 외부 호스트를 메시가 알아도 되나?" 차이 없음 (외부 등록은 패턴 무관)
Gateway "egress pod가 outer를 어떻게 받나?" tls.mode: PASSTHROUGHISTIO_MUTUAL, 포트 443 → 15443
DestinationRule "sidecar가 outer를 어떻게 만드나?" trafficPolicy.tls 신규(passthrough는 subset만)
VirtualService "각 leg를 어떻게 라우팅하나?" leg-2가 tls/sniHosts → tcp

ServiceEntry — 외부 호스트 등록 (passthrough와 동일)

apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata: { name: cnn-ext, namespace: mesh-test }
spec:
  hosts: [edition.cnn.com]
  ports:
    - number: 443
      name: tls
      protocol: TLS          # HTTPS 아님 — gateway가 L7을 파싱하지 않으므로 L4 TLS로 등록
  resolution: DNS            # istiod가 DNS로 실제 IP 해석
  location: MESH_EXTERNAL

protocol: TLS인 이유가 곧 앵커의 따름정리다 — 이 패턴에서 gateway는 앱 TLS를 끝까지 안 푸므로 L7 HTTP가 아니라 L4 TLS. origination이었다면 여기가 HTTP(앱이 평문)였을 것이다. 외부 등록 자체는 패턴 무관이라 passthrough와 동일하다.

Gateway — egress pod에 ISTIO_MUTUAL server (★ outer 봉투를 여는 곳)

apiVersion: networking.istio.io/v1
kind: Gateway
metadata: { name: egress-cnn, namespace: mesh-test }
spec:
  selector: { istio: egressgateway }   # egress pod 라벨과 일치
  servers:
    - port:
        number: 15443                  # ★ 443 아님 — passthrough(443)와 머지 충돌 회피
        name: tls-cnn
        protocol: TLS
      hosts: [edition.cnn.com]
      tls:
        mode: ISTIO_MUTUAL             # ★ PASSTHROUGH가 아니라 메시 mTLS를 *종단*+신원검증

DestinationRule — leg-1을 메시 mTLS로 래핑 (★ sidecar가 outer 봉투를 만드는 트리거)

apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata: { name: egressgateway-cnn, namespace: mesh-test }
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
    - name: cnn
      trafficPolicy:
        loadBalancer: { simple: ROUND_ROBIN }
        portLevelSettings:
          - port: { number: 15443 }
            tls:
              mode: ISTIO_MUTUAL         # ★ sidecar가 client cert 제시 + outer mTLS 생성
              sni: edition.cnn.com       # ★ gateway가 filter chain 고르는 키

VirtualService — 2-leg, leg별 라우트 타입이 다름 (★ tcp vs tls)

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata: { name: egress-cnn, namespace: mesh-test }
spec:
  hosts: [edition.cnn.com]
  gateways: [mesh, egress-cnn]          # mesh=sidecar(leg-1), egress-cnn=gateway(leg-2)
  tls:                                  # leg-1: sidecar -> egress gw (종단 안 함 -> tls/sniHosts)
    - match:
        - gateways: [mesh]
          port: 443
          sniHosts: [edition.cnn.com]
      route:
        - destination:
            host: istio-egressgateway.istio-system.svc.cluster.local
            subset: cnn                 # DR subset cnn = 메시 mTLS 래핑
            port: { number: 15443 }
  tcp:                                  # ★ leg-2: gw -> 외부 (gw가 종단함 -> tcp 필수)
    - match:
        - gateways: [egress-cnn]
          port: 15443
      route:
        - destination:
            host: edition.cnn.com
            port: { number: 443 }
          weight: 100

정렬 지도 — 같은 magic string이 4객체에 흩어진다. 이 값들이 한 글자라도 어긋나면 filter chain 매칭이나 SAN 검증이 깨진다.

  SNI host   :  DR tls.sni        == Gateway hosts[]   == VS sniHosts[]     (모두 edition.cnn.com)
  종단 포트   :  DR port 15443     == Gateway port      == VS leg-1 dest port == VS leg-2 match port
  gateway ref:  Gateway name egress-cnn == VS gateways[]에 등장
  egress 대상:  DR host(egressgateway FQDN) == VS leg-1 dest host

CRD 관계 한눈에

DestinationRule egressgateway-cnn subset cnn: ISTIO_MUTUAL + sni VirtualService egress-cnn leg-1 tls / leg-2 tcp Gateway egress-cnn :15443 ISTIO_MUTUAL (종단+SPIFFE) ServiceEntry cnn-ext edition.cnn.com:443 TLS leg-1 outer mTLS 래핑·sni GW (leg-1 tls) --> leg-1 tls: mesh -> gw:15443 SE (leg-2 tcp, up) --> leg-2 tcp: gw -> cnn:443 registry whitelist (호스트 등록)
그림 2. CRD 4종 관계 — DR이 leg-1을 mTLS로 래핑하고, VS leg-1(tls)이 Gateway로, leg-2(tcp)가 외부로 흐른다. SE는 외부 호스트를 registry에 등록.

3. 예시와 결과 — 실측으로 봉투 메커니즘 입증

위 4객체를 mesh-test 네임스페이스에 apply한 뒤, 앵커의 세 주장("outer를 종단하며 신원을 본다 / inner는 풀지 않는다 / 그래서 200")을 각각 한 줄씩으로 검증한다. (전체 실측: Egress mTLS 리포트)

TEST 1 — end-to-end로 통하는가 + gateway가 inner를 안 건드렸나

kubectl exec -n mesh-test deploy/sleep -c sleep -- \
  curl -sS -o /dev/null -w "HTTP=%{http_code} ssl_verify=%{ssl_verify_result} remote=%{remote_ip}:%{remote_port}\n" \
  https://edition.cnn.com/
# 실제: HTTP=200  ssl_verify=0  remote=151.101.195.5:443   ← 앱 TLS end-to-end 검증 OK

ssl_verify=0이 결정적이다 — 이건 앱↔cnn 사이의 cert 검증이 통과했다는 뜻이고, gateway가 inner에 끼어들었다면 SAN이 어긋나 0이 안 나온다. 즉 inner 봉인이 외부까지 온전했다는 증거다.

TEST 2 — gateway가 inner를 풀지 않고 tcp_proxy로 흘렸나 (egress-gw access log)

[11:14:34] 0 - - ... 2422 4731478 435 ... "151.101.3.5:443" outbound|443||edition.cnn.com

response flag가 -(성공, NR filter_chain_not_found 없음)이고, 4.7MB(4731478 bytes) 가 흘러갔다 — cnn 페이지 본문이 tcp_proxy로 opaque하게 통과했다는 뜻. cluster 이름 outbound|443||edition.cnn.com이 leg-2의 목적지(direction|port|subset|fqdn, subset 없음).

TEST 3 — in-mesh leg가 진짜 메시 mTLS인가 (egress-gw :15443 listener)

istioctl proxy-config listener deploy/istio-egressgateway.istio-system --port 15443 -o json \
  | grep -E 'sni|requireClientCertificate|validationContext|secretName'
# requireClientCertificate : True   ← client cert 강제(메시 mTLS)
# validationContext        : True   ← mesh CA로 SPIFFE 검증

requireClientCertificate: True + validationContext: True = "client cert를 강제하고 mesh CA로 검증한다" = 앵커의 '신원을 본다'가 설정 레벨에서 참. 이 두 필드가 곧 데이터 경로 3단계의 물증이다.

TEST 4 — sidecar leg-1이 outer mTLS를 래핑하고 sni를 넣었나 (sleep cluster)

istioctl proxy-config cluster deploy/sleep.mesh-test \
  --fqdn istio-egressgateway.istio-system.svc.cluster.local -o json | grep -E 'sni|mode|subset'
# cluster outbound|15443|cnn|...egressgateway 에 tls(mode ISTIO_MUTUAL, sni edition.cnn.com)

cluster 이름 outbound|15443|cnn|...egressgateway의 subset cnn이 DR의 subset과 일치하고, 거기 tls 컨텍스트가 붙어 있다 = sidecar가 데이터 경로 2단계대로 outer를 만든다는 증거.

검증 요약선: HTTP=200 + ssl_verify=0(inner end-to-end) + requireClientCertificate=True(신원 강제) + validationContext=True(SPIFFE 검증) + access log response flag -(종단·전달 성공). 다섯 신호가 동시에 참이면 이중 TLS가 의도대로 동작한 것이다. 기존 httpbin passthrough(control)는 무손상(간헐 200, 503/timeout은 외부 flakiness + outlier DR).

실측은 처음 manifest 그대로는 실패했다 — 두 함정을 실제로 밟았다. ① 포트 443을 httpbin passthrough가 선점한 상태로 cnn ISTIO_MUTUAL server를 같은 443에 두니 머지 충돌로 cnn 서버가 드롭(curl: Connection reset, egw log NR filter_chain_not_found) → 15443 분리로 FIX. ② leg-2에 tls/sniHosts를 걸자 종단 listener에 network filter가 0개라 istiod가 omitting listener ... must have more than 0 chains로 통째 omit → tcp로 FIX. (리포트 §3)

3.1 장점 / 단점 — 위 실측이 곧 근거

이 패턴을 채택했을 때 실제로 얻는 것과 치르는 비용. 각 항목의 "메커니즘적 근거"는 위 데이터 경로/실측에서 곧장 나온다.

장점

장점 메커니즘적 근거
egress에서 호출자 SPIFFE 신원 식별 gateway가 outer mTLS를 종단하며 client cert를 mesh CA로 검증(TEST 3). IP/namespace가 아닌 암호학적 워크로드 신원.
신원 기반 egress 인가 가능 그 신원으로 AuthorizationPolicy(principals=cluster.local/ns/.../sa/...)를 gateway에 걸어 "특정 SA만 이 외부로" 강제. (authz 멘탈모델)
end-to-end 앱 암호화 보존 gateway는 inner 앱 TLS를 복호화하지 않음(blind relay, TEST 1의 ssl_verify=0). payload가 gateway 메모리에 평문으로 없음 → PCI/PII 경계에서 gateway를 복호화 주체에서 제외.
mesh mTLS가 PERMISSIVE여도 leg-1 강제 암호화 DR/Gateway의 명시적 ISTIO_MUTUAL이 mesh-wide 설정과 무관하게 in-mesh leg를 암호화+인증.
외부 인증서 관리 불필요 origination/MUTUAL-to-external과 달리 gateway가 외부용 cert를 보관·갱신할 필요 없음(앱이 알아서 TLS).

단점

단점 메커니즘적 근거
L7 사각은 그대로 이중 TLS라 gateway는 여전히 method/path/status를 못 봄(inner 미복호화) → per-URL egress 정책 불가, 관측은 istio_tcp_*(L4)뿐. egress gateway를 흔히 쓰는 이유(L7 감사/정책)를 못 얻는다.
이중 TLS 비용 handshake 2회(sidecar↔gw mesh mTLS + 앱↔외부) + 홉 1개 추가 → 지연·CPU 증가.
설정 복잡성·함정 포트 머지 충돌(passthrough vs 종단), leg-2 tcp/tls 혼동, DR sni↔Gateway hosts↔VS sniHosts 3자 정렬. 실측에서 2개 함정을 실제로 밟음(§3 위).
Istio 단독으로는 강제 아님 sidecar 우회(root/hostNetwork) 시 그냥 나감. 진짜 강제하려면 Calico NetworkPolicy로 egress pod 외 직접 송신 차단 필요.
드물게 쓰임 → 자료·예제 적음 커뮤니티 레퍼런스가 passthrough/origination 대비 희소 → 트러블슈팅이 self-support.

4. 활용 사례 — 이 패턴이 "유일하게 맞는" 경우 (조사)

§1에서 "교집합이 드물다"고 했다. 그 드문 교집합에 정확히 드는 구체 시나리오 — 여기선 다른 두 패턴이 둘 다 탈락한다. (웹 자료: Istio 공식·Tetrate·실무 가이드, §7)

  1. 규제·컴플라이언스 — "복호화 없는 감사" PCI-DSS/개인정보처럼 gateway가 payload를 복호화하면 안 되는 데이터를 외부 파트너로 보내면서도, "모든 외부 호출이 알려진 암호화 chokepoint를 지났고 + 어떤 워크로드(SA)가 호출했는지 감사 로그로 입증"해야 할 때. origination은 gateway가 복호화하므로 탈락, passthrough는 신원이 없어 탈락 → 이 패턴만 둘 다 만족.

  2. 워크로드 단위 egress allow-list (인가) "오직 sa/paymentpartner-bank.example.com으로 나갈 수 있다"를 spoof 가능한 IP가 아니라 SPIFFE principal로 강제. gateway에 AuthorizationPolicy(principals)를 걸어 구현. (authz, SPIFFE)

  3. 멀티테넌트 클러스터에서 IP/namespace로는 신원이 불충분할 때 여러 팀이 한 클러스터를 공유하고 egress 권한을 팀(SA)별로 갈라야 하는데 namespace 라벨/IP가 신뢰 경계로 약할 때, mesh CA가 보증하는 SPIFFE가 더 강한 식별자.

  4. 외부가 HTTPS-only / cert-pinning이라 종단이 불가능한데도 신원이 필요할 때 외부 서버가 앱과의 end-to-end TLS(예: client cert pinning)를 요구해 gateway가 끼어들 수 없는데도 egress 신원 통제가 필요한 경계 사례.

거꾸로, L7 per-URL egress 정책이 목표라면 이 패턴은 틀린 선택이다(L7 사각). 그 경우 origination.


5. 운영 시 고려할 점 (의견)

전제: 채택 자체를 신중히 — "end-to-end 보존 + egress 신원"이 동시에 진짜 요구사항일 때만. 아니면 passthrough(단순) 또는 origination(L7).


핵심 정리


6. What you might be missing


7. 참조

아카이브 내부 - Egress mTLS 리포트 — 실측 · Egress Gateway 개념 정본 · Egress 운영 정본 - HTTP vs HTTPS egress · HTTPS passthrough 가이드 - SPIFFE 신원 · AuthorizationPolicy 멘탈모델 · 보안 3리소스 - Envoy filter chain · sidecar scope

관련 IaC (실제 manifest) - 📎 gateway-egress-cnn-mtls.yaml · 📎 destinationrule-egress-cnn-mtls.yaml - 📎 virtualservice-egress-cnn-mtls.yaml · 📎 serviceentry-cnn-ext.yaml · 📎 20-egress/README.md

외부 (조사 출처) - ↗ Istio: Understanding TLS Configuration - ↗ Istio: Egress Gateways with TLS Origination - ↗ Tetrate: Enforce egress traffic using Istio's authorization policies - ↗ Istio: Security Best Practices

반대 선택의 근거이중 TLS 없이 egress 신원 — passthrough + Calico