LabHub
배우기 러닝패스 코스

ICA — Istio認定アソシエイト

アイデンティティはIPではなくサービスアカウントだ

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

Istio 에서 워크로드의 신원은 IP 도 파드 이름도 아닌 쿠버네티스 서비스어카운트입니다. 이 사실 하나에서 mTLS, 인가 정책, 그리고 대부분의 정책 디버깅이 파생됩니다.

フロー図: 쿠버네티스 서비스어카운트・개인키가 파드를 떠나지 않는다・좁은 범위가 항상 이깁니다.・평문 요청에는 principal 이 비어 있어 절대 매칭되지 않습니다.

왜 이게 필요했나

클러스터 내부는 흔히 신뢰할 수 있는 네트워크로 취급되지만, 실제로는 파드 하나만 탈취당해도 나머지 전부에 평문으로 접근할 수 있는 평평한 네트워크입니다. 제로트러스트는 이 가정을 뒤집습니다. 문제는 이것을 애플리케이션 코드로 구현하려면 모든 서비스에 인증서 발급·갱신, 상대 검증, 권한 검사 로직을 넣어야 한다는 점입니다. 언어 스택이 여럿인 조직에서 이를 일관되게 유지하는 것은 사실상 불가능합니다.

그래서 Istio 는 세 가지(암호화, 워크로드 인증, 인가)를 인프라 계층으로 내렸습니다. 그 토대가 신원 체계입니다. IP 는 파드가 재시작하면 바뀌고 스푸핑도 가능하지만, 서비스어카운트 기반 신원은 인증서에 새겨져 핸드셰이크에서 암호학적으로 검증됩니다.

어떻게 동작하나

신원은 SPIFFE 표준 형식을 따릅니다.

spiffe://cluster.local/ns/payments/sa/payments-api
         트러스트 도메인   네임스페이스  서비스어카운트

인증서 발급 흐름에서 기억할 점은 개인키가 파드를 떠나지 않는다는 것입니다. 파드 안의 istio-agent 가 키 쌍을 만들고 CSR 만 istiod 에 보냅니다. istiod 는 서비스어카운트 토큰으로 요청자를 검증한 뒤 SPIFFE ID 를 SAN 에 새긴 인증서를 서명해 돌려줍니다. 인증서는 기본 24시간 유효하고, 수명의 절반쯤 지난 시점부터 agent 가 알아서 재발급받습니다. Envoy 는 SDS 로 인증서를 받으므로 갱신에 파드 재시작이나 커넥션 드레인이 필요 없습니다.

PeerAuthentication 은 "들어오는 트래픽에 mTLS 를 어떻게 요구할 것인가"를 정합니다. PERMISSIVE(둘 다 수락, 기본값), STRICT(mTLS 만), DISABLE 셋이고, 좁은 범위가 항상 이깁니다. 워크로드 > 네임스페이스 > 메시 전역 순입니다. 메시 전역 정책은 루트 네임스페이스(보통 istio-system)에 이름 default 로 둡니다. 헬스 체크나 메시 밖 프로메테우스가 긁어가는 포트 하나만 예외를 두고 싶다면 portLevelMtls 를 씁니다.

AuthorizationPolicy 의 평가 순서는 시험에 거의 반드시 나옵니다.

1. CUSTOM  → 외부 인가기가 거부하면 즉시 거부
2. DENY    → 하나라도 매칭되면 즉시 거부
3. ALLOW   → 대상 워크로드에 ALLOW 정책이 하나도 없으면 허용(기본 개방)
             ALLOW 정책이 하나라도 있으면 매칭되어야 허용(기본 거부로 전환)

마지막 줄이 핵심 성질입니다. ALLOW 정책을 하나 추가하는 순간 그 워크로드는 화이트리스트 모드로 뒤집힙니다. 이 성질을 이용해 spec: {} 인 빈 정책 하나로 네임스페이스 기본 거부를 만듭니다. "ALLOW 정책은 존재하지만 매칭 규칙이 없다"는 뜻이라 아무것도 통과하지 못합니다.

또 하나 자주 걸리는 함정. principals 는 mTLS 인증서에서 나오므로 평문 요청에는 principal 이 비어 있어 절대 매칭되지 않습니다. PERMISSIVE는 평문과 mTLS를 모두 받습니다. 평문 요청에 principal이 없다는 뜻이지, PERMISSIVE의 모든 요청에 신원이 없다는 뜻은 아닙니다. mTLS 요청은 이 모드에서도 principal을 가질 수 있으므로 정책 디버깅에서는 실제 연결 방식을 함께 확인하세요. STRICT는 평문을 받지 않겠다는 별도의 결정입니다.

RequestAuthentication 은 최종 사용자 토큰(JWT)을 검증합니다. 여기서 가장 흔한 오해는 이 리소스만으로는 토큰 없는 요청이 그냥 통과한다는 점입니다. "JWT 가 있다면 유효해야 한다"만 강제하기 때문입니다. 토큰 필수화에는 AuthorizationPolicy도 필요하지만, 단순히 JWT 조건의 ALLOW를 하나 더 추가하면 안 됩니다. 여러 ALLOW는 합집합입니다. 기존 orders 신원 ALLOW가 있으면 JWT 없는 orders가 그 정책으로 통과하고, JWT만 검사하는 ALLOW는 다른 신원·경로까지 허용할 수 있습니다.

두 조건을 함께 요구하려면 같은 ALLOW 규칙의 같은 source에 principalsrequestPrincipals를 넣거나, 기존 최소 권한 ALLOW를 유지하면서 JWT 주체가 없는 요청을 notRequestPrincipals: ["*"]인 DENY로 막습니다. 같은 source의 필드는 AND이고, 서로 다른 from 항목이나 ALLOW 정책은 OR라는 차이를 기억하세요. DENY는 HTTP 속성이 없는 TCP 요청도 잡을 수 있으므로 적용 포트를 명시해야 합니다. 다음 실습은 HTTP 8080 포트만 대상으로 삼습니다.

실패 코드도 원인을 전부 말해 주지는 않습니다. 격리 Istio 1.31.0 실험에서 다른 audience의 JWT는 403과 audience 거부 메시지, 신원·경로 인가 실패는 403과 RBAC 거부 메시지였습니다. 401/403 숫자 하나 대신 응답 본문과 적용 정책·검증된 주체를 함께 확인하세요.

정책을 운영에 올릴 때는 istio.io/dry-run: "true" 애너테이션을 먼저 붙입니다. 평가만 하고 실제로 차단하지 않으면서 "켰다면 무엇이 막혔을까"를 로그와 메트릭으로 보여 줍니다. 거부 목록이 의도와 일치할 때 애너테이션을 떼는 것이 안전한 순서입니다.

현장에서 만나는 모습

저자의 홈랩에서는 노드 간 파드 트래픽을 WireGuard 로 투명하게 암호화하고 있습니다. cilium status 에는 Encryption: Wireguard [cilium_wg0 (Port: 51871, Peers: 2)] 로 찍히고, Modules Health 는 OK 92 / Degraded 0 입니다.

여기서 시험에도 나오는 중요한 구분이 생깁니다. WireGuard 는 노드 간 전송 구간 암호화이고, Istio 의 mTLS 는 워크로드 신원 증명이 붙은 애플리케이션 계층 암호화입니다. 전자는 "선을 도청해도 못 읽는다"를 보장하지만 "누가 보냈는가"는 증명하지 않습니다. AuthorizationPolicy 의 principals 가 요구하는 것은 후자입니다. 두 계층을 겹쳐 쓸 수는 있지만, 어느 쪽이 암호화를 책임지는지 팀 차원에서 하나로 정해 두지 않으면 이중 정책으로 디버깅 지옥이 열립니다.

같은 클러스터에서 얻은 또 하나의 감각은 L7 판정의 로그 모양입니다. 정책 위반 요청은 DROPPED 로, 그에 대한 403 응답은 FORWARDED 로 찍혔습니다. Istio 의 RBAC 거부도 똑같이 "연결은 성립했고 403 이 돌아온" 형태입니다. 연결 자체가 안 되는 문제와 절대 혼동하지 마세요.

다음 실습에서 할 것

kwok API에 전용 서비스어카운트와 워크로드 명세를 저장한 뒤, 메시 전역 STRICT 와 워크로드 단위 포트 예외를 작성하고, 기본 거부 → 최소 권한 ALLOW → 관리 경로 DENY(dry-run) → JWT 필수화 순서로 정책을 쌓아 올립니다.

이 실습에서는 실제 컨테이너나 Envoy가 실행되지 않습니다. 매니페스트 설계와 실제 트래픽 검증을 구분하세요.

공식 문서