Istio 서비스 메시 · 보안 — mTLS 와 AuthorizationPolicy · 실습
PERMISSIVE 에서 STRICT 까지 밀어 올리기
목표
mTLS 정책의 세 가지 범위와 우선순위를 손으로 다뤄 보고, 운영 중인 메시를 끊지 않고 STRICT 로 올리는 절차를 계획으로 남깁니다.
왜 중요한가
STRICT 전환은 기술적으로는 필드 하나를 바꾸는 일이지만, 운영에서는 가장 사고가 잦은 작업 중 하나입니다. 이유는 단순합니다 — 평문으로 들어오던 경로가 예고 없이 전부 끊기기 때문입니다. 사이드카 없는 크론, 메시 밖 배치, 커스텀 프로브는 대시보드에 잘 드러나지 않다가 STRICT 를 켠 순간 장애로 나타납니다. 그래서 정석은 PERMISSIVE 로 두고 평문 트래픽의 출발지를 전수 조사한 뒤, 좁은 범위부터 올리는 것입니다.
또 하나 반드시 익혀야 할 것은 방향의 구분입니다. PeerAuthentication 은 받는 쪽(인바운드), DestinationRule 의 trafficPolicy.tls 는 보내는 쪽(아웃바운드)을 다룹니다. 이 둘이 어긋나면 연결이 실패하는데, 애플리케이션 로그에는 그냥 503 으로만 보입니다. 게다가 이 조합은 istioctl analyze 가 잡아 주지 않습니다 — 예전에는 전용 분석기가 있었지만 지금 버전의 분석기 목록에는 없습니다. 그래서 두 리소스를 짝으로 놓고 사람이 직접 대조하는 습관이 그대로 안전장치가 됩니다.
이 환경에서는 실제 핸드셰이크가 일어나지 않으므로, 채점은 정책의 이름·범위·필드와 정적 분석 결과를 봅니다.
단계
시작 전 준비. 실습 파드는 실습마다 새로 뜨므로 앞 실습의 메시 설정은 남아 있지 않습니다. kubectl get crd peerauthentications.security.istio.io 가 비어 있으면 istioctl manifest generate --set profile=minimal > /root/istio/manifest.yaml 후 kubectl apply -f /root/istio/manifest.yaml 을 두 번 실행하세요. 이 매니페스트가 istio-system 네임스페이스도 함께 만드는데, 2번에서 메시 전역 정책을 둘 곳이라 반드시 있어야 합니다. 그다음 kubectl create ns mesh-lab && kubectl label ns mesh-lab istio-injection=enabled 로 작업 네임스페이스를 준비하세요.
1. /root/istio/mtls/pa-permissive.yaml 을 만드세요 — 문서 하나짜리 PeerAuthentication 이며 metadata.name 은 default, metadata.namespace 는 mesh-lab, spec.mtls.mode 는 PERMISSIVE 이고 selector 는 두지 마세요(네임스페이스 전체 정책입니다). 만든 뒤 적용하세요.
2. istio-system 네임스페이스에 이름이 default 인 PeerAuthentication 을 spec.mtls.mode: STRICT 로, selector 없이 적용하세요. 그리고 /root/istio/mtls/out/scope-note.txt 에 메시 전역 / 네임스페이스 / 워크로드 세 층 중 더 좁고 구체적인 범위가 우선한다는 규칙을 적으세요.
3. mesh-lab 에 payments 워크로드를 만드세요 — ServiceAccount payments, Service payments(포트 이름 http 8080, http-metrics 9090), Deployment payments(파드 라벨 app: payments, serviceAccountName: payments). 그다음 PeerAuthentication legacy-metrics 를 mesh-lab 에 만드세요: selector.matchLabels.app 은 payments, spec.mtls.mode 는 STRICT, portLevelMtls 에는 포트 9090 하나만 mode: DISABLE 로 두세요.
4. mesh-lab 에 DestinationRule payments-mtls 를 만드세요. spec.host 는 payments, spec.trafficPolicy.tls.mode 는 ISTIO_MUTUAL 입니다. 그리고 /root/istio/mtls/out/direction-note.txt 에 PeerAuthentication 이 받는 쪽(인바운드), DestinationRule 이 보내는 쪽(클라이언트/아웃바운드)을 다룬다는 차이를 적으세요.
5. /root/istio/mtls/identity.txt 에 payments 워크로드의 SPIFFE 아이덴티티를 정확히 한 줄로 적으세요: spiffe://cluster.local/ns/mesh-lab/sa/payments. 그리고 /root/istio/mtls/out/identity-note.txt 에 메시의 신원이 IP 주소가 아니라 서비스 어카운트라는 요지를 적으세요.
6. mesh-lab 에 RequestAuthentication jwt-payments 를 만드세요. selector.matchLabels.app 은 payments, jwtRules[0].issuer 는 https://idp.labhub.example/, jwtRules[0].jwksUri 는 https://idp.labhub.example/.well-known/jwks.json 입니다. 그리고 /root/istio/mtls/out/jwt-note.txt 에 이 리소스만으로는 토큰 없는 요청을 막지 못하며 AuthorizationPolicy 가 함께 필요하다는 사실을 적으세요.
7. mesh-lab 의 default PeerAuthentication 을 STRICT 로 바꿔 적용하세요. 그 상태에서 spec.trafficPolicy.tls.mode: DISABLE 인 DestinationRule(예: payments-plaintext)을 적용하고 istioctl analyze -n mesh-lab 결과를 /root/istio/mtls/out/analyze-conflict.txt 에 저장하세요. 이 버전의 분석기 목록에는 mTLS 조합 충돌을 보는 분석기가 없어 출력에 그 충돌이 나타나지 않습니다 — 무엇과 무엇이 어긋났는지 한 줄로 덧붙여 기록에 남기세요. 그다음 그 DestinationRule 을 삭제하거나 ISTIO_MUTUAL 로 고쳐 충돌을 없애고, 다시 분석해 /root/istio/mtls/out/analyze-fixed.txt 에 저장하세요. mesh-lab 에 tls.mode: DISABLE 인 DestinationRule 이 하나도 남으면 안 됩니다.
8. /root/istio/mtls/migration.md 를 400바이트 이상으로 쓰세요. 문서 안에서 PERMISSIVE 와 관측(메트릭/모니터링) 이야기가 STRICT 라는 단어보다 먼저(윗줄에) 나와야 하고, 네임스페이스 단위 단계 적용과 롤백(되돌리는) 방법이 들어가야 합니다. 마지막으로 mesh-lab 의 default PeerAuthentication 이 STRICT 인 상태로 마무리하세요.
참고
- 실습 파드는 실습마다 새로 뜨므로 앞 실습의 클러스터 상태는 남아 있지 않습니다. 그래서 메시 설정을 매니페스트로 남겨 두는 것이 곧 재현 가능성입니다. 보안 정책은 특히 그렇습니다 — 손으로 켠 STRICT 는 클러스터가 사라지면 함께 사라지지만, 저장소에 든 정책은 다음 클러스터에서도 그대로 재현됩니다.
- 8번에서 문서 제목에
STRICT를 먼저 쓰면 순서 검사가 걸립니다. 제목은 "mTLS 전환 계획" 처럼 두고, 본문을 단계 0(관측, PERMISSIVE 유지) → 단계 1(평문 출발지 제거) → 단계 2(네임스페이스 단위 STRICT) → 단계 3(메시 전역 STRICT) → 롤백 순으로 쓰세요. - 실제 운영에서 평문 비율은
istio_requests_total의connection_security_policy라벨로 봅니다. 이 환경에는 메트릭이 없지만, 계획서에는 그 판단 근거를 적어 두는 것이 맞습니다. - 3번의 Deployment 는
/opt/lab/fixtures/istio/inject-target.yaml을 복사해serviceAccountName만 추가하면 편합니다. - 흔한 실수 1: 네임스페이스 전체 정책에 selector 를 붙이는 것. selector 가 붙는 순간 워크로드 단위 정책이 되어 나머지 워크로드에는 적용되지 않습니다.
- 흔한 실수 2: 메시 전역 정책을 아무 네임스페이스에나 두는 것. 루트 네임스페이스(
istio-system)에 이름default로 두어야 전역이 됩니다.
단계 8개
- 네임스페이스 기본 정책을 PERMISSIVE 로 두기
- 메시 전역 기본값을 STRICT 로 올리기
- 워크로드 하나의 포트 하나만 예외로 열기
- 보내는 쪽 mTLS 선언하기
- 워크로드의 신원을 적어 보기
- 최종 사용자 JWT 검증 정책 만들기
- STRICT 와 DISABLE 의 충돌 만들고 해소하기
- 단계적 전환 계획 쓰고 전환 끝내기