# [작업 B: connection-churn 강제용] DestinationRule = 43(TLS origination) + maxRequestsPerConnection:1. # # 왜 새 파일이 필요한가 (경험적으로 확인된 사실, 가정 아님): # fortio `-keepalive=false`(또는 netshoot curl 반복 호출)는 **client(downstream) 쪽** 소켓만 # 요청마다 새로 연다 — 실측: 80 req 에 fortio "Sockets used: 82"로 downstream 은 매번 갱신됨. # 그런데 같은 런에서 netshoot 사이드카의 `upstream_cx_total` 델타는 8→12(+4)에 불과했다 # (전 요청 80건 중 4건만 신규 upstream 연결). 즉 **Envoy 는 downstream 연결이 몇 번 여닫히든 # upstream(Envoy→backend) 커넥션 풀은 독립적으로 재사용한다** — 2026-07-01 mode2가 유실을 # 못 만든 이유(§6)도 바로 이 upstream 재사용이다. client 쪽 설정만으로는 upstream 을 churn 시킬 수 없다. # # 해결: connectionPool.http.maxRequestsPerConnection=1 로 **Envoy 자신이** 요청 1건마다 # upstream 연결을 닫고 새로 연다 — 이게 실제로 매 요청 LB 재선택(round-robin over cluster # members)을 강제하는 유일한 지점이다. dead-IP 가 host 목록에 남아있으면 매 요청마다 그걸 # 뽑을 기회가 생긴다 = 유실 재현 가능. # # ⚠ 실측 함정 (그대로 기록): 처음엔 이 필드를 trafficPolicy **top-level**에 뒀다가 실패했다 — # config_dump로 확인하니 portLevelSettings가 존재하는 포트(443)는 top-level connectionPool을 # 전혀 상속하지 않고(포트 80처럼 portLevelSettings가 없는 포트에만 top-level이 적용됨), 결과적으로 # 443 cluster에 typed_extension_protocol_options 자체가 안 생겼다(cx_total 델타가 여전히 4/82라 # churn 미적용이 그대로 드러남). **portLevelSettings\[port:443\] 블록 "안"에 connectionPool.http를 # 같이 둬야** 이 포트에 실제로 반영된다 — 아래가 그 수정본. # # 43 과 이름을 다르게 둔 이유: 43/44 는 다른 기존 리포트(mode1/mode3/inflight)가 참조하는 # "churn 없는 순정 DNS resolution 베이스라인"이므로 의미를 보존한다. 이 파일은 이번 실험 # 전용이며, 실험 종료 후 43 을 재적용해 원복한다(§ 종료 상태). # # connectTimeout:1s 도 같이 둔 이유: dead ClusterIP(엔드포인트 0개인 Service) 로의 connect는 # RST 없이 그냥 행 걸린다(kube-proxy가 매치 룰이 없어 packet을 그냥 드롭) — 기본 connect_timeout # 10s를 그대로 두면 curl -m 2 가 먼저 클라이언트 타임아웃으로 끊어버려 Envoy 쪽 connect_fail # 집계 시점과 클라이언트 관측 시점이 어긋난다. 44(outlier)가 이미 같은 이유로 1s를 썼던 것과 # 동일 근거 — outlier 유무와 무관하게 "실패를 빨리 판정"은 베이스라인에도 필요하다. apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: gslb-tls-origination # 43/44 와 같은 이름 — apply 로 교체(스왑) namespace: dns-lab spec: exportTo: ["."] host: gslb.lab.internal trafficPolicy: portLevelSettings: - port: { number: 443 } connectionPool: tcp: { connectTimeout: 1s } # dead ClusterIP connect hang 방지(44와 동일 근거) http: maxRequestsPerConnection: 1 # 매 요청마다 upstream 연결 폐기+재생성 = churn 강제 tls: mode: SIMPLE sni: gslb.lab.internal insecureSkipVerify: true