13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] mTLS

  • [인프라] Istio 프로덕션 도입 1년: 서비스 메시 운영에서 얻은 교훈과 팁

    [인프라] Istio 프로덕션 도입 1년: 서비스 메시 운영에서 얻은 교훈과 팁

    [인프라] Istio 프로덕션 도입 1년: 서비스 메시 운영에서 얻은 교훈과 팁

    Istio 프로덕션 운영을 1년 정도 해보니, 처음 기대했던 장점과 실제 운영에서 마주치는 현실은 꽤 다르더라고요. 쿠버네티스 서비스 메시를 도입하면 트래픽 제어, 보안 정책, 관측성(Observability, 시스템 상태를 관찰하는 능력)이 한 번에 정리될 것 같았는데, 막상 운영에 들어가니 설정은 늘어나고, 장애 포인트도 새로 생기고, 팀의 이해도 차이도 크게 느껴졌습니다. 저도 처음엔 이게 뭔가 싶었는데요. 그래도 지나고 보니 Istio 도입 사례에서 중요한 건 기능 자체보다, 어디까지 맡기고 어디서 멈출지 경계를 정하는 일이었습니다.

    이번 글에서는 제가 직접 겪은 Istio 프로덕션 운영 경험을 바탕으로, 도입 초기에 놓치기 쉬운 부분과 서비스 메시 운영 노하우를 정리해보겠습니다. 특히 Istio 장애 해결 과정에서 배운 점, 운영 기준을 어떻게 세웠는지, 그리고 어떤 팀에 정말 잘 맞는지 현실적으로 풀어볼게요.

    Istio 프로덕션 운영 아키텍처를 보여주는 쿠버네티스 서비스 메시 다이어그램

    프로덕션 환경에서 Ingress(인그레스, 외부 트래픽 진입점), Envoy 프록시, 서비스 간 통신 흐름을 한눈에 보여주는 구조 이미지입니다.

    1. 왜 Istio 프로덕션 운영이 생각보다 어렵냐면

    쉽게 말해 Istio는 애플리케이션 바깥에서 네트워크 정책을 통제하게 해주는 계층이거든요. 애플리케이션 코드를 크게 바꾸지 않고도 mTLS(mutual TLS, 상호 인증 암호화), Traffic Split(트래픽 분할), Retry(재시도), Timeout(타임아웃), Access Control(접근 제어)을 걸 수 있거든요. 듣기만 하면 정말 좋죠.

    근데 여기서 중요한 포인트! 기능이 많다는 건 운영자가 알아야 할 상태값도 많아진다는 뜻입니다. 실제로 써보니까, 애플리케이션 장애인지, 쿠버네티스 네트워크 문제인지, Envoy 설정 문제인지, Istiod 제어 평면(Control Plane, 정책 배포를 담당하는 핵심 컴포넌트) 문제인지 구분하는 데 시간이 꽤 걸렸습니다. 특히 밤에 장애 나면 정신없습니다 ㅎㅎ

    • 좋았던 점: 일관된 트래픽 정책, 보안 정책 표준화, 메트릭 수집 편의성
    • 어려웠던 점: 사이드카(Sidecar, 애플리케이션 옆에서 붙는 프록시) 리소스 오버헤드, 디버깅 복잡도, 운영 지식 요구치 상승
    • 결론: 기능보다 운영 모델을 먼저 정해야 합니다

    2. 서비스 메시를 쉽게 말하면 이런 개념입니다

    서비스 메시(Service Mesh, 마이크로서비스 간 통신 제어 계층)는 애플리케이션끼리 주고받는 네트워크 요청을 공통 프록시가 대신 관리하는 구조거든요. 개발팀은 비즈니스 로직에 집중하고, 플랫폼팀이나 인프라팀은 통신 정책을 중앙에서 제어하는 식이죠.

    항목 서비스 메시 없이 Istio 사용 시
    재시도 정책 애플리케이션 코드마다 개별 구현 VirtualService(가상 서비스 규칙)로 일관 적용
    서비스 간 암호화 앱별 구현 편차 큼 mTLS 정책으로 표준화 가능
    트래픽 분할 배포 파이프라인에 강하게 의존 Canary(카나리, 점진 배포) 구성 수월
    관측성 로그/메트릭 포맷 제각각 프록시 기준으로 공통 지표 확보

    제가 멘토링할 때 자주 드리는 말이 있는데요. Istio는 네트워크 운영체제처럼 접근해야 한다는 겁니다. 단순히 설치하고 끝나는 애드온(add-on)이 아니거든요. 정책, 배포, 인증서, 모니터링이 다 얽혀 있습니다.

    3. 제가 실제로 잡았던 Istio 도입 범위와 기준

    처음부터 클러스터 전체에 강하게 적용하면 사고 납니다. 저도 초반에 의욕이 앞서서 네임스페이스(namespace, 쿠버네티스 논리 격리 단위) 여러 개에 한 번에 사이드카 주입을 걸었다가, 예상 못 한 헬스체크 경로와 내부 호출 정책 때문에 삽질 좀 했습니다.

    그래서 운영 기준을 이렇게 다시 잡았습니다.

    1. 외부 공개 API와 내부 핵심 서비스만 우선 적용
    2. 관측성과 mTLS부터 도입
    3. 복잡한 Fault Injection(장애 주입)이나 고급 라우팅은 나중으로 미룸
    4. 기본 Retry, Timeout, Circuit Breaker(회로 차단) 정책만 표준화
    5. 온보딩 문서와 디버깅 명령어를 먼저 팀에 공유

    이 접근이 좋았던 이유는 명확합니다. Istio 도입 사례를 보면 성공한 팀들은 대부분 단계적으로 갑니다. 반대로, 기능을 다 켜놓고 팀이 따라오길 기대하면 운영 피로도가 급격히 올라갑니다.

    4. 실전 구현: 최소한의 프로덕션 시작 구성

    아래 예시는 과하게 복잡하지 않으면서도, 프로덕션에서 바로 의미가 있는 패턴입니다. Ingress Gateway(인그레스 게이트웨이), DestinationRule(대상 규칙), VirtualService를 기본으로 잡고, Timeout과 Retry를 명시해두는 방식이죠.

    4-1. 네임스페이스에 사이드카 자동 주입

    kubectl create namespace prod-app
    kubectl label namespace prod-app istio-injection=enabled
    kubectl get namespace prod-app --show-labels

    여기서 라벨(label)이 붙었다고 끝이 아닙니다. 기존 파드(Pod, 쿠버네티스 실행 단위)는 재생성이 필요합니다. 저도 이걸 놓쳐서 “왜 프록시가 안 붙지?” 하고 한참 봤었네요.

    4-2. 기본 라우팅 정책 정의

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: app-service
      namespace: prod-app
    spec:
      hosts:
        - app-service
      http:
        - timeout: 3s
          retries:
            attempts: 2
            perTryTimeout: 1s
          route:
            - destination:
                host: app-service
                subset: stable

    4-3. 서브셋과 mTLS 정책 정의

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: app-service
      namespace: prod-app
    spec:
      host: app-service
      trafficPolicy:
        tls:
          mode: ISTIO_MUTUAL
      subsets:
        - name: stable
          labels:
            version: v1

    실제로 써보니까 Timeout을 명시하지 않은 서비스가 생각보다 많았습니다. 서비스 메시가 들어오면 느린 응답이 더 잘 보이거든요. 이전에는 그냥 “가끔 느리네” 하고 넘어가던 게, 이제는 메트릭으로 드러납니다. 이건 불편한 게 아니라, 원래 있던 문제가 보이기 시작한 겁니다.

    Istio 프로덕션 운영에서 VirtualService와 DestinationRule 트래픽 제어를 설명하는 이미지

    VirtualService, DestinationRule, mTLS 정책이 어떻게 연결되어 실제 요청 흐름을 제어하는지 설명하는 구성 이미지입니다.

    4-4. 점검 명령어는 꼭 표준화하세요

    kubectl get pod -n prod-app
    kubectl describe pod <pod-name> -n prod-app
    istioctl proxy-status
    istioctl analyze
    kubectl logs <pod-name> -c istio-proxy -n prod-app

    여기서 istioctl analyze는 진짜 자주 씁니다. 리소스 참조가 꼬였을 때 생각보다 빠르게 힌트를 주더라고요.

    5. ⚠️ 실제 겪었던 문제와 Istio 장애 해결 팁

    Istio 장애 해결은 “증상”보다 “레이어”를 먼저 구분해야 빨라집니다. 저도 초반에는 애플리케이션 로그만 봤었는데, 나중엔 아래 순서로 보는 습관이 생겼습니다.

    1. 애플리케이션 컨테이너가 느린 건지 확인
    2. istio-proxy 컨테이너 로그 확인
    3. VirtualService, DestinationRule, PeerAuthentication 적용 범위 확인
    4. Ingress와 내부 서비스 호출 경로 분리해서 테스트
    5. mTLS 강제 여부와 예외 대상 확인

    5-1. 사이드카 주입 누락

    가장 흔했습니다. 특히 배치 잡(Job)이나 운영성 파드에서 자주 빠졌어요. 네임스페이스 라벨만 믿지 말고, 실제 파드에 프록시 컨테이너가 붙었는지 확인해야 합니다.

    5-2. mTLS 적용 후 일부 통신 실패

    이건 정말 많이 겪습니다. Plain Text(평문 통신)를 쓰던 워크로드가 남아 있거나, 외부 연동 경로가 예외 처리되지 않으면 통신 실패가 납니다. 저도 처음엔 애플리케이션 버그인 줄 알았는데 아니더라고요. 정책 범위를 좁혀서 단계적으로 적용하는 게 답이었습니다.

    5-3. Retry 때문에 지연이 더 커진 경우

    Retry는 만능이 아닙니다. 다운스트림 서비스가 이미 과부하인데 재시도를 추가하면 요청 폭주가 더 심해질 수 있거든요. 그래서 저는 모든 서비스에 같은 재시도 정책을 넣지 않고, 읽기 요청과 쓰기 요청을 구분해서 적용했습니다.

    • 읽기 요청: 제한적 Retry 허용
    • 쓰기 요청: 중복 처리 위험 때문에 신중 적용
    • 긴 작업: Timeout 기준부터 재설계

    5-4. 리소스 사용량 증가

    사이드카가 붙으면 메모리와 CPU 사용량은 당연히 늘어납니다. 이건 피할 수 없는 비용입니다. 중요한 건 놀라지 않는 거예요. 처음 용량 계획(Capacity Planning, 자원 수용량 계획)을 할 때부터 프록시 오버헤드를 포함해야 합니다.

    6. 검증은 이렇게 했습니다: 운영 지표와 확인 루틴

    프로덕션 반영 후에는 “설치됐다”보다 “통제되고 있다”를 확인해야 합니다. 저는 검증 기준을 크게 네 가지로 잡았습니다.

    • 서비스 간 호출 성공률이 안정적인가
    • 에러율이 특정 경로에서 급증하지 않는가
    • 배포 후 트래픽 분할이 의도대로 동작하는가
    • 프록시 로그와 애플리케이션 로그를 함께 볼 수 있는가
    kubectl get virtualservice -A
    kubectl get destinationrule -A
    kubectl get peerauthentication -A
    istioctl proxy-config routes <pod-name> -n prod-app

    특히 proxy-config routes로 실제 라우팅 결과를 확인하는 습관이 중요했습니다. YAML은 맞아 보여도 프록시에 반영된 상태가 기대와 다를 때가 있거든요. 처음엔 좀 귀찮은데, 이 루틴 덕분에 배포 직후 이상 동작을 빨리 잡았습니다.

    Istio 프로덕션 운영 검증을 위한 트래픽 모니터링 대시보드 이미지

    성공률, 지연 시간, 에러율, 서비스 간 호출 관계를 한 화면에서 확인하는 운영 대시보드 예시 이미지입니다.

    7. 1년 운영 후 정리한 서비스 메시 운영 노하우

    여기서는 좀 현실적인 이야기를 드릴게요. 쿠버네티스 서비스 메시가 모든 팀에 정답은 아닙니다. 서비스 수가 적고, 트래픽 정책도 단순하고, 팀이 네트워크 추상화에 익숙하지 않다면 오히려 복잡도만 늘 수 있습니다.

    반대로 아래 조건이면 Istio 프로덕션 운영의 효과가 꽤 큽니다.

    잘 맞는 경우 조심해야 하는 경우
    마이크로서비스 수가 많음 서비스 수가 적고 구조가 단순함
    팀별 통신 정책을 표준화해야 함 운영 인력이 매우 적음
    보안 정책과 암호화 요구가 큼 장애 분석 도구나 관측 체계가 약함
    카나리 배포와 세밀한 라우팅이 중요함 플랫폼 운영 문서가 없는 상태

    제가 얻은 핵심 교훈은 세 가지입니다.

    1. 작게 시작할 것: 전체 적용보다 핵심 서비스 우선
    2. 운영 명령어를 표준화할 것: 장애 대응 속도가 달라집니다
    3. 정책 소유권을 분명히 할 것: 누가 어떤 라우팅, 보안 정책을 관리하는지 애매하면 반드시 꼬입니다

    이 부분은 다음 글에서 다룰 예정인데요. 특히 Gateway API와 기존 Ingress 운영을 어떻게 나눠 가져갈지, 그리고 멀티 클러스터까지 확장할 때 무엇이 달라지는지는 따로 정리해보겠습니다. 이전 글에서 다뤘던 쿠버네티스 리소스 요청/제한(Request/Limit) 설계와도 연결되는 주제라 같이 보시면 흐름이 더 잘 잡히실 겁니다.

    Istio 프로덕션 운영 도입 전후를 비교한 서비스 메시 운영 요약 이미지

    도입 전후의 운영 방식 차이와 핵심 체크포인트를 직관적으로 비교하는 요약 이미지입니다.

    8. 마무리: Istio는 기능보다 운영 습관이 더 중요했습니다

    1년 정도 돌려보니, Istio 도입 사례에서 진짜 중요한 건 화려한 기능이 아니라 운영 습관이더라고요. YAML 몇 개 잘 쓴다고 끝나는 게 아니었습니다. 누가 정책을 만들고, 누가 검증하고, 장애가 났을 때 어느 레이어부터 볼지 팀이 합의되어 있어야 합니다.

    혹시 지금 Istio 도입을 고민하고 계시다면, 제 경험상 가장 먼저 할 일은 기능 체크리스트가 아닙니다. 우리 팀이 이 복잡도를 감당할 준비가 되었는지를 보는 겁니다. 준비가 되어 있다면 Istio 프로덕션 운영은 분명히 강력한 무기가 됩니다. 다만 준비 없이 들어가면, 편해지려고 넣은 도구가 가장 큰 장애 포인트가 되기도 합니다.

    정리하면 이렇습니다.

    • Istio는 강력하지만 운영 난도가 낮지는 않습니다
    • 서비스 메시 운영 노하우의 핵심은 단계적 도입과 표준화입니다
    • Istio 장애 해결은 로그보다 레이어 구분이 먼저입니다
    • 쿠버네티스 서비스 메시의 가치는 규모와 표준화 요구가 클수록 올라갑니다

    저도 처음엔 헷갈렸는데, 한 번 기준이 잡히고 나니까 훨씬 수월해졌습니다. 여러분도 처음부터 완벽하게 하려 하지 마시고, 작은 범위에서 검증하면서 가져가보세요. 그게 결국 제일 덜 아프고, 제일 오래 갑니다. 🎉

    9. 자주 묻는 질문 정리

    Istio는 모든 쿠버네티스 환경에 필요한가요?

    아닙니다. 서비스 수가 적고 통신 정책이 단순하다면 오버엔지니어링이 될 수 있습니다.

    처음 도입할 때 가장 먼저 볼 것은 뭔가요?

    mTLS와 관측성부터입니다. 그다음에 라우팅 정책을 최소 단위로 붙여보는 게 좋습니다.

    Istio 장애 해결에서 가장 자주 놓치는 부분은 뭔가요?

    사이드카 주입 여부, 정책 적용 범위, 그리고 실제 프록시에 반영된 설정 확인입니다.

  • [k8s] 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개월은 꽤 힘들었어요. 근데 한 번 익숙해지고 나면, 이게 없는 환경으로 돌아가기가 싫어지더라고요.

    오늘 다룬 내용을 정리하면:

    1. ✅ istioctl로 Istio 설치 및 네임스페이스 레이블 설정
    2. ✅ VirtualService + DestinationRule로 카나리 배포, A/B 테스트 구현
    3. ✅ PeerAuthentication STRICT으로 mTLS 강제 적용
    4. ✅ AuthorizationPolicy로 서비스 간 접근 제어
    5. ✅ Kiali + Prometheus로 서비스 메시 가시성 확보

    다음 글에서는 Istio를 활용한 멀티 클러스터 서비스 메시 구성과 Istio 업그레이드 전략을 다뤄볼 예정입니다. 그리고 이전 글에서 다뤘던 Kubernetes 네트워크 정책(NetworkPolicy)과 Istio를 함께 쓰는 방법도 참고하시면 좋아요.

    궁금한 점이나 막히는 부분 있으시면 댓글로 남겨주세요. 같이 삽질해봐요! 🎉