Day 9: Istio Service Mesh 소개와 첫걸음

문한성·3일 전
0

K8S 정복하기

목록 보기
9/9

목차

  1. 마이크로서비스의 한계와 Service Mesh의 필요성
  2. Istio란 무엇인가
  3. Istio 아키텍처 깊이 이해하기
  4. 실습: Istio 환경 구축
  5. Gateway와 VirtualService 완벽 이해
  6. 트래픽 흐름 완전 분석
  7. Istio의 강력한 기능들
  8. 다음 계획

1. 마이크로서비스의 한계와 Service Mesh의 필요성

마이크로서비스 환경의 복잡성

현대 클라우드 네이티브 애플리케이션은 수십, 수백 개의 마이크로서비스로 구성됩니다. 각 서비스는 독립적으로 배포되고 확장되지만, 이로 인해 새로운 문제들이 발생합니다:

전통적인 모놀리식 아키텍처:
┌─────────────────────────────┐
│     Single Application   │
│  ┌─────┐ ┌─────┐ ┌─────┐   │
│  │ UI  │ │Logic│ │ DB  │  │
│  └─────┘ └─────┘ └─────┘   │
└─────────────────────────────┘
문제: 단일 장애점, 확장성 제한

마이크로서비스 아키텍처:
┌─────┐    ┌─────┐      ┌─────┐
│User │───▶│Order│───▶│ Pay │
│  UI │    │ Svc │     │ Svc │
└─────┘    └──┬──┘      └─────┘
              │
              ├─────▶┌─────┐
              │      │Notif│
              │      └─────┘
              │
              └─────▶┌─────┐
                     │ Log │
                     └─────┘
문제: 서비스 간 통신 복잡도 폭발!

개발자가 직면하는 문제들

1. 서비스 간 통신 관리의 복잡성

# 각 서비스 코드에 반복적으로 작성해야 하는 코드들

# 재시도 로직
for retry in range(3):
    try:
        response = requests.get('http://payment-service/pay')
        break
    except TimeoutError:
        if retry == 2:
            raise
        time.sleep(2 ** retry)

# 타임아웃 설정
response = requests.get('http://service', timeout=3.0)

# 서킷 브레이커
if circuit_breaker.is_open('payment-service'):
    return fallback_response()

# 로깅
logger.info(f"Calling {service_name} at {timestamp}")

# 메트릭 수집
metrics.increment('http_requests_total')

문제점:

  • 모든 서비스에 동일한 로직 중복 구현
  • 언어별로 다른 라이브러리 사용 (Java, Python, Go...)
  • 업그레이드 시 모든 서비스 수정 필요
  • 일관성 없는 구현

2. 관측성(Observability) 부재

  • "어느 서비스에서 장애가 발생했나?"
  • "왜 응답 시간이 느려졌나?"
  • "서비스 A → B → C로 요청이 흐르는데 어디서 병목인가?"

3. 보안 문제

  • 서비스 간 통신 암호화 (mTLS) 수동 구현
  • 인증/인가 로직 각 서비스에 구현
  • 인증서 관리의 복잡성

Service Mesh가 해결하는 방법

핵심 아이디어: 네트워크 기능을 애플리케이션 코드에서 분리

Service Mesh 없이:
┌─────────────────────────────┐
│   Application Code        │
│  ┌──────────────────────┐   │
│  │  Business Logic    │   │
│  ├──────────────────────┤   │
│  │ ❌ Retry Logic      │  │ ← 중복 코드!
│  │ ❌ Timeout          │  │
│  │ ❌ Metrics          │  │
│  │ ❌ Tracing          │  │
│  │ ❌ mTLS             │  │
│  └──────────────────────┘   │
└─────────────────────────────┘

Service Mesh와 함께:
┌─────────────────────────────┐
│   Application Code        │
│  ┌──────────────────────┐   │
│  │  Business Logic     │  │ ← 비즈니스 로직만!
│  │  (순수 코드)         │  │
│  └──────────────────────┘   │
└─────────────────────────────┘
              ↕
┌─────────────────────────────┐
│      Sidecar Proxy        │
│  ┌──────────────────────┐   │
│  │ ✅ Retry Logic      │  │ ← 인프라 레벨에서 처리
│  │ ✅ Timeout          │  │
│  │ ✅ Metrics          │  │
│  │ ✅ Tracing          │  │
│  │ ✅ mTLS             │  │
│  └──────────────────────┘   │
└─────────────────────────────┘

2. Istio란 무엇인가

Istio 정의

Istio는 오픈소스 Service Mesh 플랫폼으로, 마이크로서비스 간 통신을 관리하고 보안, 관측성, 트래픽 제어를 제공하는 인프라 레이어입니다.

주요 특징:

  • 애플리케이션 코드 변경 없음: 기존 서비스 그대로 사용
  • 언어 독립적: Java, Python, Go, Node.js 등 모두 지원
  • 선언적 구성: YAML로 트래픽 정책 정의
  • 강력한 관측성: 메트릭, 로그, 분산 추적 자동 제공

Istio가 제공하는 핵심 기능

┌──────────────────────────────────────────────────────┐
│                   Istio Service Mesh            │
├──────────────────────────────────────────────────────┤
│                                                 │
│  📊 Traffic Management (트래픽 관리)              │
│  ├─ Canary Deployment (점진적 배포)               │
│  ├─ A/B Testing (버전 분기)                       │
│  ├─ Circuit Breaker (장애 격리)                   │
│  └─ Retry & Timeout (자동 재시도)                  │
│                                                  │
│  🔒 Security (보안)                              │
│  ├─ Mutual TLS (서비스 간 암호화)                  │
│  ├─ Authentication (인증)                         │
│  └─ Authorization (권한 관리)                      │
│                                                  │
│  👁 Observability (관측성)                         │
│  ├─ Metrics (메트릭 자동 수집)                      │
│  ├─ Distributed Tracing (분산 추적)                │
│  ├─ Access Logs (접근 로그)                        │
│  └─ Topology Visualization (토폴로지 시각화)        │
│                                                  │
└──────────────────────────────────────────────────────┘

3. Istio 아키텍처 깊이 이해하기

전체 아키텍처

┌─────────────────────────────────────────────────────────────┐
│                    Control Plane                       │
│  ┌────────────────────────────────────────────────────┐    │
│  │                    istiod                     │     │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────────┐    │     │
│  │  │  Pilot  │  │ Citadel  │  │   Galley   │    │     │
│  │  │(트래픽)  │  │ (보안)   │  │ (설정 검증)   │    │     │
│  │  └──────────┘  └──────────┘  └──────────────┘    │     │
│  └─────────────────────┬──────────────────────────────┘     │
│                        │ xDS API (설정 푸시)             │
└────────────────────────┼────────────────────────────────────┘
                         │
        ┌────────────────┼────────────────┐
        │                │             │
        ▼                ▼             ▼
┌─────────────────────────────────────────────────────────────┐
│                      Data Plane                        │
│  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐       │
│  │   Pod A    │   │   Pod B    │   │   Pod C    │       │
│  │ ┌─────────┐ │   │ ┌─────────┐ │   │ ┌─────────┐ │       │
│  │ │  App   │ │   │ │  App    │ │   │ │  App   │ │       │
│  │ └────┬────┘ │   │ └────┬────┘ │   │ └────┬────┘ │       │
│  │     │      │   │      │      │   │      │     │       │
│  │ ┌────▼────┐ │   │ ┌────▼────┐ │    │ ┌────▼────┐ │       │
│  │ │ Envoy  │◀┼───┼▶│ Envoy  │◀┼───┼▶│ Envoy  │ │      │
│  │ │ Proxy  │ │   │ │ Proxy   │ │    │ │ Proxy  │ │      │
│  │ └─────────┘ │   │  └─────────┘ │   │ └─────────┘ │       │
│  └─────────────┘    └─────────────┘   └─────────────┘       │
│      Sidecar           Sidecar           Sidecar       │
└─────────────────────────────────────────────────────────────┘

Control Plane: istiod

istiod는 3가지 핵심 컴포넌트를 통합한 단일 바이너리입니다 (Istio 1.5 이후):

1. Pilot (트래픽 관리)

역할: VirtualService, DestinationRule 등을 Envoy 설정으로 변환

예시:
VirtualService (사람이 작성) → Pilot → Envoy Config (기계가 이해)

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: reviews-route
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        user:
          exact: "jason"
    route:
    - destination:
        host: reviews
        subset: v2    # jason만 v2로 라우팅
  - route:
    - destination:
        host: reviews
        subset: v1    # 나머지는 v1로

2. Citadel (보안 관리)

역할: 인증서 자동 발급 및 갱신

동작 과정:
1. Pod 생성 시 Service Account 확인
2. X.509 인증서 자동 발급 (90일 만료)
3. Envoy에 인증서 주입
4. 서비스 간 mTLS 자동 활성화
5. 인증서 만료 전 자동 갱신

결과: 개발자가 인증서 관리 불필요!

3. Galley (설정 검증)

역할: Istio 설정 YAML 유효성 검증

검증 항목:
- YAML 문법 오류
- 필수 필드 누락
- 중복된 리소스
- 참조 무결성 (존재하지 않는 서비스 참조 등)

kubectl apply 전에 미리 검증:
istioctl analyze

Data Plane: Envoy Proxy

Envoy는 고성능 L7 프록시로 각 Pod에 Sidecar로 주입됩니다.

Sidecar 패턴 동작 원리:

Pod 내부 구조:

┌─────────────────────────────────────────────┐
│              Pod (productpage-v1)       │
│                                         │
│  ┌────────────────────────────────────┐    │
│  │    productpage Container        │    │
│  │    (Python Flask App)           │    │
│  │    Port: 9080                   │    │
│  │    localhost:9080으로 요청 보냄   │    │
│  └──────────────┬─────────────────────┘    │
│                │                        │
│                │ 127.0.0.1:9080         │
│                ▼                        │
│  ┌────────────────────────────────────┐    │
│  │    istio-proxy Container        │    │
│  │    (Envoy Sidecar)              │    │
│  │                                 │    │
│  │  ┌──────────────────────────────┐  │    │
│  │  │  Inbound Listener         │  │    │
│  │  │  15006: 모든 inbound 트래픽 │  │    │
│  │  └──────────────────────────────┘  │    │
│  │                                 │    │
│  │  ┌──────────────────────────────┐  │    │
│  │  │  Outbound Listener        │  │    │
│  │  │  15001: 모든 outbound 트래픽│  │    │
│  │  └──────────────────────────────┘  │    │
│  └────────────────────────────────────┘    │
│                                         │
└─────────────────────────────────────────────┘

Envoy가 수행하는 작업:

  1. 트래픽 인터셉트

    # iptables 규칙으로 모든 트래픽을 Envoy로 리다이렉트
    
    Outbound 트래픽:
    App → localhost:9080
        ↓ (iptables 리다이렉트)
    Envoy:15001 → 목적지 서비스
    
    Inbound 트래픽:
    외부 → Envoy:15006 → App:9080
  2. 로드 밸런싱

    reviews 서비스 호출 시:
    
    Envoy가 3개 엔드포인트 중 선택:
    - reviews-v1-pod-1 (10.1.2.3:9080)
    - reviews-v2-pod-1 (10.1.2.4:9080)
    - reviews-v3-pod-1 (10.1.2.5:9080)
    
    알고리즘: Round Robin, Random, Least Request
  3. 재시도 & 타임아웃

    # VirtualService에 정의
    http:
    - route:
      - destination:
          host: reviews
      retries:
        attempts: 3           # 3번 재시도
        perTryTimeout: 2s     # 시도당 2초
  4. 메트릭 자동 수집

    모든 요청에 대해 자동 수집:
    - 요청 수 (istio_requests_total)
    - 응답 시간 (istio_request_duration_milliseconds)
    - 에러율 (istio_request_errors_total)
    - 트래픽 크기 (istio_request_bytes)

4. 실습: Istio 환경 구축

환경 정보

# 클러스터 정보
kubectl get nodes -o wide
NAME   ROLES           VERSION    INTERNAL-IP
cpu1   control-plane   v1.31.13   172.30.1.43
cpu2   worker          v1.31.13   172.30.1.80
gpu1   worker          v1.31.13   172.30.1.38

Step 1: Istio 다운로드

cd ~/istio-demo
curl -L https://istio.io/downloadIstio | sh -

# 환경변수 설정
export PATH="/root/istio-demo/istio-1.28.0/bin:$PATH"

# 확인
istioctl version

다운로드된 디렉토리 구조:

istio-1.28.0/
├── bin/
│   └── istioctl              # Istio CLI 도구
├── manifests/
│   ├── profiles/             # 설치 프로파일
│   │   ├── default.yaml      # 프로덕션용 (우리가 사용)
│   │   ├── demo.yaml         # 데모/학습용
│   │   └── minimal.yaml      # 최소 설치
│   └── charts/               # Helm Charts
├── samples/
│   ├── bookinfo/             # 샘플 애플리케이션
│   │   ├── platform/kube/    # Pod/Service 정의
│   │   └── networking/       # Gateway/VirtualService
│   └── addons/               # 관측 도구
│       ├── kiali.yaml
│       ├── prometheus.yaml
│       └── grafana.yaml
└── tools/                    # 유틸리티

Step 2: Istio 설치 (default 프로파일)

프로파일 비교:

프로파일용도istiodIngress GWEgress GW
default프로덕션
demo학습/데모
minimal최소 구성

설치 명령:

istioctl install --set profile=default -y

설치 결과 확인:

kubectl get pods -n istio-system -o wide
NAME                                    READY   STATUS    NODE
istiod-57b4d7f8b8-875cs                 1/1     Running   cpu2
istio-ingressgateway-76cc55cb99-9nvnt   1/1     Running   cpu1

컴포넌트 설명:

  1. istiod (Control Plane)

    • Pilot: 트래픽 관리
    • Citadel: mTLS 인증서 관리
    • Galley: 설정 검증
    • 단일 바이너리로 통합
  2. istio-ingressgateway (Ingress Gateway)

    • 외부 트래픽 진입점
    • Envoy 기반 L7 로드 밸런서
    • LoadBalancer 타입 Service

왜 Egress Gateway가 없나?

  • default 프로파일은 프로덕션 환경 최적화
  • Egress Gateway는 외부 API 호출 제어가 필요할 때만 사용
  • 필요시 별도 설치 가능

Step 3: Sidecar 자동 주입 설정

Sidecar 자동 주입 원리:

Kubernetes Mutating Admission Webhook 활용

1. kubectl apply로 Pod 생성 요청
   ↓
2. API Server가 Webhook 호출
   ↓
3. Istio가 Pod spec 수정 (istio-proxy 컨테이너 추가)
   ↓
4. 수정된 spec으로 Pod 생성

default namespace에 자동 주입 활성화:

kubectl label namespace default istio-injection=enabled

# 확인
kubectl get namespace default --show-labels
NAME      LABELS
default   istio-injection=enabled,kubernetes.io/metadata.name=default

동작 확인:

  • 이제 default namespace에 생성되는 모든 Pod에 자동으로 istio-proxy 컨테이너가 주입됩니다.

Step 4: Bookinfo 샘플 애플리케이션 배포

Bookinfo 아키텍처:

┌──────────────────────────────────────────────────────┐
│                   Bookinfo App                   │
│                                                  │
│  ┌─────────────┐                                  │
│  │ productpage│ (Python)                         │
│  │     v1     │                                  │
│  └──────┬──────┘                                  │
│         │                                        │
│    ├────┼─────┬─────────────┐                      │
│    │    │     │             │                    │
│    ▼    ▼     ▼             ▼                    │
│  ┌───┐ ┌───┐ ┌───┐         ┌───┐                    │
│  │det│ │rev│ │rev│        │rat│                   │
│  │ v1│ │ v1│ │ v2│ ★     │ v1│                  │
│  └───┘ └───┘ └─┬─┘         └───┘                    │
│  Ruby   Java   │ │         Node.js               │
│                │ │                               │
│              ┌─▼─▼┐                              │
│              │rev │ ★★                         │
│              │ v3 │                              │
│              └────┘                              │
│               Java                               │
│                                                  │
│  ★ = reviews v2/v3는 ratings 호출                │
│  v1/v2/v3 = 3가지 버전으로 Canary 테스트 가능       │
└──────────────────────────────────────────────────────┘

배포:

kubectl apply -f ~/istio-demo/istio-1.28.0/samples/bookinfo/platform/kube/bookinfo.yaml

결과 확인:

kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-77b775f46-m68lr        2/2     Running   0          5m
productpage-v1-78dfd4688c-k7m2h   2/2     Running   0          5m
ratings-v1-7c4c8d6794-bgd99       2/2     Running   0          5m
reviews-v1-849f9bc5d6-glqll       2/2     Running   0          5m
reviews-v2-5c757d5846-rxn2k       2/2     Running   0          5m
reviews-v3-6d5d98f5c4-n4gj8       2/2     Running   0          5m

Sidecar 주입 확인:

kubectl get pod productpage-v1-78dfd4688c-k7m2h -o jsonpath='{range .spec.containers[*]}{.name}{"\n"}{end}'
productpage       ← 애플리케이션 컨테이너
istio-proxy       ← Envoy Sidecar (자동 주입됨!)

Pod 내부 구조 확인:

kubectl describe pod productpage-v1-78dfd4688c-k7m2h
Init Containers:
  istio-init:                    # iptables 규칙 설정
    Image: docker.io/istio/proxyv2:1.28.0

Containers:
  productpage:                   # 애플리케이션
    Image: docker.io/istio/examples-bookinfo-productpage-v1:1.20.3
    Port: 9080/TCP

  istio-proxy:                   # Envoy Sidecar
    Image: docker.io/istio/proxyv2:1.28.0
    Ports: 15090/TCP (메트릭), 15021/TCP (헬스체크)

5. Gateway와 VirtualService 완벽 이해

Gateway 리소스

Gateway는 Istio의 외부 트래픽 진입점 설정입니다.

apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  # 어떤 Ingress Gateway Pod에 이 설정을 적용할지 선택
  selector:
    istio: ingressgateway    # istio=ingressgateway 라벨을 가진 Pod 선택

  # 어떤 포트와 프로토콜을 열지 정의
  servers:
  - port:
      number: 8080           # Envoy 내부 리스닝 포트
      name: http
      protocol: HTTP
    hosts:
    - "*"                    # 모든 호스트명 허용

항목별 설명:

항목설명예시
selector어떤 Ingress Gateway Pod에 적용할지istio: ingressgateway
port.numberEnvoy가 리스닝할 포트8080 (Service에서 80→8080 매핑)
port.protocol프로토콜HTTP, HTTPS, TCP
hosts허용할 호스트명* (모두), bookinfo.com

Selector 매칭 원리:

# Gateway 리소스의 selector
selector:
  istio: ingressgateway

# istio-ingressgateway Pod의 라벨 확인
kubectl get pod -n istio-system -l istio=ingressgateway --show-labels
NAME                                    LABELS
istio-ingressgateway-76cc55cb99-9nvnt   istio=ingressgateway,...
                                                ↑
                                        매칭됨! 이 Pod에 설정 적용

VirtualService 리소스

VirtualService는 트래픽 라우팅 규칙을 정의합니다.

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: bookinfo
spec:
  # 어떤 호스트 요청을 처리할지
  hosts:
  - "*"                      # 모든 호스트 요청 받음

  # 어느 Gateway를 통해 들어온 트래픽에 적용할지
  gateways:
  - bookinfo-gateway         # 위에서 만든 Gateway와 연결

  # HTTP 라우팅 규칙
  http:
  - match:                   # 다음 URL 중 하나라도 매칭되면
    - uri:
        exact: /productpage       # 정확히 /productpage
    - uri:
        prefix: /static           # /static으로 시작
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products

    route:                   # 위 조건에 매칭되면 여기로 라우팅
    - destination:
        host: productpage    # productpage 서비스로 전달
        port:
          number: 9080       # 9080 포트로

항목별 설명:

항목설명예시
hosts처리할 호스트명*, reviews.default.svc.cluster.local
gateways적용할 Gatewaybookinfo-gateway, mesh (내부 트래픽)
match.uri.exact정확한 경로 매칭/productpage
match.uri.prefix접두사 매칭/static/static/css/style.css 포함
destination.host목적지 서비스productpage (Kubernetes Service 이름)

Gateway + VirtualService 연결 원리:

1. Gateway 리소스 생성
   name: bookinfo-gateway

2. VirtualService에서 참조
   gateways:
   - bookinfo-gateway    ← 이름으로 연결!

3. istiod가 매칭을 감지하고 Envoy 설정 생성

배포 및 확인

kubectl apply -f ~/istio-demo/istio-1.28.0/samples/bookinfo/networking/bookinfo-gateway.yaml

# 확인
kubectl get gateway,virtualservice
NAME                                           AGE
gateway.networking.istio.io/bookinfo-gateway   1m

NAME                                          GATEWAYS               HOSTS
virtualservice.networking.istio.io/bookinfo   ["bookinfo-gateway"]   ["*"]

6. 트래픽 흐름 완전 분석

포트 매핑 이해

istio-ingressgateway Service 확인:

kubectl get svc -n istio-system istio-ingressgateway -o yaml | grep -A 20 "ports:"
ports:
- name: status-port
  nodePort: 30670
  port: 15021
  targetPort: 15021
- name: http2
  nodePort: 30192         # ← NodePort (외부 접근)
  port: 80                # ← Service Port
  targetPort: 8080        # ← Pod 내부 Envoy 포트
- name: https
  nodePort: 31797
  port: 443
  targetPort: 8443

포트 매핑:

외부 요청: http://172.30.1.43:30192/productpage

NodePort 30192
    ↓
Service Port 80
    ↓
Pod targetPort 8080
    ↓
Envoy Listener (0.0.0.0:8080)
    ↓
Gateway 리소스 (port: 8080에서 매칭)
    ↓
VirtualService 라우팅 (/productpage → productpage:9080)
    ↓
productpage Service (ClusterIP 10.105.75.162:9080)
    ↓
productpage Pod
    ├─ istio-proxy (15006 → 9080 포트포워딩)
    └─ productpage Container (9080)

전체 트래픽 흐름 다이어그램

┌─────────────────────────────────────────────────────────────────────┐
│                         외부 사용자 (브라우저)                   │
│                    curl http://172.30.1.43:30192/productpage  │
└──────────────────────┬──────────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────────────┐
│                    Kubernetes Node (cpu1)                     │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │          NodePort 30192 (iptables NAT)                 │   │
│  │          DNAT: 외부IP:30192 → Service:80                │   │
│  └──────────────────────┬──────────────────────────────────────┘   │
└─────────────────────────┼───────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────────────┐
│              istio-ingressgateway Service                     │
│                  Type: LoadBalancer                           │
│                  ClusterIP: 10.104.64.238:80                  │
│  ┌────────────────────────────────────────────────────────────┐    │
│  │  PORT MAPPING:                                         │    │
│  │  port: 80  →  targetPort: 8080                         │    │
│  └──────────────────────┬─────────────────────────────────────┘    │
└─────────────────────────┼───────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────────────┐
│         istio-ingressgateway Pod (istio-system namespace)     │
│  ┌────────────────────────────────────────────────────────────┐    │
│  │              Envoy Proxy (Container)                  │    │
│  │  ┌──────────────────────────────────────────────────┐      │    │
│  │  │  Listener: 0.0.0.0:8080 (HTTP)               │      │    │
│  │  │  "8080 포트에서 HTTP 요청 대기 중..."           │      │    │
│  │  └─────────────────┬────────────────────────────────┘      │    │
│  │                    │                                   │    │
│  │                    ▼                                   │    │
│  │  ┌──────────────────────────────────────────────────┐      │    │
│  │  │  Gateway 리소스 매칭 (bookinfo-gateway)        │      │    │
│  │  │  - selector: istio=ingressgateway ✓          │      │    │
│  │  │  - port: 8080 ✓                              │      │    │
│  │  │  - hosts: "*" ✓                              │      │    │
│  │  │  → "이 Gateway 설정 적용!"                     │      │    │
│  │  └─────────────────┬────────────────────────────────┘      │    │
│  │                    │                                   │    │
│  │                    ▼                                   │    │
│  │  ┌──────────────────────────────────────────────────┐      │    │
│  │  │  VirtualService 라우팅 규칙 (bookinfo)         │      │    │
│  │  │  - gateways: [bookinfo-gateway] ✓            │      │    │
│  │  │  - uri.exact: "/productpage" ✓               │      │    │
│  │  │  - destination.host: "productpage"           │      │    │
│  │  │  - destination.port: 9080                    │      │    │
│  │  │  → "productpage:9080으로 라우팅!"              │      │    │
│  │  └─────────────────┬────────────────────────────────┘      │    │
│  └────────────────────┼───────────────────────────────────────┘    │
└─────────────────────────┼───────────────────────────────────────────┘
                          │ HTTP Request
                          │ Host: productpage:9080
                          │ Path: /productpage
                          ▼
┌─────────────────────────────────────────────────────────────────────┐
│              productpage Service (ClusterIP)                  │
│                  ClusterIP: 10.105.75.162:9080                │
│                  Selector: app=productpage                    │
│  ┌────────────────────────────────────────────────────────────┐    │
│  │  Endpoint: productpage-v1-pod (10.244.2.15:9080)      │    │
│  └──────────────────────┬─────────────────────────────────────┘    │
└─────────────────────────┼───────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────────────┐
│                  productpage-v1 Pod (default namespace)       │
│  ┌───────────────────┐    ┌────────────────────────────────────┐   │
│  │  istio-proxy      │    │                                │   │
│  │  (Envoy Sidecar)  │    │                                │   │
│  │                   │    │                                │   │
│  │  Inbound:         │    │                                │   │
│  │  15006 포트       │───▶│  productpage Container         │   │
│  │    ↓              │    │  (Python Flask App)            │   │
│  │  iptables로       │    │  Port: 9080                    │   │
│  │  9080으로 전달    │    │  "HTML 응답 생성"                 │   │
│  │                   │    │                                │   │
│  └───────────────────┘    └────────────────────────────────────┘    │
│         │                                                      │
│         │ 메트릭 수집, 로그 기록, 트레이스 생성                     │
│         ↓                                                      │
│  [Prometheus, Jaeger로 전송]                                    │
└─────────────────────────────────────────────────────────────────────┘

실제 테스트

# 클러스터 내부에서 테스트
curl -s http://172.30.1.43:30192/productpage | head -20
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Simple Bookstore App</title>

성공! Gateway → VirtualService → productpage 흐름이 정상 작동합니다.


7. Istio의 강력한 기능들

1. Traffic Management (트래픽 관리)

Canary Deployment (카나리 배포)

기존 방식 vs Istio:

기존 Kubernetes:
- Deployment replicas 조정으로 비율 제어
- 정밀한 비율 제어 어려움 (예: 95:5 불가능)
- 코드 변경 필요

Istio:
- VirtualService로 정확한 비율 제어
- 코드 변경 없이 YAML만 수정
- 헤더 기반 라우팅 가능

예시: reviews v3로 10% 트래픽 전환

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 90         # 90% → v1
    - destination:
        host: reviews
        subset: v3
      weight: 10         # 10% → v3 (신규 버전)

사용 시나리오:
1. 새 버전 배포 시 10%만 테스트
2. 에러율 모니터링
3. 문제 없으면 50% → 100% 점진적 증가

A/B Testing (사용자 기반 라우팅)

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        user:
          exact: "jason"    # jason 사용자만
    route:
    - destination:
        host: reviews
        subset: v2          # v2로 라우팅 (별점 검은색)
  - route:
    - destination:
        host: reviews
        subset: v1          # 나머지는 v1 (별점 없음)

Circuit Breaker (장애 격리)

apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100        # 최대 연결 수
      http:
        http1MaxPendingRequests: 10
        maxRequestsPerConnection: 2
    outlierDetection:              # 비정상 인스턴스 자동 제외
      consecutiveErrors: 5         # 5회 연속 실패 시
      interval: 30s                # 30초마다 체크
      baseEjectionTime: 30s        # 30초간 제외

동작:
1. reviews-v2 Pod가 5회 연속 에러 응답
2. Envoy가 해당 Pod를 30초간 로드밸런싱에서 제외
3. 정상 Pod로만 트래픽 전달
4. 30초 후 재시도

2. Security (보안)

Mutual TLS (mTLS)

기존 방식 vs Istio:

기존 방식:
1. 인증서 생성 (openssl)
2. 각 서비스에 인증서 배포
3. 애플리케이션 코드에서 TLS 설정
4. 인증서 만료 전 수동 갱신

Istio:
1. PeerAuthentication 리소스 생성
2. 끝! (자동 활성화)

Istio mTLS 자동화:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT    # 모든 서비스 간 통신 암호화 강제

Citadel (istiod)이 자동 수행:

  • X.509 인증서 자동 발급
  • 90일 만료 시 자동 갱신
  • Envoy에 자동 주입
  • 암호화/복호화 자동 처리

효과:

productpage → reviews 호출 시

기존:
productpage ──HTTP(평문)──▶ reviews
             ↑ 스니핑 가능!

Istio mTLS:
productpage ──TLS(암호화)──▶ reviews
istio-proxy ────────────────▶ istio-proxy
             ↑ 암호화된 통신

Authorization (권한 관리)

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-productpage-to-reviews
spec:
  selector:
    matchLabels:
      app: reviews                # reviews 서비스에 대한 접근 제어
  action: ALLOW
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/productpage"]
    to:
    - operation:
        methods: ["GET"]           # GET만 허용

효과: productpage만 reviews를 호출 가능, 다른 서비스는 차단

3. Observability (관측성)

자동 메트릭 수집

Envoy가 모든 요청에 대해 자동 수집:

Prometheus 메트릭:
- istio_requests_total{destination_service="reviews"}
  → reviews 서비스로의 요청 수

- istio_request_duration_milliseconds{destination_service="reviews"}
  → reviews 응답 시간

- istio_request_bytes_sum
  → 요청 크기

코드 변경 없이 자동 수집!

Distributed Tracing (분산 추적)

사용자 요청 하나의 전체 경로 추적:

Request ID: abc123
┌────────────────────────────────────────┐
│ productpage (50ms)                     │
│  ├─ details (10ms)                     │
│  ├─ reviews-v2 (30ms)                  │
│  │   └─ ratings (15ms)  ← 병목 발견!  │
│  └─ ...                                │
└────────────────────────────────────────┘

Jaeger UI에서 시각화:

  • 전체 요청 경로
  • 각 구간 소요 시간
  • 에러 발생 지점

Service Graph (서비스 토폴로지)

Kiali 대시보드:

       ┌─────────────┐
       │ productpage │
       └──────┬──────┘
              │
      ┌───────┼───────┬─────────┐
      │       │       │         │
      ▼       ▼       ▼         ▼
   ┌───┐   ┌───┐   ┌───┐     ┌───┐
   │det│   │rev│   │rev│     │rev│
   │ v1│   │ v1│   │ v2│     │ v3│
   └───┘   └───┘   └─┬─┘     └─┬─┘
                     │         │
                     └────┬────┘
                          │
                          ▼
                       ┌─────┐
                       │ rat │
                       │  v1 │
                       └─────┘

- 초록색 선: 정상 트래픽
- 빨간색 선: 에러 발생
- 선 굵기: 트래픽 양

4. Resilience (복원력)

Retry & Timeout

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
    timeout: 10s              # 10초 타임아웃
    retries:
      attempts: 3             # 3번 재시도
      perTryTimeout: 2s       # 시도당 2초
      retryOn: 5xx            # 5xx 에러 시 재시도

효과:

  • 일시적 네트워크 오류 자동 복구
  • 사용자에게 에러 노출 감소

Fault Injection (장애 주입 - 테스트용)

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percentage:
          value: 10           # 10% 요청에
        fixedDelay: 5s        # 5초 지연 주입
    route:
    - destination:
        host: ratings

사용 시나리오:

  • 프로덕션 배포 전 장애 상황 테스트
  • Circuit Breaker 동작 검증
  • Timeout 설정 적절성 확인

다음 계획

Day 10: Istio 관측 도구 (Observability)

학습 내용:
1. Kiali 설치 및 활용

  • Service Graph 시각화
  • 실시간 트래픽 모니터링
  • VirtualService 설정 검증
  1. Prometheus & Grafana

    • 메트릭 수집 확인
    • Istio 대시보드 분석
    • 커스텀 메트릭 생성
  2. Jaeger (분산 추적)

    • Trace 수집 설정
    • 요청 경로 분석
    • 성능 병목 발견
  3. 실습: 트래픽 시나리오 테스트

    • Canary 배포 (reviews v1 → v3)
    • A/B 테스트 (사용자별 라우팅)
    • 장애 주입 및 복구 테스트

Day 11-19: Istio 심화 학습

  • Day 11: Sail Operator (Istio Lifecycle 관리)
  • Day 12: Envoy Proxy 심화 (Filter, Listener)
  • Day 13: Istio Gateway 고급 (mTLS, SNI)
  • Day 14: Traffic Management 실전 (Canary, Blue-Green)
  • Day 15: Security 심화 (JWT, RBAC)
  • Day 16: Multi-Cluster Mesh
  • Day 17: Istio Performance Tuning
  • Day 18: Istio Troubleshooting
  • Day 19: Production Best Practices

핵심 요약

Istio를 사용하는 이유

  1. 개발자는 비즈니스 로직에만 집중

    • 재시도, 타임아웃 → Istio가 처리
    • 로깅, 메트릭 → 자동 수집
    • 보안 → 자동 암호화
  2. 언어 독립적

    • Java, Python, Go, Node.js 모두 동일하게 동작
    • 라이브러리 없이 YAML만으로 제어
  3. 강력한 관측성

    • 코드 변경 없이 메트릭 수집
    • 전체 서비스 토폴로지 시각화
    • 분산 추적으로 병목 발견
  4. 프로덕션급 보안

    • mTLS 자동 활성화
    • 인증서 자동 갱신
    • 세밀한 권한 제어

오늘 배운 핵심 개념

1. Service Mesh = 마이크로서비스 간 통신 관리 인프라 레이어

2. Istio 아키텍처:
   - Control Plane (istiod): 설정 관리
   - Data Plane (Envoy): 실제 트래픽 처리

3. Sidecar 패턴:
   - 각 Pod에 Envoy Proxy 자동 주입
   - 애플리케이션 코드 변경 없음

4. Gateway + VirtualService:
   - Gateway: 외부 트래픽 진입점
   - VirtualService: 라우팅 규칙
   - Selector로 Ingress Gateway Pod 선택
   - 이름으로 Gateway와 VirtualService 연결

5. 트래픽 흐름:
   NodePort → Service → Envoy (Gateway)
   → VirtualService 라우팅 → 목적지 서비스
   → Envoy (Sidecar) → App

실무 적용 포인트

언제 Istio를 도입해야 하나?

도입 권장:

  • 마이크로서비스 10개 이상
  • 서비스 간 통신 복잡도 높음
  • Canary 배포, A/B 테스트 필요
  • 관측성 부재로 장애 대응 어려움
  • 서비스 간 보안 요구사항 있음

도입 불필요:

  • 모놀리식 애플리케이션
  • 마이크로서비스 5개 미만
  • 단순한 CRUD API만 존재
  • 운영 리소스 부족 (학습 비용 高)

Istio 도입 단계:
1. Pilot 프로젝트 (1-2개 서비스)
2. Sidecar 주입 검증
3. Gateway 설정 및 트래픽 테스트
4. 관측 도구 설치 (Kiali, Prometheus)
5. 점진적 확대 (서비스별 순차 적용)


다음 포스트에서는 Kiali, Prometheus, Grafana를 설치하고 Istio의 강력한 관측성을 직접 체험해보겠습니다!

profile
기록하고 공유하려고 노력하는 DevOps 엔지니어

0개의 댓글