Anthos Service Mesh 예시: mTLS


Anthos Service Mesh 1.5 이상에서는 자동 상호 TLS(자동 mTLS)가 기본적으로 사용 설정됩니다. 자동 mTLS를 사용하면 클라이언트 사이드카 프록시가 서버에 사이드카가 있는지 자동으로 감지합니다. 클라이언트 사이드카는 사이드카가 있는 워크로드에는 mTLS를 전송하고, 사이드카 없는 워크로드에는 일반 텍스트를 전송합니다. 하지만 서비스는 일반 텍스트와 mTLS 트래픽을 모두 수락합니다. 포드에 사이드카 프록시를 삽입할 때에도 mTLS 트래픽만 허용하도록 서비스를 구성하는 것이 좋습니다.

Anthos Service Mesh를 사용하면 단일 YAML 파일을 적용하여 애플리케이션 코드 외부에서 mTLS를 적용할 수 있습니다. Anthos Service Mesh는 전체 서비스 메시, 네임스페이스, 개별 워크로드에 인증 정책을 적용할 수 있는 유연성을 제공합니다.

상호 mTLS

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

이 튜토리얼을 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않도록 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

Online Boutique 액세스

  1. kubectl의 현재 컨텍스트를, Online Boutique를 배포한 클러스터로 설정합니다.

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION
    
  2. frontend 네임스페이스의 서비스를 나열합니다.

    kubectl get services -n frontend
    

    frontend-externalLoadBalancer이며 외부 IP 주소를 포함합니다. 샘플 애플리케이션에는 부하 분산기에 해당하는 서비스가 포함되어 Anthos Service Mesh가 없는 GKE에 배포될 수 있습니다.

  3. frontend-external 서비스의 외부 IP 주소를 사용하여 브라우저에서 애플리케이션을 방문합니다.

    http://FRONTEND_EXTERNAL_IP/
    
  4. Anthos Service Mesh는 인그레스 게이트웨이를 배포하는 기능을 제공합니다. 또한 인그레스 게이트웨이의 외부 IP 주소를 사용하여 Online Boutique에 액세스할 수 있습니다. 게이트웨이의 외부 IP를 가져옵니다. 자리표시자를 다음 정보로 바꿉니다.

    • GATEWAY_SERVICE_NAME : 인그레스 게이트웨이 서비스의 이름입니다. 샘플 게이트웨이를 수정하지 않고 배포한 경우 또는 기본 인그레스 게이트웨이를 배포한 경우 이름은 istio-ingressgateway입니다.
    • GATEWAY_NAMESPACE: 인그레스 게이트웨이를 배포한 네임스페이스입니다. 기본 인그레스 게이트웨이를 배포한 경우 네임스페이스는 istio-system입니다.
    kubectl get service GATEWAY_NAME -n GATEWAY_NAMESPACE
    
  5. 브라우저에서 다른 탭을 열고 인그레스 게이트웨이의 외부 IP 주소를 사용하여 애플리케이션을 방문합니다.

    http://INGRESS_GATEWAY_EXTERNAL_IP/
    
  6. 다음 명령어를 실행하여 다른 포드의 일반 HTTP로 frontend 서비스를 curl합니다. 서비스가 서로 다른 네임스페이스에 있으므로 frontend 서비스의 DNS 이름을 curl해야 합니다.

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    기본적으로 TLS 및 일반 텍스트 트래픽이 모두 수락되므로 요청이 200 상태로 성공합니다.

네임스페이스당 상호 TLS 사용 설정

kubectl을 사용해 PeerAuthentication 정책을 적용하여 mTLS를 적용합니다.

  1. 다음 인증 정책을 mtls-namespace.yaml로 저장합니다.

    cat <<EOF > mtls-namespace.yaml
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "namespace-policy"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    YAML의 mode: STRICT 줄에서 mTLS만 허용하도록 서비스를 구성합니다. 기본적으로 modePERMISSIVE이며 일반 텍스트와 mTLS를 모두 허용하도록 서비스를 구성합니다.

  2. 인증 정책을 적용하여 모든 Online Boutique 서비스에서 mTLS만 수락하도록 구성합니다.

    for ns in ad cart checkout currency email frontend loadgenerator \
         payment product-catalog recommendation shipping; do
    kubectl apply -n $ns -f mtls-namespace.yaml
    done
    

    예상 출력:

    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created

  3. 브라우저에서 frontend-external 서비스의 외부 IP 주소를 사용하여 Online Boutique에 액세스하는 탭으로 이동합니다.

    http://FRONTEND_EXTERNAL_IP/
    
  4. 페이지를 새로고침합니다. 브라우저에 다음 오류가 표시됩니다.

    사이트에 연결할 수 없습니다.

    페이지를 새로고침하면 일반 텍스트가 frontend 서비스로 전송됩니다. STRICT 인증 정책으로 인해 사이드카 프록시는 서비스에 대한 요청을 차단합니다.

  5. 브라우저에서 istio-ingressgateway의 외부 IP 주소를 사용하여 Online Boutique에 액세스하는 탭으로 이동하고 정상적으로 표시되는 페이지를 새로고침합니다. 인그레스 게이트웨이를 사용하여 Online Boutique에 액세스하면 요청은 다음 경로를 사용합니다.

    상호 mTLS

    mTLS 인증 흐름은 다음과 같습니다.

    1. 브라우저에서 서버로 일반 텍스트 HTTP 요청을 보냅니다.
    2. 인그레스 게이트웨이 프록시 컨테이너가 요청을 가로챕니다.
    3. 인그레스 게이트웨이 프록시는 서버 측 프록시(이 예시에서는 프런트엔드 서비스)와 TLS 핸드셰이크를 수행합니다. 이 핸드셰이크에는 인증서 교환이 포함됩니다. 이러한 인증서는 Anthos Service Mesh를 통해 프록시 컨테이너에 사전 로드됩니다.
    4. 인그레스 게이트웨이 프록시는 서버 인증서의 보안 이름 확인을 실행하여 승인된 ID가 서버를 실행 중인지 확인합니다.
    5. 인그레스 게이트웨이와 서버 프록시는 상호 TLS 연결을 설정하며, 서버 프록시는 요청을 서버 애플리케이션 컨테이너(프런트엔드 서비스)로 전달합니다.
  6. 다음 명령어를 실행하여 다른 포드의 일반 HTTP로 frontend 서비스를 curl합니다.

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    모든 Online Boutique 서비스가 STRICT mTLS로 설정되고 사이드카 프록시가 서비스에 대한 요청을 차단하기 때문에 요청이 실패합니다.

    예상 출력:

    000
    command terminated with exit code 56

mTLS 상태 보기

Google Cloud 콘솔에서 인증 정책을 포함한 Anthos 보안 기능의 상태를 볼 수 있습니다.

  1. Google Cloud 콘솔에서 GKE Enterprise 보안 페이지로 이동합니다.

    GKE Enterprise 보안으로 이동

  2. 메뉴 바의 드롭다운 목록에서 Google Cloud 프로젝트를 선택합니다.

    정책 요약에는 mTLS를 포함한 애플리케이션 보안 상태가 표시됩니다.

  3. 정책 감사를 클릭하여 각 클러스터 및 네임스페이스의 워크로드 정책 상태를 확인합니다. mTLS 상태 카드에는 개요가 제공합니다. 워크로드 목록에는 각 워크로드의 mTLS 상태가 표시됩니다.

    모든 서비스 엄격한 mTLS

인증 정책 찾기 및 삭제하기

  1. 서비스 메시의 모든 PeerAuthentication 정책 목록을 보려면 다음을 실행하세요.

    kubectl get peerauthentication --all-namespaces
    

    출력은 다음과 비슷합니다.

    NAMESPACE         NAME               MODE     AGE
    ad                namespace-policy   STRICT   17m
    cart              namespace-policy   STRICT   17m
    checkout          namespace-policy   STRICT   17m
    currency          namespace-policy   STRICT   17m
    email             namespace-policy   STRICT   17m
    frontend          namespace-policy   STRICT   17m
    loadgenerator     namespace-policy   STRICT   17m
    payment           namespace-policy   STRICT   17m
    product-catalog   namespace-policy   STRICT   17m
    recommendation    namespace-policy   STRICT   17m
    shipping          namespace-policy   STRICT   17m
    
  2. 모든 Online Boutique 네임스페이스에서 인증 정책을 삭제합니다.

    for ns in ad cart checkout currency email frontend loadgenerator payment \
      product-catalog recommendation shipping; do
        kubectl delete peerauthentication -n $ns namespace-policy
    done;
    

    예상 출력:

    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    
  3. frontend-external 서비스의 외부 IP 주소를 사용하여 Online Boutique에 액세스하고 페이지를 새로 고칩니다. 페이지가 예상한 대로 표시됩니다.

  4. 다음 명령어를 실행하여 다른 포드의 일반 HTTP로 frontend 서비스를 curl합니다.

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    기본적으로 TLS 및 일반 텍스트 트래픽이 모두 수락되므로 요청이 200 상태로 성공합니다.

Google Cloud 콘솔에서 워크로드 목록을 표시하는 페이지를 새로 고치면 mTLS 상태가 Permissive로 표시됩니다.

워크로드당 상호 TLS 사용 설정

특정 워크로드의 PeerAuthentication 정책을 설정하려면 selector 섹션을 구성하고 원하는 워크로드와 일치하는 라벨을 지정해야 합니다. 하지만 Anthos Service Mesh는 아웃바운드 mTLS 트래픽에 대한 워크로드 수준 정책을 서비스로 집계할 수 없습니다. 이 동작을 관리하려면 대상 규칙을 구성해야 합니다.

  1. 특정 워크로드에 인증 정책을 적용합니다. 다음 정책에서 어떻게 라벨 및 선택기를 사용하여 특정 frontend 배포를 타겟팅하는지 확인하세요.

    cat <<EOF | kubectl apply -n frontend -f -
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "frontend"
      namespace: "frontend"
    spec:
      selector:
        matchLabels:
          app: frontend
      mtls:
        mode: STRICT
    EOF
    

    예상 출력:

    peerauthentication.security.istio.io/frontend created
  2. 일치하는 대상 규칙을 구성합니다.

    cat <<EOF | kubectl apply -n frontend -f -
    apiVersion: "networking.istio.io/v1alpha3"
    kind: "DestinationRule"
    metadata:
      name: "frontend"
    spec:
      host: "frontend.demo.svc.cluster.local"
      trafficPolicy:
        tls:
          mode: ISTIO_MUTUAL
    EOF
    

    예상 출력:

    destinationrule.networking.istio.io/frontend created
  3. frontend-external 서비스의 외부 IP 주소를 사용하여 Online Boutique에 액세스하고 페이지를 새로 고칩니다. frontend serviceSTRICT mTLS로 설정되어 있고 사이드카 프록시가 요청을 차단하기 때문에 페이지가 표시되지 않습니다.

  4. 다음 명령어를 실행하여 다른 포드의 일반 HTTP로 frontend 서비스를 curl합니다.

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    56 상태 코드와 함께 요청이 실패합니다.

    Google Cloud 콘솔에서 워크로드 목록을 표시하는 페이지를 새로 고치면 frontend 서비스의 mTLS 상태가 Strict로 표시되고 다른 서비스는 Permissive로 설정됩니다.

    프런트엔드 서비스만 엄격한 mTLS입니다

  5. 인증 정책을 삭제합니다.

    kubectl delete peerauthentication -n frontend frontend
    

    예상 출력:

    peerauthentication.security.istio.io "frontend" deleted
    
  6. 대상 규칙을 삭제합니다.

    kubectl delete destinationrule -n frontend frontend
    

    예상 출력:

    destinationrule.networking.istio.io "frontend" deleted
    

메시 전체 mTLS 적용

메시의 모든 서비스에서 일반 텍스트 트래픽을 허용하지 않도록 하려면 mTLS 모드를 STRICT로 설정하여 메시 전체 PeerAuthentication 정책을 설정합니다. 메시 전체 PeerAuthentication 정책에 선택기가 없어야 하며 정책이 루트 네임스페이스 istio-system에 적용되어야 합니다. 정책을 배포하면 워크로드가 서로 인증할 수 있도록 제어 영역이 TLS 인증서를 자동으로 프로비저닝합니다.

  1. 메시 전체 mTLS를 적용합니다.

    kubectl apply -f - <<EOF
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "mesh-wide"
      namespace: "istio-system"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    예상 출력:

    peerauthentication.security.istio.io/mesh-wide created

  2. frontend-external 서비스의 외부 IP 주소를 사용하여 Online Boutique에 액세스하고 페이지를 새로 고칩니다. 페이지가 표시되지 않습니다.

  3. 다음 명령어를 실행하여 다른 포드의 일반 HTTP로 frontend 서비스를 curl합니다.

    kubectl exec \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -c istio-proxy -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    56 상태 코드와 함께 요청이 실패합니다.

  4. mesh-wide 정책을 삭제합니다.

    kubectl delete peerauthentication -n istio-system mesh-wide
    

    예상 출력:

    peerauthentication.security.istio.io "mesh-wide" deleted
    

    Google Cloud 콘솔에서 페이지를 새로 고치면 모든 서비스의 mTLS 세부정보에 Permissive가 표시됩니다.

삭제

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

  • 추가 요금이 청구되지 않도록 하려면 클러스터를 삭제하세요.

    gcloud container clusters delete  CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION
    
  • 클러스터를 유지하고 Online Boutique를 삭제하려면 다음 안내를 따르세요.

    1. 애플리케이션 네임스페이스를 삭제합니다.
    kubectl delete -f online-boutique/kubernetes-manifests/namespaces
    

    예상 출력:

    namespace "ad" deleted
    namespace "cart" deleted
    namespace "checkout" deleted
    namespace "currency" deleted
    namespace "email" deleted
    namespace "frontend" deleted
    namespace "loadgenerator" deleted
    namespace "payment" deleted
    namespace "product-catalog" deleted
    namespace "recommendation" deleted
    namespace "shipping" deleted
    
    1. 서비스 항목을 삭제합니다.
    kubectl delete -f online-boutique/istio-manifests/allow-egress-googleapis.yaml
    

    예상 출력:

    serviceentry.networking.istio.io "allow-egress-googleapis" deleted
    serviceentry.networking.istio.io "allow-egress-google-metadata" deleted
    

다음 단계

  • PeerAuthentication 정책 구성에 대한 일반적인 가이드는 전송 보안 구성을 참조하기