본문 바로가기
클라우드/Istio

내 서비스만 암호화? 🔒 Istio mTLS, 무작정 STRICT 모드 쓰면 큰일나는 이유

by gasbugs 2025. 11. 28.

서비스 메시, 특히 Istio를 도입하면서 가장 먼저 기대하는 것 중 하나는 바로 강력한 '상호 TLS(mTLS)' 암호화일 겁니다. 모든 서비스 간의 통신을 암호화하여 중간에서 데이터를 탈취하더라도 내용을 알 수 없게 만드는 것, 생각만 해도 든든하죠. 💪

그래서 많은 분들이 Istio를 적용하자마자 보안 설정을 STRICT 모드로 변경하곤 합니다. "이왕 하는 거, 가장 강력한 보안으로 가자!" 라는 생각이죠. 하지만 이런 성급한 결정이 오히려 전체 서비스를 마비시키는 원인이 될 수 있다는 사실, 알고 계셨나요?

오늘은 왜 STRICT 모드를 무작정 적용하면 안 되는지, 그리고 더 안전하고 유연한 마이그레이션 전략을 위한 핵심 키인 PERMISSIVE 모드에 대해 깊이 알아보겠습니다.


🤔 "우리 서비스는 모두 메시 안에 있는데 괜찮지 않나요?"

물론, 개발 환경이나 모든 서비스가 처음부터 Istio 서비스 메시 안에서 함께 시작되었다면 STRICT 모드는 훌륭한 선택입니다. STRICT 모드는 이름 그대로, 오직 Istio 프록시(Sidecar)를 통해 mTLS로 암호화된 트래픽만 허용하는 '엄격한' 정책입니다.

이 정책을 YAML로 표현하면 다음과 같습니다.

# apiVersion: security.istio.io/v1beta1
# kind: PeerAuthentication
# metadata:
#   name: "default-strict-mtls"
#   namespace: "your-namespace"
# spec:
#   mtls:
#     mode: STRICT

STRICT 모드는 메시 내부의 서비스끼리 통신할 때는 전혀 문제가 없습니다. 둘 다 사이드카를 가지고 있고, 서로 mTLS로 통신하는 법을 알고 있으니까요.

하지만 현실 세계의 시스템은 이렇게 이상적이지 않습니다. 😥

💥 진짜 문제는 '메시 외부'에서 시작됩니다

실제 운영 환경은 다음과 같은 복잡한 상황에 놓여 있습니다.

  1. 점진적 마이그레이션: 모든 서비스를 한 번에 서비스 메시로 옮기는 것은 거의 불가능합니다. 일부는 메시 안에, 일부는 아직 외부에 남아있는 과도기 상태가 오랫동안 유지됩니다.
  2. 레거시 시스템: 서비스 메시로 마이그레이션할 계획이 없는 오래된 레거시 시스템이 존재합니다.
  3. 외부 솔루션: 모니터링 시스템(e.g., Prometheus)이나 특정 헬스 체크(Health Check) 시스템처럼 메시 외부에서 내부 서비스의 상태를 직접 확인해야 하는 경우가 있습니다.

이런 상황에서 STRICT 모드를 적용하면 어떻게 될까요?

상황 예시: 메시 외부에 있는 legacy-monitor가 메시 내부에 있는 user-service의 헬스 체크 엔드포인트(/healthz)를 호출한다고 가정해 봅시다.

  • user-service: Istio 메시 안에 있으며, STRICT 모드가 적용됨. (mTLS 통신만 허용)
  • legacy-monitor: 메시 외부에 있으므로 Istio 사이드카가 없음. (일반 텍스트, Plaintext HTTP 통신 시도)

결과: legacy-monitor가 보낸 일반 텍스트 HTTP 요청은 user-service의 사이드카에서 차단됩니다. 사이드카는 "어? 이거 mTLS 암호화된 요청이 아니네? 못 들여보내줘!" 라며 연결을 끊어버리죠. 💥

# legacy-monitor Pod에서 실행
$ curl http://user-service.your-namespace.svc.cluster.local/healthz

# 예상되는 결과
curl: (56) Recv failure: Connection reset by peer

결국 모니터링 시스템은 서비스가 죽었다고 판단하고 장애 알림을 보내게 됩니다. 서비스는 멀쩡히 살아있는데도 말이죠!


🌉 과도기의 현명한 다리, PERMISSIVE 모드

이러한 대혼란을 막기 위해 존재하는 것이 바로 PERMISSIVE (허용) 모드입니다.

PERMISSIVE 모드는 mTLS로 암호화된 트래픽과 일반 텍스트 트래픽을 모두 수락하는 유연한 정책입니다. 마치 공항의 보안 검색대에서 내국인 전용 줄과 외국인 전용 줄을 모두 운영하는 것과 같습니다. ✈️

YAML 설정은 매우 간단합니다. mode만 변경해주면 됩니다.

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "default-permissive-mtls"
  namespace: "your-namespace"
spec:
  mtls:
    mode: PERMISSIVE # <--- 바로 이 부분!

PERMISSIVE 모드에서는 워크로드가 다음과 같이 동작합니다.

  • 메시 내부 서비스 간의 통신: 상대방도 사이드카가 있다면, 알아서 mTLS로 암호화하여 통신합니다. (보안 유지 ✅)
  • 메시 외부에서 들어오는 통신: 상대방이 사이드카가 없어 일반 텍스트로 요청을 보내도, 일단 수락합니다. (호환성 유지 ✅)

전체 마이그레이션 여정 🗺️

PERMISSIVE 모드를 활용하면 전체 시스템을 중단 없이 안전하게 서비스 메시로 전환할 수 있습니다.

1단계: 도입 및 전환 (PERMISSIVE)

  • 새로운 서비스들을 Istio 메시 내에 배포하고, PeerAuthentication을 PERMISSIVE 모드로 설정합니다.
  • 결과:
    • 메시 안의 서비스끼리는 mTLS로 안전하게 통신합니다.
    • 메시 밖의 레거시 서비스들도 기존처럼 일반 텍스트로 문제없이 통신합니다.
    • 시스템은 중단 없이 안정적으로 운영됩니다. 😌

2단계: 안정화 및 검증

  • 모든 서비스가 메시 안으로 들어왔는지, 외부 의존성이 모두 사라졌는지 꼼꼼히 확인합니다.
  • Kiali 같은 대시보드를 통해 모든 트래픽이 자물쇠(🔒) 아이콘으로 표시되는지(mTLS) 확인하며 확신을 가집니다.

3단계: 최종 강화 (STRICT)

  • 모든 서비스가 메시 안에 성공적으로 안착했고, 더 이상 외부의 일반 텍스트 트래픽을 허용할 필요가 없다고 판단되면, 그때 PeerAuthentication을 STRICT 모드로 전환합니다.
  • 결과: 이제 우리의 서비스 메시는 외부의 암호화되지 않은 접근을 원천 차단하는 견고한 요새가 됩니다. 🏰

✨ 결론: 상황에 맞는 전략이 최고의 보안입니다

Istio의 STRICT 모드는 분명 강력하고 이상적인 보안 목표입니다. 하지만 모든 여정에는 과정이 있듯이, 서비스 메시로의 전환 과정에서는 PERMISSIVE 모드가 필수적인 '징검다리' 역할을 합니다.

무작정 가장 강력한 설정을 고집하기보다는, 현재 우리 시스템의 구성과 마이그레이션 단계를 이해하고 그에 맞는 유연한 전략을 선택하는 것이야말로 진정한 의미의 안정적인 시스템을 구축하는 길입니다.

여러분의 서비스 메시는 지금 어떤 단계에 있나요? 혹시 모를 장애를 막기 위해 지금 바로 PeerAuthentication 설정을 점검해 보세요!