--- title: GSLB 절체(DNS 변경) 때 실제로 벌어지는 일 — 계획·장애 절체 운영 가이드 date: 2026-07-10 type: guide domain: istio tags: [istio, egress, dns, gslb, failover, outlier-detection, operations] --- > [!abstract] > 자매 문서 [egress ServiceEntry resolution은 DNS(STRICT)로 쓴다](/docs/istio/egress/se-strict-dns-adoption/)가 > "무엇을 표준으로, 왜 쓰는가"를 다뤘다면, 이 문서는 **절체(GSLB가 도메인의 A레코드를 다른 > VIP로 바꾸는 일)가 실제로 일어난 순간 트래픽에 무슨 일이 벌어지는가**를 다룬다. 결론 세 줄: > **① 계획 절체(옛 VIP가 살아있는 배수)는 무손실이 가능하다** — 단, 옛 VIP가 조용해지는 > 시간은 Istio가 아니라 앱의 커넥션 수명이 결정한다. > **② 장애 절체(VIP 사망)는 유손실 구간이 구조적으로 존재한다** — 단일 A레코드 구조에서 그 > 길이를 정하는 것은 Envoy가 아니라 GSLB의 감지 속도와 TTL이다. > **③ outlier detection은 DNS를 다시 묻는 장치가 아니다** — 목록에 살아있는 대안이 있을 때만 > 작동한다. > [!note] > **근거 등급** — 이 문서의 모든 주장에는 근거 등급을 붙였다: **[실측]** = 홈랩 재현 랩에서 > 직접 측정(원시 리포트 공개), **[공식 문서]** = Envoy 공식 문서 원문 인용, **[논리 귀결]** = > 앞의 두 사실로부터의 직접 도출. 이 세 등급에 들지 못하는 추정성 서술은 싣지 않았다. ## 1. 전제 - 환경은 **mTLS passthrough** — 앱이 직접 HTTPS를 맺고, egress gateway는 TLS를 열어보지 않고 나른다(L4). **Envoy가 HTTP 요청 단위로 개입하는 기능(요청 재시도 등)은 이 경로에 없다.** 환경 상세와 `resolution: DNS`(STRICT) 채택 근거는 자매 문서 1·3절 참조. - **절체** = GSLB가 도메인의 A레코드(도메인→IP 매핑)를 다른 VIP로 바꾸는 일. 계획된 점검 배수일 수도, 장애 대응일 수도 있다. - "절체 순간 기존 세션이 끊긴다"는 걱정은 기우로 확인됐다(자매 문서 2절, 공식 문서+실측). 이 문서는 그 다음 이야기 — **안 끊기는 것과 별개로, 절체의 이유에 따라 완전히 다른 두 상황이 된다.** ## 2. 계획 절체 (점검 배수 — 옛 VIP가 살아있는 상태) → 무손실 가능 ```mermaid sequenceDiagram participant APP as app participant E as egress Envoy (L4) participant A as VIP-A (계속 살아있음) participant B as VIP-B participant G as GSLB DNS Note over G: 절체 - A레코드를 VIP-A에서 VIP-B로 변경 G-->>E: TTL 주기 갱신 - IP 목록 = [B] Note over APP,A: 1) 진행 중이던 요청 - 그대로 완료 (실측) APP->>E: keepalive로 쥔 기존 연결의 다음 요청 E->>A: 2) 같은 연결 그대로 - 여전히 VIP-A로 (실측) APP->>E: 새 연결 E->>B: 3) 새 연결부터 VIP-B로 (실측) Note over A: 옛 VIP가 조용해지는 시점 =
앱 커넥션 수명이 다한 뒤 ``` 무손실이다. 갈래 2)(keepalive 연결이 계속 옛 VIP로 가는 것)까지 실측으로 확정했다 **[실측, 2런 동일]** — 하나의 TLS 연결을 유지한 채 순차 요청을 보내며 중간에 절체: | 요청 | 연결 | 실제 접속지 | 응답 서버 | |---|---|---|---| | 1번 (절체 전) | 새 연결 | pod-A | backend-a | | 2번 (절체 반영 확인 후, **같은 연결**) | 재사용 (로컬 포트 동일) | **pod-A 그대로** | backend-a | | 3번 (같은 연결) | 재사용 | pod-A 그대로 | backend-a | | 4번 (연결 닫고 새로 맺음) | 새 연결 | **pod-B** | backend-b | 연결 재사용은 Envoy 카운터로 교차 증명했다 — 요청 4개에 연결 생성 카운터는 정확히 2번만 증가(1번·4번 시점). 원시 리포트: [keepalive-pin](/docs/istio/egress/gslb-flip-inflight-qa/files/raw/2026-07-09_204354_dns-passthrough-keepalive-pin.md). 따라서 **"옛 VIP가 조용해지는 시간"은 Istio가 아니라 앱의 커넥션 수명이 결정한다** — L4에서는 요청이 끝나도 Envoy가 연결을 회수하지 않으므로. 절체 runbook에 필요한 것: 1. 절체 후 **옛 VIP를 앱 커넥션 최대 수명만큼 살려둘 것** (바로 내리면 아래 장애 절체가 됨) 2. 앱 커넥션 풀의 **max lifetime 상한 합의** (절체 완료 목표 시간보다 짧게) 3. 배수 완료 판단은 DNS가 아니라 **옛 VIP의 연결 수 모니터링**으로 ## 3. 장애 절체 (VIP 사망 → GSLB가 감지 후 변경) → 유손실 구간이 구조적으로 존재 ```mermaid sequenceDiagram participant APP as app participant E as egress Envoy (L4) participant A as VIP-A (사망) participant B as VIP-B participant G as GSLB DNS Note over A: t=0 - VIP-A 사망 APP->>E: 요청 (진행 중 + 신규) E-xA: 연결/요청 실패 - 실패가 앱까지 전달 Note over APP,G: 유손실 구간 W - 목록엔 죽은 VIP-A뿐
W(단일 A레코드) = GSLB 감지 + TTL + Envoy 갱신
W(복수 A레코드로 바꾸면) = outlier 격리 - 수 초 Note over G: GSLB가 장애 감지 - A레코드를 VIP-B로 변경 G-->>E: TTL 주기 갱신 - IP 목록 = [B] APP->>E: 이후 새 연결 E->>B: 정상 ``` 주의: "세션 안 끊김" 확인은 **IP 변경 때문에는 안 끊긴다**는 뜻이다. 서버가 죽으면 그 위의 요청은 당연히 죽고, L4에서는 Envoy가 이 실패를 앱 대신 흡수하지 못한다(실측: 완화 없이 요청 44%가 실패로 앱 도달). **단일 A레코드 구조에서 W를 줄이는 실질 레버는 Envoy가 아니라 GSLB에 있다** — 감지 주기와 TTL. 이 구간엔 목록에 죽은 VIP 하나뿐이라 Envoy 차원의 우회가 성립하지 않기 때문이다. Envoy/앱 쪽에서 유효한 것과 한계: - **짧은 connect timeout (1초)** — 죽은 IP를 만나도 1초 만에 실패 판정 (요청이 매달리는 것 방지 — 단일 A레코드에서도 유효) - **앱의 연결 실패 한정 재시도** — 단, W 안에서 즉시 재시도하면 같은 죽은 VIP를 다시 만난다. **재시도 간격(백오프)이 W를 넘어설 때만** 구제가 된다 — W가 수 초대가 아니라면 재시도 횟수보다 백오프 설계가 중요 - **outlier detection** — 단일 A레코드 구조에서는 우회 효과 없음(다음 절). 복수 A레코드로 바꾸면 W 자체가 수 초로 줄어드는 구조가 된다 (실측 실패율 51.7%→0.21%가 그 조건) **따라서 "GSLB가 복수 A레코드를 반환하게 할 수 있는가"가 이 설계의 가장 큰 갈림길이다** — 가능하다면 장애 절체의 유손실 구간이 "GSLB 감지+TTL"(수십 초 단위 가능성)에서 "outlier 격리"(수 초)로 구조적으로 줄어든다. ## 4. outlier detection이 하는 일과 안 하는 일 반드시 나올 질문: "outlier가 되면 뭐가 되는데? 실패하면 DNS 질의를 다시 하나?" **아니다 — DNS와 outlier는 서로를 호출하지 않는 별개의 장치다.** 둘 다 같은 IP 목록을 만지되 역할이 다르다: | 장치 | 역할 | 트리거 | |---|---|---| | DNS 갱신 | 목록에 **누가 있는가** (명단) | 자기 주기 (TTL) — 실패와 무관하게 돈다 | | outlier detection | 명단 중 **누구에게 새 연결을 줄 것인가** (건강 표시) | 연결 실패 누적 | | 앱 재시도 | **이미 실패한 그 요청**의 구제 | 실패 그 자체 | outlier가 하는 일: 어떤 VIP로의 연결 실패가 연속 3회 쌓이면, 그 VIP를 **목록에서 지우는 게 아니라 "일시 제외" 표시**를 한다(우리 설정 기준 30초, 반복되면 제외 시간이 늘어난다). 그동안 새 연결은 목록에 남은 다른 VIP로만 간다. 제외 시간이 지나면 다시 후보에 넣어 살아났는지 자연스럽게 확인된다. outlier가 **안 하는** 일 세 가지: 1. **DNS 재질의를 유발하지 않는다.** DNS 갱신은 자기 주기로만 돈다. outlier는 그 주기 사이의 공백("GSLB는 아직 모르는 죽은 VIP")을 메우는 장치다. 2. **이미 실패한 요청을 살려내지 못한다.** 격리는 다음 연결부터의 예방이다. 첫 1~3건의 실패는 앱에 도달한다 — 그걸 흡수하는 것이 앱 재시도의 몫이다. 3. **목록에 대안이 없으면 우회시킬 곳도 없다.** GSLB가 A레코드를 하나만 반환하는 순간의 목록은 VIP 1개다 — 그게 죽어 있으면 outlier로도 갈 곳이 없고, 복구는 DNS 갱신(TTL)을 기다려야 한다. **outlier의 효과는 목록에 살아있는 대안이 있을 때 성립한다** — 우리 실측 (51.7%→0.21%)도 목록에 정상 endpoint가 함께 있던 조건이다 **[실측]**. 덧붙여 권장 설정의 `maxEjectionPercent: 50`은 목록이 1개일 때 그 하나를 제외하는 것 자체를 막는다 **[공식 문서]** — "최소 1개는 무조건 제외"는 별도 옵션 `always_eject_one_host`(기본 **false**)를 켜야만 하는 동작이다([outlier_detection.proto](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/outlier_detection.proto): "Will eject at least one host regardless of the value **if always_eject_one_host is enabled**"). 즉 단일 A레코드 구조에서 outlier는 문자 그대로 아무 일도 하지 않는다. GSLB가 복수 A레코드를 반환하게 할 수 있다면 이 장치의 가치가 온전해진다. ## 5. 운영 시 주의 - **연결 정리 상태를 endpoint 목록으로 판단하지 말 것.** 목록에서 제거된 VIP에 아직 살아있는 연결은 `istioctl proxy-config endpoints`에 보이지 않는다(cluster 합계 `upstream_cx_active` 카운터로만 보임). 실측으로 확인된 관측 사각지대. - **클라이언트가 IP를 직접 지정해도 소용없다 [실측]**: passthrough SE 경로에서 클라이언트가 특정 backend IP로 강제 접속(`--resolve`)해도 실제 행선지는 Envoy가 자기 IP 목록에서 고른 곳이었다. 행선지를 지배하는 것은 클라이언트의 접속 IP가 아니라 Envoy의 목록이다 — 디버깅 때 착각하기 쉬운 지점. - **미실측 범위**: ① 수 분급 초장기 스트림의 drain 동작, ② HTTP/2 경로. 해당 워크로드 적용 전 추가 확인 필요. ## 6. 근거 자료 1. [egress ServiceEntry resolution은 DNS(STRICT)로 쓴다](/docs/istio/egress/se-strict-dns-adoption/) — 자매 문서: 채택 결정과 근거, 실측 데이터 색인 2. [Q&A — GSLB가 IP를 바꾸면 내 요청은 어떻게 되나](/docs/istio/egress/gslb-flip-inflight-qa/) — 실측 부록 + 원시 데이터 26파일 색인 3. [결정 브리프 전체판(백업)](/docs/istio/egress/se-resolution-dns-brief/) — 검증 전 과정 포함 4. [DNS/GSLB resolution 재현 랩](/docs/istio/egress/dns-gslb-repro-lab/) — 직접 재현 가능한 절차·킷 5. 공식 문서: [Envoy — Service discovery](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery) · [outlier_detection.proto](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/outlier_detection.proto) 6. 다운로드 사본: [files.homelab89.com/istio-egress/dns-resolution/](https://files.homelab89.com/istio-egress/dns-resolution/)