Platform Engineering · Network Architecture Decision

DB 연결의 Istio Egress 경유 제외 구성 제안
excludeOutboundPorts 채택 타당성 검토

istio-egressgateway로 DB 연결을 관리하는 방안에 대한 타당성 검증·조사 결과, DB 트래픽은 sidecar 인터셉트에서 제외(excludeOutboundPorts)하고 기존 3층 통제로 관리할 것을 제안합니다.

상태 검토 완료 · 2026-08-03 작성 2026-08 · Platform/DevOps 결론 exclude 채택 — 직접 연결
범위 k8s 앱 → 사내 DB 연결 경로 범위 외 외부 HTTPS egress 체계 (유지·확장)
본문의 모든 외부 주장에 근거 등급을 부착함 — 공식 벤더 발표 커뮤니티 규제 사내
Part 01

요약 — 결론과 핵심 논거

결론

k8s 앱의 사내 DB 연결은 sidecar → istio-egressgateway 경유 구성을 채택하지 않고, traffic.sidecar.istio.io/excludeOutboundPorts로 DB 포트를 sidecar 인터셉트에서 제외하여 앱이 DB에 직접 연결하도록 구성함. 통제는 기존 3층 — ① 존 경계 방화벽, ② Calico egress NetworkPolicy, ③ DB 계정·TLS·접속기록 — 이 담당하며, 이 3층은 egress gateway 방식을 채택하더라도 어차피 필요한 기반임(4.1절).

핵심 논거 3가지

검토안 — sidecar → egressgateway 경유 App Pod app + sidecar EgressGateway stateful chokepoint DB (VIP) TTL=1 domain mTLS TCP STRICT_DNS poll: every 1s sidecar + gateway 전체 -> paydns 상시 부하 제안안 — excludeOutboundPorts 직접 연결 (채택) App Pod DB port: iptables RETURN DB (VIP) app pool direct plain TCP (sidecar·gateway 미경유, DNS 폴링 0) 통제 3층 (기존 유지) (1) Zone Firewall (2) Calico egress NetworkPolicy (3) DB account · TLS · audit 경로 위 모든 지점에 3층 통제 적용
그림 1 · 검토안(경유)과 제안안(직접 연결)의 경로·통제 비교

※ 본 제안은 DB 연결에 한정됨. 외부 HTTPS 통신(Squid 경유)의 egress gateway 체계 — ISTIO_MUTUAL·SPIFFE 기반 워크로드 인가 — 는 구성·테스트·검증이 완료된 별개 체계로 유지·확장 대상임(2.1절).

Part 02

배경 — 현행 구성·기본 개념·사내 제약

2.1현행 구성과 이번 결정의 범위

2.2배경지식 — 앱은 DB에 어떻게 연결되어 있는가

이후 분석의 전제가 되는 기본 모델임. DB 연결은 HTTP 요청과 근본적으로 다른 성질을 가짐.

항목내용
연결 수립 비용DNS 조회 → TCP 3-way handshake → (TLS) → DB 프로토콜 인증. 왕복 다수·수~수십 ms 소요, DB 측도 세션당 자원 소모함
Connection Pool이 비용 때문에 앱은 연결 N개를 미리 열어 재사용함(borrow → query → return). 연결은 수 시간 유지되는 장수명 TCP
DNS 소비 시점연결을 새로 만들 때만 조회함. 기존 연결은 IP에 이미 붙어 있어 TTL과 무관함
TTL(Time To Live)의 의미"failover 후 신규 연결이 얼마나 빨리 새 IP를 보는가"를 결정함. TTL=1 = 신규 연결이 항상 최신 레코드를 봄
failover 시 흐름기존 연결 에러 감지(socketTimeout·validation) → pool이 폐기 → 신규 연결 생성 → 이때 DNS가 새 primary를 가리키면 복구됨
표 1 — 앱 ↔ DB 연결의 기본 모델

핵심: 직접 연결 모델에서 DNS 질의는 on-demand(연결 생성 시점)로만 발생함. pool 안정 상태(예: pool 20 × maxLifetime 30분)의 질의량은 앱당 시간당 수십 회 = 약 0.01 QPS 수준임. 이 기준선이 3.1절 분석의 비교 대상이 됨.

2.3사내 제약사항 사내

Part 03

기술 분석 — mesh 경유 시 발생하는 문제

mesh 경유안(ServiceEntry + egressgateway)을 채택했을 때 발생하는 기술 문제를 ① DNS 계층② TCP/세션 계층으로 나눠 분석함. 각 항목은 "왜 생기는가(메커니즘) → 얼마나 발생하는가(산식·수치) → 무엇이 깨지는가(증상)" 순서로 기술하며, 검토 과정에서 실측으로 기각된 항목은 기각 사실과 근거를 남겨 둠(3.1.4).

3.1DNS 문제 — on-demand에서 상시 폴링으로의 구조 회귀

3.1.1 한눈에 보는 변화

구분현행 모델 (직접 연결)mesh 경유 모델 (SE resolution: DNS)
질의 주체앱 (연결 생성 시점의 리졸버)SE가 보이는 모든 Envoy 프록시 (sidecar + egressgateway)
질의 시점연결을 새로 만들 때만 (on-demand)상시 — 트래픽 유무와 무관, TTL 주기 타이머
질의량≈ 0.01 QPS/앱 (pool 안정 상태)(스코프 내 프록시 수 × 호스트 수) ÷ TTL(1s)
paydns 도달 부하사실상 0폴링 프록시 보유 노드 수 × 호스트 수 QPS 상시
DNS ↔ 커넥션 결합없음 (질의 결과는 신규 연결에만 반영)신규 연결 방향만 — 기존 커넥션 강제 종료는 없음 (3.1.4 실측)
표 2 — DNS 소비 모델 비교 (색인 · 상세 해설은 아래)

3.1.2 왜 생기는가 — 메커니즘 5단계

  1. STRICT_DNS cluster 생성. ServiceEntry를 resolution: DNS로 등록하면 Envoy에 STRICT_DNS 타입 cluster가 생성됨. 이 타입은 트래픽이 없어도 타이머 기반으로 지속 재질의하여 질의 결과의 IP 집합을 endpoint로 유지함 [5].
  2. TTL 주기 준수. Istio는 레코드 TTL을 따르므로(respect_dns_ttl) TTL=1이면 1초 주기로 재질의함. 사내 파일럿 환경에서 egressgateway가 TTL 주기로 재질의·캐싱함을 실측으로 확인사내.
  3. 폴링 주체는 gateway만이 아님. cluster는 SE가 스코프에 보이는 모든 프록시에 생성됨. exportTo 기본값(*)이면 mesh 전체 sidecar가 각자 폴링함. 트래픽이 VirtualService에 의해 gateway로 라우팅되어 sidecar의 해당 cluster를 사용하지 않아도 폴링은 수행됨. 스코프를 좁혀도 하한이 있음 — sidecar가 VIP 할당·라우팅을 위해 SE를 봐야 하므로 "DB 사용 네임스페이스의 전 sidecar + gateway"까지만 축소 가능함.
  4. 실질 질의 주체의 이동. 현행 DNS proxying 구조에서 앱의 질의는 istio-agent가 auto-allocated VIP로 로컬 응답하므로 앱 측 질의는 paydns에 도달하지 않음. 즉 mesh 경유안에서 DNS 부하의 실체는 전부 Envoy 폴링임.
  5. nodelocaldns는 소거가 아니라 축약임. TTL=1인 레코드는 nodelocaldns에서도 1초만 캐시됨. 캐시는 같은 노드 안 여러 프록시의 질의를 합쳐줄 뿐이므로, 부하는 "프록시 수 → 노드 수"로 축약될 뿐 사라지지 않고 상류인 paydns에 상시 도달함. 폴링 프록시가 노드당 1개꼴로 분산되어 있으면 캐시 이득은 0임.
sidecar Envoy x N poll: 1 QPS each sidecar Envoy x N poll: 1 QPS each egressgw Envoy poll: 1 QPS each nodelocaldns (node A) cache lifetime = TTL = 1s nodelocaldns (node B) cache lifetime = TTL = 1s paydns 전사 공용 DNS 1 QPS/host 1 QPS/host paydns 상시 부하 = (폴링 프록시 보유 노드 수) x (DB 호스트 수) QPS 예시: 노드 30 x 호스트 10 = 300 QPS 상시 <-> 현행: 앱당 약 0.01 QPS (4~5자릿수 차이)
그림 2 · mesh 경유 시 DNS 폴링 구조 — 캐시는 노드 단위 축약일 뿐, paydns 상시 부하는 유지됨

3.1.3 얼마나 발생하는가 — 부하 산식

폴링 총량 = (스코프 내 프록시 수 × DB 호스트 수) ÷ TTL(1s)
paydns 도달량 = (폴링 프록시 보유 노드 수 × DB 호스트 수) QPS — 24시간 상시
※ 예시 수치(노드 30 · 호스트 10 → 300 QPS)는 산정 예시임. 적용 검토 시 실제 노드 수·SE 스코프·DB 호스트 수로 치환 필요함

3.1.4 검토했으나 논거에서 제외한 항목 — DNS 응답 변화와 기존 커넥션

교정

본 검토의 초안에는 "STRICT_DNS에서는 DNS 응답이 바뀌면 그 endpoint로 향하던 기존 커넥션이 강제 종료된다"는 서술이 있었으나, 자체 검증 랩 실측(Istio 1.30.0)에서 성립하지 않음을 확인하여 철회하고 논거에서 제외함 [29] 사내. 3.1의 논거는 폴링 부하(3.1.1~3.1.3)로 한정되며, 제안의 결론은 이 항목 없이 성립함(3.2·4절).

실측으로 확인한 동작은 다음과 같음. DNS 응답 변화는 cluster membership — 즉 다음 연결이 붙을 대상만 바꾸고, 이미 맺어진 커넥션에는 개입하지 않음.

1초마다의 응답 상황Envoy 동작기존 커넥션 영향 (실측)
이전과 동일한 결과no-op없음
IP 교체 (정상 failover)cluster membership 갱신 — endpoint가 새 IP로 교체됨기존 연결 유지 — 강제 종료 없음. DB 경로에 해당하는 L4(tcp_proxy)에는 connection pool 자체가 없어, 이미 맺어진 소켓이 CDS/EDS 갱신과 무관하게 살아 있음. L7(pool) 경로에서도 in-flight 요청은 완주하며 정리는 요청이 끝난 뒤에 일어남
응답 셋 플래핑
(GSLB 단일 레코드 로테이션 등)
매초 membership 갱신같은 이유로 기존 연결에 영향 없음. 바뀌는 것은 이후 신규 연결이 붙는 대상뿐임
빈 응답 / NXDOMAIN
(레코드 삭제→재등록형 작업 창)
endpoint 0건신규 연결만 불가(503 UH 계열). 기존 연결의 종료 여부는 실측하지 않음 — 미검증으로 표기함
질의 실패 (타임아웃·SERVFAIL)마지막 성공 결과 유지·재시도없음 — DNS 서버 장애가 곧 DB 단절은 아님
표 3 — DNS 응답 변화 시 Envoy 동작과 기존 커넥션 영향 (자체 검증 랩 실측 기준)

3.2TCP/세션 문제 — 장수명 상태를 프록시 홉에 태우는 비용

DB 커넥션은 수 시간 유지되는 상태(stateful) 자원임. 요청 단위로 소멸하는 HTTP와 달리, 경로 위 프록시의 수명주기·설정이 곧 커넥션의 수명주기·설정이 됨. 문제 4가지를 색인 후 해설함.

문제원인증상완화 가능성
① 재시작 = 재연결 폭증gateway 파드 종료 시 보유 커넥션 전체 단절롤아웃·업그레이드·scale-in마다 전사 DB 재연결 이벤트완화만 가능, 제거 불가
② chokepoint 수렴전 앱 pool 커넥션이 소수 파드에 집중용량 관리·재분배 문제 (커넥션은 재접속 시에만 재분배됨)replicas 고정 등 관리로 대응
③ 타임아웃 층 중첩Envoy tcp_proxy idle_timeout(기본 1시간) 등유휴 커넥션 절단 — "한가한 시간대 첫 쿼리 실패" 패턴pool keepalive로 우회 (관리 포인트 증가)
④ DB 측 시야 상실소스 IP가 gateway로 수렴user@host grant·방화벽·DB 감사로그의 앱 식별 불가gateway 로그 상관분석 체계 별도 구축 필요
표 4 — mesh 경유 시 TCP/세션 계층 문제 (색인 · 해설은 아래)

① gateway 수명주기 = 커넥션 수명주기

② 커넥션의 chokepoint 수렴

③ 타임아웃·프로토콜 층의 중첩

④ DB 측 소스 식별 상실

3.3공정성 확보 — 사용하지 않는 논거와 유지되는 가치

FAIRNESS
  • latency는 반대 논거로 사용하지 않음. Istio 공식 성능 실측(외부 MongoDB 대상 egress gateway 추가 실험)에서 응답시간 분포에 유의미한 차이가 없었음 [7] 공식.
  • "DNS 응답 변화가 기존 커넥션을 끊는다"도 사용하지 않음. 초안의 서술이었으나 자체 실측으로 기각함(3.1.4). 따라서 본 제안의 근거는 DNS 폴링 부하(3.1.1~3.1.3)와 세션 수명주기(3.2), 업계 표준(4절)으로 한정됨.
  • egress gateway 체계의 가치는 유지됨. SPIFFE 기반 워크로드 인가·고정 egress 지점·중앙 로그는 외부 HTTPS 통신에서 계속 유효하며, 본 제안은 그 체계를 축소하지 않음. 다만 DB(L4)에는 mesh의 L7 가치(retry·timeout·circuit breaking·HTTP 텔레메트리)가 적용 자체가 되지 않고, gateway 경유 강제조차 NetworkPolicy·방화벽이 담당해야 하므로(4.1절) DB에서의 순가치가 얇다는 것이 논지임.
Part 04

업계 레퍼런스 — 표준·구현 사례·토스

주장의 강도를 구분하기 위해 모든 항목에 근거 등급을 표기함: 공식 프로젝트 공식 문서 · 벤더 클라우드/벤더 공식 가이드 · 발표 기업 공식 컨퍼런스 · 커뮤니티 정리글/권고문 · 규제 규제기관 자료 · 사내 사내 확인 사항.

4.1Istio 스스로의 명시 — "gateway 방식조차 NetworkPolicy·방화벽을 전제로 함" 공식

논리적 귀결

DB를 gateway에 태우든 태우지 않든 존 방화벽 + Calico egress NetworkPolicy는 어차피 구축·유지해야 하는 기반임. 따라서 exclude안은 "통제를 빼는 선택"이 아니라, gateway 방식의 필수 기반만으로 충분한 트래픽 유형(DB)에서 부가 홉을 생략하는 선택임. 통제 수준의 후퇴가 없음(5.2절 매핑).

4.2컴플라이언스 표준 — 세그먼테이션 수단은 NetworkPolicy임

3대 클라우드의 PCI 레퍼런스 어느 것도 DB 경로 요건으로 mesh egress gateway를 두지 않음. PCI 환경의 세그먼테이션 정석은 NetworkPolicy 기반 통제이며, 이는 exclude안의 통제 모델과 정확히 일치함.

4.3mesh 계층 스스로의 DB 특별취급 공식

4.4구현 사례 4패턴 — "직접 연결 + 계층 통제"가 문서화된 표준 경로임

패턴구현·문서화 주체핵심 내용
직접 연결 + SG/방화벽 AWS EKS 공식 Best Practices [12][13] 벤더 기본값: RDS 인바운드가 노드 SG를 허용하면 워커노드 전 파드가 접근 — 노드/서브넷 단위 허용이 문서화된 기본 상태이고, Security Groups for Pods(파드 ENI에 SG 부착)가 그 정밀화임
DB 전용 프록시 sidecar Google Cloud SQL 공식 문서 [14] 벤더 Auth Proxy를 파드별 sidecar로 권장 — 중앙 프록시 서비스 대신 분산을 택한 명시 사유가 "단일 장애점 방지·앱별 독립성"임. 권장 경로는 DB 전용 프록시이지 service mesh가 아님
DB 프록시 티어 Slack·YouTube 등 (Vitess/VTGate) [26] 발표 연결 관리·failover를 DB 프로토콜을 이해하는 전용 계층(VTGate)에서 해결 — mesh가 아닌 층의 해법
고정 egress IP (CNI 층) Cilium(Corner Banca 은행 사례)·OpenShift EgressIP [19][20] 벤더 좁은 고정 소스 IP가 규제 요건인 경우조차 업계 정석은 mesh가 아닌 CNI/L3 층임. Calico는 해당 기능이 Enterprise 전용 [11]
표 5 — k8s 앱 → 외부 DB 연결의 문서화된 구현 패턴

부재의 보고: 반대 방향 — "mesh egress gateway로 프로덕션 DB를 경유"한 실명 기업 공개 사례는 조사 범위에서 발견되지 않음. 존재하는 것은 공식 레퍼런스 구현(MongoDB 예제 [6])· 벤더 가이드·커뮤니티 시도 스레드 수준임.

4.5토스 사례 — Istio 전면 운영 환경의 공개된 DB 연결 구조 발표

확인된 사실과 추론을 구분해 기술함. 국내에서 우리와 가장 유사한 환경(온프렘 k8s + Istio + 금융)의 공개 자료임.

확인된 사실 (SLASH 21 공식 세션)

추론 (근거와 함께 명시)

App Pod k8s + Istio sidecar Service IP (VIP) rw.toss.bz -> VIP 직접 MMM이 failover 시 이동 MySQL Master-Master (DC1) DC2 (대칭 · super_read_only) 양방향 MM 복제 + binlog filter domain resolve -> 직접 연결 failover: DC 내 장애 = MMM이 VIP 이동 · DC 간 비계획 = 도메인 타겟 변경(DNS) · DC 간 계획 = L7 임시 삽입 후 일괄 전환 공개 서술 어디에도 mesh 오브젝트(ServiceEntry / egressgateway) 개입 없음 — SLASH 21 기준
그림 3 · 토스의 공개된 DB 연결·failover 구조 (SLASH 21 발표 기준 재구성)

4.6국내 규제 관점 규제

Part 05

제안 구성 — exclude 적용·통제 매핑·검증

5.1excludeOutboundPorts 적용

동작 원리: istio-init이 설정하는 iptables 규칙에서 지정 포트의 outbound 트래픽에 RETURN 규칙을 추가함 — 해당 포트 트래픽은 Envoy를 커널 레벨에서 아예 거치지 않고 목적지로 직행함 [5]. ServiceEntry가 불필요하므로 STRICT_DNS cluster도, DNS 폴링도 생성되지 않음(폴링 0).

# 파드(Deployment) 단위 적용 — DB 연결 워크로드에 부착
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-api
spec:
  template:
    metadata:
      annotations:
        traffic.sidecar.istio.io/excludeOutboundPorts: "3306,5432,27017,9200"
        # ^ 사내 DB 포트 목록으로 확정 필요 (MySQL·PostgreSQL·MongoDB·OpenSearch 등)

5.2통제 매핑 — "빠지는 통제가 없음"의 증명

통제 질문수단담당
① 경계어느 네트워크가 DB존에 도달 가능한가존 방화벽 — 클러스터 egress 대역 → DB존:포트 허용네트워크·보안
② 클러스터어느 워크로드가 나갈 수 있는가Calico egress NetworkPolicy (라벨 기반 목적지·포트 제한)플랫폼
③ 엔드포인트누가·무엇을 했는가DB 계정·비밀번호/TLS·DB 접속기록(감사)DBA·보안
표 6 — exclude안의 3층 통제 매핑
App Pod exclude: DB ports (2) Calico egress NetworkPolicy which workload (1) Zone Firewall cluster egress subnet -> DB zone:port DB (3) account · TLS · audit log plain TCP — 홉 없이 통제 3층을 순서대로 통과함 (1)(2)는 gateway 경유안에서도 필수인 기반 (Istio 공식 [1][2]) — exclude로 빠지는 통제 없음
그림 4 · 제안안의 통제 3층 — 경로에서 홉을 빼되 통제는 전부 유지됨

5.3대안 비교

평가 항목(a) egressgateway 경유(b) sidecar 통과
SE resolution: NONE
(c) exclude [채택]
DNS 폴링 (paydns)스코프 내 전 프록시 상시 폴링0 (resolution: NONE 전제)0 (SE 자체 없음)
커넥션 경로 홉sidecar + gateway 2홉sidecar 1홉0홉 (직결)
프록시 수명주기 결합gateway 재시작 = 전사 재연결sidecar 재시작 = 해당 파드 재연결(파드와 동일 운명이라 영향 최소)없음
Envoy 타임아웃 관리필요 (idle 1h 등, 전 앱 pool 정합)필요 (동일)불필요
DB측 소스 식별gateway IP로 수렴 — 식별 상실파드/노드 소스 유지파드/노드 소스 유지
mesh 관측성(TCP 메트릭)있음있음없음 — DB측·APM으로 대체(5.5)
워크로드 단위 통제SPIFFE AuthorizationPolicyCalico NPCalico NP
운영 복잡도높음 (SE·GW·VS·DR + 5.1~5.4의 상시 관리)중간 (SE 스코프·리스너 관리)낮음 (어노테이션 표준화만)
표 7 — 대안 비교 (색인 · 해설은 아래)

5.4적용·검증·롤백 절차

사전 확인 (적용 전 필수) 사내

검증 커맨드

# 1) iptables 반영 확인 — istio-init 로그에서 exclude 포트의 RETURN 규칙
kubectl logs deploy/<app> -c istio-init | grep -i exclude

# 2) Envoy 구성에서 DB 목적지 cluster 부재 확인 (SE 미등록이므로 없어야 정상)
istioctl proxy-config cluster <pod> -n <ns> --fqdn <db-host>   # -> 결과 없음이 정상

# 3) DNS 폴링 0 확인 — 해당 노드에서 DB 호스트 질의가 관측되지 않아야 함
tcpdump -i any port 53 | grep <db-host>                          # -> 연결 생성 시점 외 무출력

# 4) 연결 경로 확인 — 앱 컨테이너에서 DB VIP로의 직접 ESTABLISHED 세션
kubectl exec <pod> -c <app> -- ss -tn state established '( dport = :5432 )'

# 5) failover 리허설 — DB팀 협조 하에 전환 수행, pool 재수립 소요시간 실측

롤백

5.5남는 리스크·한계와 보완

항목내용보완
mesh 관측성 상실Kiali·Istio TCP 메트릭에 DB 트래픽 미표시 DB측 세션·성능 모니터링 + 앱 APM(커넥션 풀 메트릭) + 필요 시 노드 플로우 로그. 요구 확정 시 (b)안 전환 가능
앱측 DNS 캐시가 관리 포인트로 복귀mesh를 빼면 resolve 주체가 앱(JVM)이 됨 — JVM 기본 캐시(30초 등)가 TTL=1보다 김 JVM networkaddress.cache.ttl=5 이하 표준화 + 드라이버 socketTimeout — 배포 표준에 편입
어노테이션 누락 리스크신규 워크로드에서 exclude 누락 시 DB 트래픽이 sidecar로 유입됨 공통 차트 표준 항목화 + admission 검사(정책 엔진)로 강제
파드 전 컨테이너 적용exclude는 포트 기준으로 파드 전체에 적용됨 대상 포트의 타 용도 사용 여부 사전 점검(5.4)
표 8 — 잔여 리스크와 보완책
Part 06

예상 반론과 답변 (FAQ)

Q1"mesh를 이미 운영하는데 왜 DB만 태우지 않는가?"

Q2"향후 DB존 방화벽이 좁은 고정 소스 IP를 요구하면?"

Q3"감사·통제 수준이 후퇴하는 것 아닌가?"

Part 07

출처 목록

Part 08

개정 이력

일자변경 내용
v1.12026-08-03 3.1.4 철회 — "DNS 응답 변화가 기존 커넥션을 강제 종료한다"는 초안 서술을 자체 검증 랩 실측(Istio 1.30.0)으로 기각하고 논거에서 제외함 [29]. 부수 수정: 표 3을 실측 기준으로 재작성, 표 2의 "DNS ↔ 커넥션 결합" 행 정정, 3.3(공정성)에 기각 항목 추가, 출처 [29] 신설. 제안의 결론과 나머지 논거(폴링 부하 3.1.1~3.1.3 · 세션 수명주기 3.2 · 업계 표준 4절)는 변경 없음.
v1.02026-08 최초 작성 — "DB 연결도 istio-egressgateway로 관리하는 방안"의 타당성 검증·조사 결과와 exclude 채택 제안.