Service Mesh란?
마이크로서비스 아키텍처에서 서비스 간 통신은 복잡해진다. 각 서비스에 재시도, 타임아웃, mTLS, 로드밸런싱 로직을 개별 구현하면 코드 중복과 운영 부담이 기하급수적으로 늘어난다. Service Mesh는 이 통신 로직을 애플리케이션 밖으로 분리해 인프라 레이어에서 일괄 관리하는 패턴이다. Istio는 가장 널리 쓰이는 Service Mesh 구현체로, Envoy 사이드카 프록시를 기반으로 동작한다.
Istio 아키텍처
Istio는 데이터 플레인과 컨트롤 플레인으로 나뉜다.
| 구성요소 | 역할 |
|---|---|
| Envoy (사이드카) | 각 Pod에 자동 주입되어 모든 트래픽을 가로채고 제어 |
| istiod | Pilot(라우팅) + Citadel(인증서) + Galley(설정) 통합 컨트롤러 |
| Ingress/Egress Gateway | 메시 외부 트래픽의 진입·이탈 제어 |
핵심 원리: Pod에 Envoy 프록시가 사이드카로 자동 주입되면, 애플리케이션의 모든 인바운드·아웃바운드 트래픽이 Envoy를 통과한다. 애플리케이션 코드는 변경하지 않아도 된다.
설치와 사이드카 주입
# Istio 설치 (demo 프로필)
istioctl install --set profile=demo -y
# 네임스페이스에 사이드카 자동 주입 활성화
kubectl label namespace default istio-injection=enabled
# 확인 — Pod마다 컨테이너 2개(앱 + envoy)
kubectl get pods -n default
# NAME READY STATUS CONTAINERS
# user-svc-7d8f9b6c4-x2k 2/2 Running 2
istio-injection=enabled 라벨을 붙이면 해당 네임스페이스의 모든 새 Pod에 Envoy 사이드카가 자동 주입된다. 기존 Pod는 재시작해야 적용된다.
트래픽 관리: VirtualService
VirtualService는 Istio의 핵심 라우팅 규칙이다. K8s Ingress보다 훨씬 세밀한 제어가 가능하다.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: user-service
spec:
hosts:
- user-service
http:
# 헤더 기반 라우팅
- match:
- headers:
x-version:
exact: "v2"
route:
- destination:
host: user-service
subset: v2
# 가중치 기반 카나리
- route:
- destination:
host: user-service
subset: v1
weight: 90
- destination:
host: user-service
subset: v2
weight: 10
# 타임아웃·재시도
timeout: 3s
retries:
attempts: 3
perTryTimeout: 1s
retryOn: 5xx,reset,connect-failure
DestinationRule: 서브셋과 로드밸런싱
DestinationRule은 트래픽이 도달한 후의 정책을 정의한다. 서브셋 분류, 로드밸런싱 알고리즘, 커넥션 풀, 서킷 브레이커를 설정한다.
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: user-service
spec:
host: user-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
h2UpgradePolicy: DEFAULT
http1MaxPendingRequests: 100
http2MaxRequests: 1000
loadBalancer:
simple: LEAST_REQUEST # ROUND_ROBIN, RANDOM, PASSTHROUGH
outlierDetection:
consecutive5xxErrors: 3
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
outlierDetection은 서킷 브레이커다. 5xx 에러가 3회 연속 발생하면 해당 Pod을 30초간 로드밸런싱 풀에서 제거한다. 애플리케이션 레벨의 Resilience4j 서킷 브레이커와 달리, 인프라 레벨에서 투명하게 동작한다.
mTLS: 서비스 간 암호화
Istio의 킬러 기능 중 하나다. 서비스 간 모든 통신을 상호 TLS로 자동 암호화한다.
# 메시 전체 STRICT mTLS
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system # 메시 전체 적용
spec:
mtls:
mode: STRICT # PERMISSIVE(호환), STRICT(강제), DISABLE
# 특정 네임스페이스만 PERMISSIVE (마이그레이션 시)
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: legacy-ns
namespace: legacy
spec:
mtls:
mode: PERMISSIVE
STRICT 모드에서는 사이드카가 없는 서비스의 요청이 거부된다. 마이그레이션 중에는 PERMISSIVE로 시작해 점진적으로 STRICT으로 전환하자.
AuthorizationPolicy: L7 접근 제어
어떤 서비스가 어떤 서비스에 접근할 수 있는지 L7 레벨에서 제어한다.
# order-service는 user-service의 GET만 허용
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: user-service-policy
namespace: default
spec:
selector:
matchLabels:
app: user-service
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/order-service"]
to:
- operation:
methods: ["GET"]
paths: ["/api/users/*"]
- from:
- source:
principals: ["cluster.local/ns/default/sa/admin-service"]
# admin-service는 모든 메서드 허용
# 기본 거부 정책 (화이트리스트 방식)
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: default
spec: {} # 빈 spec = 모든 트래픽 거부
Fault Injection: 카오스 엔지니어링
프로덕션 장애를 시뮬레이션해 서비스의 탄력성을 테스트한다.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: user-service
spec:
hosts:
- user-service
http:
- fault:
# 지연 주입: 50% 요청에 3초 딜레이
delay:
percentage:
value: 50
fixedDelay: 3s
# 에러 주입: 10% 요청에 503 반환
abort:
percentage:
value: 10
httpStatus: 503
route:
- destination:
host: user-service
실제 코드를 변경하지 않고 네트워크 레벨에서 장애를 주입할 수 있다. 타임아웃, 재시도, 폴백 로직이 제대로 동작하는지 검증하는 데 필수적이다.
Observability: Kiali·Jaeger 연동
# Kiali 대시보드 (서비스 토폴로지)
istioctl dashboard kiali
# Jaeger (분산 트레이싱)
istioctl dashboard jaeger
# Grafana (메트릭)
istioctl dashboard grafana
# Envoy 프록시 상태 확인
istioctl proxy-status
istioctl proxy-config routes deploy/user-service
# 메시 전체 진단
istioctl analyze -n default
Envoy가 모든 트래픽을 중계하므로 별도 계측 코드 없이 요청 수, 지연 시간, 에러율, 서비스 의존성 그래프를 자동으로 수집한다.
운영 주의사항
| 항목 | 주의점 |
|---|---|
| 리소스 오버헤드 | 사이드카당 메모리 ~50MB, CPU ~10m. Pod 수 × 오버헤드 계산 필수 |
| 지연 시간 | 사이드카 경유로 요청당 ~1-3ms 추가. 지연 민감 서비스는 측정 필요 |
| 사이드카 주입 순서 | Init Container로 iptables 규칙 설정 → 앱보다 먼저 시작되어야 함 |
| 디버깅 복잡도 | 문제 발생 시 앱 vs 사이드카 vs istiod 구분이 어려움 |
| 버전 호환성 | Istio와 K8s 버전 호환 매트릭스 반드시 확인 |
정리
Istio Service Mesh는 트래픽 관리(VirtualService), 보안(mTLS·AuthorizationPolicy), 관측성(Kiali·Jaeger), 탄력성(서킷 브레이커·Fault Injection)을 애플리케이션 코드 변경 없이 인프라 레벨에서 제공한다. 마이크로서비스가 10개를 넘어가면 Service Mesh 도입을 진지하게 고려해야 한다. 단, 리소스 오버헤드와 운영 복잡도를 감안해 팀의 역량과 규모에 맞춰 판단하자.