카테고리 없음

[Istio 스터디] 3주차 - Traffic control, Resilience

★용호★ 2025. 4. 26. 15:46

(참고) 배포와 릴리즈의 차이

  • 배포(Deployment): 새 버전의 애플리케이션을 인프라에 올리는 것
  • 릴리즈(Release): 실제 프로덕션 환경의 트래픽을 새 버전으로 전달하는 것
  • 배포 전략
    • 블루-그린 배포: 새 버전을 완전히 배포한 후 한 번에 전환
    • 카나리 배포: 일부 트래픽만 새 버전으로 점진적 전환
    • 다크 런치: 특정 사용자(예: 내부 QA 팀)만 새 버전에 접근 가능하게 함

Istio API 리소스 핵심 개념

VirtualService

  • 트래픽 라우팅 방법을 지정하는 리소스
  • 약어: vs
  • 트래픽 분배, 경로 지정, 헤더 기반 라우팅 등 설정

DestinationRule

  • 트래픽 대상과 서브셋을 정의하는 리소스
  • 약어: dr
  • 서비스 내의 다양한 버전을 서브셋으로 정의

카탈로그 서비스의 버전 관리 및 다크 런치

초기 환경 구성

1. 카탈로그 서비스 v1 배포

2. Gateway 설정을 통한 외부 노출

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: catalog-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "catalog.example.com"

 

 

3. VirtualService 설정으로 게이트웨이와 서비스 연결

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog-vs
spec:
  hosts:
  - "catalog.example.com"
  gateways:
  - catalog-gateway
  http:
  - route:
    - destination:
        host: catalog

 

 

4. 노드포트(30000)를 통한 접근 테스트

트래픽 흐름 이해

  • 외부 요청 → istio-ingressgateway(포트 30000) → 내부 포트 80/8080 → 카탈로그 서비스 파드
  • Envoy 프록시 동작 흐름:
    • Listener: 트래픽을 수신하는 포트
    • Route: 트래픽 라우팅 규칙
    • Cluster: 대상 서비스 정의
    • Endpoint: 실제 트래픽을 받는 파드 IP

Envoy 설정 확인 방법

# 특정 포트의 리스너 정보 확인
istioctl proxy-config listener $POD_NAME --port 8080

# JSON 형식으로 상세 정보 출력
istioctl proxy-config listener $POD_NAME -o json

# 클러스터 정보 필터링
istioctl proxy-config cluster $POD_NAME | grep catalog

# 엔드포인트 정보 확인
istioctl proxy-config endpoint $POD_NAME --cluster "outbound|80|v1|catalog.istio-inaction.svc.cluster.local"

# Envoy 어드민 웹 인터페이스 접근
kubectl port-forward $POD_NAME 15000:15000
# 브라우저에서 http://localhost:15000 접속
 

버전 2 배포 및 다크 런치 구현

1) 카탈로그 서비스 v2 배포

kubectl apply -f catalog-v2.yaml
  • v2는 이미지 URL 필드가 추가된 버전

2) 초기 상태 확인

  • 기본적으로 v1과 v2 간 로드밸런싱 발생
  • 트래픽이 두 버전에 균등 분산

3) DestinationRule로 서브셋 정의

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: catalog-dr
spec:
  host: catalog
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
 

4) v1으로만 트래픽 라우팅

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog-vs
spec:
  hosts:
  - "catalog.example.com"
  gateways:
  - catalog-gateway
  http:
  - route:
    - destination:
        host: catalog
        subset: v1
 

5) 특정 헤더가 있는 요청만 v2로 라우팅

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog-vs
spec:
  hosts:
  - "catalog.example.com"
  gateways:
  - catalog-gateway
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: catalog
        subset: v2
  - route:
    - destination:
        host: catalog
        subset: v1

 

6) 헤더 기반 라우팅 테스트

# v1으로 라우팅(일반 사용자)
curl -H "Host: catalog.example.com" http://localhost:30000/items

# v2로 라우팅(특정 헤더 사용)
curl -H "Host: catalog.example.com" -H "end-user: jason" http://localhost:30000/items

Envoy 프록시 설정 이해

Envoy 컴포넌트

  1. 리스너(Listener): 트래픽을 수신하는 포트 및 설정
  2. 라우트(Route): 수신된 트래픽 라우팅 규칙
  3. 클러스터(Cluster): 트래픽 대상 서비스 그룹
  4. 서브셋(Subset): 특정 레이블을 가진 파드들의 그룹
  5. 엔드포인트(Endpoint): 실제 트래픽을 받는 파드 IP

Envoy 설정이 변경되는 흐름

  1. Istio API 리소스(VirtualService, DestinationRule) 변경
  2. Istio 컨트롤 플레인(istiod)이 변경 감지
  3. xDS API를 통해 Envoy 프록시에 새 설정 전달
  4. Envoy가 새 설정 적용
    • 리스너 설정(LDS)
    • 라우트 설정(RDS)
    • 클러스터 설정(CDS)
    • 엔드포인트 설정(EDS)

트래픽 관리 전략 정리

다크 런치 패턴

  • 신규 버전을 배포하되 일반 사용자는 접근 불가
  • 특정 헤더나 쿠키를 가진 내부 테스터만 접근 가능
  • 단계:
    1. 두 버전 모두 배포
    2. DestinationRule로 서브셋 정의
    3. VirtualService로 기본 트래픽은 v1으로 라우팅
    4. 특정 조건(헤더 등)을 가진 요청만 v2로 라우팅
    5. 검증 후 점진적으로 트래픽 비율 조정

순차적 라우팅 규칙 적용

  • 더 구체적인 규칙(match 조건이 많은)을 먼저 배치
  • VirtualService의 http 배열 내 규칙은 순서대로 평가됨
  • 매치되는 첫 번째 규칙이 적용됨

추가 설명: Istio에서 트래픽 제어의 중요성

  • Istio의 트래픽 제어 기능은 마이크로서비스 환경에서 중요한 역할을 함
  • 이를 통해 블루-그린 배포, 카나리 배포, A/B 테스팅과 같은 현대적인 배포 전략을 코드 변경 없이 인프라 레벨에서 구현할 수 있음
  • 특히 다크 런치 패턴은 신규 기능의 위험을 최소화하면서 실제 환경에서 테스트할 수 있게 해주는 강력한 방법
  • Istio의 Envoy 프록시는 서비스 간 통신을 중개하며, 모든 트래픽 제어 규칙은 결국 Envoy 설정으로 변환됨
    • 애플리케이션 코드를 수정하지 않고도 네트워크 동작을 세밀하게 제어할 수 있게 해주는 서비스 메시의 핵심 가치

메시 라우팅(Mesh Routing) 개념

메시 라우팅은 호출 그래프의 깊은 위치에서 트래픽 라우팅을 수행하는 기능

  • 일반적인 라우팅: 엣지 게이트웨이에서 Virtual Service를 통해 트래픽을 제어
  • 메시 라우팅: 서비스 메시 내부의 사이드카 프록시(Envoy)에서도 트래픽 라우팅 가능

메시 라우팅을 통해 서비스 간 호출에서도 세밀한 트래픽 제어가 가능해짐

실습 환경 구성

기본 환경 설정

 
# 기존 환경 초기화
kubectl delete -f <previous-config>

# 웹 앱과 카탈로그 서비스 배포
kubectl apply -f webapp-catalog-deployment.yaml

# 게이트웨이와 Virtual Service 생성
kubectl apply -f gateway-vs-config.yaml

# 로깅 활성화 (Istio Proxy 컨테이너 로그 확인)
kubectl logs -f <pod-name> -c istio-proxy

텔레메트리 활성화

# webapp의 Istio 프록시 로그 활성화
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
  name: webapp-logs
spec:
  selector:
    matchLabels:
      app: webapp
  accessLogging:
    - providers:
        - name: envoy
      filter:
        expression: "true"

메시 라우팅 설정 방법

Destination Rule 추가

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: catalog
spec:
  host: catalog
  subsets:
  - name: version-1
    labels:
      version: v1
  - name: version-2
    labels:
      version: v2

 

 

Virtual Service에 메시 게이트웨이 설정

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  gateways:
  - mesh  # 메시 게이트웨이 지정
  http:
  - match:
    - headers:
        internal-header:
          exact: "version-2"
    route:
    - destination:
        host: catalog
        subset: version-2
  - route:
    - destination:
        host: catalog
        subset: version-1
 
  • 중요한 점은 gateways 섹션에 mesh를 추가한 것
    • 이를 통해 메시 내부의 모든 사이드카 프록시가 이 라우팅 규칙을 적용할 수 있게 됨

트래픽 쉬프팅(Traffic Shifting)

트래픽 쉬프팅은 두 가지 방식으로 구현할 수 있음

  1. 수동 카나리 릴리즈: 직접 트래픽 비율을 조정
  2. 자동 카나리 릴리즈: Flagger와 같은 도구를 사용한 자동화

수동 카나리 릴리즈 구현

초기 세팅 (모든 트래픽을 버전 1으로)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  gateways:
  - mesh
  http:
  - route:
    - destination:
        host: catalog
        subset: version-1
 

트래픽 10%를 버전 2로 라우팅

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  gateways:
  - mesh
  http:
  - route:
    - destination:
        host: catalog
        subset: version-1
        weight: 90
    - destination:
        host: catalog
        subset: version-2
        weight: 10
 

트래픽 50%:50% 분배

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  gateways:
  - mesh
  http:
  - route:
    - destination:
        host: catalog
        subset: version-1
        weight: 50
    - destination:
        host: catalog
        subset: version-2
        weight: 50
 

라우팅 규칙 확인

istioctl proxy-config routes <pod-name>
  • 라우트 세부 정보는 JSON 형식으로 검사할 수 있으며, 가중치 클러스터(weighted clusters) 정보를 확인할 수 있음

Flagger를 사용한 자동 카나리 릴리즈

Flagger는 Kubernetes를 위한 프로그레시브 딜리버리 오퍼레이터로, 자동화된 카나리 릴리즈를 지원함

 

Flagger 설치

# CRD 설치
kubectl apply -f https://raw.githubusercontent.com/fluxcd/flagger/main/artifacts/flagger/crd.yaml

# Helm을 통한 설치
helm repo add flagger https://flagger.app
helm upgrade -i flagger flagger/flagger --namespace=istio-system --set meshProvider=istio --set metricsServer=http://prometheus:9090
 

Flagger 동작 방식 (예시)

  1. 초기화 단계:
    • 원본 디플로이먼트를 복제하여 프라이머리 디플로이먼트 생성
    • 원본 디플로이먼트의 레플리카를 0으로 설정
    • 프라이머리 디플로이먼트와 카나리 서비스 생성
  2. 진행 단계:
    • 신규 버전이 배포되면 카나리 디플로이먼트 생성
    • 트래픽을 단계적으로 카나리 버전으로 이동 (기본값: 10% 씩 증가)
    • 각 단계마다 Prometheus 매트릭 분석 (45초 간격)
  3. 성공/실패 판단:
    • 성공 조건: 요청 성공률 99% 이상, 요청 처리 시간 500ms 미만
    • 실패 조건: 연속 5회 이상 조건 불만족 시 롤백

Flagger 설정 예제

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: catalog
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: catalog
  service:
    port: 80
    targetPort: 8080
    gateways:
    - mesh
  analysis:
    interval: 45s
    threshold: 5
    maxWeight: 50
    stepWeight: 10
    metrics:
    - name: request-success-rate
      thresholdRange:
        min: 99
      interval: 1m
    - name: request-duration
      thresholdRange:
        max: 500
      interval: 1m
 

Flagger의 추가 기능

Flagger는 다음과 같은 배포 전략을 지원함

  • 카나리 릴리즈
  • A/B 테스팅
  • 블루/그린 배포
  • 미러링(Mirroring)
  • 세션 어피니티(Session Affinity)

참고

  • 사이드카 프록시(Envoy)의 역할 : 사이드카 프록시는 각 서비스 Pod에 함께 배포되어 네트워크 트래픽을 가로채고 제어하는 컨테이너입니다. Istio에서는 Envoy 프록시가 사이드카로 사용됩니다. 이 프록시는 서비스 메시의 핵심 구성 요소로, 트래픽 라우팅, 로드 밸런싱, 안전한 통신 등을 담당합니다.
  • 메시 라우팅의 실제 사용 사례 :
    • 마이크로서비스 간 통신에서 세밀한 트래픽 제어가 필요할 때
    • 서비스 내부 컴포넌트 간의 버전 관리가 필요할 때
    • 특정 조건(헤더, 쿼리 파라미터 등)에 따라 내부 서비스 호출을 다르게 처리해야 할 때

 

트래픽 미러링

트래픽 미러링(Traffic Mirroring)은 실제 운영 중인 서비스의 트래픽을 복제하여 다른 서비스 버전으로 전송하는 기능

실습 환경 설정

  • 기존 실습 환경 초기화
  • 카탈로그 서비스의 두 가지 버전(v1, v2) 배포
  • VirtualService를 통한 메시 게이트웨이 설정
  • 초기 상태: 모든 트래픽은 v1으로만 라우팅되고, v2는 배포되어 있지만 사용되지 않음

트래픽 미러링의 목적과 장점

  • 기존 배포 방식(Canary, Blue/Green)은 실제 트래픽을 전환하여 위험성이 존재
  • 미러링은 사용자에게 영향을 주지 않으면서 새 버전 테스트 가능
  • 주요 사용 사례:
    • 보안 시스템에서 복제된 트래픽 분석
    • 새 버전의 코드 동작 검증
    • 성능 모니터링 및 이슈 발견
  • 용어 구분: 미러링 vs 리플리케이션
    • 미러링(Mirroring): 트래픽을 복제하여 다른 대상으로 전송하되, 응답은 무시하는 방식
    • 리플리케이션(Replication): 데이터나 서비스 자체를 복제하는 것으로, 주로 가용성과 내결함성을 위해 사용

미러링 설정 방법

미러링 설정은 VirtualService API 리소스에 선언:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  http:
  - route:
    - destination:
        host: catalog
        subset: version-1  # 원본 트래픽 대상
    mirror:
      host: catalog
      subset: version-2    # 미러링 대상
  • 원본 트래픽은 version-1으로 전달
  • 복제된 트래픽은 version-2로 미러링
  • 미러링 대상(version-2)에서의 응답은 무시됨

프록시 로그 활성화 및 모니터링

# 카탈로그 서비스에 Istio 프록시 로그 활성화
kubectl logs -f -l app=catalog -c istio-proxy

# 특정 버전의 로그만 확인
kubectl logs -f -l app=catalog,version=v2 -c istio-proxy
 
  • telemetry 시스템에서 두 서비스가 모두 표시됨
  • 로그를 통해 요청 흐름 확인 가능

Kiali를 통한 트래픽 시각화

  • 트래픽이 50:50 비율로 표시됨 (실제 트래픽 vs 미러링 트래픽)
  • 미러링 설정은 특별한 화살표로 시각적으로 표현
  • 미러링된 트래픽이 version-2로 전달되는 것을 확인 가능

패킷 분석 방법

mTLS 비활성화

# Istio의 mTLS 기능 비활성화
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system
spec:
  mtls:
    mode: DISABLE
EOF
 

 

TCP 덤프를 통한 패킷 분석

# 파드 IP 확인
kubectl get pod -l app=catalog,version=v2 -o wide
# 결과: 10.0.0.2 (예시 IP)

# 호스트의 veth 인터페이스 확인
ip -c a | grep -A 2 veth

# TCP 덤프 실행
ngrep -d <veth-interface> host 10.0.0.2
 

 

미러링된 트래픽의 특징

  • 미러링된 요청의 Host 헤더에는 "-shadow" 접미사 추가
    • 예: 원본 Host: "catalog" → 미러링 Host: "catalog-shadow"
  • 이를 통해 Istio가 미러링된 트래픽임을 식별
  • 패킷 분석 시 HTTP 헤더에서 확인 가능

미러링 응답 처리

  • 미러링된 서비스(version-2)는 응답을 반환하지 않는 것이 이상적
  • 응답을 반환하더라도 원본 서비스에서는 무시됨
  • 웹 애플리케이션에서는 미러링 대상에서 온 응답을 식별하여 처리하지 않음

트래픽 흐름 분석

  1. 클라이언트가 원본 서비스(version-1)로 요청
  2. Istio가 요청을 복제하여 미러링 대상(version-2)으로도 전송
  3. 원본 서비스는 정상적으로 요청을 처리하고 응답
  4. 미러링 대상도 요청을 처리하지만, 그 응답은 클라이언트에게 전달되지 않음

 

서비스 엔트리(Service Entry)

  • Istio 서비스 메시 외부에 있는 서비스를 내부 서비스처럼 등록하여 관리할 수 있게 해주는 Istio의 리소스
  • 이를 통해 외부 서비스와의 통신을 Istio의 기능(보안, 모니터링, 트래픽 제어 등)을 활용하여 관리할 수 있음
  • 서비스 엔트리의 주요 목적:
    • 외부 서비스를 내부 서비스처럼 참조하고 관리
    • 외부 통신에 대한 안전한 방어막 구성
    • 메시 외부 리소스에 대한 서비스 디스커버리 활용

아웃바운드 트래픽 정책(Outbound Traffic Policy)

Istio에서는 메시 내부에서 외부로의 트래픽 흐름을 제어하기 위해 아웃바운드 트래픽 정책을 설정할 수 있음. 이 설정은 MeshConfig의 outboundTrafficPolicy 항목에서 지정

 

아웃바운드 트래픽 정책 모드:

  1. ALLOW_ANY (기본값):
    • 모든 외부 통신 허용
    • 내부에서 외부로의 통신이 자유롭게 가능
  2. REGISTRY_ONLY:
    • 등록된 서비스만 외부 통신 허용
    • Service Entry로 등록되지 않은 외부 서비스와의 통신은 차단됨
    • 차단 시 "블랙홀 라우팅"으로 처리됨 (요청이 블랙홀 클러스터로 보내져 실패)

실습 환경 구성

  • 웹앱(Web App): 사용자 인터페이스 제공
  • 포럼 서비스(Forum Service): 외부 API에서 데이터를 가져와 표시하는 서비스
  • 외부 서비스(jsonplaceholder.typicode.com): 가짜 REST API를 제공하는 무료 서비스

아웃바운드 트래픽 제한 설정

Istio의 MeshConfig를 수정하여 외부 트래픽을 제한:

istioctl install --set profile=default -y

 

outboundTrafficPolicy를 REGISTRY_ONLY로 설정 후 결과 확인:

  • 포럼 서비스에서 외부 API 호출 시 오류 발생
  • 로그에서 "블랙홀 클러스터" 라우팅 확인
  • HTTP 500 에러 응답

서비스 엔트리 생성

외부 서비스(jsonplaceholder.typicode.com)를 메시에 등록하기 위한 Service Entry 생성:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: jsonplaceholder
spec:
  hosts:
  - jsonplaceholder.typicode.com
  ports:
  - number: 80
    name: http
    protocol: HTTP
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
  location: MESH_EXTERNAL
 
  • hosts: 외부 서비스의 도메인 이름
  • ports: 통신에 사용할 포트 및 프로토콜 정의
  • resolution: DNS를 통해 호스트 이름을 해석
  • location: MESH_EXTERNAL은 서비스가 메시 외부에 있음을 표시

서비스 엔트리 적용 결과

  1. 프록시 구성 변경 확인:
    • 포럼 서비스의 Envoy 프록시 구성에 새로운 아웃바운드 클러스터 추가
    • 외부 서비스(jsonplaceholder.typicode.com)가 EDS(Endpoint Discovery Service)에 추가됨
  2. 기능 동작 확인:
    • 포럼 서비스가 외부 API의 사용자 정보를 성공적으로 가져옴
    • 웹 앱에서 외부 API 데이터 표시 확인
  3. Kiali에서 확인:
    • Kiali 대시보드에서 등록된 외부 서비스(jsonplaceholder) 확인 가능
    • 헬스 체크 정보는 외부 서비스이므로 제공되지 않음

추가 활용 방안

다양한 외부 서비스 등록

  • httpbin.org와 같은 다른 외부 테스트 서비스 등록 가능
  • 기업 내부의 레거시 시스템, 클라우드 서비스, 써드파티 API 등을 Service Entry로 등록하여 통합 관리

서비스 메시 경계 설정

  • Service Entry를 통해 메시의 경계를 명확히 정의하고 관리
  • 필요한 외부 서비스만 선택적으로 등록하여 보안 강화

복원력 패턴

  • 복원력 패턴의 필요성
    • 어플리케이션이나 서비스 전반에 일관된 복원력 패턴 적용이 필요함
    • 여러 개의 애플리케이션에 각각 복원력 기능을 구현하는 것은 어렵고 비효율적
    • 언어와 상관없이 일관된 복원력 기능 구현이 운영 측면에서 큰 도움이 됨
  • 기존 방식의 문제점
    • 언어별로 각각 구현해야 함
    • 다양한 오픈소스, 프레임워크, 라이브러리 관리 필요
    • 라이브러리 업데이트에 따른 운영 부담 발생
    • 설정의 비일관성으로 인한 운영 복잡성 증가
  • Istio의 해결책
    • Istio는 프록시(Envoy)를 통해 복원력 기능을 언어와 무관하게 구현합니다.
    • 중앙화된 API 게이트웨이 방식과 달리, 분산된 방식으로 복원력 패턴을 구현합니다.
    • 트래픽이 급증하거나 갑자기 확장해야 하는 상황에서도 마이크로서비스 아키텍처를 통해 효과적으로 대응할 수 있습니다.

클라이언트 측 로드 밸런싱

  • 클라이언트 측 로드 밸런싱은 클라이언트가 서비스 요청을 여러 백엔드 인스턴스에 분산하는 방식
  • Istio에서는 사이드카 프록시(Envoy)가 이 역할을 담당

동작 원리

  • Istio 프록시가 서비스 디스커버리를 통해 엔드포인트를 발견합니다.
  • 클라이언트에게 사용 가능한 여러 엔드포인트를 알려줍니다.
  • 선택한 로드 밸런싱 알고리즘에 따라 트래픽을 분산합니다.

로드 밸런싱 알고리즘 (Istio 1.17 기준)

  • Round Robin (RR): 기본 알고리즘, 순차적으로 요청 분배
  • Random: 무작위로 요청 분배
  • Least Connection (LC): 활성 연결이 가장 적은 서버에 요청 분배
  • Weighted: 가중치에 따라 요청 분배

설정 방법

  • DestinationRule(DR) 리소스를 통해 로드 밸런싱 정책을 지정합니다.

실습: 클라이언트 측 로드 밸런싱

초기 환경 설정

  1. 웹 프론트엔드(simple-web)와 백엔드(simple-backend) 서비스 배포
  2. 게이트웨이 및 가상 서비스(VirtualService) 설정
  3. 호스트 도메인 등록

현재 환경 상태 확인

  • 배포된 파드: ingress-gateway, simple-backend(v1, v2, v3), simple-web
  • simple-web이 프론트엔드 역할을 하고 simple-backend에 요청을 전달
  • 현재 상태에서는 simple-backend v1에 1개 파드, v2에 2개 파드가 있어 트래픽이 33%:66% 비율로 분산됨

DestinationRule을 통한 로드 밸런싱 설정

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: simple-backend
spec:
  host: simple-backend
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
 

부하 테스트 시나리오

  1. simple-backend v1에 1초의 응답 지연 설정 (지연이 발생하는 환경 구성)
  2. 다양한 로드 밸런싱 알고리즘으로 성능 비교

Fortio를 활용한 부하 테스트

Fortio는 그리스어로 '부하'를 의미하는 부하 테스트 도구로, Istio 커뮤니티에서 널리 사용됨

  • 테스트 설정:
    • 60초 동안
    • 10개의 동시 연결
    • 초당 1,000개 요청(1,000 RPS)
    • 타임아웃 2초

알고리즘별 성능 비교 결과

  1. Round Robin 알고리즘
    • 결과: 75번째 백분위수부터 응답 시간이 1초 이상으로 증가
    • 25%의 사용자가 지연된 응답을 경험
  2. Random 알고리즘
    • 결과: Round Robin과 유사한 성능
    • 무작위로 분산해도 느린 서버(v1)가 선택될 확률이 여전히 약 1/3임
  3. Least Connection 알고리즘
    • 결과: 상당한 개선 효과
    • 90번째 백분위수까지 0.1초 이내의 응답 시간 유지
    • 약 90%의 사용자가 빠른 응답을 경험

Least Connection 알고리즘의 동작 원리

  • 각 엔드포인트의 활성 요청 수(큐 깊이)를 체크
  • 응답 지연이 발생하는 서버(v1)는 활성 연결이 많아지므로 새로운 요청이 다른 서버로 라우팅
  • 따라서 지연 서버로의 트래픽이 자동으로 줄어들어 전체 응답 성능이 향상됨
  • 참고 : Istio에서는 'Least Connection'이라고 부르는 알고리즘을 Envoy 공식 문서에서는 'Least Request'라고 표현함
    • 두 용어는 동일한 개념을 지칭

로컬리티 어웨어 로드 밸런싱(지역인식 로드 밸런싱)

개념 및 중요성

  • 로컬리티 어웨어 로드 밸런싱은 서비스 메시가 전체 네트워크 토폴로지를 이해하고 지능적으로 트래픽을 라우팅하는 메커니즘
    • 응답 지연시간 감소: 같은 지역 내 서비스 간 통신은 응답이 빠름
    • 네트워크 비용 절감: 클라우드 환경에서 지역 간 트래픽은 비용이 발생하므로, 같은 영역 내 통신으로 비용 절감

토폴로지 구조

  • 리전(Region): 지리적으로 분리된 대규모 지역 단위(예: us-west-1)
  • 가용 영역(Availability Zone): 리전 내 물리적으로 분리된 데이터센터 집합(약 200km 이상 떨어져 있음, 예: us-west-1a)

구현 방법

서비스 배포 시 다음과 같은 레이블을 통해 토폴로지 정보를 Istio에 제공:

metadata:
  labels:
    topology.istio.io/region: us-west-1
    topology.istio.io/zone: us-west-1a

활성화 방법

Istio에서는 로컬리티 어웨어 로드 밸런싱이 기본적으로 활성화되어 있지만, 실제 동작을 위해서는 DestinationRule에 아웃라이어 디텍션(Outlier Detection)을 설정해야 함:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: backend-destination-rule
spec:
  host: sample-backend
  trafficPolicy:
    outlierDetection:
      consecutive5xxErrors: 1
      interval: 1s
      baseEjectionTime: 3m
      maxEjectionPercent: 100
 
  • 이 설정은 1초 간격으로 헬스체크를 수행하고, 연속된 5xx 에러가 1회 이상 발생하면 해당 엔드포인트를 최대 3분간 제외

가중치를 사용한 로컬리티 로드 밸런싱

특정 상황(예: 이벤트, 트래픽 피크)에서는 같은 영역과 다른 영역에 트래픽 비율을 지정할 수 있음:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sample-backend
spec:
  host: sample-backend
  trafficPolicy:
    loadBalancer:
      localityLbSetting:
        distribute:
        - from: us-west-1/us-west-1a/*
          to:
            "us-west-1/us-west-1a/*": 70
            "us-west-1/us-west-1b/*": 30
    outlierDetection:
      # 필수: 아웃라이어 디텍션 설정
  • 이 설정은 us-west-1a 영역에서 출발한 트래픽의 70%는 같은 영역으로, 30%는 us-west-1b 영역으로 분산됨

타임아웃(Timeout)

네트워크 통신에서 지연 시간은 다루기 어려운 문제입니다. 특히 서비스가 연쇄적으로 호출되는 환경에서 한 서비스의 지연은 연쇄적인 장애로 이어질 수 있음

타임아웃 설정

VirtualService에 timeout 속성을 설정하여 요청의 최대 대기 시간을 정의할 수 있음:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sample-backend
spec:
  hosts:
  - sample-backend
  http:
  - route:
    - destination:
        host: sample-backend
    timeout: 0.5s  # 500ms 타임아웃 설정
  • 이 설정으로 요청이 0.5초 내에 응답하지 않으면 타임아웃 처리

재시도(Retry)

  • 일시적인 네트워크 오류나 서비스 장애 시 자동으로 요청을 재시도하여 사용자 경험을 향상시키는 기능
  • Istio는 기본적으로 재시도 기능이 활성화되어 있으며, HTTP 503 오류에 대해 기본 2회 재시도를 수행함

전역 재시도 설정

MeshConfig에서 전역적으로 재시도 정책을 설정할 수 있음:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    enableHttpRetry: false  # 전역 재시도 비활성화
 

VirtualService에서 재시도 설정

개별 서비스에 대한 재시도 정책을 설정할 수 있음:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sample-backend
spec:
  hosts:
  - sample-backend
  http:
  - route:
    - destination:
        host: sample-backend
    retries:
      attempts: 2        # 재시도 횟수
      perTryTimeout: 2s  # 각 시도당 타임아웃
      retryOn: 5xx       # 5xx 에러에 대해서만 재시도

재시도 대상 에러 코드 확장

기본적으로 Istio는 503 에러에 대해서만 재시도하지만, retryOn 필드를 통해 다른 에러 코드에 대해서도 재시도를 설정할 수 있음:

retries:
  attempts: 2
  perTryTimeout: 2s
  retryOn: "5xx,connect-failure,refused-stream"  # 5xx 및 연결 실패 시 재시도
  • retryOn 값을 "5xx"로 설정하면 모든 5xx 에러에 대해 재시도함
  • 주의사항: 천둥 무리(Thundering Herd) 현상
    • 서비스 체인에서 모든 서비스가 재시도 정책을 가지고 있다면, 하위 서비스의 일시적 장애 시 상위 서비스들이 모두 재시도하여 하위 서비스에 과도한 부하를 줄 수 있음
    • 이를 방지하기 위한 방안
      • 서비스 체인의 가장 깊은 곳에서만 재시도 설정
      • 상위 서비스는 재시도를 최소화하거나 비활성화
      • 적절한 타임아웃 설정으로 재시도 시간 제한

고급 재시도 기법 (EnvoyFilter 사용)

  • Istio의 표준 API만으로 제어할 수 없는 고급 설정을 위해 EnvoyFilter를 사용하여 Envoy 프록시 설정을 직접 수정할 수 있음

고급 재시도 설정 예

408, 500 등의 다른 에러 코드에 대한 재시도 및 백오프 시간 조정:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: retry-settings
spec:
  configPatches:
  - applyTo: HTTP_ROUTE
    match:
      context: SIDECAR_OUTBOUND
    patch:
      operation: MERGE
      value:
        route:
          retry_policy:
            retry_back_off:
              base_interval: "0.05s"  # 기본값 25ms를 50ms로 변경
            retriable_status_codes:
            - 408
            - 500
            - 502
            - 503
            - 504

요청 헤징(Request Hedging)

지연 시간에 임계값에 도달하면 다른 호스트에도 동일한 요청을 보내 가장 빠른 응답을 사용자에게 전달하는 고급 기능:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: hedging-settings
spec:
  configPatches:
  - applyTo: HTTP_ROUTE
    patch:
      operation: MERGE
      value:
        route:
          hedge_policy:
            hedge_on_per_try_timeout: true

EnvoyFilter 사용 시 주의사항

  1. 비표준 방식이므로 Istio 버전 업그레이드 시 호환성 문제가 발생할 수 있음
  2. Envoy 프록시의 내부 동작을 이해해야 안전하게 사용 가능
  3. 가능하면 표준 Istio API 사용을 권장
  4. 적용 전 테스트 환경에서 충분한 검증 필요

서킷 브레이킹 개념

  • 마이크로서비스 아키텍처에서 연쇄 장애(cascading failure)를 방지하기 위한 중요한 기법
    • "회로 차단기"라는 용어가 비유적으로 적합한데, 전기 회로에서 과부하가 발생했을 때 차단기가 작동하여 전체 시스템을 보호하는 것과 유사
  • 서비스 간에 연쇄적으로 연결된 시스템에서 특정 서비스에 부하가 집중되거나 장애가 발생했을 때, 해당 엔드포인트로의 요청을 제한하거나 차단함으로써 다른 시스템의 대기 시간 증가나 장애 전파를 방지함

Istio에서 제공하는 서킷 브레이킹 메커니즘

커넥션 및 요청 제어 (Connection Pool Management)

  • Istio 프록시(Envoy)가 특정 서비스로 향하는 커넥션 및 미해결 요청의 개수를 통제
  • 설정된 임계값을 초과할 경우 새로운 요청은 거부되며, 이를 통해 과부하 상태의 서비스가 완전히 중단되는 것을 방지함

오동작 엔드포인트 퇴출 (Outlier Detection)

  • Istio가 엔드포인트의 상태를 주기적으로 모니터링하여, 특정 조건(예: 연속적인 오류)이 발생하면 해당 엔드포인트를 로드밸런싱 풀에서 일시적으로 제외시킴
    • 이렇게 하면 정상 작동하는 엔드포인트로만 트래픽을 라우팅하여 전체 시스템의 안정성을 유지할 수 있게됨

커넥션 풀 제어 설정 (Connection Pool Configuration)

Istio의 DestinationRule 리소스를 통해 커넥션 풀 설정 (아래는 설정 예시)

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: simple-backend-dr
spec:
  host: simple-backend
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        http2MaxRequests: 1
        maxRequestsPerConnection: 1
        maxRetries: 1
  • maxConnections: 전체 커넥션의 총 개수를 제한 (TCP 설정에 포함됨)
  • http1MaxPendingRequests: 사용할 커넥션이 없어 대기 중인 요청의 최대 개수를 지정
  • http2MaxRequests: 모든 호스트에 대한 최대 동시(병렬) 요청 수를 지정 (이름에 HTTP/2가 포함되어 있지만, 모든 HTTP 프로토콜에 적용됨)
  • maxRequestsPerConnection: 각 커넥션당 최대 요청 수를 지정
  • maxRetries: 요청 재시도 횟수를 제한

 

서킷 브레이크 동작 시 메트릭 모니터링

  • 서킷 브레이커가 작동할 때 Envoy 프록시는 다양한 메트릭을 생성하며, 이 메트릭들은 기본적으로 모두 활성화되어 있지 않으므로, 필요에 따라 활성화해야함
  • 주요 모니터링 메트릭
    • upstream_cx_overflow: 최대 연결 수를 초과했을 때 증가하는 카운터
    • upstream_rq_pending_overflow: 대기 큐가 가득 찼을 때 증가하는 카운터

메트릭 활성화 방법

Pod에 다음과 같은 애너테이션을 추가하여 상세한 통계 수집을 활성화

annotations:
  proxy.istio.io/config: |
    proxyStatsMatcher:
      inclusionRegexps:
      - ".*outlier_detection.*"
      - ".*upstream_rq_retry.*"
      - ".*upstream_cx_.*"
      - ".*upstream_rq_.*"
 

오버로드 상태 헤더 전달 (x-envoy-overloaded)

  • 서킷 브레이커가 작동했을 때, Envoy 프록시는 x-envoy-overloaded: true 헤더를 응답에 추가함
  • 애플리케이션 코드는 이 헤더를 감지하여 대체 전략(예: 다른 서비스로 요청 전환)을 구현할 수 있음

이상 엔드포인트 감지 및 제거 (Outlier Detection)

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: simple-backend-dr
spec:
  host: simple-backend
  trafficPolicy:
    outlierDetection:
      consecutive5xxErrors: 1  # 기본값 5
      interval: 5s             # 기본값 10s
      baseEjectionTime: 5s     # 기본값 30s
      maxEjectionPercent: 100  # 기본값 10%
  • consecutive5xxErrors: 엔드포인트를 퇴출시키기 위한 연속 5xx 오류 횟수
  • interval: 이상 감지를 위한 검사 주기
  • baseEjectionTime: 엔드포인트 퇴출 시간 (이후 자동으로 다시 포함됨)
  • maxEjectionPercent: 로드 밸런서 풀에서 최대로 제거할 수 있는 엔드포인트의 비율

재시도 정책과 함께 사용

  • 서킷 브레이킹과 재시도 정책을 함께 사용하면 시스템의 복원력을 크게 향상시킬 수 있음
  • 오동작하는 엔드포인트가 감지되어 로드 밸런싱 풀에서 제외되기 전에도, 재시도 정책을 통해 다른 정상 엔드포인트로 요청을 재시도하여 사용자 경험을 개선할 수 있음

재시도 정책 설정

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: simple-backend-vs
spec:
  hosts:
  - simple-backend
  http:
  - route:
    - destination:
        host: simple-backend
    retries:
      attempts: 3
      perTryTimeout: 2s
      retryOn: gateway-error,connect-failure,refused-stream

실제 적용 시 고려사항

  1. 적절한 임계값 설정: 서비스의 처리 능력에 맞는 적절한 임계값을 설정해야 함. 너무 낮으면 불필요한 오류가 발생하고, 너무 높으면 서킷 브레이킹의 효과가 줄어들게 됨
  2. 모니터링 및 경고: 서킷 브레이커가 작동할 때 이를 감지하고 알림을 받을 수 있는 모니터링 시스템을 구축해야 함
  3. 단계적 롤아웃: 서킷 브레이킹 설정을 적용할 때는 점진적으로 적용하고 모니터링하면서 조정하는 것이 안전
  4. 재시도 및 타임아웃과의 조합: 서킷 브레이킹, 재시도, 타임아웃 정책을 함께 고려하여 복원력 있는 시스템을 구성해야 함