목차
- 마이크로서비스가 늘어날수록 머리가 아파지더라고요
- Istio 서비스 메시가 뭔지 먼저 짚고 가죠
- 서비스 메시(Service Mesh)란?
- Istio 핵심 구성 요소
- Istio 설치 — 제가 권장하는 방법
- 사전 준비
- istioctl 설치
- Istio 프로파일 선택 및 설치
- 네임스페이스에 사이드카 자동 주입 활성화
- Istio 트래픽 관리 — 이게 진짜 핵심입니다
- VirtualService와 DestinationRule 이해하기
- 카나리 배포 설정 예시
- 헤더 기반 라우팅 — A/B 테스트에 유용해요
- 서킷 브레이커(Circuit Breaker) 설정
- Istio 보안 — mTLS로 서비스 간 통신 암호화
- mTLS(Mutual TLS) 이해하기
- AuthorizationPolicy — 세밀한 접근 제어
- JWT 인증 설정
- ⚠️ 삽질 경험 — 이것만 조심하세요
- 문제 1: 사이드카가 주입이 안 된다
- 문제 2: mTLS STRICT 모드 전환 후 통신 두절
- 문제 3: VirtualService 적용했는데 트래픽 분배가 안 된다
- 문제 4: 리소스 사용량이 예상보다 높다
- Kiali로 서비스 메시 시각화 확인하기
- Istio 도입 전후 비교 정리
- 자주 묻는 질문 (FAQ)
- Q. Istio는 소규모 환경에도 도입할 만한가요?
- Q. Istio 업그레이드는 어떻게 하나요?
- Q. Linkerd와 비교하면 어떤가요?
- Q. 사이드카 없이 Istio를 쓸 수 있나요?
- 마무리 — 처음엔 어렵지만 익숙해지면 없어서 못 삽니다
마이크로서비스가 늘어날수록 머리가 아파지더라고요
처음 마이크로서비스(Microservices) 아키텍처를 도입했을 때만 해도 "이제 서비스별로 독립 배포되니까 편하겠다!" 싶었거든요. 근데 서비스가 10개, 20개를 넘어가면서 슬슬 문제가 생기기 시작했습니다. 서비스 A가 서비스 B를 호출하다 타임아웃이 나는데, 어디서 문제가 생겼는지 추적이 안 되고... 보안 정책은 각 서비스마다 따로 관리해야 하고... 트래픽을 특정 버전으로 라우팅하고 싶은데 코드를 건드려야 하고...
그때 Istio 서비스 메시(Service Mesh)를 처음 접했습니다. 솔직히 처음엔 "또 새로운 복잡한 거 배워야 하나..." 싶었는데, 써보고 나서 생각이 완전히 바뀌었어요. 오늘은 Istio 설치부터 트래픽 관리, 보안까지 제가 직접 삽질하며 쌓은 경험을 공유해 드리려 합니다.
Istio 서비스 메시의 전체 아키텍처 — 컨트롤 플레인(istiod)과 데이터 플레인(Envoy 사이드카)의 관계를 보여줍니다.
Istio 서비스 메시가 뭔지 먼저 짚고 가죠
서비스 메시(Service Mesh)란?
쉽게 말해, 마이크로서비스들 사이의 통신을 인프라 레벨에서 투명하게 관리해주는 레이어입니다. 각 서비스 옆에 Envoy(엔보이)라는 프록시를 붙여놓고, 모든 네트워크 트래픽이 이 프록시를 거치게 하는 방식이에요. 개발자는 코드를 건드릴 필요 없이 운영팀에서 트래픽 정책을 관리할 수 있게 됩니다.
Istio는 현재 가장 널리 쓰이는 서비스 메시 솔루션으로, CNCF(Cloud Native Computing Foundation)의 그래듀에이티드 프로젝트입니다.
Istio 핵심 구성 요소
- istiod: 컨트롤 플레인(Control Plane). Pilot, Citadel, Galley가 합쳐진 단일 바이너리. 정책 관리의 두뇌 역할을 합니다
- Envoy Sidecar(엔보이 사이드카): 각 Pod에 자동 주입되는 프록시. 실제 트래픽을 처리하는 데이터 플레인(Data Plane)입니다
- Ingress Gateway(인그레스 게이트웨이): 클러스터 외부에서 들어오는 트래픽의 진입점입니다
- Egress Gateway(이그레스 게이트웨이): 클러스터 외부로 나가는 트래픽을 제어합니다
| 구성 요소 | 역할 | 위치 |
|---|---|---|
| istiod | 설정 배포, 인증서 관리, 서비스 디스커버리 | 컨트롤 플레인 (istio-system 네임스페이스) |
| Envoy Proxy | 실제 트래픽 처리, 메트릭 수집 | 각 Pod 내 사이드카 컨테이너 |
| Ingress Gateway | 외부 트래픽 수신 및 라우팅 | 데이터 플레인 (별도 Pod) |
Istio 설치 — 제가 권장하는 방법
사전 준비
Istio 설치 전에 Kubernetes 클러스터가 준비되어 있어야 합니다. 저는 홈랩에서 k3s 위에 올려서 테스트했고, 실무에서는 EKS, GKE 환경에서도 써봤어요. 공통적으로 잘 동작하더라고요.
- Kubernetes 1.21 이상 (권장)
- kubectl 설치 및 클러스터 접근 설정
- 충분한 리소스 (컨트롤 플레인용 최소 4GB RAM 권장)
istioctl 설치
Istio 공식 CLI 도구인 istioctl을 먼저 설치합니다. 가장 간단한 방법은 공식 설치 스크립트를 사용하는 거예요.
# Istio 최신 버전 다운로드 및 설치
curl -L https://istio.io/downloadIstio | sh -
# 다운로드된 디렉토리로 이동 (버전 번호는 다를 수 있습니다)
cd istio-*
# PATH에 istioctl 추가
export PATH=$PWD/bin:$PATH
# 영구 적용을 원하면 ~/.bashrc 또는 ~/.zshrc에 추가
echo 'export PATH=$HOME/istio-*/bin:$PATH' >> ~/.bashrc
# 설치 확인
istioctl version
Istio 프로파일 선택 및 설치
Istio는 여러 설치 프로파일(Profile)을 제공합니다. 처음엔 이게 뭔 차이인지 몰라서 그냥 default로 했다가 나중에 조정했었는데요. 미리 파악해두시면 정말 도움이 됩니다.
| 프로파일 | 특징 | 권장 사용처 |
|---|---|---|
| default | istiod + Ingress Gateway 포함 | 프로덕션 환경 |
| demo | 모든 기능 활성화, 모니터링 포함 | 학습/테스트 |
| minimal | istiod만 설치 | 커스텀 구성 |
| external | 외부 컨트롤 플레인 연결용 | 멀티 클러스터 |
# 사전 체크 (클러스터 호환성 확인)
istioctl x precheck
# demo 프로파일로 설치 (학습 목적)
istioctl install --set profile=demo -y
# 설치 확인
kubectl get pods -n istio-system
# 출력 예시:
# NAME READY STATUS RESTARTS AGE
# istiod-xxxxxxxxx-xxxxx 1/1 Running 0 2m
# istio-ingressgateway-xxxxxxxxx-xxxxx 1/1 Running 0 2m
# istio-egressgateway-xxxxxxxxx-xxxxx 1/1 Running 0 2m
네임스페이스에 사이드카 자동 주입 활성화
이 단계를 빠뜨리면 나중에 "왜 메시가 안 되지?" 하고 한참 헤맵니다. 저도 처음에 이거 놓쳐서 30분을 날렸어요 ㅎㅎ
# default 네임스페이스에 사이드카 자동 주입 레이블 추가
kubectl label namespace default istio-injection=enabled
# 확인
kubectl get namespace default --show-labels
Envoy 사이드카가 Pod에 자동 주입되는 과정 — 모든 인바운드/아웃바운드 트래픽이 사이드카 프록시를 거쳐 처리됩니다.
Istio 트래픽 관리 — 이게 진짜 핵심입니다
트래픽 관리가 Istio를 쓰는 가장 큰 이유 중 하나라고 생각해요. 카나리 배포(Canary Deployment), 블루/그린 배포(Blue/Green Deployment), A/B 테스트를 코드 변경 없이 할 수 있거든요.
VirtualService와 DestinationRule 이해하기
Istio 트래픽 관리의 두 핵심 리소스입니다.
- VirtualService(버추얼 서비스): "이 트래픽을 어디로 보낼지" 라우팅 규칙을 정의합니다
- DestinationRule(데스티네이션 룰): "목적지 서비스를 어떻게 나눌지" 서브셋(Subset) 및 로드밸런싱 정책을 정의합니다
카나리 배포 설정 예시
실제로 제가 가장 많이 쓰는 패턴입니다. 새 버전(v2)에 10%만 트래픽을 보내고, 안정적이면 점진적으로 늘리는 방식이에요.
# destination-rule.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: my-service-destination
spec:
host: my-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
# virtual-service.yaml — 90% v1, 10% v2로 트래픽 분배
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-service-vs
spec:
hosts:
- my-service
http:
- route:
- destination:
host: my-service
subset: v1
weight: 90
- destination:
host: my-service
subset: v2
weight: 10
# 적용
kubectl apply -f destination-rule.yaml
kubectl apply -f virtual-service.yaml
# 확인
kubectl get virtualservice
kubectl get destinationrule
헤더 기반 라우팅 — A/B 테스트에 유용해요
특정 헤더가 있는 요청만 새 버전으로 보내는 방식입니다. QA팀이나 내부 테스터에게만 새 버전을 보여줄 때 정말 유용하더라고요.
# 헤더 기반 라우팅 VirtualService
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-service-header-routing
spec:
hosts:
- my-service
http:
- match:
- headers:
x-test-user:
exact: "true"
route:
- destination:
host: my-service
subset: v2
- route:
- destination:
host: my-service
subset: v1
서킷 브레이커(Circuit Breaker) 설정
장애가 전파되는 걸 막는 패턴입니다. 특정 서비스가 느려지거나 에러가 많이 나면 자동으로 차단해서 전체 시스템을 보호해주는 거예요.
# circuit-breaker.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: my-service-cb
spec:
host: my-service
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 5 # 연속 5xx 에러 5회
interval: 30s # 30초 간격으로 체크
baseEjectionTime: 30s # 30초 동안 제외
maxEjectionPercent: 100 # 최대 100% 제외 가능
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 100
http2MaxRequests: 1000
Istio 보안 — mTLS로 서비스 간 통신 암호화
mTLS(Mutual TLS) 이해하기
Istio 보안의 핵심은 mTLS(상호 TLS 인증)입니다. 클라이언트와 서버 양쪽 모두 인증서로 신원을 증명하는 방식이에요. 일반 TLS는 서버만 인증서를 제시하지만, mTLS는 양방향 인증이라 훨씬 강력합니다.
Istio 1.5 버전부터는 기본적으로 mTLS가 PERMISSIVE(허용) 모드로 설정됩니다. 암호화된 연결과 평문 연결 모두 허용하는 모드예요. 마이그레이션할 때 유용하지만, 프로덕션에서는 STRICT 모드로 바꾸는 걸 강력히 권장합니다.
# peer-auth-strict.yaml — STRICT mTLS 적용
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICT
# 적용
kubectl apply -f peer-auth-strict.yaml
# 검증 — 사이드카 없는 Pod에서 호출하면 실패해야 함
kubectl exec -it [pod-name] -c istio-proxy -- curl http://my-service:8080
AuthorizationPolicy — 세밀한 접근 제어
mTLS로 암호화는 됐는데, 어떤 서비스가 어떤 서비스를 호출할 수 있는지 제어하고 싶을 때 AuthorizationPolicy(인가 정책)를 사용합니다.
# authz-policy.yaml — frontend 서비스만 backend 서비스 호출 허용
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: backend-authz
namespace: default
spec:
selector:
matchLabels:
app: backend
action: ALLOW
rules:
- from:
- source:
principals:
- "cluster.local/ns/default/sa/frontend-service-account"
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/*"]
JWT 인증 설정
# request-auth.yaml — JWT 토큰 검증
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: jwt-auth
namespace: default
spec:
selector:
matchLabels:
app: my-service
jwtRules:
- issuer: "https://your-auth-server.com"
jwksUri: "https://your-auth-server.com/.well-known/jwks.json"
⚠️ 삽질 경험 — 이것만 조심하세요
제가 Istio 도입하면서 겪었던 주요 문제들 공유합니다. 미리 알고 계시면 정말 시간 많이 절약하실 거예요.
문제 1: 사이드카가 주입이 안 된다
# Pod 확인 — READY가 2/2가 아니라 1/1이면 사이드카 미주입
kubectl get pods
# 네임스페이스 레이블 확인
kubectl get namespace default --show-labels
# istio-injection=enabled 레이블이 없으면 추가
kubectl label namespace default istio-injection=enabled
# 기존 Pod는 재시작해야 사이드카가 주입됨!
kubectl rollout restart deployment/my-deployment
문제 2: mTLS STRICT 모드 전환 후 통신 두절
STRICT 모드로 바꿨더니 레거시 서비스들이 다 죽어버린 경험이 있습니다. 사이드카가 없는 서비스는 mTLS를 못 하거든요.
# 어떤 서비스가 mTLS를 안 하고 있는지 확인
istioctl x describe service my-service
# 특정 네임스페이스만 STRICT, 나머지는 PERMISSIVE 유지하는 방법
# 네임스페이스별로 PeerAuthentication 적용 가능
문제 3: VirtualService 적용했는데 트래픽 분배가 안 된다
VirtualService의 hosts 필드와 실제 Kubernetes Service 이름이 정확히 일치해야 합니다. FQDN(완전 정규화 도메인 이름)으로 쓰거나 짧은 이름으로 통일해야 해요.
# Istio 설정 검증
istioctl analyze
# 특정 Pod의 Envoy 설정 확인
istioctl proxy-config cluster [pod-name]
istioctl proxy-config route [pod-name]
# 트래픽 흐름 확인
istioctl proxy-config listeners [pod-name]
문제 4: 리소스 사용량이 예상보다 높다
사이드카가 모든 Pod에 붙으니까 메모리, CPU 사용량이 꽤 올라갑니다. 소규모 환경에서는 부담이 될 수 있어요. 저는 홈랩에서 처음 올렸을 때 메모리가 모자라서 한참 고생했습니다.
- Envoy 프록시 하나당 약 50~100MB 메모리 사용 (환경마다 다름)
- 사이드카 리소스 제한 설정을 통해 조절 가능
- 꼭 필요한 네임스페이스에만 주입하는 것도 방법
Kiali로 서비스 메시 시각화 확인하기
Kiali(키알리)는 Istio의 공식 관찰성(Observability) 대시보드입니다. 서비스 간 트래픽 흐름을 그래프로 보여줘서 정말 유용해요. 처음 켰을 때 "오, 이게 되네!" 하고 감탄했습니다.
# Kiali 설치 (demo 프로파일이면 이미 설치되어 있을 수 있음)
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.17/samples/addons/kiali.yaml
# Prometheus, Grafana, Jaeger도 함께 설치 권장
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.17/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.17/samples/addons/grafana.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.17/samples/addons/jaeger.yaml
# Kiali 대시보드 열기
istioctl dashboard kiali
Kiali 대시보드에서 서비스 간 트래픽 흐름을 시각적으로 확인 — 실시간 RPS, 에러율, 레이턴시를 한눈에 볼 수 있습니다.
Istio 도입 전후 비교 정리
| 항목 | Istio 도입 전 | Istio 도입 후 |
|---|---|---|
| 트래픽 라우팅 | 코드 변경 필요, 재배포 필요 | YAML 수정만으로 즉시 적용 |
| 서비스 간 암호화 | 개별 서비스에서 TLS 직접 구현 | mTLS 자동 적용 |
| 장애 추적 | 로그 뒤지며 수동 추적 | 분산 트레이싱(Distributed Tracing)으로 자동 추적 |
| 접근 제어 | 각 서비스에서 개별 구현 | AuthorizationPolicy로 중앙 관리 |
| 카나리 배포 | Ingress 설정 복잡, 별도 도구 필요 | VirtualService weight 조정만으로 가능 |
| 서킷 브레이커 | 라이브러리 직접 구현 (Hystrix 등) | DestinationRule로 선언적 설정 |
Istio 서비스 메시 도입 전후 비교 — 트래픽 관리, 보안, 관찰성 측면에서의 변화를 한눈에 정리한 인포그래픽입니다.
자주 묻는 질문 (FAQ)
Q. Istio는 소규모 환경에도 도입할 만한가요?
솔직히 말씀드리면, 서비스가 5개 미만이면 오버엔지니어링일 수 있습니다. Istio 자체의 운영 복잡도가 있거든요. 서비스가 10개 이상이고, 트래픽 관리나 보안 요구사항이 복잡해질 때 도입을 고려하는 걸 권장합니다.
Q. Istio 업그레이드는 어떻게 하나요?
istioctl upgrade 명령어로 인플레이스(In-place) 업그레이드가 가능합니다. 다만 프로덕션에서는 카나리 업그레이드 방식을 권장해요. 이 부분은 다음 글에서 자세히 다룰 예정입니다.
Q. Linkerd와 비교하면 어떤가요?
Linkerd는 더 가볍고 단순하지만 기능이 제한적입니다. Istio는 기능이 풍부하지만 복잡도가 높아요. 팀의 기술 역량과 요구사항에 따라 선택하시면 됩니다. 서비스 메시 솔루션 비교는 별도 글로 정리해 드리겠습니다.
Q. 사이드카 없이 Istio를 쓸 수 있나요?
Istio 1.15부터 Ambient Mesh(앰비언트 메시)라는 사이드카 없는 방식이 알파로 도입됐습니다. 사이드카의 리소스 오버헤드를 줄이는 방향으로 발전하고 있어요. 아직 프로덕션에 쓰기엔 이르지만 지켜볼 만한 기술입니다.
마무리 — 처음엔 어렵지만 익숙해지면 없어서 못 삽니다
처음 Istio를 배울 때는 개념도 많고, CRD(Custom Resource Definition)도 낯설고, 트러블슈팅도 어렵게 느껴집니다. 저도 처음 3개월은 꽤 힘들었어요. 근데 한 번 익숙해지고 나면, 이게 없는 환경으로 돌아가기가 싫어지더라고요.
오늘 다룬 내용을 정리하면:
- ✅ istioctl로 Istio 설치 및 네임스페이스 레이블 설정
- ✅ VirtualService + DestinationRule로 카나리 배포, A/B 테스트 구현
- ✅ PeerAuthentication STRICT으로 mTLS 강제 적용
- ✅ AuthorizationPolicy로 서비스 간 접근 제어
- ✅ Kiali + Prometheus로 서비스 메시 가시성 확보
다음 글에서는 Istio를 활용한 멀티 클러스터 서비스 메시 구성과 Istio 업그레이드 전략을 다뤄볼 예정입니다. 그리고 이전 글에서 다뤘던 Kubernetes 네트워크 정책(NetworkPolicy)과 Istio를 함께 쓰는 방법도 참고하시면 좋아요.
궁금한 점이나 막히는 부분 있으시면 댓글로 남겨주세요. 같이 삽질해봐요! 🎉
'IT > k8s' 카테고리의 다른 글
| [k8s] 쿠버네티스 모니터링: Prometheus & Grafana 구축 및 대시보드 활용 가이드 (1) | 2026.05.10 |
|---|---|
| [k8s] Kubernetes Longhorn 스토리지: 설치부터 운영까지 완벽 가이드 (0) | 2026.05.09 |
| [쿠버네티스] Nginx vs Traefik Ingress Controller 선택 가이드: 13년차 엔지니어의 경험담 (0) | 2026.05.08 |
| [k8s] 쿠버네티스 Pod 트러블슈팅: CrashLoopBackOff, OOMKilled 완벽 해결 (0) | 2026.05.04 |
| [k8s] ArgoCD 프로덕션 환경 GitOps 베스트 프랙티스: 안정적인 배포와 보안 강화 (0) | 2026.04.30 |
| [k8s] 쿠버네티스 영구 스토리지: Longhorn vs Rook Ceph 비교 및 선택 가이드 (0) | 2026.04.27 |