Anthos Service Mesh를 사용한 Anthos 클러스터 간의 안전하고 암호화된 통신

Last reviewed 2021-04-30 UTC

이 문서에서는 Kubernetes 클러스터를 관리하는 네트워크, 플랫폼, 보안 엔지니어가 Anthos Service Mesh 인그레스 및 이그레스 게이트웨이를 사용하여 외부 클러스터 간 통신을 처리하는 방법을 보여줍니다. 이 문서에서는 Anthos Service Mesh를 사용하여 한 Kubernetes 클러스터에 배포된 워크로드에서 다른 Kubernetes 클러스터에서 실행되는 워크로드로 아웃바운드 트래픽(이그레스)을 암호화하고 보호하는 방법을 설명합니다. 여기서 설명된 기법은 상호 암호화된 클러스터 간 통신에 별도의 인증서를 사용하는 방법을 보여줍니다.

이 문서의 안내는 클러스터 내 통신에 특정 루트 인증 기관(CA)을 사용해야 하는 고객 요구사항에서 비롯되었습니다. 금융 서비스 또는 의료와 같이 규제가 심한 시장에서 이러한 요구사항을 찾아볼 수 있습니다. 또한 여기에 제시된 안내에서는 재무 승인 제공업체 또는 민감한 정보에 대한 API 인터페이스와 같이 Kubernetes 클러스터가 아닌 엔드포인트의 사용을 허용할 수 있습니다. 이 안내는 특히 엄격한 보안 및 감사 정책을 준수해야 하는 조직과 관련이 있습니다.

클러스터에서 실행 중인 워크로드를 터치하지 않고도 암호화된 통신을 운영하고 처리할 수 있습니다. 고유 클러스터를 구성하는 방법은 함께 제공되는 튜토리얼을 참조하세요.

소개

기업은 처음 Kubernetes를 도입하기 시작할 때 단일 클러스터로 시작하며, 대부분의 통신은 해당 클러스터 내에서 유지됩니다. 곧 네임스페이스 간 상호작용이 점점 더 중요해지게 됩니다. 여기서 Calico 또는 Cillium과 같은 네트워크 정책 제공업체가 도움이 될 수 있습니다. 하지만 컨테이너 환경이 증가함에 따라 외부 서비스와 Kubernetes 클러스터 내부에서 실행 중인 컨테이너 간에 통신이 안전하게 이루어질 수 있도록 하는 것이 더욱 중요합니다.

네트워크 정책은 클러스터 내부 방화벽 규칙 만들기와 같은 기존 보안 개념을 처리하는 좋은 방법이지만 클러스터 외부에서만 사용할 수 있습니다. 특정 IP 주소만 연결하도록 허용할 수 있지만 콘텐츠나 ID를 제어할 수는 없습니다. 따라서 보다 다각적인 개념이 필요하며 이는 다른 외부 서비스에 대한 트래픽을 암호화하는 데에도 도움이 됩니다. 다음 다이어그램에서는 한 가지 방법을 제공합니다.

공개 인증서와 함께 비공개(보안 비밀) 인증서를 사용하여 트래픽을 암호화합니다.

애플리케이션의 환경에서 암호화는 일반적으로 TLS(전송 계층 보안)를 사용하여 수행됩니다. 즉, 이전 다이어그램에 표시된 것처럼 공개 인증서와 함께 비공개(보안 비밀) 인증서를 사용하여 트래픽을 암호화할 수 있습니다. 수신자는 신뢰할 수 있는 소스에서 정보를 가져오는지 확인하는 데 사용되는 공개 인증서를 보유합니다. HTTPS 웹 트래픽은 TLS를 사용하여 클라이언트와 웹 서버 간의 안전하고 암호화된 통신을 보장합니다. 이 경우 공개 인증서는 CA라고도 하는 공개 키 인프라(PKI)의 일부인 신뢰할 수 있는 발급기관(예: Google Trust Services)에서 가져옵니다. TLS는 서버의 ID를 확인하지만 클라이언트의 ID는 확인하지 않습니다.

클라이언트 자체도 인증해야 하는 경우 상호 인증 또는 mTLS가 필요합니다. 다음 다이어그램과 같이 발신자와 수신자가 모두 자신을 식별해야 하는 경우 mTLS를 사용합니다.

상호 인증(mTLS)을 사용하여 트래픽 암호화

이 방법은 종종 추가 보안 레이어가 필요한 애플리케이션에 사용됩니다. 금융 업계와 개인 식별 정보(PII)의 경우 규제 기관에는 mTLS가 필요한 경우가 많습니다.

Anthos Service Mesh

Anthos Service Mesh는 OSS Istio를 기반으로 하는 Google 관리형 서비스 메시 솔루션입니다. 즉, Istio API와 완벽하게 호환됩니다. Anthos Service Mesh는 애플리케이션 코드 내부가 아닌 플랫폼 수준에서 mTLS 기능을 제공할 수 있습니다. 즉, 모든 서비스를 다시 코딩할 필요 없이 서비스에 적용할 수 있습니다. 인증서 순환과 같은 작업도 Anthos Service Mesh의 일부입니다. 이 문서는 mTLS 및 Anthos Service Mesh의 외부 통신 기능에 초점을 맞추고 있습니다. 결함 주입, 고급 부하 분산, 오류 처리와 같은 여러 가지 다른 기능이 있습니다.

사이드카 프록시(Envoy)를 통해 모든 트래픽을 라우팅하면 Anthos Service Mesh와 같은 서비스 메시가 개발자에게 암호화 및 인증서 처리와 같은 일상적이지만 중요한 작업으로 인한 부담을 줄여줍니다. 서비스 메시는 투명 프록시를 사용하여 헤더 정보를 기준으로 HTTP 및 HTTPS 호출 라우팅과 같은 강력한 L7 함수를 사용 설정할 수 있습니다. 하지만 Anthos Service Mesh는 트래픽 캡슐화 및 암호화를 지원하므로 보안을 개선하는 데 도움이 됩니다.

구성 예시: 클러스터 간 MySQL 통신

서로 다른 클러스터의 서비스 간에 안전하고 신뢰할 수 있는 통신이 필요한 경우 이 시나리오를 사용할 수 있습니다. 이 예시에서 MySQL 클라이언트 애플리케이션은 다음 다이어그램과 같이 다른 Kubernetes 클러스터에서 실행 중인 MySQL 서버 DB 워크로드와 통신합니다.

다른 Kubernetes 클러스터에서 실행 중인 MySQL 서버 DB 워크로드와 통신하는 MySQL 클라이언트 애플리케이션

서비스 메시는 OSI L7에서 작동하는 경우도 많지만 일부 기능을 사용하여 L4 통신을 제어할 수도 있습니다.

개념을 작동하는 데 필요한 사항은 다음과 같습니다.

  • 애플리케이션과 클러스터 간의 통신은 암호화되어야 합니다.
  • 클라이언트와 서버 통신은 상호 인증을 거쳐야 합니다(mTLS).
  • 클라이언트 및 서버 워크로드는 변경할 필요가 없습니다.

암호화된 연결만 허용하도록 MySQL 데이터베이스를 설정할 수 있지만, 이 설정에서는 전체 제어 권한이 없는 데이터베이스 클라이언트를 변경해야 합니다.

Anthos Service Mesh를 사용하여 이러한 요구사항을 해결하는 방법에는 여러 가지가 있습니다. 한 가지 방법은 클러스터 간에 공유 Istio 제어 영역을 만들고 서비스가 서로 통신하도록 하는 것입니다(서비스가 단일 논리적 서비스 메시에 속하기 때문). 단일 프로젝트 또는 다중 프로젝트 설정에서 Anthos Service Mesh를 사용하여 Anthos 지원 GKE 클러스터에 이 작업을 수행할 수 있습니다.

그러나 클러스터 간 통신을 위한 별도의 신뢰 체인이 있어야 하기 때문에 mTLS를 사용하여 이그레스 게이트웨이 <–> 인그레스 게이트웨이 접근 방식을 사용합니다.

이그레스 및 인그레스 게이트웨이는 메시의 경계에 있는 Envoy 프록시입니다.

서비스 메시를 드나드는 트래픽 흐름을 제어하도록 구성할 수 있습니다. 이 방법은 Kubernetes가 아닌 엔드포인트에서도 작동하며 암호화된 통신에 다른 인증서를 사용할 수 있습니다.

Anthos Service Mesh 이그레스 및 인그레스 구성

앞의 시나리오에서는 각 클러스터 간 이그레스 및 인그레스 게이트웨이를 사용하여 안전한 클러스터 간 통신을 처리합니다.

이그레스 게이트웨이란 무엇인가?

이그레스는 서비스 메시에서 나오는 트래픽을 의미합니다. 이그레스 게이트웨이는 해당 트래픽의 제어 종료점을 제공합니다.

추가 구성이 없으면 사이드카 프록시가 삽입된 포드의 경우 메시 외부에 있는 서비스(예: 공개 API 서비스)를 대상으로 하는 트래픽이 포드에서 사이드카 프록시로 라우팅됩니다. GKE 클러스터(및 대부분의 Kubernetes 클러스터)에서 노드 IP 주소는 NAT를 사용하여 사이드카 프록시 트래픽을 변환하며, 이 트래픽은 서비스의 외부 주소로 직접 전달됩니다. 다음 다이어그램은 이 구성을 보여줍니다.

클라이언트는 외부 서비스를 나타내는 서버 측을 호출합니다.

이 다이어그램에서 클라이언트는 외부 서비스를 나타내는 서버 측을 호출합니다. 메시에 대해서는 이 트래픽이 아웃바운드이므로 클라이언트 측에서 이그레스 게이트웨이를 구성해야 합니다(예: MySQL 클라이언트).

외부 서비스로 호출을 전달하도록 이그레스 게이트웨이를 구성합니다. 외부 서비스가 요청을 처리하고 응답을 반환하면 이그레스 게이트웨이를 통해 클라이언트 프록시로 다시 이동한 후 마지막으로 호출을 실행하는 포드(예: MySQL 클라이언트)로 이동합니다.

인그레스 게이트웨이란 무엇인가?

인그레스는 서비스 메시로 들어가는 트래픽을 의미합니다. 인그레스 게이트웨이는 서비스를 외부(즉, 서비스 메시 외부)에 노출하고 이러한 서비스에 액세스하는 방법을 처리합니다. Kubernetes 인그레스 객체와 비교할 수 있습니다.

인그레스 게이트웨이를 사용하면 트래픽이 메시로 이동하는 단일 제어 진입점을 정의할 수 있습니다. 처음에는 트래픽이 인그레스 게이트웨이 서비스를 정의하여 만든 부하 분산기를 통과합니다. 여기에서 요청은 사이드카 프록시로 전달되고 프록시에서 포드로 전달됩니다. 포드 요청을 처리하고 동일한 경로를 반대로 사용하여 응답을 반환할 수 있습니다. 다음 다이어그램은 이 구성을 보여줍니다.

트래픽은 부하 분산기를 거치고, 요청이 사이드카 프록시에서 포드로 전달됩니다.

이 트래픽은 다른 클러스터(VPC 2)의 메시로 전송되는 인바운드 트래픽입니다. 따라서 이러한 호출을 처리하도록 서버 측에서 인그레스 게이트웨이를 구성해야 합니다.

인그레스 게이트웨이의 서버 측 구성에서 호출을 내부 서비스로 전달합니다. 내부 서비스에서 요청을 처리한 후 인그레스 게이트웨이를 통해 클라이언트로 다시 순회를 반환합니다.

상호 TLS의 이그레스 및 인그레스 기능 결합

앞서 언급했듯이 클라이언트 측에서는 서비스 메시의 제어 종료점 역할을 하는 이그레스 게이트웨이를 정의해야 합니다. 게이트웨이를 통해 메시를 통과하는 트래픽이 mTLS로 암호화되도록 하려면 TLS 원본이라는 기법을 사용하면 됩니다. 외부 서비스에 대한 트래픽에 TLS 원본을 수행하도록 이그레스 게이트웨이를 구성합니다.

클라이언트 측에서 서비스 메시를 나가는 트래픽이 암호화된 경우 서버 측에서 클라이언트에 대해 자신을 식별하고 암호화된 트래픽을 복호화할 수 있는지 확인해야 합니다.

이를 위해 인그레스 게이트웨이를 메시에 대한 단일 진입점으로 사용합니다. 상호 암호화된 트래픽을 예상하도록 인그레스 게이트웨이를 구성합니다.

메시 아키텍처 개요

다음 다이어그램은 애플리케이션 또는 서버에서 아무것도 변경하지 않고 MySQL 시나리오에서 이 개념을 구현하는 데 필요한 사항을 설명합니다.

VPC 1에서는 MySQL 클라이언트를 실행하는 클라이언트 클러스터가 서버에 액세스하는 것을 확인할 수 있습니다. 서버는 VPC 2에 있습니다.

애플리케이션이 이그레스 게이트웨이를 사용하도록 하려면 트래픽 일치 및 라우팅을 약간 더 수행해야 하므로 클라이언트 측은 서버 측에 비해 높은 구성입니다. 하지만 이 구성은 어렵지 않으며 한 번만 수행하면 됩니다. 구현한 후에는 유지 관리가 쉽습니다.

Kubernetes를 사용하여 이 개념을 구현하면 모든 구성 항목이 YAML 파일에 저장됩니다. 즉, 버전이 지정된 저장소에서 전체 구성을 사용할 수 있으므로 변경사항을 추적하고 필요한 경우 손쉽게 되돌릴 수 있습니다.

클라이언트 측

이 하위 섹션에서는 클라이언트 측 구성을 검토합니다. 다이어그램에 표시된 각 요소는 메시에서 고유한 기능을 가지고, 트래픽이 이그레스 게이트웨이를 통해 대상인 MySQL 서버에 라우팅되는 방식을 제어합니다.

트래픽 라우팅은 필수 기능 중 하나일 뿐입니다. 다른 요소들이 트래픽 암호화를 완전히 투명하게 제어하여 통신이 항상 안전하도록 지원합니다. 다음 섹션에서는 이 시나리오에서 이러한 요소의 역할과 기능을 더욱 자세히 이해할 수 있도록 요소를 살펴봅니다.

이그레스 게이트웨이를 통해 MySQL 서버로 트래픽이 라우팅되는 방법을 보여주는 클라이언트 측 구성입니다.

서비스 항목

서비스 메시는 Kubernetes 클러스터에 자체 서비스 레지스트리를 만듭니다. 제어 영역은 이 레지스트리를 사용하여 사이드카 프록시를 라우팅 테이블로 구성합니다. Kubernetes에서 실행 중인 서비스가 자동으로 검색되고 서비스 메시 레지스트리에 추가됩니다. Kubernetes 클러스터 내에서 실행되지 않는 서비스는 자동으로 검색할 수 없지만 ServiceEntries를 사용하여 정의할 수 있습니다. 이렇게 하면 클라이언트는 항목을 호스트 이름으로 사용하여 외부 서비스에 연결할 수 있습니다.

Anthos Service Mesh에서는 모든 서비스를 식별하는 데 정규화된 도메인 이름(FQDN)이 사용됩니다. 인증서는 호스트 이름을 기반으로 하므로 FQDN은 이 구성에서 가장 중요한 부분입니다. FQDN을 변경할 수도 있지만 필요한 모든 인증서도 다시 생성해야 합니다.

통신을 사용 설정하려면 트래픽을 올바르게 라우팅하기 위해 외부 서비스에 대한 호출을 리슨하도록 서비스 메시를 구성해야 합니다. 메시를 사용하면 외부 서비스를 가리키는 서비스 항목을 정의할 수 있습니다.

이 구성은 MESH_EXTERNAL이라고 하며 이러한 사용 사례에 적합합니다. 원하는 내용을 지정할 수도 있습니다. L4 사용 사례이며 IP 주소와 포트만 제어할 수 있으므로 프로토콜과 특정 포트를 메시에 알려야 합니다. 이 경우 TCP와 포트 3306(표준 MySQL 프로토콜 포트)입니다. 또한 앞의 다이어그램에 표시된 대로 서버 측 메시는 포트 13306(서버 클러스터의 이그레스 게이트웨이)에서 리슨합니다. 마지막으로, 이 포트 태그를 사용하여 트래픽을 캡처하도록 서비스 항목에 지시해야 합니다.

다음 YAML 서비스 항목 예시는 이 구성을 보여줍니다.

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
 name: mysql-external
spec:
 hosts:
   - mysql.fqdn.example
 location: MESH_EXTERNAL
 ports:
   - number: 3306
     name: tcp
     protocol: TCP
   - number: 13306
     name: tls
     protocol: TLS
 resolution: DNS
 endpoints:
   - address: mysql.fqdn.example
     ports:
       tls: 13306

hosts 필드를 사용하여 외부 서비스의 FQDN을 설정하거나 location 필드를 MESH_EXTERNAL로 지정할 수 있습니다. 또한 외부 서비스에서 사용하는 ports 값(이 경우 133063306)을 지정해야 합니다. 13306은 서버 측 인그레스 게이트웨이에서 노출된 포트입니다. 이 서비스 항목에서 둘 다 지정하는 것이 중요합니다. 이 연결은 L4 기반 TLS 통신을 제공하므로 프로토콜에는 TLS를 지정해야 합니다.

서비스 항목을 정의하면 메시는 이러한 규칙에 따라 호출을 리슨하고 라우팅을 변경할 수 있습니다.

서비스 항목은 기존 DNS 또는 IP 주소 항목을 기반으로 해야 합니다. 즉, DNS 이름은 이미 DNS 서버에서 확인할 수 있어야 합니다. 예를 들어 Kubernetes 내부에서 핵심 DNS 서비스를 사용하고 아직 kube-dns에 없는 항목을 추가할 수 있습니다. 서비스 항목을 사용하여 DNS 항목을 만들 수 없습니다.

가상 서비스

가상 서비스는 트래픽 라우팅 패턴에 영향을 주는 데 사용되는 정의입니다. 가상 서비스를 사용하여 MySQL 클라이언트에서 서비스 항목으로의 호출이 이그레스 게이트웨이로 라우팅되는지 확인합니다. 따라서 매우 다양한 요소를 기반으로 트래픽을 라우팅하도록 가상 서비스를 설정할 수 있습니다. L7 사용 사례에서 이러한 요소는 트래픽 라우팅을 초과합니다. 예를 들어 타겟에 연결할 수 없는 경우 조치 방법을 가상 서비스에 알릴 수 있습니다. 이 예시에서는 추가 처리를 위해 일치하는 트래픽만 이그레스 게이트웨이로 라우팅하기 위해 이 기능의 하위 집합을 사용합니다.

가상 서비스를 사용하여 포드에서 프록시를 통해 이그레스 게이트웨이로, 이그레스 게이트웨이에서 외부 서비스로 트래픽을 라우팅합니다.

위 다이어그램은 가상 서비스를 사용하여 프록시를 통해 포드에서 프록시를 통해 이그레스 게이트웨이로, 이그레스 게이트웨이에서 외부 서비스로 트래픽을 라우팅하는 방법을 보여줍니다.

또한 이그레스 게이트웨이의 포트(외부 공개)를 지정해야 합니다. 기본적으로 15443입니다. 이 포트는 이그레스 포트 생성 후 이그레스 게이트웨이에 설정됩니다. 다른 무료 포트를 선택할 수 있지만 선택한 포트를 열려면 게이트웨이를 패치해야 합니다.

다음 코드 스니펫은 이러한 가상 서비스 정의가 어떤 모습인지 보여줍니다.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: direct-mysql-through-egress-gateway
spec:
 hosts:
   - mysql.fqdn.example
 gateways:
   - istio-egressgateway-mysql
   - mesh
 tcp:
   - match:
       - gateways:
           - mesh
         port: 3306
     route:
       - destination:
           host: istio-egressgateway.istio-system.svc.cluster.local
           subset: mysql
           port:
             number: 15443
         weight: 100
   - match:
       - gateways:
           - istio-egressgateway-mysql
         port: 15443
     route:
       - destination:
           host: mysql.fqdn.example
           port:
             number: 13306
         weight: 100

FQDN URL이 포함된 hosts 필드는 특별히 일치 규칙을 지정된 URL에 적용하는 데 사용됩니다. 첫 번째 match 절은 메쉬에 정의되어 있으며, 이는 예약된 키워드로, 메쉬 내의 모든 게이트웨이에 적용됩니다. 첫 번째 route 블록은 일치 항목이 true인 경우에 수행할 작업을 메시에 알리도록 정의됩니다. 이 경우 일치하는 트래픽을 이그레스 게이트웨이로 보냅니다. 여기서는 경로의 가중치를 비롯해 이그레스 포트가 정의됩니다. 블록에는 나중에 정의하는 subset 값도 언급됩니다.

두 번째 match 절은 이그레스 게이트웨이에 적용됩니다. 두 번째 match 절에 추가되는 두 번째 route 블록은 인그레스 FQDN와 함께 host 필드를 사용하고 포트 13306을 지정하여 트래픽을 서버 클러스터 인그레스로 전송하도록 메시를 구성합니다.

다음 단계에서는 mTLS 통신을 위해 게이트웨이에 인증서 삽입을 프로그래밍해야 합니다.

대상 규칙

이제 트래픽을 올바르게 식별(서비스 항목)하고 프록시를 통해 포드에서 게이트웨이(가상 서비스)로 라우팅했으므로 다음 단계는 트래픽을 암호화하는 것입니다. 대상 규칙을 사용하여 트래픽을 암호화합니다. 이러한 서비스 메시의 규칙은 라우팅 이후의 트래픽에 적용되며 부하 분산과 기타 트래픽 관리 기능을 도입하는 데 사용됩니다.

라우팅 후 트래픽에 대상 규칙 적용

이 경우 대상 규칙을 사용하여 표준 부하 분산 패턴을 정의하고 인증서를 추가하여 mTLS 통신을 사용하는 엔드포인트를 사용 설정합니다. 이 단계는 서버 클러스터의 인그레스 게이트웨이를 통해 노출된 MySQL 서버의 FQDN을 일치시키고 mTLS 규칙을 정의하여 수행됩니다.

다음 정의는 이러한 대상 규칙의 예시입니다.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: egressgateway-for-mysql
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
    - name: mysql
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN
        portLevelSettings:
          - port:
              number: 15443
            tls:
              mode: ISTIO_MUTUAL
              sni: mysql.fqdn.example

host 필드는 이그레스 게이트웨이의 클러스터 FQDN으로 설정됩니다. 첫 번째 대상 규칙은 ISTIO_MUTUAL 모드(이그레스 게이트웨이의 FQDN 사용)를 사용하여 트래픽의 내부 메시 암호화를 수행합니다. 코드 스니펫에서 라운드 로빈 부하 분산을 만들고 포트를 15443으로 설정(덮어쓰기)하는 데 사용되는 subset을 정의합니다. 이그레스 게이트웨이는 이 포트를 사용하여 트래픽을 전송합니다.

내부 메시 정책(ISTIO_MUTUAL)을 정의하므로 tls 필드를 올바르게 설정하는 것이 중요합니다. sni(서비스 이름 표시) 필드에 서버 클러스터의 인그레스 게이트웨이 FQDN을 추가합니다.

두 번째 대상 규칙은 이그레스 게이트웨이를 통해 전송하기 전에 커스텀 제공 루트 CA 인증서로 트래픽을 암호화합니다.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: originate-mtls-for-mysql
spec:
 host: mysql.fqdn.example
 trafficPolicy:
   loadBalancer:
     simple: ROUND_ROBIN
   portLevelSettings:
   - port:
       number: 13306
     tls:
       mode: MUTUAL
       credentialName: client-credential
       sni: mysql.fqdn.example

host 필드가 외부 FQDN으로 다시 설정됩니다. trafficPolicy 필드는 부하 분산기 모드를 ROUND_ROBIN으로 설정합니다. 또한 포트를 13306으로 설정하고 tls 모드를 MUTUAL로 설정합니다. 이는 이제 커스텀 루트 CA 인증서를 사용하고 상대측(tls MUTUAL도 사용하는 인그레스 게이트웨이)도 동일한 서명된 루트 CA 인증서를 사용하여 자신을 식별해야 하기 때문입니다. 이 포트를 사용하면 트래픽이 인그레스 게이트웨이를 사용하여 서버 클러스터를 통해 MySQL 데이터베이스에 도달할 수 있습니다.

커스텀 루트 CA 인증서를 사용하는 암호화는 일반적으로 인증서를 보유하는 Kubernetes의 보안 비밀을 사용하여 Envoy 보안 비밀 검색 서비스(SDS)를 통해 수행됩니다. credentialName 필드를 사용하여 대상 규칙에 보안 비밀 이름을 추가합니다.

요약하면 이제 트래픽에서 다음이 수행됩니다.

  • MySQL에서 외부 FQDN으로 투명하게 발급됩니다. 이 FQDN은 메시 등록에 있습니다.
  • 내부 메시 인증서를 사용하는 대상 규칙을 사용하여 암호화됩니다.
  • 가상 서비스를 통해 게이트웨이로 라우팅됩니다.
  • 대상 규칙에 따라 커스텀 루트 CA를 사용하여 암호화됩니다(메시 인증서에 사용되는 메시 CA와 다름).
  • mTLS 모드의 이그레스 게이트웨이를 통해 전달됩니다.

서버 측

이 시나리오에서는 서버 측이 클라이언트 측보다 구성하기 더 쉽습니다. 다음 다이어그램에 표시된 대로 트래픽을 MySQL DB 서버로 라우팅하는 데 인그레스 게이트웨이와 가상 서비스 항목만 필요합니다.

트래픽을 MySQL DB 서버로 라우팅하는 인그레스 게이트웨이 및 가상 서비스 항목이 있는 서버 측 구성

서버 클러스터 인그레스 게이트웨이

인그레스 게이트웨이가 포트 13306을 노출합니다. 모든 포트가 가능하지만 이 경우 쉽게 식별할 수 있도록 표준 MySQL 포트 앞에 '1'을 추가합니다. 보안상의 이유로 표준 MySQL 포트(3306)를 인터넷에 직접 노출하지 않는 것이 좋습니다.

기본 Istio 인그레스 게이트웨이는 포트 13306에서 리슨하지 않으므로 이 기능을 추가해야 합니다. 다음 예시 코드 스니펫은 포트 13306을 게이트웨이에 패치합니다.

[{
  "op": "add",
  "path": "/spec/ports/0",
  "value": {
    "name": "tls-mysql",
    "protocol": "TCP",
    "targetPort": 13306,
    "port": 13306
  }
}]

이 코드를 JSON 파일에 저장하고 kubectl 패치 명령어와 함께 사용하여 인그레스 게이트웨이 서비스에 적용할 수 있습니다.

트래픽을 올바르게 처리하려면 인그레스 게이트웨이를 MUTUAL 모드로 설정해야 합니다.

이때 인그레스 게이트웨이는 사용자 인증 정보 저장소의 인증서를 사용하여 수신 트래픽을 복호화하고, 메시 내부 인증서를 사용하여 트래픽을 다시 암호화하는 메시로 트래픽을 전송합니다. 다음 예시 코드 스니펫은 구성 방법을 보여줍니다.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: gateway-mysql
spec:
 selector:
   istio: ingressgateway # Istio default gateway implementation
 servers:
 - port:
     number: 13306
     name: tls-mysql
     protocol: TLS
   tls:
     mode: MUTUAL
     credentialName: mysql-credential
   hosts:
   - "mysql.fqdn.example"

이 예시에서는 표준 Istio 인그레스 게이트웨이가 selector 필드에서 사용됩니다. servers 필드를 사용하여 인그레스가 예상해야 할 포트 number(13306) 및 protocol(TLS) 값을 설정할 수 있습니다. 포트에 고유한 이름을 지정해야 합니다.

tls를 정의하고 credentialName 필드를 사용하여 이그레스 게이트웨이에서 사용한 것과 동일한 루트 CA로 서명된 인증서를 포함하는 보안 비밀을 제공합니다. 인증서는 Kubernetes 보안 비밀에 저장해야 합니다.

마지막으로 MySQL DB FQDN을 전달하는 트래픽을 일치시킵니다. hosts에서 설정된 이 FQDN의 이름 확인을 인그레스 게이트웨이의 공개 IP 주소로 설정해야 합니다.

서버 클러스터 가상 서비스

클라이언트 클러스터(작성자)의 이그레스 게이트웨이에서 포트 13306을 통해 트래픽이 메시에 들어간 후에는 이 트래픽을 식별하고 MySQL DB 서버에 도달하는지 확인해야 합니다. 이 작업은 가상 서비스를 정의하여 수행합니다.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: mysql-virtual-service
spec:
 hosts:
   - "mysql.fqdn.example"
 gateways:
   - gateway-mysql
 tcp:
   - route:
     - destination:
         port:
           number: 3306
         host: mysql.default.svc.cluster.local

MySQL DB 서비스로 트래픽을 전송하려면 hosts 필드를 사용하여 FQDN 호스트를 다시 확인해야 합니다. 또한 gateways 필드를 사용하여 이 가상 서비스 정의를 적용할 위치를 구성해야 합니다. 이전의 YAML 파일에서 정의한 게이트웨이 객체입니다. L4 트래픽이므로 tcp 필드를 설정하고 route 필드가 MySQL DB Kubernetes 서비스를 가리키도록 설정합니다. Kubernetes 클러스터 내부 FQDN을 사용하여 host 필드에 서비스 이름을 지정해야 합니다.

MySQL DB는 포트 `3306`에서 클라이언트의 요청을 가져옵니다. 트래픽은 MySQL DB 서버의 사이드카 프록시를 통해 순회합니다.

MySQL DB는 포트 3306에서 클라이언트의 요청을 가져올 수 있습니다. 트래픽은 MySQL DB 서버의 사이드카 프록시를 통해 순회합니다. MySQL DB 서버에는 암호화되지 않은 로컬 데이터베이스 액세스 요청처럼 표시됩니다.

서버가 요청에 응답하면 트래픽은 같은 경로를 사용하여 클라이언트에 다시 전달되고 클라이언트는 로컬 DB가 방금 요청에 응답한 것처럼 보입니다.

트래픽은 클라이언트에서 서버로 순회하는 여러 인증서를 사용하여 세 번 암호화되므로 클라이언트 서버 통신을 보호합니다.

트래픽이 처음으로 암호화되거나 복호화될 때는 메시 CA를 사용하는 인증서가 있는 클라이언트 측 메시로 들어올 때입니다.

트래픽이 두 번째로 암호화될 때는 커스텀 루트 CA의 인증서를 사용하는 이그레스 게이트웨이에서 메시를 나갈 때입니다. 그런 다음 동일한 커스텀 루트 CA에서 서명한 인증서를 사용하는 인그레스 게이트웨이에서 트래픽이 인증되고 복호화됩니다.

트래픽이 마지막(세 번째)로 암호화되거나 복호화될 때는 인그레스 게이트웨이에서 MySQL 서버로 순회할 때 서버 측 메시로 들어올 때입니다. 이 경우에도(메시 내부에 있기 때문에) 메시 CA의 인증서가 사용됩니다.

이 시나리오에서는 언급된 루트 CA를 사용하여 두 클러스터 간의 통신을 암호화해야 했습니다. 이 구성을 적용하면 메시 내부 인증서 및 애플리케이션 자체와 별도로 이 부분을 별도로 독립적으로 처리할 수 있습니다.

이 추가 단계를 통해 각 Kubernetes 클러스터의 메시 CA를 변경하지 않고도 이러한 인증서를 정기적으로 순환할 수 있습니다.

다음 단계