서비스 메시: Istio와 Linkerd, mTLS 및 트래픽 관리
Kubernetes의 마이크로서비스 아키텍처에서 각 서비스는 수십 개의 다른 서비스와 통신합니다. 이러한 통신이 암호화된다는 것을 누가 보장합니까? 다음과 같은 경우 자동 재시도를 관리하는 사람은 누구입니까? 서비스에 일시적으로 연결할 수 없나요? 대기 시간 및 속도 측정항목을 제공하는 사람 각 소스-대상 쌍에 대한 오류는 무엇입니까? 서비스 메시가 없으면 다음 질문에 대답하세요. 질문에는 각 서비스마다 사용자 정의 코드가 필요합니다.
Un 서비스 메시 인프라 수준에서 이러한 문제를 해결합니다. 애플리케이션에 투명합니다. Kubernetes 환경의 두 주요 플레이어는 다음과 같습니다. 이스티오, 가장 기능이 풍부하고 링커드, 단순성과 최소한의 오버헤드를 위해 설계되었습니다. 이 문서에서는 설치 방법을 보여줍니다. 둘 다 자동 mTLS를 구성하고 카나리아 배포를 통해 트래픽을 관리하며 회로 차단 및 둘 중 하나를 선택하는 경우.
무엇을 배울 것인가
- 서비스 메시 작동 방식: 데이터 플레인(사이드카) 및 제어 플레인
- 자동 mTLS: 의미, 확인 방법, 예외 처리 방법
- Istio: 설치, VirtualService, DestinationRule, Canary 및 파란색/녹색
- Linkerd: 경량 설치, SMI TrafficSplit, 확장
- Istio OutlierDetection을 사용한 회로 차단
- 인프라 수준에서 재시도 및 시간 초과
- 관찰 가능성: 서비스 메시의 골든 신호 지표
- Istio vs Linkerd: 언제 어느 것을 선택해야 할까요?
서비스 메시 작동 방식
서비스 메시는 자동 주입을 기반으로 합니다. 사이드카 프록시 (Istio의 경우 Envoy, Linkerd의 경우 Linkerd2-proxy)를 각 Pod에 추가합니다. 사이드카가 모든 것을 가로막는다 변경 없이 애플리케이션 컨테이너 내부 및 외부로의 트래픽 코드에.
Il 데이터 평면 트래픽을 처리하는 모든 프록시 사이드카 세트 효과적이다. 그만큼 제어 평면 (Istio의 경우 Istiod, Linkerd의 경우 linkerd-control-plane) 구성을 프록시에 배포하고, mTLS용 인증서를 관리하고, 원격 측정을 수집합니다.
Istio와 Linkerd 비교
| 특성 | 이스티오 | 링커드 |
|---|---|---|
| 사이드카 프록시 | 특사(C++, 50-100MB) | linkerd2-proxy (Rust, 10-20MB) |
| 포드의 메모리 오버헤드 | 100-200MB | 20-30MB |
| 지연 시간 오버헤드 P99 | 2-5ms | 0.5-1ms |
| 자동 mTLS | 예(인증서 관리자 또는 내장) | 예(24시간 자동 회전) |
| 교통관리 | 전체(VirtualService, DR) | 기본(HTTPRoute, TrafficSplit) |
| L7 정책 | HTTP, gRPC, TCP | HTTP, gRPC |
| 입구 | API 게이트웨이 + Istio 게이트웨이 | API 게이트웨이 |
| 학습 곡선 | 험한 | 보통의 |
| 생산 성숙도 | 높음(구글, 에어비앤비) | 높음(Shopify, Microsoft) |
Istio: 기본 설치 및 구성
istioctl을 사용하여 설치
# Scarica e installa istioctl
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.0 sh -
export PATH=$PWD/istio-1.22.0/bin:$PATH
# Installa Istio con profilo di produzione
istioctl install --set profile=production -y
# Il profilo production abilita:
# - HA con multiple repliche del control plane
# - Affinity rules per distribuire su nodi diversi
# - Risorse CPU/memoria adeguate
# - Solo le feature necessarie (no addon come Kiali, Jaeger)
# Abilita l'iniezione automatica del sidecar nel namespace
kubectl label namespace production istio-injection=enabled
# Verifica lo stato del mesh
istioctl proxy-status
# Analizza la configurazione per possibili problemi
istioctl analyze --namespace production
Istio를 사용한 mTLS: PeerAuthentication 및 DestinationRule
Istio는 삽입된 모든 사이드카 Pod 간에 자동 mTLS를 구현합니다. 와 PeerAuthentication은 mTLS를 통해 수행될 수 있습니다. 엄격한 (필수) 네임스페이스 또는 전체 메시 수준:
# mtls-strict.yaml
# Abilita mTLS STRICT per tutto il namespace production
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default-mtls
namespace: production
spec:
mtls:
mode: STRICT # DISABLE, PERMISSIVE, STRICT
---
# Eccezione: un servizio legacy che non ha sidecar
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: legacy-service-exception
namespace: production
spec:
selector:
matchLabels:
app: legacy-service
mtls:
mode: PERMISSIVE # accetta anche connessioni plain-text
# Verifica mTLS
kubectl exec -n production frontend-pod -c istio-proxy -- \
pilot-agent request GET /config_dump | grep -A5 "tls_context"
# Visualizza lo stato mTLS con istioctl
istioctl x describe pod frontend-pod.production
VirtualService: 라우팅 및 트래픽 분할
VirtualService는 서비스에 대한 트래픽이 라우팅되는 방식을 정의합니다. HTTP 헤더, 가중치, 경로 일치를 기반으로 하는 규칙을 사용합니다.
# virtual-service-canary.yaml
# Canary deployment: 90% traffico a v1, 10% a v2
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api-service-vs
namespace: production
spec:
hosts:
- api-service # nome del Kubernetes Service
http:
# Routing per header: dev e QA ricevono sempre v2
- match:
- headers:
x-user-group:
exact: "beta-testers"
route:
- destination:
host: api-service
subset: v2
# Traffico generale: 90/10 split
- route:
- destination:
host: api-service
subset: v1
weight: 90
- destination:
host: api-service
subset: v2
weight: 10
# Timeout e retry a livello di infrastruttura
timeout: 5s
retries:
attempts: 3
perTryTimeout: 2s
retryOn: "5xx,reset,connect-failure,retriable-4xx"
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: api-service-dr
namespace: production
spec:
host: api-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http2MaxRequests: 1000
maxRequestsPerConnection: 10
loadBalancer:
simple: LEAST_CONN # ROUND_ROBIN, RANDOM, LEAST_CONN
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
OutlierDetection 기능이 있는 회로 차단기
회로 차단기는 로드 밸런싱에서 "비정상" 호스트를 일시적으로 제거합니다. 정의된 오류 임계값을 초과하는 경우 풀:
# destination-rule-circuit-breaker.yaml
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: payment-service-circuit-breaker
namespace: production
spec:
host: payment-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
connectTimeout: 3s
http:
http1MaxPendingRequests: 100
http2MaxRequests: 500
maxRetries: 3
outlierDetection:
# Rimuovi un host se in 10 secondi riceve 5 errori 5xx
consecutiveGatewayErrors: 5
consecutive5xxErrors: 5
interval: 10s
# Tienilo fuori per 30 secondi
baseEjectionTime: 30s
# Massimo 50% degli host puo essere rimosso
maxEjectionPercent: 50
# Analizza solo richieste con 100ms o piu di latenza
minHealthPercent: 50
인그레스 트래픽을 위한 Istio 게이트웨이
# istio-gateway.yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: production-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: wildcard-tls-cert # Secret con cert TLS
hosts:
- "*.federicocalo.dev"
- port:
number: 80
name: http
protocol: HTTP
tls:
httpsRedirect: true # redirect tutto HTTP a HTTPS
hosts:
- "*.federicocalo.dev"
---
# Collega il Gateway al VirtualService
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: api-gateway-vs
namespace: production
spec:
hosts:
- "api.federicocalo.dev"
gateways:
- istio-system/production-gateway
- mesh # anche per traffico interno al mesh
http:
- route:
- destination:
host: api-service
port:
number: 8080
AuthorizationPolicy: 액세스 제어
# authorization-policy.yaml
# Solo il frontend puo chiamare il backend
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: backend-access-policy
namespace: production
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
- from:
- source:
principals:
- "cluster.local/ns/production/sa/frontend-service-account"
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/v1/*"]
---
# Blocca tutto il resto (default deny)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: production
spec:
action: DENY
# Nessun selector = si applica a tutti i Pod nel namespace
# Nessuna rule = blocca tutto
Linkerd: 설치 및 구성
Linkerd는 운영 단순성과 성능을 선호합니다. Rust로 작성된 프록시 P99 지연 시간이 ~1ms이고 포드당 메모리가 ~20MB이므로 이상적입니다. 마이크로서비스가 많거나 리소스 제약이 있는 클러스터의 경우.
링커드 설치
# Installa Linkerd CLI
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh
export PATH=$HOME/.linkerd2/bin:$PATH
# Prerequisiti: verifica che il cluster sia compatibile
linkerd check --pre
# Installa il control plane
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -
# Verifica installazione
linkerd check
# Abilita injection sul namespace
kubectl annotate namespace production linkerd.io/inject=enabled
# Installa l'estensione Viz per osservabilita
linkerd viz install | kubectl apply -f -
linkerd viz check
linkerd viz dashboard &
Linkerd 및 HTTPRoute를 사용하는 카나리아(Gateway API)
# linkerd-canary-httproute.yaml
# Linkerd usa la Gateway API per il traffic splitting
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-service-canary
namespace: production
spec:
parentRefs:
- name: api-service
kind: Service
group: core
port: 80
rules:
- backendRefs:
- name: api-service-v1
port: 80
weight: 90
- name: api-service-v2
port: 80
weight: 10
# Monitora il canary con linkerd viz
linkerd viz stat httproute/api-service-canary -n production
linkerd viz routes deploy/api-service-v2 -n production
Linkerd로 관찰 가능
# Visualizza metriche golden signals per tutti i deployment
linkerd viz stat deploy -n production
# Output tipico:
# NAME MESHED SUCCESS RPS LATENCY_P50 LATENCY_P99 TCP_CONN
# api-service 4/4 99.8% 245 1ms 12ms 42
# backend-service 3/3 98.2% 180 3ms 45ms 28
# payment-service 2/2 100.0% 65 8ms 89ms 12
# Visualizza il traffico per un singolo Pod
linkerd viz tap pod/api-service-xyz -n production
# Genera un report di osservabilita
linkerd viz check --proxy -n production
Istio Telemetry: 지표, 추적 및 로깅
Istio는 자동으로 황금 신호 (지연 시간, 트래픽, 오류, 포화) 각 소스-대상 쌍에 대해. 측정항목은 형식으로 노출됩니다. Prometheus는 공식 Istio 대시보드를 통해 Grafana에서 볼 수 있습니다.
# telemetry-config.yaml
# Configura il sampling per il distributed tracing
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: mesh-tracing
namespace: istio-system
spec:
tracing:
- providers:
- name: tempo # o jaeger, zipkin
randomSamplingPercentage: 1.0 # campiona 1% del traffico in produzione
---
# Metriche custom per un servizio specifico
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: payment-service-metrics
namespace: production
spec:
selector:
matchLabels:
app: payment-service
metrics:
- providers:
- name: prometheus
overrides:
- match:
metric: REQUEST_COUNT
tagOverrides:
destination_version:
value: "request.headers['x-version'] | 'unknown'"
# Importa le dashboard Grafana ufficiali Istio
# Dashboard ID: 7639 (Mesh Overview), 11829 (Service), 12378 (Workload)
서비스 메시와 Cilium eBPF: 사용 시기
사이드카 없이(커널의 eBPF를 통해) mTLS 및 L7 정책을 제공하는 Cilium의 출현으로 선택이 복잡해요. 실용적인 가이드는 다음과 같습니다.
| 대본 | 추천 선택 | 이유 |
|---|---|---|
| 고급 트래픽 관리 기능을 갖춘 마이크로서비스(카나리아, 헤더 기반 라우팅) | 이스티오 | 대체할 수 없는 VirtualService/DestinationRule |
| 최소한의 오버헤드로 mTLS 보안 | 링커드 또는 실리움 | Rust 프록시 또는 최소 eBPF |
| 수백 개의 마이크로서비스, 제한된 리소스로 구성된 클러스터 | 링커드 또는 Cilium mTLS | 각 포드에 사이드카 오버헤드를 곱한 값 |
| 멀티 클러스터 또는 멀티 클라우드 | 이스티오 | 메시 페더레이션 내장 |
| 서비스 메시를 처음 접하는 팀 | 링커드 | 학습 곡선이 현저히 낮아짐 |
서비스 메시 모범 사례
프로덕션 서비스 메시 체크리스트
- PERMISSIVE 모드에서 시작: 아직 사이드카가 없는 서비스를 식별하려면 STRICT로 만들기 전에 PERMISSIVE에서 mTLS를 활성화하세요.
- 모든 VirtualServices에 시간 초과를 설정합니다. 시간 초과가 없으면 느린 종속성으로 인해 전체 호출 체인이 차단됩니다.
- 각 외부 종속성에 대한 회로 차단기: 데이터베이스, 외부 API, 결제 서비스
- 멱등성 오류에만 재시도를 사용하세요. 멱등성 키 없이 POST에서 자동 재시도를 수행하지 마십시오. 그렇지 않으면 중복 주문이 생성됩니다.
- CPU/메모리 사이드카 모니터링: 포드가 많은 클러스터에서는 총 사이드카 오버헤드가 상당할 수 있습니다.
- 테스트 장애 조치: 포드를 수동으로 비활성화하고 회로 차단기와 재시도가 예상대로 작동하는지 확인합니다.
- 메시를 최신 상태로 유지하세요. Istio 및 Linkerd 버전은 수명 주기가 짧습니다(6~12개월). 정기적인 업그레이드 계획
일반적인 안티 패턴
- 증폭을 통한 무한 재시도: A가 3번의 재시도를 통해 B를 호출하고 B가 3번의 재시도를 통해 C를 호출하는 경우 단일 오류로 인해 C에 대한 9번의 시도가 생성됩니다(재시도 폭풍).
- 시간 초과가 너무 관대함: 중요한 API의 시간 제한이 60초라는 것은 중단 중에 모든 애플리케이션 스레드/고루틴이 60초 동안 차단된다는 의미입니다.
- 제어 영역 오버헤드 무시: Istiod는 연결된 각 프록시에 대해 상당한 CPU/메모리를 소비합니다. 1000개 이상의 포드가 있는 클러스터에는 전용 노드가 필요합니다.
- 평면 없는 선택적 주입: 일부 포드에만 사이드카가 있는 경우 사이드카가 없는 포드와의 통신에 mTLS STRICT가 실패합니다.
결론 및 다음 단계
서비스 메시는 더 이상 "있으면 좋은 것"이 아니며 다음 요구 사항이 되었습니다. 심각한 마이크로서비스 아키텍처. 자동 mTLS, 세분화된 관찰 가능성, 회로 차단 및 선언적 트래픽 관리를 통해 실제 문제를 해결합니다. 서비스 메시에는 각 서비스에 사용자 정의 코드가 필요합니다.
Istio와 Linkerd 사이의 선택은 요구 사항에 따라 다릅니다. Istio는 다음과 같은 복잡한 시나리오를 위한 것입니다. 고급 및 다중 클러스터 트래픽 관리, 운영 단순성과 오버헤드를 위한 Linkerd 최소. 두 경우 모두 학습 및 설정에 대한 초기 투자는 애플리케이션 및 가시성의 인프라 코드 감소로 보상을 받았습니다. 클러스터 내 트래픽에 전례 없는 영향을 미칩니다.
Kubernetes at Scale 시리즈의 향후 기사
이전 기사
관련 시리즈
- Kubernetes 네트워킹: eBPF를 사용한 Cilium — mTLS용 서비스 메시의 대안
- 관찰 가능성 및 OpenTelemetry — Istio와 통합된 분산 추적
- 플랫폼 엔지니어링 — 내부 플랫폼으로서의 서비스 메시







