TL;DR

1. 개념

HTTP/2 – 멀티플렉싱과 바이너리 프레이밍 3.

2. 배경

  1. HTTP/2 – 멀티플렉싱과 바이너리 프레이밍

3. 이유

  1. mTLS – 제로 트러스트 보안의 핵심

4. 특징

  1. Waypoint Proxy – Ambient Mesh의 L7 처리기

5. 상세 내용

Kubernetes 서비스 메시 핵심 기술

목차

  1. 개요
  2. HTTP/2 – 멀티플렉싱과 바이너리 프레이밍
  3. mTLS – 제로 트러스트 보안의 핵심
  4. Waypoint Proxy – Ambient Mesh의 L7 처리기
  5. Circuit Breaker – 연쇄 장애 방지
  6. 4가지 기술 통합 아키텍처
  7. 실전 시나리오별 적용 가이드
  8. YAML 설정 레퍼런스
  9. 프로덕션 체크리스트
  10. 기술 선택 가이드
  11. 자주 묻는 질문 (FAQ)
  12. 요약 및 키워드

1. 개요

Kubernetes 서비스 메시에서 가장 중요한 4가지 핵심 기술을 다룬다. 이 문서는 각 기술의 등장 배경, 동작 원리, K8s에서의 구현 방법, 그리고 실전 적용 패턴까지 포괄한다.

1.1 핵심 기술 관계도

┌──────────────────────────────────────────────────────────────────────┐
│                K8s 서비스 메시 핵심 기술 관계도                        │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│               ┌──────────────┐         ┌──────────────┐             │
│               │   HTTP/2     │────────►│    mTLS      │             │
│               │ (전송 프로토콜)│         │ (보안 계층)   │             │
│               └──────┬───────┘         └──────┬───────┘             │
│                      │                        │                      │
│         HTTP/2가 mTLS의 │               mTLS가 Waypoint│             │
│         전송 기반 제공   │               간 터널 보호   │             │
│                      │                        │                      │
│                      ▼                        ▼                      │
│               ┌──────────────┐         ┌──────────────┐             │
│               │  Waypoint    │◄────────│   Circuit    │             │
│               │   Proxy      │         │   Breaker    │             │
│               │ (L7 처리 엔진)│         │ (장애 격리)   │             │
│               └──────────────┘         └──────────────┘             │
│                                                                      │
│   관계 요약:                                                         │
│   ┌────────────────────────────────────────────────────────────┐    │
│   │ HTTP/2    → mTLS 위에서 바이너리 프레임 전송               │    │
│   │ mTLS      → ztunnel/Waypoint 간 HBONE 터널 암호화          │    │
│   │ Waypoint  → HTTP/2 프레임 파싱 후 L7 정책 적용             │    │
│   │ Circuit   → Waypoint 내부에서 장애 엔드포인트 격리         │    │
│   │   Breaker                                                  │    │
│   └────────────────────────────────────────────────────────────┘    │
└──────────────────────────────────────────────────────────────────────┘

1.2 각 기술 한 줄 요약

기술 핵심 가치 한 줄 요약
HTTP/2 전송 효율 하나의 TCP 연결에서 다수 요청을 동시에 처리 (멀티플렉싱)
mTLS 보안 서비스 간 상호 인증 + 암호화로 Zero Trust 네트워크 구현
Waypoint Proxy L7 처리 Sidecar 없이 L7 트래픽 관리를 수행하는 Ambient Mesh의 핵심 컴포넌트
Circuit Breaker 장애 격리 장애 서비스로의 요청을 차단하여 연쇄 장애(cascading failure) 방지

2. HTTP/2 – 멀티플렉싱과 바이너리 프레이밍

2.1 왜 등장했는가: HTTP/1.1 Head-of-Line Blocking

HTTP/1.1에서는 하나의 TCP 연결에서 요청/응답이 순차적으로 처리된다. 앞의 요청이 완료되기 전까지 뒤의 요청이 블로킹되는 문제가 Head-of-Line(HOL) Blocking이다.

┌───────────────────────────────────────────────────────────────┐
│           HTTP/1.1 Head-of-Line Blocking 문제                  │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  클라이언트                              서버                  │
│     │                                     │                   │
│     │──── GET /api/orders ──────────────►│                   │
│     │                    (대용량 응답)     │                   │
│     │◄─── 200 OK (100KB) ───────────────│  ← 3초 소요       │
│     │                                     │                   │
│     │──── GET /api/users ───────────────►│  ← 3초 대기!      │
│     │◄─── 200 OK (1KB) ────────────────│  ← 실제 처리 10ms  │
│     │                                     │                   │
│  문제: /users 요청은 1KB 응답인데 3초를 대기                   │
│                                                               │
│  해결 시도: 병렬 TCP 연결 (브라우저 기본 6개)                   │
│  ┌─ Connection 1: GET /api/orders                             │
│  ├─ Connection 2: GET /api/users                              │
│  ├─ Connection 3: GET /api/products                           │
│  ├─ Connection 4: GET /api/cart                               │
│  ├─ Connection 5: GET /api/reviews                            │
│  └─ Connection 6: GET /api/recommendations                    │
│                                                               │
│  문제점:                                                      │
│  - 각 연결마다 TCP 3-way handshake + TLS handshake 비용       │
│  - 서버 소켓/메모리 리소스 6배 소비                            │
│  - 연결 수 제한으로 7번째 요청부터 다시 HOL Blocking           │
└───────────────────────────────────────────────────────────────┘

2.2 HTTP/2의 등장 배경

HTTP/2는 Google SPDY 프로토콜에서 시작되었다.

  • 2009: Google이 SPDY 실험 시작
  • 2009-2015: SPDY 실험 결과 11~47% 페이지 로드 성능 개선 입증
  • 2015.05: SPDY 기반으로 RFC 7540 (HTTP/2) 표준화
  • 2022: RFC 9113으로 HTTP/2 업데이트
버전 연도 표준 핵심 변화
HTTP/1.0 1996 RFC 1945 요청/응답 모델, 비지속 연결
HTTP/1.1 1997 RFC 2068 지속 연결(Keep-Alive), 파이프라이닝
HTTP/2 2015 RFC 7540 바이너리 프레이밍, 멀티플렉싱
HTTP/3 2022 RFC 9114 QUIC/UDP 기반, UDP 위의 멀티플렉싱

2.3 핵심 기능

Binary Framing Layer

HTTP/1.1의 텍스트 기반 프로토콜을 바이너리 프레이밍 계층으로 대체한다.

┌───────────────────────────────────────────────────────┐
│              HTTP/2 Binary Frame 구조                  │
├───────────────────────────────────────────────────────┤
│                                                       │
│  ┌─────────────────────────────────────────────┐     │
│  │  Length (24 bit)                             │     │
│  ├─────────────────────────────────────────────┤     │
│  │  Type (8 bit)  │  Flags (8 bit)             │     │
│  ├─────────────────────────────────────────────┤     │
│  │  R │  Stream Identifier (31 bit)            │     │
│  ├─────────────────────────────────────────────┤     │
│  │  Frame Payload (가변 길이)                   │     │
│  └─────────────────────────────────────────────┘     │
│                                                       │
│  주요 프레임 타입:                                    │
│  - HEADERS       : 요청/응답 헤더                    │
│  - DATA          : 본문 데이터                       │
│  - SETTINGS      : 연결 설정                         │
│  - WINDOW_UPDATE : 흐름 제어                         │
│  - PUSH_PROMISE  : 서버 푸시 예약                    │
│  - RST_STREAM    : 스트림 취소                       │
│  - PING          : 연결 유지 확인                    │
│  - GOAWAY        : 연결 종료 알림                    │
└───────────────────────────────────────────────────────┘

Multiplexing (멀티플렉싱)

하나의 TCP 연결에서 여러 스트림이 독립적으로 동작한다. HTTP/1.1에서 4~8개 필요했던 병렬 연결이 1개로 축소된다.

┌───────────────────────────────────────────────────────┐
│            HTTP/2 Multiplexing 동작 원리               │
├───────────────────────────────────────────────────────┤
│                                                       │
│  하나의 TCP 연결:                                     │
│  ┌─────────────────────────────────────────────┐     │
│  │ Stream 1 [HEADERS]──[DATA]──[DATA]──[END]   │     │
│  │ Stream 3 [HEADERS]──[DATA]──[END]           │     │
│  │ Stream 5 [HEADERS]──[DATA]──[DATA]──[END]   │     │
│  │ Stream 7 [HEADERS]──[END]                   │     │
│  └─────────────────────────────────────────────┘     │
│                                                       │
│  프레임 인터리빙 (실제 전송 순서):                    │
│  [S1:H][S3:H][S1:D][S5:H][S3:D][S5:D][S7:H]...     │
│                                                       │
│  각 스트림은 독립적 → 하나가 느려도 다른 것에 영향 X │
└───────────────────────────────────────────────────────┘

HPACK 헤더 압축 (RFC 7541)

HTTP/2 전용 헤더 압축 알고리즘이다.

  • 정적 사전: 61개 사전 정의 항목 (:method GET, :status 200 등)
  • 동적 사전: 연결 내에서 새로운 헤더를 학습하여 인덱스로 참조
  • Huffman 인코딩: 자주 사용되는 문자에 짧은 코드 할당

Cloudflare 측정 결과: 평균 69% 압축률 달성.

Server Push

PUSH_PROMISE 프레임으로 클라이언트가 요청하기 전에 리소스를 미리 전송한다. 브라우저에서는 Chrome이 2022년에 지원을 제거했으나, 서버-서버 통신(gRPC Server Streaming 등)에서는 여전히 유용하다.

Stream 우선순위

스트림에 의존성과 가중치를 설정하여 중요한 요청을 우선 처리할 수 있다.

2.4 h2 vs h2c (TLS 유무)

항목 h2 (HTTP/2 over TLS) h2c (HTTP/2 Cleartext)
TLS 필수 (ALPN으로 협상) 불필요 (평문)
포트 443 (일반적) 80 또는 임의
보안 암호화 + 인증 없음
성능 TLS 핸드셰이크 오버헤드 오버헤드 없음
K8s 내부 Service Mesh mTLS 사용 시 Pod 간 직접 통신 시
프로토콜 협상 TLS ALPN HTTP Upgrade 또는 Prior Knowledge
┌───────────────────────────────────────────────────────┐
│              h2 vs h2c 프로토콜 협상                    │
├───────────────────────────────────────────────────────┤
│                                                       │
│  h2 (TLS 있음):                                      │
│  Client ──TLS ClientHello (ALPN: h2)──► Server       │
│  Client ◄──TLS ServerHello (ALPN: h2)── Server       │
│  → TLS 핸드셰이크에서 HTTP/2 합의                     │
│                                                       │
│  h2c (TLS 없음 - HTTP Upgrade):                      │
│  Client ──GET / HTTP/1.1                              │
│            Connection: Upgrade                        │
│            Upgrade: h2c ──────────────► Server        │
│  Client ◄──101 Switching Protocols──── Server        │
│  → HTTP/1.1에서 HTTP/2로 업그레이드                   │
│                                                       │
│  h2c (TLS 없음 - Prior Knowledge):                   │
│  Client ──HTTP/2 Connection Preface──► Server        │
│  → 서버가 h2c 지원을 미리 알고 있으면 바로 HTTP/2    │
│  → K8s Service Mesh에서 주로 사용                     │
└───────────────────────────────────────────────────────┘

K8s에서의 적용:

  • Service Mesh 사용 시: Pod 간 통신은 h2c, mTLS는 Sidecar/ztunnel이 처리
  • Service Mesh 미사용 시: 보안이 필요하면 h2 (애플리케이션 레벨 TLS)
  • K8s Service 설정: appProtocol: kubernetes.io/h2c 또는 포트명 http2-*

2.5 Kubernetes에서의 과제: kube-proxy L4 로드밸런싱

K8s 환경에서 HTTP/2를 사용할 때 가장 심각한 문제는 로드밸런싱 불균형이다.

┌───────────────────────────────────────────────────────┐
│            kube-proxy의 L4 로드밸런싱 한계              │
├───────────────────────────────────────────────────────┤
│                                                       │
│  kube-proxy = L4 (TCP 연결 단위) 로드밸런싱            │
│  HTTP/2    = 하나의 TCP 연결에 수백 개 요청            │
│                                                       │
│  결과: 모든 요청이 최초 연결된 Pod 하나에 집중          │
│                                                       │
│  order-service (클라이언트)                            │
│       │                                               │
│       │  TCP 연결 1개 (HTTP/2 멀티플렉싱)             │
│       │  → 100개의 gRPC 호출이 모두 이 연결 사용       │
│       │                                               │
│       ▼                                               │
│  kube-proxy (iptables/IPVS)                           │
│       │                                               │
│       │  TCP 연결 수립 시 1번만 Pod 선택               │
│       │                                               │
│       ▼                                               │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐           │
│  │ Pod A    │  │ Pod B    │  │ Pod C    │           │
│  │ 100 요청 │  │  0 요청  │  │  0 요청  │           │
│  │ CPU 90%  │  │ CPU 5%   │  │ CPU 5%   │           │
│  └──────────┘  └──────────┘  └──────────┘           │
│                                                       │
│  Pod A만 과부하, Pod B/C는 유휴 상태 → HPA 비정상     │
└───────────────────────────────────────────────────────┘

영향범위:

  • gRPC 서비스 (HTTP/2 필수)
  • HTTP/2를 명시적으로 설정한 REST 서비스
  • WebSocket 등 long-lived 연결 서비스

2.6 해결 방법

방법 1: Istio DestinationRule (L7 로드밸런싱)

# Istio가 HTTP/2 프레임 단위로 로드밸런싱
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: order-service-lb
  namespace: production
spec:
  host: order-service
  trafficPolicy:
    connectionPool:
      http:
        h2UpgradePolicy: UPGRADE         # HTTP/2 업그레이드 강제
        http2MaxRequests: 1000            # 동시 요청 제한
        maxRequestsPerConnection: 100     # 연결당 100 요청 후 재연결 → 재분배
    loadBalancer:
      simple: ROUND_ROBIN                 # L7 라운드 로빈

방법 2: gRPC Client-side 로드밸런싱

# Headless Service (ClusterIP: None)
apiVersion: v1
kind: Service
metadata:
  name: order-service-headless
spec:
  clusterIP: None                         # DNS가 모든 Pod IP 반환
  selector:
    app: order-service
  ports:
    - name: grpc
      port: 50051
      appProtocol: kubernetes.io/h2c
// gRPC 클라이언트 설정 (Go)
// DNS resolver + round_robin 로드밸런싱
conn, err := grpc.Dial(
    "dns:///order-service-headless.production.svc.cluster.local:50051",
    grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`),
    grpc.WithTransportCredentials(insecure.NewCredentials()),
)

방법 3: MaxConnectionAge (서버측)

// gRPC 서버에서 연결 수명 제한
// 주기적으로 연결이 끊기면 kube-proxy가 새 Pod에 재연결
server := grpc.NewServer(
    grpc.KeepaliveParams(keepalive.ServerParameters{
        MaxConnectionAge:      5 * time.Minute,  // 5분마다 연결 갱신
        MaxConnectionAgeGrace: 30 * time.Second,  // 진행 중 요청 완료 유예
    }),
)

방법 4: Linkerd L7 로드밸런싱

Linkerd는 자동으로 HTTP/2 요청 단위 로드밸런싱을 수행한다. 별도 설정 없이 Linkerd Sidecar가 주입되면 HTTP/2 멀티플렉싱 문제가 해결된다.

2.7 서비스 메시별 HTTP/2 벤치마크 (arXiv 2411.02267)

실제 벤치마크 연구에서 측정한 서비스 메시별 성능 오버헤드이다.

┌───────────────────────────────────────────────────────────────┐
│          서비스 메시 성능 벤치마크 (arXiv 2411.02267)           │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  P99 지연시간 증가율 (베이스라인 대비):                         │
│                                                               │
│  Istio Sidecar   ████████████████████████████████  +166%      │
│  Cilium          ██████████████████████            +99%       │
│  Linkerd         ████████████████                  +33% (*)   │
│  Istio Ambient   ██                               +8%        │
│                                                               │
│  (*) Linkerd: P99 +33%이지만 P50에서는 가장 낮은 오버헤드      │
│                                                               │
│  핵심 인사이트:                                               │
│  ┌─────────────────────────────────────────────────────┐     │
│  │ Istio Ambient(ztunnel L4)는 L7 파싱을 하지 않아     │     │
│  │ 오버헤드가 가장 낮다 (+8%).                          │     │
│  │ L7 기능(Waypoint)을 추가하면 오버헤드가 증가하지만,  │     │
│  │ 필요한 서비스에만 선택적으로 적용 가능하다.          │     │
│  └─────────────────────────────────────────────────────┘     │
│                                                               │
│  메모리 사용량 (Pod당):                                       │
│  Istio Sidecar   ~60-100MB (Envoy per Pod)                   │
│  Linkerd         ~20-30MB  (Linkerd-proxy per Pod)            │
│  Istio Ambient   ~10-15MB  (ztunnel per Node, 공유)           │
│  Cilium          ~0MB      (eBPF, 커널 내 처리)               │
└───────────────────────────────────────────────────────────────┘

2.8 HTTP/3 (QUIC) 미래 전망

HTTP/2의 TCP-level HOL Blocking을 해결하기 위해 QUIC(UDP) 위에 구축된 HTTP/3가 등장했다.

HTTP/2의 남은 문제:

HTTP/2는 애플리케이션 레벨 HOL Blocking은 해결했지만, TCP 레벨의 HOL Blocking은 여전히 존재한다. TCP 패킷 하나가 유실되면 그 위의 모든 HTTP/2 스트림이 블로킹된다.

현재 채택 현황 (Cloudflare Radar 2025):

프로토콜 글로벌 트래픽 비율
HTTP/1.x 8%
HTTP/2 67%
HTTP/3 25%

K8s 생태계 지원 현황:

구성요소 HTTP/3 지원 수준
Envoy (다운스트림) GA
Envoy (업스트림) Alpha
Istio Gateway Alpha/Experimental
Istio 내부 통신 미지원
NGINX Ingress 실험적

권장 사항 (2026년 현재):

  • 외부 에지(CDN, API Gateway): HTTP/3 적용 검토 가능
  • 내부 서비스 간 통신: 아직 HTTP/2가 안정적. HTTP/3 미채택 권장
  • 모바일 클라이언트: HTTP/3의 연결 마이그레이션이 유리 (네트워크 전환 시)

3. mTLS – 제로 트러스트 보안의 핵심

3.1 왜 등장했는가: 경계 기반 보안의 한계

기존 보안 모델은 경계(perimeter) 를 기준으로 내부/외부를 구분했다. K8s 클러스터 내부는 “신뢰할 수 있는 영역”으로 간주하고, 서비스 간 통신은 평문(HTTP)이었다.

┌───────────────────────────────────────────────────────────────┐
│           경계 기반 보안 vs Zero Trust                          │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  [경계 기반 보안 - 기존 모델]                                  │
│                                                               │
│  ┌─── 방화벽 ──────────────────────────────────────┐         │
│  │  "클러스터 내부 = 신뢰"                          │         │
│  │                                                  │         │
│  │  order-svc ──HTTP(평문)──► payment-svc           │         │
│  │       │                                          │         │
│  │       └──HTTP(평문)──► user-svc                  │         │
│  │                                                  │         │
│  │  위험: 내부 침입자가 트래픽 도청/변조 가능        │         │
│  │  위험: Pod 간 네트워크는 기본적으로 암호화 없음    │         │
│  └──────────────────────────────────────────────────┘         │
│                                                               │
│  [Zero Trust 모델 - mTLS 적용]                                │
│                                                               │
│  ┌──────────────────────────────────────────────────┐         │
│  │  "아무것도 신뢰하지 않는다"                       │         │
│  │                                                  │         │
│  │  order-svc ──mTLS──► payment-svc                 │         │
│  │  (SPIFFE ID)  (상호 인증 + 암호화)  (SPIFFE ID)  │         │
│  │       │                                          │         │
│  │       └──mTLS──► user-svc                        │         │
│  │                   (SPIFFE ID)                    │         │
│  │                                                  │         │
│  │  모든 통신: 인증 + 암호화 + 인가                  │         │
│  └──────────────────────────────────────────────────┘         │
└───────────────────────────────────────────────────────────────┘

K8s 기본 네트워킹의 위험:

위협 K8s 기본 상태 mTLS 적용 후
도청 (Eavesdropping) 평문 트래픽 노출 AES-GCM 암호화로 불가
스푸핑 (Spoofing) IP 위변조 가능 X.509 인증서로 신원 검증
중간자 공격 (MITM) 방어 없음 상호 인증서 검증으로 차단
리플레이 (Replay) 방어 없음 TLS 세션 키로 무효화
비인가 접근 NetworkPolicy만 SPIFFE ID 기반 인가 정책

3.2 단방향 TLS vs 양방향 mTLS 비교

┌───────────────────────────────────────────────────────────────┐
│              TLS vs mTLS 핸드셰이크 비교                       │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  [단방향 TLS - 일반 HTTPS]                                    │
│                                                               │
│  클라이언트                         서버                      │
│     │──ClientHello────────────────►│                         │
│     │◄──ServerHello + 서버 인증서──│                         │
│     │  (서버 인증서 검증)           │                         │
│     │──Finished──────────────────►│                         │
│     │                              │                         │
│     └─ 클라이언트 → 서버 인증: O                              │
│     └─ 서버 → 클라이언트 인증: X  ← 서버는 클라이언트 모름   │
│                                                               │
│  [양방향 mTLS - 서비스 메시]                                  │
│                                                               │
│  클라이언트(order-svc)             서버(payment-svc)          │
│     │──ClientHello────────────────►│                         │
│     │◄──ServerHello + 서버 인증서──│                         │
│     │  (서버 인증서 검증)           │                         │
│     │◄──CertificateRequest────────│  ← 클라이언트 인증서 요구│
│     │──클라이언트 인증서──────────►│                         │
│     │                (클라이언트 인증서 검증)                  │
│     │──Finished──────────────────►│                         │
│     │                              │                         │
│     └─ 클라이언트 → 서버 인증: O                              │
│     └─ 서버 → 클라이언트 인증: O  ← 양쪽 모두 신원 확인      │
└───────────────────────────────────────────────────────────────┘
항목 단방향 TLS 양방향 mTLS
서버 인증 O O
클라이언트 인증 X O
인증서 관리 서버만 양쪽 모두
K8s에서 사용 Ingress (외부→클러스터) Pod 간 내부 통신
주요 용도 브라우저-서버 HTTPS Zero Trust 서비스 메시

3.3 SPIFFE/SPIRE 워크로드 아이덴티티

SPIFFE (Secure Production Identity Framework For Everyone)는 워크로드에 표준화된 아이덴티티를 부여하는 프레임워크이다.

┌───────────────────────────────────────────────────────────────┐
│              SPIFFE 아이덴티티 체계                             │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  SPIFFE ID 형식:                                              │
│  spiffe://<trust-domain>/<workload-path>                      │
│                                                               │
│  예시:                                                        │
│  spiffe://cluster.local/ns/production/sa/order-service        │
│  ├─ trust-domain : cluster.local                              │
│  ├─ namespace    : production                                 │
│  └─ service-acct : order-service                              │
│                                                               │
│  SVID (SPIFFE Verifiable Identity Document):                  │
│  ┌──────────────────────────────────────────┐                │
│  │  X.509 인증서 내용:                       │                │
│  │  - Subject Alternative Name (SAN):       │                │
│  │    URI: spiffe://cluster.local/ns/        │                │
│  │         production/sa/order-service       │                │
│  │  - Issuer: Istio CA (istiod)             │                │
│  │  - Not After: 24h (자동 갱신)            │                │
│  │  - Key Algorithm: ECDSA P-256            │                │
│  └──────────────────────────────────────────┘                │
│                                                               │
│  PKI 계층:                                                    │
│  ┌─ Root CA (Istio 자체 CA 또는 외부 CA)                      │
│  ├─── Intermediate CA (istiod)                                │
│  │    ├─── Workload Cert (order-service)                      │
│  │    ├─── Workload Cert (payment-service)                    │
│  │    └─── Workload Cert (user-service)                       │
│  └─ Root CA는 10년, Workload Cert는 24시간 수명               │
└───────────────────────────────────────────────────────────────┘

SPIRE (SPIFFE Runtime Environment)는 SPIFFE를 구현한 런타임이다. Istio는 자체 SPIFFE 구현을 내장하고 있어 SPIRE 없이도 동작하지만, 멀티 클러스터에서는 SPIRE를 별도 사용하기도 한다.

구성요소 역할 Istio에서의 대응
SPIFFE ID 워크로드 아이덴티티 표준 SAN URI에 자동 포함
SVID 검증 가능한 인증서 X.509 인증서 (24시간)
SPIRE Server 인증서 발급 서버 istiod (Citadel 통합)
SPIRE Agent 노드별 인증서 배포 istio-agent (Sidecar 내) / ztunnel (Ambient)

3.4 Istio PeerAuthentication (STRICT / PERMISSIVE / DISABLE)

# 메시 전체 STRICT mTLS (가장 안전)
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: mesh-wide-strict
  namespace: istio-system              # istio-system = 메시 전체 적용
spec:
  mtls:
    mode: STRICT                       # 평문 요청 거부
모드 동작 사용 시점
STRICT mTLS만 허용. 평문 거부 프로덕션 안정화 후
PERMISSIVE mTLS + 평문 모두 허용 마이그레이션 중
DISABLE mTLS 비활성화 (평문만) 특수한 경우만
UNSET 상위 정책 상속 기본값

적용 우선순위 (높은 순):

  1. 워크로드별 (selector 지정)
  2. 네임스페이스별 (namespace 지정, selector 없음)
  3. 메시 전체 (istio-system 네임스페이스)
# 프로덕션 네임스페이스: STRICT, 단 헬스체크 포트는 PERMISSIVE
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: production-strict
  namespace: production
spec:
  mtls:
    mode: STRICT
  portLevelMtls:
    8080:
      mode: PERMISSIVE                 # kubelet 헬스체크용 (mTLS 불가)

3.5 cert-manager 연동

외부 CA를 사용하거나 인증서 관리를 세밀하게 제어할 때 cert-manager를 Istio와 연동한다.

# cert-manager Issuer (Istio CA 대체)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: istio-ca
spec:
  ca:
    secretName: istio-ca-secret        # Root CA 키 쌍
---
# Istio가 cert-manager를 CA로 사용하도록 설정
# istio-operator 또는 Helm values:
# pilot:
#   env:
#     EXTERNAL_CA: ISTIOD_RA_KUBERNETES_API
#     K8S_RA_ISSUER_NAME: istio-ca
#     K8S_RA_ISSUER_KIND: ClusterIssuer
#     K8S_RA_ISSUER_GROUP: cert-manager.io

cert-manager 연동 장점:

항목 Istio 기본 CA cert-manager 연동
Root CA 관리 Istio 자동 생성 외부 CA (Vault, AWS ACM PCA 등)
인증서 수명 24시간 (고정) 커스텀 가능
갱신 방식 istio-agent 자동 cert-manager 자동
감사 추적 제한적 cert-manager 이벤트/로그
멀티 클러스터 클러스터별 Root CA 공유 Root CA 가능

3.6 Istio Ambient: ztunnel에서의 L4 mTLS

Ambient Mesh에서는 ztunnel(DaemonSet)이 노드 레벨에서 L4 mTLS를 처리한다.

┌───────────────────────────────────────────────────────────────┐
│              Ambient Mesh: ztunnel L4 mTLS                     │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  Node A                           Node B                      │
│  ┌──────────────────────┐       ┌──────────────────────┐     │
│  │  ┌──────────────┐   │       │  ┌──────────────┐    │     │
│  │  │ order-svc    │   │       │  │ payment-svc  │    │     │
│  │  │ (Sidecar 없음)│   │       │  │ (Sidecar 없음)│    │     │
│  │  └──────┬───────┘   │       │  └──────▲───────┘    │     │
│  │         │ 평문       │       │         │ 평문       │     │
│  │         ▼            │       │         │            │     │
│  │  ┌──────────────┐   │       │  ┌──────────────┐    │     │
│  │  │  ztunnel     │   │       │  │  ztunnel     │    │     │
│  │  │  (DaemonSet) │───┼─mTLS──┼──│  (DaemonSet) │    │     │
│  │  │  HBONE:15008 │   │       │  │  HBONE:15008 │    │     │
│  │  └──────────────┘   │       │  └──────────────┘    │     │
│  └──────────────────────┘       └──────────────────────┘     │
│                                                               │
│  장점:                                                        │
│  - Pod에 Sidecar 주입 불필요                                  │
│  - Pod 재시작 없이 mTLS 즉시 활성화                            │
│  - 노드당 1개 ztunnel → 메모리 대폭 절감                      │
│  - L4 only → P99 오버헤드 +8% (arXiv 2411.02267)             │
└───────────────────────────────────────────────────────────────┘

3.7 성능 영향

mTLS 자체의 오버헤드는 미미하다.

항목 측정값 비고
TLS 1.3 핸드셰이크 1-RTT (~1ms LAN) 연결 수립 시 1회만
AES-256-GCM 암호화 ~1GB/s (CPU HW 가속) 현대 CPU에서 무시할 수준
P99 지연시간 증가 +1~3% (L4 mTLS) ztunnel 기준
메모리 (Sidecar 모드) ~60-100MB/Pod Envoy Sidecar 비용
메모리 (Ambient 모드) ~10-15MB/Node ztunnel 공유

실제 성능 병목은 mTLS 암호화가 아니라 L7 HTTP 파싱이다. Ambient ztunnel이 낮은 오버헤드를 보이는 이유는 L4에서만 동작하기 때문이다.

3.8 마이그레이션 전략: PERMISSIVE에서 STRICT로

┌───────────────────────────────────────────────────────────────┐
│         mTLS 마이그레이션 단계 (안전한 전환 절차)               │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  1단계: 현황 파악                                             │
│  ├─ 비메시 클라이언트 식별 (모니터링, CI/CD, 외부 시스템)     │
│  ├─ 헬스체크 포트 확인 (kubelet은 mTLS 불가)                 │
│  └─ 트래픽 메트릭 수집 (mTLS vs 평문 비율)                   │
│                                                               │
│  2단계: PERMISSIVE 적용 (메시 전체)                           │
│  ├─ mTLS + 평문 모두 허용                                    │
│  ├─ connection_security_policy 메트릭 모니터링                │
│  └─ 2주간 안정성 확인                                        │
│                                                               │
│  3단계: 네임스페이스별 STRICT 전환                            │
│  ├─ 비핵심 네임스페이스부터 STRICT                            │
│  ├─ portLevelMtls로 헬스체크 포트 예외 처리                  │
│  ├─ 에러 로그 모니터링 (connection reset, TLS handshake fail)│
│  └─ 문제 발생 시 즉시 PERMISSIVE로 롤백                     │
│                                                               │
│  4단계: 메시 전체 STRICT                                     │
│  ├─ istio-system에 STRICT PeerAuthentication 적용            │
│  ├─ 평문 트래픽 비율 0% 확인                                 │
│  └─ 완료 후 PERMISSIVE 정책 제거 (정리)                      │
└───────────────────────────────────────────────────────────────┘
# mTLS 적용 비율 모니터링 (Prometheus 쿼리)
# mTLS 연결 비율 확인
sum(istio_requests_total{connection_security_policy="mutual_tls"}) /
sum(istio_requests_total) * 100

# 평문 연결 추적 (STRICT 전환 전 0%여야 함)
sum(istio_requests_total{connection_security_policy!="mutual_tls"}) by (source_workload, destination_workload)

4. Waypoint Proxy – Ambient Mesh의 L7 처리기

4.1 왜 등장했는가: Sidecar 모델의 리소스 오버헤드

기존 Istio Sidecar 모델에서는 모든 Pod에 Envoy Proxy가 주입된다. Pod가 1,000개면 Envoy도 1,000개가 실행되며, 이는 상당한 리소스 낭비이다.

┌───────────────────────────────────────────────────────────────┐
│            Sidecar 모델의 문제점                                │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  [Sidecar 모델 - 기존]                                        │
│                                                               │
│  Pod 1                Pod 2                Pod 3               │
│  ┌────────────┐      ┌────────────┐      ┌────────────┐     │
│  │ App (50MB) │      │ App (80MB) │      │ App (30MB) │     │
│  │ Envoy(70MB)│      │ Envoy(70MB)│      │ Envoy(70MB)│     │
│  └────────────┘      └────────────┘      └────────────┘     │
│                                                               │
│  문제점:                                                      │
│  - Pod 1000개 × Envoy 70MB = 약 70GB 메모리 소비              │
│  - Envoy 업그레이드 = 모든 Pod 재시작 (rolling restart)       │
│  - L7 파싱이 불필요한 TCP-only 서비스에도 Envoy 주입           │
│  - 사이드카 주입 실패 시 서비스 장애 가능                      │
│  - istio-init 컨테이너의 iptables 규칙으로 네트워크 복잡도 증가│
│                                                               │
│  벤치마크 (arXiv 2411.02267):                                 │
│  Sidecar 모델 P99 지연시간: +166% (베이스라인 대비)            │
└───────────────────────────────────────────────────────────────┘

4.2 Istio Ambient Mesh 2단계 아키텍처

Ambient Mesh는 프록시를 Pod에서 분리하여 2단계로 나눈다.

┌───────────────────────────────────────────────────────────────┐
│            Ambient Mesh 2단계 아키텍처                          │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │ 1단계: ztunnel (Zero Trust Tunnel) - L4 처리             │ │
│  │                                                         │ │
│  │ - DaemonSet (노드당 1개)                                │ │
│  │ - L4 TCP 프록시                                         │ │
│  │ - mTLS 암호화/복호화 (SPIFFE ID)                        │ │
│  │ - L4 AuthorizationPolicy (IP/포트 기반)                 │ │
│  │ - L4 Telemetry (TCP 메트릭)                             │ │
│  │ - HBONE 터널링 (포트 15008)                             │ │
│  │ - Pod 재시작 불필요, 네임스페이스 레이블만으로 활성화    │ │
│  │                                                         │ │
│  │ 성능: P99 +8% (매우 낮은 오버헤드)                      │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                               │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │ 2단계: Waypoint Proxy - L7 처리 (선택적)                 │ │
│  │                                                         │ │
│  │ - Deployment (네임스페이스당 또는 서비스당)              │ │
│  │ - L7 HTTP/gRPC 파싱                                     │ │
│  │ - VirtualService (라우팅, Canary, A/B)                  │ │
│  │ - L7 AuthorizationPolicy (HTTP 메서드/경로 기반)        │ │
│  │ - Circuit Breaker (outlierDetection)                    │ │
│  │ - Retry / Timeout                                       │ │
│  │ - RequestAuthentication (JWT 검증)                      │ │
│  │ - L7 Telemetry (HTTP 메트릭, 트레이싱)                  │ │
│  │                                                         │ │
│  │ L7이 필요한 서비스에만 선택적으로 배포                   │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                               │
│  핵심 원리: "필요한 곳에만 L7 비용을 지불한다"                │
└───────────────────────────────────────────────────────────────┘

4.3 HBONE 프로토콜 (HTTP CONNECT 기반 터널링)

HBONE (HTTP-Based Overlay Network Environment)은 ztunnel 간 통신에 사용되는 터널링 프로토콜이다.

┌───────────────────────────────────────────────────────────────┐
│              HBONE 프로토콜 동작                                │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  HBONE = HTTP/2 CONNECT 메서드 기반 터널                      │
│  포트: 15008 (ztunnel 전용)                                   │
│                                                               │
│  1. ztunnel A가 ztunnel B에 HTTP/2 CONNECT 요청:             │
│     CONNECT 10.0.1.5:8080 HTTP/2                              │
│     Host: 10.0.1.5:8080                                       │
│     x-]envoy-peer-metadata: (원본 Pod 메타데이터)              │
│                                                               │
│  2. ztunnel B가 200 OK 응답:                                  │
│     HTTP/2 200 OK                                             │
│                                                               │
│  3. 터널 수립 후 원본 TCP 데이터 투명 전달                    │
│                                                               │
│  데이터 흐름:                                                 │
│  ┌────────┐      ┌──────────┐      ┌──────────┐    ┌────────┐│
│  │ App A  │─TCP─►│ztunnel A │─HBONE│ztunnel B │─TCP│ App B  ││
│  │        │      │ mTLS암호화│:15008│ mTLS복호화│─►  │        ││
│  └────────┘      └──────────┘      └──────────┘    └────────┘│
│                                                               │
│  장점:                                                        │
│  - 표준 HTTP/2 사용 → 기존 인프라(로드밸런서, 방화벽) 호환    │
│  - mTLS가 터널 레벨에서 적용 → 애플리케이션 무관               │
│  - HTTP/2 멀티플렉싱 → 다수 연결을 하나의 HBONE 터널로 공유   │
└───────────────────────────────────────────────────────────────┘

4.4 Gateway API 연동 (gateway.networking.k8s.io/Gateway)

Waypoint Proxy는 Kubernetes Gateway API 리소스로 선언한다.

# payment 네임스페이스에 Waypoint Proxy 배포
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  labels:
    istio.io/waypoint-for: service     # 서비스 레벨 Waypoint
  name: payment-waypoint
  namespace: payment
spec:
  gatewayClassName: istio-waypoint     # Istio Waypoint 클래스
  listeners:
    - name: mesh
      port: 15008                      # HBONE 포트
      protocol: HBONE                  # HBONE 프로토콜
# istioctl로 Waypoint 배포 (간편 명령)
istioctl waypoint apply --namespace payment --name payment-waypoint

# 특정 서비스에 Waypoint 연결
kubectl label service payment-service \
  istio.io/use-waypoint=payment-waypoint \
  -n payment

Waypoint 적용 범위 제어:

레이블 위치 효과
istio.io/waypoint-for: service Gateway 서비스 트래픽에 적용
istio.io/waypoint-for: workload Gateway 워크로드(Pod) 트래픽에 적용
istio.io/waypoint-for: all Gateway 모든 트래픽에 적용
istio.io/use-waypoint: <name> Service/Namespace 특정 Waypoint 지정

4.5 Sidecar vs Ambient 비교

항목 Sidecar 모델 Ambient 모델
프록시 위치 Pod 내부 (컨테이너) 노드(ztunnel) + 네임스페이스(Waypoint)
L4 mTLS Sidecar Envoy ztunnel (DaemonSet)
L7 처리 Sidecar Envoy Waypoint Proxy (선택적)
메모리 (1000 Pod) ~70GB (70MB x 1000) ~1.5GB (ztunnel 공유 + Waypoint 일부)
P99 오버헤드 +166% (arXiv) +8% (L4 only)
Pod 재시작 Sidecar 주입/업그레이드 시 필요 불필요
활성화 방법 Namespace 레이블 + Pod 재시작 Namespace 레이블만
EnvoyFilter 지원 미지원 (WASM 대체)
성숙도 프로덕션 검증 (2017~) GA (Istio v1.24, Nov 2024)
혼합 사용 - 같은 메시에서 Sidecar와 혼용 가능

4.6 리소스 절감 효과

┌───────────────────────────────────────────────────────────────┐
│           리소스 절감 효과 (Sidecar → Ambient 전환)             │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  사례: 500 Pod 클러스터 (10 노드, 50 Pod/노드)                │
│                                                               │
│  [Sidecar 모델]                                               │
│  - Envoy: 500 x 70MB  = 35,000 MB (35 GB)                    │
│  - Istio-init: 500 x 10MB = 5,000 MB (시작 시)               │
│  - 총 메모리: ~35 GB (상시)                                    │
│                                                               │
│  [Ambient 모델 - L4 only]                                     │
│  - ztunnel: 10 x 40MB = 400 MB                                │
│  - 총 메모리: ~400 MB (상시)                                   │
│  - 절감: 약 98.9%                                             │
│                                                               │
│  [Ambient 모델 - L4 + Waypoint (30% 서비스)]                  │
│  - ztunnel: 10 x 40MB = 400 MB                                │
│  - Waypoint: 5 x 100MB = 500 MB                               │
│  - 총 메모리: ~900 MB (상시)                                   │
│  - 절감: 약 97.4%                                             │
│                                                               │
│  메모리 비교 (막대 그래프):                                    │
│  Sidecar    ████████████████████████████████████  35,000 MB   │
│  Ambient L4 █                                       400 MB   │
│  Ambient+WP ██                                      900 MB   │
│                                                               │
│  최대 90% 이상 메모리 절감 달성                                │
└───────────────────────────────────────────────────────────────┘

4.7 Istio v1.24 GA 이후 프로덕션 전환 가이드

Istio v1.24 (2024년 11월)에서 Ambient Mesh가 GA(General Availability)로 승격되었다.

프로덕션 전환 단계:

┌───────────────────────────────────────────────────────────────┐
│        Sidecar → Ambient 프로덕션 전환 가이드                   │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  사전 조건:                                                   │
│  ├─ Istio v1.24 이상                                         │
│  ├─ CNI 플러그인 호환성 확인 (Cilium, Calico 등)             │
│  └─ HBONE 포트(15008) 방화벽/SecurityGroup 허용              │
│                                                               │
│  1단계: 비프로덕션 환경 테스트 (2주)                          │
│  ├─ dev/staging 네임스페이스에 ambient 레이블 적용            │
│  ├─ kubectl label ns dev istio.io/dataplane-mode=ambient     │
│  ├─ 기존 사이드카 Pod과 Ambient Pod 간 통신 테스트            │
│  └─ L4 mTLS 메트릭 확인                                     │
│                                                               │
│  2단계: 비핵심 프로덕션 서비스 전환 (2주)                     │
│  ├─ 모니터링/로깅 등 비핵심 네임스페이스 전환                 │
│  ├─ 사이드카 injection 비활성화                               │
│  │  kubectl label ns monitoring istio-injection-             │
│  ├─ Ambient 활성화                                           │
│  │  kubectl label ns monitoring istio.io/dataplane-mode=ambient│
│  └─ Pod 재시작으로 사이드카 제거                              │
│                                                               │
│  3단계: L7 서비스에 Waypoint 배포 (1주)                       │
│  ├─ L7 정책이 필요한 서비스에만 Waypoint 추가                 │
│  ├─ VirtualService, AuthorizationPolicy 동작 확인             │
│  └─ Waypoint HPA/리소스 설정                                  │
│                                                               │
│  4단계: 핵심 프로덕션 서비스 전환 (2주)                       │
│  ├─ 핵심 서비스 네임스페이스 순차 전환                        │
│  ├─ 카나리 방식: 일부 Pod만 먼저 전환                         │
│  └─ 모든 메트릭 안정 확인 후 전체 전환                        │
│                                                               │
│  5단계: 정리                                                  │
│  ├─ 모든 네임스페이스 ambient 확인                            │
│  ├─ 불필요한 Sidecar 관련 리소스 정리                         │
│  └─ istio-injection 관련 레이블/웹훅 제거                     │
└───────────────────────────────────────────────────────────────┘

5. Circuit Breaker – 연쇄 장애 방지

5.1 왜 등장했는가: 마이크로서비스 연쇄 장애

마이크로서비스 아키텍처에서는 서비스 간 의존성이 복잡하다. 하나의 서비스 장애가 호출 체인을 따라 전파되어 전체 시스템 장애로 이어질 수 있다.

┌───────────────────────────────────────────────────────────────┐
│              연쇄 장애 (Cascading Failure) 시나리오             │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  정상 상태:                                                   │
│  order-svc ──► payment-svc ──► bank-api (외부)               │
│  200 OK         200 OK          200 OK                        │
│  응답: 50ms     응답: 100ms     응답: 200ms                   │
│                                                               │
│  bank-api 장애 발생:                                          │
│  order-svc ──► payment-svc ──► bank-api (외부)               │
│  ??? (대기)     ??? (대기)      ✕ Timeout (30s)               │
│                                                               │
│  연쇄 장애 전파:                                              │
│  1. bank-api 응답 없음 → payment-svc 스레드 고갈              │
│  2. payment-svc 응답 없음 → order-svc 스레드 고갈             │
│  3. order-svc 응답 없음 → frontend 장애                       │
│  4. frontend 장애 → 전체 서비스 중단                          │
│                                                               │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐                 │
│  │ frontend │   │ order    │   │ payment  │   ┌──────────┐  │
│  │   ✕      │◄──│   ✕      │◄──│   ✕      │◄──│ bank-api │  │
│  │ 스레드   │   │ 스레드   │   │ 스레드   │   │   ✕      │  │
│  │ 풀 고갈  │   │ 풀 고갈  │   │ 풀 고갈  │   │ 원인     │  │
│  └──────────┘   └──────────┘   └──────────┘   └──────────┘  │
│                                                               │
│  핵심 문제: 장애 서비스에 계속 요청을 보내서 리소스 낭비      │
└───────────────────────────────────────────────────────────────┘

5.2 Retry/Timeout만으로는 부족한 이유

패턴 대상 한계
Timeout 단일 요청의 대기 시간 제한 장애 서비스에 계속 요청 전송. 부하 가중
Retry 일시적(Transient) 장애 복구 지속적 장애 시 Retry Storm 발생. 부하 N배 증가
Circuit Breaker 지속적 장애 격리 장애 감지 시 요청 자체를 차단 (Fail-Fast). 복구 시간 확보

Timeout과 Retry는 일시적 장애에 효과적이지만, 지속적 장애에서는 오히려 상황을 악화시킨다. Circuit Breaker는 장애가 지속될 때 빠르게 실패하여 리소스를 보호한다.

5.3 상태 머신: Closed -> Open -> Half-Open

Circuit Breaker는 3가지 상태를 순환하는 상태 머신이다.

┌───────────────────────────────────────────────────────────────┐
│            Circuit Breaker 상태 머신                            │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│                   실패율 < 임계값                              │
│                  ┌──────────────┐                             │
│                  │              │                             │
│                  ▼              │                             │
│            ┌──────────┐        │                             │
│     ──────►│  CLOSED  │────────┘                             │
│     │      │ (정상)    │                                      │
│     │      └────┬─────┘                                      │
│     │           │                                            │
│     │           │ 실패율 >= 임계값                            │
│     │           │ (예: 50% 이상 또는 연속 5회 에러)           │
│     │           ▼                                            │
│     │      ┌──────────┐                                      │
│     │      │  OPEN    │   ← 모든 요청 즉시 실패 (503)        │
│     │      │ (차단)    │   ← 장애 서비스 보호                 │
│     │      └────┬─────┘                                      │
│     │           │                                            │
│     │           │ 대기 시간 경과 (baseEjectionTime)           │
│     │           │ (예: 30초)                                  │
│     │           ▼                                            │
│     │      ┌──────────┐                                      │
│     └──────│HALF-OPEN │   ← 제한된 프로브 요청만 허용         │
│   성공     │ (시험)    │   ← 성공하면 CLOSED로 복귀           │
│            └──────────┘   ← 실패하면 다시 OPEN               │
│                                                               │
│  CLOSED    : 정상 상태. 모든 요청 통과. 실패율 모니터링       │
│  OPEN      : 차단 상태. 즉시 실패 반환 (Fail-Fast)           │
│  HALF-OPEN : 시험 상태. 제한된 요청만 통과시켜 복구 확인      │
└───────────────────────────────────────────────────────────────┘

5.4 Netflix Hystrix -> Resilience4j -> Istio/Envoy 진화 역사

┌───────────────────────────────────────────────────────────────┐
│            Circuit Breaker 진화 역사                            │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  2007  Michael Nygard "Release It!" 출간                      │
│        └─ 소프트웨어에서 Circuit Breaker 패턴 최초 정의       │
│                                                               │
│  2012  Netflix Hystrix 오픈소스 공개                           │
│        └─ 마이크로서비스에서 대중화                            │
│        └─ Netflix 내부 수천 서비스에 적용                      │
│        └─ 애플리케이션 코드에 직접 구현 (Java 라이브러리)     │
│                                                               │
│  2017  Istio/Envoy 출시                                       │
│        └─ 인프라 레벨 Circuit Breaking 도입                   │
│        └─ 애플리케이션 코드 변경 없이 적용                    │
│        └─ YAML 선언만으로 Circuit Breaker 설정                │
│                                                               │
│  2018.11  Netflix Hystrix maintenance 모드 선언               │
│           └─ Resilience4j가 공식 후속 라이브러리               │
│           └─ Hystrix 대비 가볍고 함수형 프로그래밍 지원       │
│                                                               │
│  2024  Istio Ambient Mesh GA                                  │
│        └─ Sidecarless Circuit Breaking 가능                   │
│        └─ Waypoint Proxy에서 L7 Circuit Breaker 실행          │
│                                                               │
│  진화 방향:                                                   │
│  애플리케이션 레벨(코드) → 인프라 레벨(YAML) → 선택적 L7     │
└───────────────────────────────────────────────────────────────┘

5.5 outlierDetection (수동적/패시브 감지)

실제 트래픽의 응답을 모니터링하여 비정상 엔드포인트를 자동으로 제거한다.

# payment-service에 대한 Outlier Detection 설정
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: payment-service
  namespace: production
spec:
  host: payment-service
  trafficPolicy:
    outlierDetection:
      # 감지 조건
      consecutive5xxErrors: 3          # 3회 연속 5xx → 즉시 제거
      consecutiveGatewayErrors: 3      # 3회 연속 502/503/504 → 제거
      interval: 5s                     # 5초 간격으로 분석

      # 제거 정책
      baseEjectionTime: 30s            # 최소 30초 제거 (이후 점진 증가)
      maxEjectionPercent: 50           # 최대 50%만 제거 (가용성 보장)

      # Panic Threshold
      minHealthPercent: 30             # 건강한 호스트 30% 미만이면 제거 중지

동작 원리:

┌───────────────────────────────────────────────────────────────┐
│              Outlier Detection 동작 원리                        │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  order-svc ──요청──► Envoy/Waypoint (로드밸런서)              │
│                          │                                    │
│                          ├──► Pod A: 200, 200, 200 (정상)     │
│                          ├──► Pod B: 200, 503, 503 (경고)     │
│                          └──► Pod C: 503, 503, 503 (3연속!)   │
│                                                               │
│  interval(5s) 후 분석:                                        │
│  - Pod A: 정상 → 유지                                        │
│  - Pod B: 연속 에러 2회 → 아직 임계값(3) 미달 → 유지          │
│  - Pod C: 연속 에러 3회 → 임계값 도달 → 제거!                │
│                                                               │
│  Pod C 제거 후:                                               │
│  order-svc ──요청──► Envoy/Waypoint                           │
│                          ├──► Pod A: 정상                     │
│                          └──► Pod B: 정상                     │
│                          (Pod C: 30초간 제거 = ejected)       │
│                                                               │
│  30초 후 (baseEjectionTime):                                  │
│  Pod C를 다시 풀에 추가하여 프로브 요청 전송                  │
│  - 성공 → 풀에 복귀                                          │
│  - 실패 → 다시 제거 (제거 시간 2배 증가: 60초)               │
└───────────────────────────────────────────────────────────────┘

5.6 connectionPool (능동적/프로액티브 보호, Bulkhead 패턴)

connectionPool은 장애가 발생하기 전에 리소스 사용량을 제한한다. 이는 Bulkhead(격벽) 패턴의 인프라 구현이다.

# payment-service에 대한 Connection Pool 설정 (Bulkhead)
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: payment-bulkhead
  namespace: production
spec:
  host: payment-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100            # 최대 TCP 연결 100개
        connectTimeout: 5s             # TCP 연결 타임아웃 5초
      http:
        http1MaxPendingRequests: 50    # HTTP/1.1 대기 큐 50개
        http2MaxRequests: 200          # HTTP/2 동시 요청 200개
        maxRequestsPerConnection: 50   # 연결당 50 요청 후 재연결
        maxRetries: 3                  # 동시 재시도 3개 제한

connectionPool vs outlierDetection 비교:

항목 connectionPool (Bulkhead) outlierDetection (CB)
타이밍 사전 예방 (Proactive) 사후 대응 (Reactive)
감지 방식 리소스 임계값 초과 에러 응답 패턴
차단 대상 초과 요청 전체 비정상 엔드포인트만
응답 503 (overflow) 라우팅 풀에서 제거
비유 선박 격벽 (침수 격리) 전기 차단기 (과부하 차단)

5.7 Panic Threshold (최소 건강한 호스트 비율)

outlierDetection의 minHealthPercent 설정이다. 건강한 호스트 비율이 이 값 아래로 내려가면 모든 호스트에 트래픽을 분배한다 (Panic Mode).

┌───────────────────────────────────────────────────────────────┐
│              Panic Threshold 동작                               │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  설정: minHealthPercent: 50 (건강한 호스트 50% 유지)          │
│  Pod: 4개 (A, B, C, D)                                       │
│                                                               │
│  상황 1: Pod C 장애 (건강한 호스트 75%)                       │
│  → 75% > 50% → 정상 동작: Pod C만 제거                       │
│  → 트래픽: A, B, D에 분배                                    │
│                                                               │
│  상황 2: Pod B, C, D 장애 (건강한 호스트 25%)                 │
│  → 25% < 50% → Panic Mode 진입!                              │
│  → 모든 Pod(A, B, C, D)에 트래픽 분배                        │
│  → 이유: 장애 Pod에서라도 일부 요청이 성공할 수 있음          │
│         Pod A 하나에 모든 트래픽 집중 → A도 장애 위험          │
│                                                               │
│  Panic Mode 목적: "모두 장애보다 일부 성공이 낫다"            │
└───────────────────────────────────────────────────────────────┘

5.8 인프라 수준 vs 애플리케이션 수준 비교

항목 Istio/Envoy (인프라) Resilience4j (애플리케이션)
설정 방식 YAML (DestinationRule) Java/Kotlin 코드 또는 설정 파일
적용 범위 클러스터 전체 일괄 적용 서비스별 개별 적용
코드 변경 불필요 필요 (애노테이션 또는 래퍼)
Fallback 불가 (503 반환만) 커스텀 Fallback 로직 가능
언어 무관 O (모든 언어) Java/Kotlin 전용
상태 머신 간접적 (ejection 기반) 명시적 (Closed/Open/Half-Open)
메트릭 Envoy 메트릭 자동 수집 Micrometer 연동 필요
관측성 Kiali, Grafana 통합 Actuator 엔드포인트
권장 기본 보호 (모든 서비스) 핵심 서비스 추가 보호

함께 사용하는 것이 권장된다. Istio가 인프라 레벨에서 비정상 Pod를 제거하고, Resilience4j가 애플리케이션 레벨에서 커스텀 Fallback을 실행한다.


6. 4가지 기술 통합 아키텍처

HTTP/2, mTLS, Waypoint Proxy, Circuit Breaker가 하나의 요청 흐름에서 어떻게 협력하는지 보여준다.

┌──────────────────────────────────────────────────────────────────────┐
│              Istio Ambient Mesh 통합 아키텍처 (요청 흐름)             │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  [order-service Pod]                       [payment-service Pod]     │
│  (1) HTTP/2 gRPC 요청 생성                 (7) HTTP/2 gRPC 수신     │
│       │                                           ▲                  │
│       │ 평문 (Pod 내부)                           │ 평문             │
│       ▼                                           │                  │
│  [ztunnel - Node A]                        [ztunnel - Node B]        │
│  (2) SPIFFE ID로 mTLS 핸드셰이크           (6) mTLS 복호화          │
│  (3) HBONE 터널 캡슐화 (포트 15008)        (5) HBONE 디캡슐화       │
│       │                                           ▲                  │
│       │  mTLS 암호화된 HBONE 터널                 │                  │
│       ▼                                           │                  │
│  [Waypoint Proxy]─────────────────────────────────┘                  │
│  (4) L7 처리:                                                        │
│      ├─ HTTP/2 바이너리 프레임 파싱                                  │
│      ├─ L7 AuthorizationPolicy 인가 검사                             │
│      ├─ Circuit Breaker 검사 (outlierDetection)                      │
│      │  └─ 대상 Pod 건강 여부 확인                                   │
│      │  └─ 비정상이면 503 즉시 반환 (Fail-Fast)                      │
│      ├─ connectionPool 검사 (Bulkhead)                               │
│      │  └─ 동시 요청 수 확인                                         │
│      │  └─ 초과 시 503 overflow 반환                                 │
│      ├─ 로드밸런싱 (HTTP/2 요청 단위 ROUND_ROBIN)                    │
│      ├─ Retry/Timeout 정책 적용                                      │
│      └─ L7 Telemetry 수집 (HTTP 메트릭, 분산 트레이싱)              │
│                                                                      │
│  각 기술의 역할:                                                     │
│  ┌────────────────┬───────────────────────────────────────────┐      │
│  │ HTTP/2          │ 바이너리 프레이밍, 멀티플렉싱, HPACK 압축 │      │
│  │ mTLS            │ ztunnel 간 상호 인증 + AES-GCM 암호화     │      │
│  │ Waypoint Proxy  │ L7 트래픽 관리 엔진 (라우팅, 인가, CB)    │      │
│  │ Circuit Breaker │ 비정상 Pod 격리, Bulkhead 리소스 보호      │      │
│  └────────────────┴───────────────────────────────────────────┘      │
└──────────────────────────────────────────────────────────────────────┘

데이터 흐름 상세:

단계 위치 동작 관련 기술
1 order-service Pod HTTP/2(gRPC) 요청 생성 HTTP/2
2 ztunnel (Node A) SPIFFE ID로 mTLS 핸드셰이크, AES-GCM 암호화 mTLS
3 ztunnel (Node A) HBONE 터널로 캡슐화, 포트 15008 전송 HBONE
4 Waypoint Proxy HTTP/2 프레임 파싱, Circuit Breaker 검사, 라우팅 결정 Waypoint + CB
5 ztunnel (Node B) HBONE 디캡슐화 HBONE
6 ztunnel (Node B) mTLS 복호화 mTLS
7 payment-service Pod HTTP/2(gRPC) 요청 수신 및 처리 HTTP/2

7. 실전 시나리오별 적용 가이드

7.1 시나리오 1: 결제 서비스 보호 (Circuit Breaker + mTLS)

결제 서비스는 가장 높은 수준의 보호가 필요하다. Circuit Breaker + Bulkhead + mTLS STRICT를 조합한다.

# 1. payment 네임스페이스 mTLS STRICT 적용
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: payment-strict
  namespace: payment
spec:
  mtls:
    mode: STRICT                       # 평문 요청 거부 (결제 데이터 보호)
  portLevelMtls:
    8081:
      mode: PERMISSIVE                 # 헬스체크 포트 예외
---
# 2. payment-service Circuit Breaker + Bulkhead
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: payment-protection
  namespace: payment
spec:
  host: payment-service
  trafficPolicy:
    # Bulkhead: 연결 풀 제한
    connectionPool:
      tcp:
        maxConnections: 50             # 결제 서비스 최대 연결 50개
        connectTimeout: 3s             # 빠른 실패
      http:
        http2MaxRequests: 200          # 동시 요청 200개 제한
        http1MaxPendingRequests: 20    # 대기 큐 20개 제한
        maxRetries: 2                  # 재시도 최대 2회 (결제는 보수적)
    # Circuit Breaker: 장애 엔드포인트 제거
    outlierDetection:
      consecutive5xxErrors: 3          # 3회 연속 5xx → 즉시 제거
      interval: 5s                     # 5초 간격 분석 (빠른 감지)
      baseEjectionTime: 60s            # 60초 제거 (결제는 보수적)
      maxEjectionPercent: 30           # 최대 30%만 제거 (가용성 보장)
      minHealthPercent: 50             # 50% 미만이면 Panic Mode
---
# 3. 결제 요청 Timeout + Retry 정책
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: payment-routing
  namespace: payment
spec:
  hosts:
    - payment-service
  http:
    - route:
        - destination:
            host: payment-service
          weight: 100
      timeout: 5s                      # 결제 요청 타임아웃 5초
      retries:
        attempts: 2                    # 최대 2회 재시도
        perTryTimeout: 3s              # 재시도당 3초 타임아웃
        retryOn: "5xx,reset,connect-failure"

7.2 시나리오 2: gRPC 서비스 최적화 (HTTP/2 + Load Balancing)

gRPC는 HTTP/2를 필수로 사용하므로, K8s에서의 로드밸런싱 문제를 반드시 해결해야 한다.

# gRPC 서비스를 위한 통합 설정
# HTTP/2 로드밸런싱 + mTLS + Circuit Breaker
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: order-grpc-config
  namespace: production
spec:
  host: order-service
  trafficPolicy:
    # mTLS 설정
    tls:
      mode: ISTIO_MUTUAL
    # HTTP/2 연결 관리 (로드밸런싱 문제 해결)
    connectionPool:
      http:
        h2UpgradePolicy: UPGRADE       # HTTP/2 업그레이드 강제
        http2MaxRequests: 1000          # gRPC 동시 요청 허용량
        maxRequestsPerConnection: 100   # 연결당 100 요청 후 재연결 → 재분배
    # gRPC 장애 감지
    outlierDetection:
      consecutiveGatewayErrors: 3       # gRPC 게이트웨이 에러 감지
      consecutive5xxErrors: 5
      interval: 10s
      baseEjectionTime: 30s
      maxEjectionPercent: 50
    # L7 로드밸런싱
    loadBalancer:
      simple: ROUND_ROBIN
// order-service gRPC 서버 설정 (Go)
// MaxConnectionAge로 연결 재분배 강제
server := grpc.NewServer(
    grpc.KeepaliveParams(keepalive.ServerParameters{
        MaxConnectionAge:      5 * time.Minute,   // 5분마다 연결 갱신
        MaxConnectionAgeGrace: 30 * time.Second,   // 진행 중 요청 완료 유예
        Time:                  30 * time.Second,   // Keepalive 핑 간격
        Timeout:               10 * time.Second,   // 핑 응답 타임아웃
    }),
)
# gRPC Service 정의 (appProtocol 명시)
apiVersion: v1
kind: Service
metadata:
  name: order-service
  namespace: production
spec:
  selector:
    app: order-service
  ports:
    - name: grpc-order
      port: 50051
      targetPort: 50051
      appProtocol: kubernetes.io/h2c   # gRPC(h2c) 명시

7.3 시나리오 3: 멀티 클러스터 통신 (mTLS + Waypoint)

서로 다른 K8s 클러스터에 있는 서비스 간 안전한 통신을 구성한다.

┌───────────────────────────────────────────────────────────────┐
│              멀티 클러스터 통신 아키텍처                        │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  Cluster A (ap-northeast-2a)     Cluster B (ap-northeast-2c) │
│  ┌──────────────────────┐       ┌──────────────────────┐     │
│  │ order-service        │       │ payment-service      │     │
│  │     │                │       │       ▲              │     │
│  │     ▼                │       │       │              │     │
│  │ ztunnel ──mTLS──────────────────► ztunnel           │     │
│  │     │                │       │       │              │     │
│  │     ▼                │       │       ▼              │     │
│  │ East-West Gateway    │       │ East-West Gateway    │     │
│  │ (Istio Gateway)      │       │ (Istio Gateway)      │     │
│  └──────────────────────┘       └──────────────────────┘     │
│                                                               │
│  핵심 요구사항:                                               │
│  - 공유 Root CA (두 클러스터가 같은 신뢰 도메인)              │
│  - East-West Gateway로 클러스터 간 mTLS 트래픽 터널링         │
│  - DNS 또는 Istio ServiceEntry로 원격 서비스 검색              │
└───────────────────────────────────────────────────────────────┘
# Cluster A: 원격 payment-service 검색을 위한 ServiceEntry
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: payment-service-cluster-b
  namespace: production
spec:
  hosts:
    - payment-service.payment.svc.cluster.local
  location: MESH_INTERNAL
  ports:
    - number: 50051
      name: grpc
      protocol: GRPC
  resolution: DNS
  endpoints:
    - address: cluster-b-eastwest-gw.example.com   # Cluster B East-West Gateway
      ports:
        grpc: 15443                                  # mTLS 포트
---
# Cluster A: 원격 서비스에 대한 mTLS + Circuit Breaker
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: payment-service-cross-cluster
  namespace: production
spec:
  host: payment-service.payment.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL                            # 클러스터 간 mTLS
    connectionPool:
      tcp:
        connectTimeout: 10s                          # 클러스터 간 네트워크 지연 고려
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 10s
      baseEjectionTime: 60s                          # 원격 클러스터 복구 시간 여유

멀티 클러스터 mTLS 사전 조건:

항목 설정 방법
공유 Root CA 두 클러스터에 같은 Root CA 인증서 배포 (cert-manager 또는 Istio 외부 CA)
신뢰 도메인 meshConfig.trustDomain: cluster.local (동일)
East-West Gateway 각 클러스터에 Istio IngressGateway 배포 (포트 15443)
서비스 검색 ServiceEntry 또는 Istio Multi-Primary 모드
방화벽 클러스터 간 15443(mTLS), 15012(istiod) 포트 허용

7.4 시나리오 4: 레거시에서 서비스메시 마이그레이션 (PERMISSIVE mTLS + Sidecar -> Ambient)

기존 레거시 시스템을 단계적으로 서비스 메시에 통합하는 전략이다.

┌───────────────────────────────────────────────────────────────┐
│           레거시 → 서비스메시 마이그레이션 단계                  │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  Phase 1: PERMISSIVE mTLS (2주)                               │
│  ├─ Ambient 모드 활성화 (레이블만 추가, 재시작 불필요)        │
│  ├─ 레거시 서비스: 평문 통신 유지                             │
│  ├─ 메시 서비스: mTLS 자동 활성화                             │
│  ├─ PERMISSIVE → 평문 + mTLS 공존                            │
│  └─ 메트릭 수집: mTLS 비율 모니터링                           │
│                                                               │
│  Phase 2: 레거시 서비스 Ambient 편입 (2주)                    │
│  ├─ 레거시 서비스 네임스페이스에 ambient 레이블 추가          │
│  ├─ ztunnel이 자동으로 L4 mTLS 적용                          │
│  ├─ 애플리케이션 코드 변경 없음                               │
│  └─ mTLS 비율 100% 목표                                      │
│                                                               │
│  Phase 3: STRICT mTLS 전환 (1주)                              │
│  ├─ 비핵심 네임스페이스부터 STRICT                            │
│  ├─ 평문 트래픽 0% 확인                                      │
│  └─ 핵심 네임스페이스 STRICT                                  │
│                                                               │
│  Phase 4: L7 정책 활성화 (1주)                                │
│  ├─ 필요한 서비스에 Waypoint 배포                             │
│  ├─ Circuit Breaker, Retry, Timeout 설정                      │
│  └─ L7 AuthorizationPolicy 적용                               │
│                                                               │
│  Phase 5: (선택) Sidecar → Ambient 전환                       │
│  ├─ 기존 Sidecar 서비스가 있으면 Ambient로 마이그레이션       │
│  ├─ 혼합 모드에서 점진적 전환                                 │
│  └─ Sidecar injection 비활성화 + Pod 재시작                   │
└───────────────────────────────────────────────────────────────┘
# Phase 1: 네임스페이스 Ambient 모드 활성화
# Pod 재시작 불필요!
kubectl label namespace legacy-app istio.io/dataplane-mode=ambient

# Phase 1: PERMISSIVE mTLS (레거시 평문 허용)
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: legacy-permissive
  namespace: legacy-app
spec:
  mtls:
    mode: PERMISSIVE                   # 평문 + mTLS 모두 허용
---
# Phase 3: STRICT mTLS 전환 (평문 0% 확인 후)
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: legacy-strict
  namespace: legacy-app
spec:
  mtls:
    mode: STRICT                       # 평문 거부, mTLS만 허용
---
# Phase 4: 레거시 서비스에 Waypoint 배포 (L7 정책 필요 시)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  labels:
    istio.io/waypoint-for: service
  name: legacy-waypoint
  namespace: legacy-app
spec:
  gatewayClassName: istio-waypoint
  listeners:
    - name: mesh
      port: 15008
      protocol: HBONE

8. YAML 설정 레퍼런스

8.1 PeerAuthentication YAML

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: example                        # 정책 이름
  namespace: production                # 적용 범위 (istio-system = mesh-wide)
spec:
  selector:                            # 선택적: 특정 워크로드만 대상
    matchLabels:
      app: order-service               # 이 레이블의 Pod에만 적용
  mtls:
    mode: STRICT                       # STRICT | PERMISSIVE | DISABLE | UNSET
    # STRICT    : mTLS만 허용, 평문 거부
    # PERMISSIVE: mTLS + 평문 모두 허용 (마이그레이션 중)
    # DISABLE   : mTLS 비활성화 (특수 케이스)
    # UNSET     : 상위 정책 상속
  portLevelMtls:                       # 선택적: 포트별 오버라이드
    8080:
      mode: PERMISSIVE                 # 이 포트만 평문 허용 (헬스체크 등)
    9090:
      mode: DISABLE                    # 이 포트는 mTLS 비활성화

적용 우선순위 (높은 순):

  1. 워크로드별 (selector 지정)
  2. 네임스페이스별 (namespace 지정, selector 없음)
  3. 메시 전체 (istio-system 네임스페이스)

8.2 DestinationRule (outlierDetection + connectionPool) YAML

apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: order-service-resilience       # 규칙 이름
  namespace: production
spec:
  host: order-service                  # 대상 서비스
  trafficPolicy:
    # ── outlierDetection: 비정상 엔드포인트 패시브 감지 ──
    outlierDetection:
      consecutive5xxErrors: 5          # 기본값: 5. 연속 5xx 에러 횟수
      consecutiveGatewayErrors: 0      # 기본값: 0 (비활성). 502/503/504 에러 횟수
      consecutiveLocalOriginFailures: 5 # 기본값: 5. 로컬 원인 실패 횟수
      interval: 10s                    # 기본값: 10s. 분석 주기
      baseEjectionTime: 30s            # 기본값: 30s. 최소 제거 시간 (이후 2배씩 증가)
      maxEjectionPercent: 10           # 기본값: 10. 최대 제거 비율 (%)
      minHealthPercent: 0              # 기본값: 0. Panic Threshold (%)
      splitExternalLocalOriginErrors: false  # 기본값: false. 로컬/원격 에러 분리
    # ── connectionPool: 프로액티브 리소스 보호 (Bulkhead) ──
    connectionPool:
      tcp:
        maxConnections: 1024           # 기본값: 2^32-1. 최대 TCP 연결
        connectTimeout: 10s            # 기본값: 10s. TCP 연결 타임아웃
        tcpKeepalive:
          time: 7200s                  # TCP Keepalive 시작 시간
          interval: 75s                # Keepalive 프로브 간격
          probes: 10                   # 최대 프로브 횟수
        maxConnectionDuration: 0s      # 기본값: 0 (무제한). 연결 최대 수명
      http:
        http1MaxPendingRequests: 1024  # 기본값: 1024. HTTP/1.1 대기 큐
        http2MaxRequests: 1024         # 기본값: 1024. HTTP/2 동시 요청
        maxRequestsPerConnection: 0    # 기본값: 0 (무제한). 연결당 요청 수
        maxRetries: 3                  # 기본값: 2^32-1. 동시 재시도 수
        idleTimeout: 3600s             # 기본값: 1h. 유휴 연결 타임아웃
        h2UpgradePolicy: DEFAULT       # DEFAULT | UPGRADE | DO_NOT_UPGRADE
        useClientProtocol: false       # 클라이언트 프로토콜 유지 여부

outlierDetection 필드별 권장값:

필드 기본값 권장값 설명
consecutive5xxErrors 5 3-5 값이 작으면 민감, 크면 둔감
consecutiveGatewayErrors 0 (비활성) 3 gRPC 서비스에 권장. 502/503/504만 감지
interval 10s 5-10s 짧으면 빠른 감지, CPU 소비 증가
baseEjectionTime 30s 30-60s 너무 짧으면 불안정, 너무 길면 복구 지연
maxEjectionPercent 10 30-50 프로덕션에서는 50% 이하 권장
minHealthPercent 0 30-50 0이면 Panic Mode 비활성화

8.3 Gateway + Waypoint YAML

# Waypoint Proxy 배포 (네임스페이스 레벨)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  labels:
    istio.io/waypoint-for: service     # 서비스 트래픽에 적용
  name: production-waypoint            # Waypoint 이름
  namespace: production                # 배포할 네임스페이스
spec:
  gatewayClassName: istio-waypoint     # Istio Waypoint 전용 클래스
  listeners:
    - name: mesh                       # 리스너 이름
      port: 15008                      # HBONE 포트 (고정)
      protocol: HBONE                  # HBONE 프로토콜 (고정)
      # allowedRoutes:                 # 선택적: 라우트 제한
      #   namespaces:
      #     from: Same                 # 같은 네임스페이스 라우트만 허용
# 서비스에 Waypoint 연결 (레이블)
kubectl label service order-service \
  istio.io/use-waypoint=production-waypoint \
  -n production

# 또는 네임스페이스 전체에 Waypoint 연결
kubectl label namespace production \
  istio.io/use-waypoint=production-waypoint

Waypoint 리소스 설정 (HPA 포함):

# Waypoint Pod 리소스 및 오토스케일링
# istioctl waypoint apply 시 자동 생성되지만, 수동 설정 권장
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: production-waypoint
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: production-waypoint-istio-waypoint  # Waypoint Deployment 이름
  minReplicas: 2                       # 최소 2개 (고가용성)
  maxReplicas: 10                      # 최대 10개
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70       # CPU 70% 기준 오토스케일링

8.4 VirtualService (retry + timeout) YAML

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: order-service-routing          # VirtualService 이름
  namespace: production
spec:
  hosts:
    - order-service                    # 대상 서비스
  http:
    # 라우트 1: 카나리 배포 (v2에 10% 트래픽)
    - match:
        - headers:
            x-canary:
              exact: "true"            # 카나리 헤더가 있으면 v2로
      route:
        - destination:
            host: order-service
            subset: v2                 # v2 서브셋
          weight: 100
      timeout: 3s                      # 카나리 요청 타임아웃 3초
      retries:
        attempts: 1                    # 카나리는 재시도 1회만
        perTryTimeout: 2s
        retryOn: "5xx"

    # 라우트 2: 기본 트래픽 (v1)
    - route:
        - destination:
            host: order-service
            subset: v1                 # v1 서브셋 (안정 버전)
          weight: 100
      timeout: 10s                     # 기본 요청 타임아웃 10초
      retries:
        attempts: 3                    # 최대 3회 재시도
        perTryTimeout: 5s             # 재시도당 5초 타임아웃
        retryOn: "5xx,reset,connect-failure,retriable-status-codes"
        retryRemoteLocalities: true    # 원격 로컬리티에도 재시도
      fault:                           # 선택적: 장애 주입 (테스트용)
        delay:
          percentage:
            value: 0.1                 # 0.1% 요청에 지연 주입
          fixedDelay: 5s

retryOn 옵션 상세:

의미
5xx 서버 5xx 에러 시 재시도
reset 연결 리셋 시 재시도
connect-failure 연결 실패 시 재시도
retriable-status-codes x-envoy-retriable-status-codes 헤더의 코드
gateway-error 502, 503, 504 에러 시 재시도
retriable-4xx 409 에러 시 재시도
refused-stream REFUSED_STREAM 에러 시 재시도

9. 프로덕션 체크리스트

4가지 핵심 기술을 프로덕션에 배포할 때 확인해야 할 항목이다.

HTTP/2 체크리스트

  • 1. Service 포트에 appProtocol: http2 또는 name: grpc-* 설정
  • 2. gRPC 서비스: MaxConnectionAge 설정 (권장 3-5분)
  • 3. DestinationRule에 maxRequestsPerConnection 설정으로 연결 재분배
  • 4. http2MaxRequests 값을 서비스 용량에 맞게 조정
  • 5. h2c 사용 시 Service Mesh mTLS 또는 NetworkPolicy로 보호
  • 6. HPA 트리거 메트릭이 Pod별 요청 수 기준인지 확인
  • 7. HTTP/2 WINDOW_UPDATE 흐름 제어 설정 검토

mTLS 체크리스트

  • 1. PERMISSIVE 모드에서 시작하여 mTLS 연결 비율 모니터링
  • 2. 비메시 클라이언트(모니터링, CI/CD 등) 식별 및 예외 처리
  • 3. 헬스체크 포트 portLevelMtls 설정 확인
  • 4. 네임스페이스별 순차적으로 STRICT 전환
  • 5. connection_security_policy="mutual_tls" 메트릭 100% 확인
  • 6. 인증서 자동 갱신 동작 확인 (Istio 기본 24시간)
  • 7. Root CA 만료일 모니터링 알림 설정
  • 8. SPIFFE ID 기반 AuthorizationPolicy 설정 확인

Waypoint 체크리스트

  • 1. 네임스페이스에 istio.io/dataplane-mode: ambient 레이블 확인
  • 2. L7 정책이 필요한 서비스에만 Waypoint 배포 (불필요한 곳은 L4 only)
  • 3. Waypoint HPA 설정 (CPU 70% 기준 오토스케일링)
  • 4. Waypoint Pod의 리소스 requests/limits 설정
  • 5. 사이드카에서 Ambient 마이그레이션 시 혼합 모드 테스트 완료
  • 6. HBONE 포트(15008) 방화벽/SecurityGroup 허용 확인
  • 7. Waypoint 장애 시 L4 fallback 동작 확인

Circuit Breaker 체크리스트

  • 1. outlierDetection 설정 (최소 consecutive5xxErrors, interval, baseEjectionTime)
  • 2. maxEjectionPercent 50% 이하로 설정 (가용성 보장)
  • 3. minHealthPercent 30% 이상으로 설정 (Panic Threshold)
  • 4. connectionPool 설정 (maxConnections, http2MaxRequests)
  • 5. 핵심 서비스에 Resilience4j Fallback 로직 구현
  • 6. Grafana 대시보드에 ejection 이벤트 알림 설정
  • 7. Chaos Engineering 테스트로 Circuit Breaker 동작 검증
  • 8. VirtualService에 적절한 timeout/retries 설정 확인

10. 기술 선택 가이드

의사결정 플로우차트

┌───────────────────────────────────────────────────────────────────────┐
│                서비스 메시 기술 선택 플로우차트                         │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  시작: K8s 서비스 메시 도입 검토                                      │
│    │                                                                  │
│    ▼                                                                  │
│  ┌─────────────────────────────┐                                     │
│  │ 서비스 간 암호화/인증 필요? │                                     │
│  └─────────┬──────────┬────────┘                                     │
│       Yes  │          │  No                                           │
│            ▼          └──────► NetworkPolicy만으로 충분 (비권장)       │
│  ┌─────────────────────────┐                                         │
│  │ 리소스 제약이 있는가?    │                                         │
│  └────┬──────────┬─────────┘                                         │
│  Yes  │          │  No                                                │
│       ▼          ▼                                                    │
│  Ambient 모드    Sidecar도 가능                                       │
│  (ztunnel L4)    (선택의 여지 있음)                                   │
│    │                │                                                 │
│    ▼                ▼                                                 │
│  ┌─────────────────────────────────┐                                 │
│  │ L7 기능 필요? (라우팅, JWT,     │                                 │
│  │   Circuit Breaker, 카나리 등)   │                                 │
│  └─────────┬──────────┬────────────┘                                 │
│       Yes  │          │  No                                           │
│            ▼          └──────► L4 only (ztunnel)로 충분               │
│  ┌─────────────────────────┐      mTLS + L4 메트릭 확보              │
│  │ Waypoint Proxy 배포     │                                         │
│  │ (필요한 서비스에만)      │                                         │
│  └─────────┬───────────────┘                                         │
│            ▼                                                          │
│  ┌─────────────────────────────────┐                                 │
│  │ gRPC 서비스 사용?               │                                 │
│  └─────────┬──────────┬────────────┘                                 │
│       Yes  │          │  No                                           │
│            ▼          └──────► 기본 HTTP/1.1 + mTLS                  │
│  HTTP/2 최적화 필수:                                                  │
│  ├─ MaxConnectionAge 설정                                            │
│  ├─ L7 로드밸런싱 또는                                               │
│  │   Client-side LB 설정                                             │
│  └─ http2MaxRequests 조정                                            │
│            │                                                          │
│            ▼                                                          │
│  ┌─────────────────────────────────┐                                 │
│  │ 외부 의존성이 있는 핵심 서비스? │                                 │
│  │ (결제, 인증, 외부 API 등)       │                                 │
│  └─────────┬──────────┬────────────┘                                 │
│       Yes  │          │  No                                           │
│            ▼          └──────► 기본 outlierDetection만 설정           │
│  Circuit Breaker 강화:                                                │
│  ├─ outlierDetection (보수적 임계값)                                 │
│  ├─ connectionPool (Bulkhead)                                        │
│  └─ Resilience4j Fallback 구현                                       │
└───────────────────────────────────────────────────────────────────────┘

비용/복잡도/효과 매트릭스

기술 도입 비용 운영 복잡도 보안 효과 성능 효과 안정성 효과 권장 우선순위
mTLS (Ambient L4) 낮음 (레이블 1개) 낮음 매우 높음 +8% 오버헤드 중간 1 (가장 먼저)
mTLS (STRICT) 낮음 중간 (예외 관리) 매우 높음 동일 중간 2
Circuit Breaker 중간 (YAML 설정) 중간 (임계값 튜닝) - - 매우 높음 3
Waypoint Proxy 중간 (배포/HPA) 중간 높음 (L7 인가) 중간 오버헤드 높음 4 (필요 시)
HTTP/2 최적화 중간 (설정 복합) 중간 (LB 모니터링) - 높음 (압축, 멀티플렉싱) - 4 (gRPC 필수)
Resilience4j 높음 (코드 변경) 높음 (서비스별 관리) - - 매우 높음 5 (핵심 서비스)

상황별 필요 기술

상황 HTTP/2 mTLS Waypoint Circuit Breaker
gRPC 서비스 필수 권장 L7 필요 시 권장
REST API (HTTP/1.1) 선택적 권장 L7 필요 시 필요 시
레거시 HTTP/1.1 전용 불필요 권장 불필요 필요 시
컴플라이언스 (PCI/HIPAA) - 필수 L7 인가 정책 시 -
리소스 제한 환경 h2c 검토 Ambient 모드 ztunnel only (L4) 앱 레벨(Resilience4j)
대규모 클러스터 (500+ Pods) 필수 Ambient 모드 선택적 필수
개발/스테이징 선택적 PERMISSIVE 불필요 불필요

기술 도입 순서 권장

┌───────────────────────────────────────────────────────┐
│           권장 도입 순서                                │
├───────────────────────────────────────────────────────┤
│                                                       │
│  1단계: mTLS (PERMISSIVE)                             │
│  ├─ Ambient 모드 활성화 (레이블 하나)                 │
│  ├─ 즉시 L4 mTLS 획득                                │
│  └─ 리스크: 매우 낮음                                 │
│                                                       │
│  2단계: mTLS (STRICT)                                 │
│  ├─ PERMISSIVE에서 모니터링 후 전환                   │
│  ├─ Zero Trust 기반 확립                              │
│  └─ 리스크: 낮음 (단계적 전환)                        │
│                                                       │
│  3단계: Circuit Breaker                               │
│  ├─ 핵심 서비스에 outlierDetection 설정               │
│  ├─ connectionPool로 Bulkhead 적용                   │
│  └─ 리스크: 낮음 (관측 후 튜닝)                       │
│                                                       │
│  4단계: Waypoint + HTTP/2                             │
│  ├─ L7 정책이 필요한 서비스에 Waypoint 배포           │
│  ├─ gRPC 서비스에 HTTP/2 최적화 적용                  │
│  └─ 리스크: 중간 (L7 파싱 오버헤드 모니터링 필요)     │
└───────────────────────────────────────────────────────┘

11. 자주 묻는 질문 (FAQ)

Q1. mTLS를 적용하면 성능이 크게 떨어지나요?

A: mTLS 암호화 자체의 오버헤드는 미미하다. TLS 1.3 핸드셰이크는 1-RTT이며, 대칭키 암호화(AES-GCM)는 현대 CPU에서 하드웨어 가속(AES-NI)된다. 실제 오버헤드의 주요 원인은 L7 HTTP 파싱이다. Ambient 모드의 ztunnel(L4 only)을 사용하면 P99 지연시간 증가가 +8% 수준으로 매우 낮다 (arXiv 2411.02267).

Q2. Sidecar 모델에서 Ambient로 마이그레이션하는 것이 안전한가요?

A: 같은 메시에서 Sidecar와 Ambient를 혼용할 수 있다. 권장 절차:

  1. 새로운 네임스페이스를 Ambient로 시작
  2. 비핵심 서비스부터 Sidecar에서 Ambient로 전환
  3. 트래픽 메트릭 비교 후 핵심 서비스 전환
  4. Sidecar injection 비활성화 + Pod 재시작

Istio v1.24부터 GA이므로 프로덕션 사용에 적합하다.

Q3. Circuit Breaker의 임계값을 어떻게 정해야 하나요?

A: 정답은 없으며, 서비스 특성에 따라 튜닝해야 한다. 권장 시작점:

  • consecutive5xxErrors: 5 (기본값, 대부분 적합)
  • interval: 10s (기본값)
  • baseEjectionTime: 30s (결제 서비스는 60s)
  • maxEjectionPercent: 30-50% (레플리카 수에 따라)

프로덕션 배포 전에 Chaos Engineering 도구(Chaos Mesh, Litmus)로 장애 주입 테스트를 수행하여 적절한 임계값을 찾는다.

Q4. HTTP/2가 K8s에서 로드밸런싱 문제를 일으키면, HTTP/1.1로 돌아가야 하나요?

A: 아니다. HTTP/2의 성능 이점(멀티플렉싱, 헤더 압축)은 매우 크다. 문제는 kube-proxy의 L4 로드밸런싱 한계이며, 이는 3가지 방법으로 해결 가능하다:

  1. MaxConnectionAge 설정 (가장 간단, 서버 코드 3줄)
  2. Service Mesh L7 로드밸런싱 (가장 포괄적)
  3. Client-side 로드밸런싱 (Headless Service + round_robin)

Q5. Waypoint Proxy를 모든 네임스페이스에 배포해야 하나요?

A: 아니다. Waypoint는 L7 기능이 필요한 곳에만 선택적으로 배포한다. L4 기능(mTLS, TCP 로드밸런싱)만 필요한 서비스는 ztunnel만으로 충분하다. 이것이 Ambient 모델의 핵심 장점이다 – 필요한 곳에만 L7 비용을 지불한다.

L7이 필요한 경우:

  • HTTP 라우팅 (경로/헤더 기반)
  • L7 AuthorizationPolicy (HTTP 메서드/경로 기반 인가)
  • Circuit Breaker / Retry / Timeout
  • 카나리 배포 / 트래픽 분할
  • JWT 검증 (RequestAuthentication)

Q6. Resilience4j와 Istio Circuit Breaker를 함께 사용해도 되나요?

A: 오히려 함께 사용하는 것이 권장된다. 역할이 다르다:

  • Istio outlierDetection: 인프라 레벨에서 비정상 엔드포인트를 자동 제거. 모든 서비스에 일괄 적용.
  • Resilience4j: 애플리케이션 레벨에서 커스텀 Fallback 로직 실행. 핵심 비즈니스 서비스에 개별 적용.

예를 들어 Istio가 장애 Pod를 제거하고, 남은 Pod에서도 장애가 발생하면 Resilience4j가 Fallback(비동기 큐잉, 캐시 반환 등)을 실행한다.

Q7. HTTP/3(QUIC)는 언제 K8s 내부 통신에 도입해야 하나요?

A: 2026년 현재, K8s 내부 통신에 HTTP/3를 도입하기에는 이르다. Istio의 내부 통신 지원이 아직 없으며, Envoy 업스트림도 Alpha 수준이다. 외부 에지(CDN, API Gateway)에서 먼저 HTTP/3를 적용하고, 내부 통신은 HTTP/2 + mTLS로 유지하는 것이 안전하다. Envoy와 Istio의 HTTP/3 로드맵을 지속적으로 모니터링할 것을 권장한다.

Q8. Ambient Mesh에서 EnvoyFilter를 사용할 수 없는데, 커스텀 필터가 필요하면?

A: WASM (WebAssembly) 플러그인을 사용한다. Istio의 WasmPlugin API를 통해 Waypoint Proxy에 커스텀 필터를 배포할 수 있다. 현재 Alpha 상태이지만, EnvoyFilter의 공식 대체 방법이다. 또는 사이드카 모델을 해당 서비스에만 유지할 수 있다 (혼합 모드).

Q9. Istio Ambient와 Cilium Service Mesh 중 무엇을 선택해야 하나요?

A: 핵심 차이는 다음과 같다:

항목 Istio Ambient Cilium
L4 처리 ztunnel (유저스페이스) eBPF (커널)
L7 처리 Waypoint (Envoy) Envoy (별도 Pod)
P99 오버헤드 +8% (L4), 더 높음(L7) +99% (arXiv)
mTLS SPIFFE 기반 WireGuard 기반
L7 정책 성숙도 매우 높음 (Istio 생태계) 발전 중
CNI 종속성 없음 (기존 CNI 유지) Cilium CNI 필수

L7 정책 풍부함이 필요하면 Istio Ambient, eBPF 기반 네트워킹을 이미 사용 중이면 Cilium이 자연스러운 선택이다.

Q10. Pod가 100개 미만인 소규모 클러스터에서도 서비스 메시가 필요한가요?

A: 규모와 관계없이 보안 요구사항이 있다면 필요하다. 컴플라이언스(PCI DSS, HIPAA), Zero Trust 정책이 요구되면 Pod 수와 무관하게 mTLS를 적용해야 한다. Ambient 모드는 소규모 클러스터에서도 오버헤드가 매우 낮다 (노드당 ztunnel 1개, ~40MB). 순수 기능적 요구(라우팅, CB)만 필요하면 서비스 메시 없이도 가능하지만, mTLS를 위해서는 서비스 메시가 가장 효율적인 방법이다.

Q11. outlierDetection의 baseEjectionTime이 지나면 즉시 모든 트래픽을 받나요?

A: 아니다. baseEjectionTime이 경과하면 해당 엔드포인트가 로드밸런싱 풀에 다시 추가되지만, Envoy는 점진적으로 트래픽을 보낸다. 다시 에러가 발생하면 제거 시간이 baseEjectionTime * (제거 횟수)로 증가한다. 예를 들어 baseEjectionTime이 30s이고 2번째 제거이면 60s, 3번째이면 90s로 점진적으로 증가하여 반복적 장애 서비스의 영향을 최소화한다.

Q12. SPIFFE ID 기반 인가 정책은 어떻게 설정하나요?

A: Istio AuthorizationPolicy에서 source.principals로 SPIFFE ID를 사용한다:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: payment-allow-order
  namespace: payment
spec:
  action: ALLOW
  rules:
    - from:
        - source:
            # SPIFFE ID로 order-service만 허용
            principals:
              - "cluster.local/ns/production/sa/order-service"
      to:
        - operation:
            methods: ["POST"]
            paths: ["/api/v1/payments"]

이렇게 하면 order-service ServiceAccount의 SPIFFE ID를 가진 워크로드만 payment-service의 /api/v1/payments POST 엔드포인트에 접근할 수 있다.


12. 요약 및 키워드

4가지 핵심 기술 요약

기술 핵심 가치 K8s 구현 도입 우선순위
HTTP/2 멀티플렉싱으로 전송 효율 극대화 appProtocol, DestinationRule h2UpgradePolicy 4 (gRPC 시 필수)
mTLS Zero Trust 네트워크 보안 PeerAuthentication, Ambient ztunnel 1 (가장 먼저)
Waypoint Proxy Sidecar 없는 L7 트래픽 관리 Gateway API, istio-waypoint 4 (L7 필요 시)
Circuit Breaker 연쇄 장애 방지, Fail-Fast outlierDetection, connectionPool 3 (핵심 서비스)

기술 간 관계 요약

┌───────────────────────────────────────────────────────────────┐
│                                                               │
│  HTTP/2  ───전송 기반 제공───►  mTLS                          │
│    │         (바이너리 프레이밍)    │                          │
│    │                              │                          │
│    │                              │ 터널 보호                │
│    │ 프레임 파싱                   │ (HBONE/SPIFFE)          │
│    │                              │                          │
│    ▼                              ▼                          │
│  Waypoint Proxy  ◄──실행 환경──  ztunnel                     │
│    │                              (L4 mTLS)                  │
│    │                                                         │
│    │ Circuit Breaker 실행                                    │
│    │ (outlierDetection + connectionPool)                     │
│    ▼                                                         │
│  건강한 Pod에만 트래픽 전달                                   │
│                                                               │
└───────────────────────────────────────────────────────────────┘

핵심 수치 요약

항목 수치 출처
Istio Sidecar P99 오버헤드 +166% arXiv 2411.02267
Istio Ambient P99 오버헤드 +8% arXiv 2411.02267
Linkerd P99 오버헤드 +33% arXiv 2411.02267
Cilium P99 오버헤드 +99% arXiv 2411.02267
HPACK 헤더 압축률 평균 69% Cloudflare
HTTP/3 글로벌 트래픽 비율 25% Cloudflare Radar 2025
Ambient 메모리 절감 최대 90%+ Sidecar 대비
Istio 인증서 기본 수명 24시간 Istio 기본 설정
mTLS 지연시간 오버헤드 +1~3% L4 ztunnel 기준

키워드 목록

HTTP/2, HTTP/3, QUIC, HPACK, Multiplexing, Binary Framing,
h2, h2c, ALPN, MaxConnectionAge, gRPC, Head-of-Line Blocking,
mTLS, Mutual TLS, Zero Trust, PeerAuthentication, STRICT, PERMISSIVE,
SPIFFE, SPIRE, SVID, X.509, cert-manager, Certificate Rotation,
Waypoint Proxy, Ambient Mesh, ztunnel, HBONE, Sidecar, DaemonSet,
Gateway API, istio-waypoint, istio.io/use-waypoint,
Circuit Breaker, Outlier Detection, Connection Pool, Bulkhead,
Resilience4j, Netflix Hystrix, Cascading Failure, Panic Threshold,
Closed, Open, Half-Open, Fail-Fast, Retry Storm,
Envoy, Istio, Linkerd, Cilium, Service Mesh, Kubernetes,
arXiv 2411.02267, WASM, WasmPlugin, East-West Gateway