실전 마이크로서비스 환경에서 서비스 메시를 도입하는 전체 과정을 다룹니다. 기술 선택, 설치, 보안 설정, 트래픽 관리, 관측 가능성, 운영 자동화까지.
이 시리즈의 마지막 장에서는 실전 마이크로서비스 환경에 서비스 메시를 도입하는 전체 과정을 프로젝트 형태로 진행합니다. 기술 선택 기준부터 설치, 보안 설정, 트래픽 관리, 관측 가능성 구축, 그리고 Day-2 운영 전략까지 포괄합니다.
전자상거래 플랫폼을 운영하는 팀이 서비스 메시를 도입하려 합니다.
현재 환경:
- Kubernetes 클러스터 (EKS, 3 노드 그룹)
- 마이크로서비스 15개
- 네임스페이스: frontend, backend, payments, shared
- 보안 요구: 서비스 간 mTLS 필수 (PCI-DSS 대응)
- 트래픽 관리: 카나리 배포 필요
- 관측 가능성: 서비스 간 의존성 시각화 필요
| 요구사항 | 가중치 | Istio Ambient | Cilium | Linkerd |
|---|---|---|---|---|
| mTLS 자동화 | 높음 | 5 | 4 | 5 |
| 카나리 배포 | 높음 | 5 | 2 | 3 |
| L7 트래픽 관리 | 중간 | 5 | 3 | 3 |
| 운영 복잡성 (낮을수록 좋음) | 중간 | 3 | 4 | 5 |
| 리소스 효율성 | 중간 | 4 | 5 | 3 |
| 커뮤니티/문서 | 중간 | 5 | 4 | 3 |
| 라이선스 비용 | 높음 | 0 | 0 | 유료 |
이 시나리오에서는 Istio Ambient 모드를 선택합니다. mTLS, 카나리 배포, L7 트래픽 관리가 모두 필요하고, Ambient 모드로 리소스 오버헤드를 최소화할 수 있기 때문입니다.
# istioctl 설치 (최신 버전)
curl -L https://istio.io/downloadIstio | sh -
export PATH=$PWD/istio-1.25.0/bin:$PATH
# Ambient 프로파일로 설치
istioctl install --set profile=ambient -y
# 설치 확인
istioctl verify-install
kubectl get pods -n istio-system설치 후 확인해야 할 컴포넌트:
$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
istiod-xxx 1/1 Running 0 2m
ztunnel-node1-xxx 1/1 Running 0 2m
ztunnel-node2-xxx 1/1 Running 0 2m
ztunnel-node3-xxx 1/1 Running 0 2m
istio-cni-node-xxx 1/1 Running 0 2m# 각 네임스페이스를 Ambient 모드로 등록
kubectl label namespace frontend istio.io/dataplane-mode=ambient
kubectl label namespace backend istio.io/dataplane-mode=ambient
kubectl label namespace payments istio.io/dataplane-mode=ambient
kubectl label namespace shared istio.io/dataplane-mode=ambient
# 등록 확인
kubectl get namespace -L istio.io/dataplane-mode이것만으로 모든 서비스 간 통신에 mTLS가 적용됩니다. Pod 재시작이 필요 없습니다.
# backend 네임스페이스에 Waypoint 배포 (카나리 배포 사용)
istioctl waypoint apply -n backend --enroll-namespace
# payments 네임스페이스에도 Waypoint 배포 (L7 인가 정책 사용)
istioctl waypoint apply -n payments --enroll-namespace
# Waypoint 상태 확인
kubectl get gateway -n backend
kubectl get gateway -n paymentsapiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT각 네임스페이스에 기본 거부 정책을 적용합니다.
# Backend 네임스페이스 기본 거부
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: backend
spec:
{}
---
# Payments 네임스페이스 기본 거부
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: payments
spec:
{}# Frontend → Backend API 허용
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-frontend-to-api
namespace: backend
spec:
selector:
matchLabels:
app: api-gateway
action: ALLOW
rules:
- from:
- source:
namespaces: ["frontend"]
to:
- operation:
methods: ["GET", "POST", "PUT", "DELETE"]
paths: ["/api/*"]
---
# Backend → Payments 서비스 허용 (결제 관련만)
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: allow-order-to-payment
namespace: payments
spec:
selector:
matchLabels:
app: payment-service
action: ALLOW
rules:
- from:
- source:
principals:
- "cluster.local/ns/backend/sa/order-service"
to:
- operation:
methods: ["POST"]
paths: ["/payments/process", "/payments/refund"]Product Service의 v2 배포를 카나리로 진행합니다.
# 서브셋 정의
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: product-service
namespace: backend
spec:
host: product-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 3
interval: 10s
baseEjectionTime: 30s
---
# 카나리 라우팅 (10% → v2)
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: product-service
namespace: backend
spec:
hosts:
- product-service
http:
- route:
- destination:
host: product-service
subset: v1
weight: 90
- destination:
host: product-service
subset: v2
weight: 10
retries:
attempts: 3
perTryTimeout: 2s
retryOn: 5xx,reset,connect-failure# Payment 서비스: 엄격한 타임아웃
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: payment-service
namespace: payments
spec:
hosts:
- payment-service
http:
- route:
- destination:
host: payment-service
timeout: 10s
retries:
attempts: 2
perTryTimeout: 5s
retryOn: 5xx,reset
---
# Payment 서비스: 서킷 브레이커
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: payment-service
namespace: payments
spec:
host: payment-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
http:
http1MaxPendingRequests: 25
http2MaxRequests: 50
outlierDetection:
consecutive5xxErrors: 5
interval: 10s
baseEjectionTime: 60s
maxEjectionPercent: 30# Prometheus, Grafana, Jaeger, Kiali 설치
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.25/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.25/samples/addons/grafana.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.25/samples/addons/jaeger.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.25/samples/addons/kiali.yamlapiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: service-mesh-alerts
namespace: monitoring
spec:
groups:
- name: service-mesh.rules
rules:
- alert: PaymentServiceDown
expr: |
sum(rate(istio_requests_total{
destination_service="payment-service.payments.svc.cluster.local",
response_code=~"5.*"
}[5m]))
/
sum(rate(istio_requests_total{
destination_service="payment-service.payments.svc.cluster.local"
}[5m]))
> 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "Payment Service 에러율 5% 초과"
- alert: CanaryErrorRate
expr: |
sum(rate(istio_requests_total{
destination_service="product-service.backend.svc.cluster.local",
destination_version="v2",
response_code=~"5.*"
}[5m]))
/
sum(rate(istio_requests_total{
destination_service="product-service.backend.svc.cluster.local",
destination_version="v2"
}[5m]))
> 0.01
for: 5m
labels:
severity: warning
annotations:
summary: "Product Service v2 카나리 에러율 1% 초과"Istio의 카나리 업그레이드를 사용하면 다운타임 없이 버전을 올릴 수 있습니다.
# 새 버전의 Istiod를 리비전과 함께 설치
istioctl install --set revision=1-26 --set profile=ambient
# 네임스페이스를 새 리비전으로 전환
kubectl label namespace backend istio.io/rev=1-26 --overwrite
# 이전 리비전 제거
istioctl uninstall --revision 1-25CI/CD 파이프라인에서 Istio 설정을 사전 검증합니다.
name: Validate Istio Config
on:
pull_request:
paths:
- 'k8s/istio/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install istioctl
run: |
curl -L https://istio.io/downloadIstio | sh -
echo "$PWD/istio-*/bin" >> $GITHUB_PATH
- name: Validate configurations
run: |
istioctl validate -f k8s/istio/
- name: Analyze mesh config
run: |
istioctl analyze k8s/istio/ --use-kube=false# 루트 CA 인증서 만료일 확인
istioctl pc secret -n istio-system deploy/istiod | head -5
# 워크로드 인증서 상태 확인
istioctl proxy-config secret <pod-name> -n backend# 서비스 간 mTLS 연결 상태 확인
istioctl authn tls-check <pod-name>.backend
# 프록시 설정 덤프 (Waypoint)
istioctl proxy-config all <waypoint-pod> -n backend
# ztunnel 로그 확인
kubectl logs -n istio-system -l app=ztunnel --tail=100
# 메시 전체 상태 요약
istioctl proxy-status이 시리즈를 통해 서비스 메시의 기초부터 실전 운영까지 체계적으로 살펴보았습니다.
핵심 메시지:
서비스 메시는 선택이 아닌 필수가 되어가고 있습니다. 마이크로서비스 규모가 커질수록 서비스 간 통신의 보안, 관측, 회복 탄력성을 인프라 수준에서 처리해야 합니다.
사이드카 없는 아키텍처가 새로운 기본값입니다. Istio Ambient와 Cilium eBPF 모두 사이드카의 한계를 극복하며, 서비스 메시의 채택 장벽을 크게 낮추었습니다.
mTLS부터 시작하세요. L4 보안(mTLS)만으로도 서비스 메시의 가치를 즉시 체감할 수 있습니다. L7 기능은 필요에 따라 점진적으로 추가하면 됩니다.
관측 가능성은 서비스 메시의 숨은 킬러 기능입니다. 코드 변경 없이 서비스 간 통신의 전체 그림을 파악할 수 있다는 것은 운영 효율성에 큰 차이를 만듭니다.
점진적 도입이 핵심입니다. 빅뱅 방식의 전환은 위험합니다. 비프로덕션 환경에서 시작하여 서비스 단위로 확장하세요.
이 글이 도움이 되셨나요?
서비스 메시의 패러다임 전환인 사이드카 없는 아키텍처를 분석합니다. Istio Ambient Mesh와 Cilium eBPF의 비교, 마이그레이션 전략, 그리고 미래 전망까지.
서비스 메시가 제공하는 관측 가능성의 세 기둥을 분석합니다. 분산 추적, 골든 시그널 메트릭, 액세스 로그, 그리고 Kiali/Grafana 연동까지.
서비스 메시의 보안 기반인 mTLS의 작동 원리, SPIFFE 워크로드 아이덴티티, 인증서 관리, 그리고 제로 트러스트 아키텍처 구현 전략을 다룹니다.