이 문서에서는 TLS 패스 스루에 구성된 Kubernetes 게이트웨이 리소스를 배포하여 Google Kubernetes Engine(GKE)에서 서버 이름 표시(SNI) 기반 라우팅을 사용 설정하는 방법을 보여줍니다. 이 접근 방식은 클라이언트와 백엔드 포드 간의 엔드 투 엔드 암호화 및 상호 TLS(mTLS)를 유지하고, HTTP가 아닌 TLS 기반 프로토콜을 지원하며, IP 주소를 보존합니다.
이 문서는 컨테이너화된 워크로드의 암호화된 네트워킹을 설계, 배포, 관리하는 클라우드 설계자, 네트워킹 전문가, 개발자를 대상으로 합니다. 일반적인 역할과 예시 작업에 대해 자세히 알아보려면 일반적인 GKE 사용자 역할 및 작업을 참조하세요.
개요
GKE 게이트웨이 컨트롤러는 레이어 7 HTTP 및 HTTPS 애플리케이션 부하 분산기 외에도 TLS 패스 스루로 구성된 레이어 4 프록시 네트워크 부하 분산기(TCP 프록시 부하 분산기)를 지원합니다.
TLS 패스 스루를 사용하면 부하 분산기가 TLS 세션을 종료하거나 복호화하지 않습니다. 대신 클라이언트가 TLS 핸드셰이크를 시작하면 부하 분산기가 암호화되지 않은 ClientHello 메시지를 검사하여 서버 이름 표시(SNI) 호스트 이름을 읽습니다. 이 SNI 호스트 이름을 기반으로 부하 분산기는 암호화되지 않은 원시 TCP 스트림을 적절한 백엔드 Kubernetes 서비스로 라우팅하며, 여기서 애플리케이션 포드가 TLS를 직접 종료합니다.
Gateway API에서 TLS 패스 스루를 사용하면 다음을 수행할 수 있습니다.
- 엔드 투 엔드 암호화 유지 및 제로 트러스트 규정 준수 지원: 부하 분산기에 비공개 키 또는 일반 텍스트 데이터에 대한 액세스 권한을 부여하지 않고 클라이언트에서 백엔드 포드까지 트래픽을 완전히 암호화된 상태로 유지합니다.
- 상호 TLS(mTLS) 인증 사용: 백엔드 애플리케이션 계층에서 직접 클라이언트를 인증합니다.
- IPv4 주소 보존: 단일 게이트웨이 IP 주소 및 포트(예:
443)를 사용하여 여러 독립적인 TLS 서비스를 여러 도메인 또는 하위 도메인에서 멀티플렉싱합니다. - HTTP가 아닌 TLS 기반 프로토콜 지원: 스테이트풀(Stateful) 워크로드, 데이터베이스, 커스텀 gRPC 서비스 또는 TLS를 통해 실행되는 독점 프로토콜의 암호화된 트래픽을 라우팅합니다.
지원되는 GatewayClass
다음 GKE GatewayClass는 TLS 패스 스루 리스너 및 TLSRoute 리소스를 지원합니다.
gke-l7-regional-external-managedgke-l7-regional-external-managed-mcgke-l7-rilbgke-l7-rilb-mcgke-l7-cross-regional-internal-managed-mc
GatewayClass 기능을 전체적으로 비교하려면 GatewayClass 기능을 참조하세요.
시작하기 전에
시작하기 전에 다음 태스크를 수행했는지 확인합니다.
- Google Kubernetes Engine API를 사용 설정합니다. Google Kubernetes Engine API 사용 설정
- 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치했으면
gcloud components update명령어를 실행하여 최신 버전을 가져옵니다. 이전 gcloud CLI 버전에서는 이 문서의 명령어를 실행하지 못할 수 있습니다.
- Gateway API가 사용 설정된 GKE 버전 1.35 이상을 실행하는 기존 Autopilot 또는 Standard 클러스터가 있는지 확인합니다. 새 클러스터를 만들려면 Autopilot 클러스터 만들기를 참조하세요. 기존 클러스터에서 Gateway API를 사용 설정하려면 클러스터에서 Gateway API 사용 설정을 참조하세요.
- OpenSSL 명령줄 도구가 설치되어 있는지 확인합니다. 이 도구를 사용하여 샘플 애플리케이션의 자체 서명 TLS 인증서를 생성합니다.
GKE Gateway Controller 요구사항
- Gateway API는 VPC 기반 클러스터에서만 지원됩니다.
- 리전 또는 교차 리전 GatewayClass를 사용하는 경우 프록시 전용 서브넷을 사용 설정해야 합니다.
- 클러스터에
HttpLoadBalancing부가기능이 사용 설정되어 있어야 합니다. - Istio를 사용하는 경우 Istio를 다음 버전 중 하나로 업그레이드해야 합니다.
- 1.15.2 이상
- 1.14.5 이상
- 1.13.9 이상
- 공유 VPC를 사용하는 경우 호스트 프로젝트에서 서비스 프로젝트에 대해 GKE 서비스 계정에
Compute Network User역할을 할당해야 합니다.
제한 및 한도
TLS 패스 스루 게이트웨이 및 TLSRoute 리소스를 배포할 때는 다음 제한사항을 준수하세요.
- 리스너에서
protocol: TLS설정을 구성할 때는tls.mode필드를Passthrough값으로 명시적으로 설정해야 합니다. GKE는TLS리스너의 기본Terminate모드를 지원하지 않습니다. TLS리스너에서certificateRefs필드를 설정하지 마세요. 게이트웨이 수준 클라이언트 인증서 검증(spec.tls.frontendValidation필드)은TLS리스너에 적용되지 않습니다. mTLS를 사용하려면 백엔드에서 클라이언트 인증서를 검증합니다.TLS리스너는 다른TLS리스너와만 포트를 공유할 수 있습니다.TLS리스너와 동일한 포트에서HTTP또는HTTPS리스너를 구성할 수 없습니다.TLSRoute.spec.hostnames필드에서 1~1,024개의 SNI 호스트 이름 목록(정확한 호스트 이름 또는 와일드 카드 프리픽스(예:*.example.com))을 지정해야 합니다. 각 항목은 253자를 초과할 수 없으며 IP 주소일 수 없습니다.TLSRoute.spec.rules필드에서 최대 하나의 규칙을 구성할 수 있습니다.- 각 규칙은 정확히 하나의
backendRef항목을 지원합니다. 레이어 4 프록시 백엔드는 여러 백엔드 간의 가중치 기반 트래픽 분할을 지원하지 않습니다. - 단일 클러스터 GatewayClass는 서비스 백엔드만 지원하고 멀티 클러스터 GatewayClass는 ServiceImport 백엔드만 지원합니다.
TLSRoute.spec.rules.backendRefs필드에서port필드를 컨테이너 포트가 아닌 대상 서비스 또는 ServiceImport 리소스에서 선언한 포트로 설정합니다.- TLSRoute 리소스에서 참조하는 백엔드 Kubernetes 서비스(ServiceImport로 내보낸 서비스 포함)는 포트 프로토콜에
TCP값을 사용해야 합니다. - 컨트롤러가 이 유형의 구성을 거부하므로 BackendTLSPolicy 리소스, IAP(Identity-Aware Proxy) 또는 Google Cloud Armor 보안 정책을 TLSRoute 백엔드에 연결할 수 없습니다.
- TLSRoute 리소스에서 참조하는 서비스 또는 ServiceImport에 GCPBackendPolicy 리소스를 연결할 때는
spec.protocol필드를TCP값으로 설정해야 합니다.spec.protocol필드를 생략하면 기본적으로HTTP값으로 설정되며, 이는 HTTPRoute 백엔드에만 적용됩니다. 서비스 또는 ServiceImport에는HTTP정책 하나와TCP정책 하나를 동시에 연결할 수 있습니다. 동일한spec.protocol값을 가진 여러 정책이 동일한 서비스 또는 ServiceImport를 타겟팅하는 경우 가장 오래된 정책이 우선 적용되고 최신 정책은 연결되지 않습니다. spec.protocol필드가TCP로 설정된 GCPBackendPolicy 리소스는spec.default필드에서 다음 필드만 지원합니다(ServiceImport 리소스를 타겟팅할 때 대신spec.default.scopes필드에서 클러스터, 영역 또는 리전별로 마지막 세 필드를 설정할 수 있음).timeoutSecconnectionDraininglogging.enabled및logging.sampleRatesessionAffinity.type(유효한 값은CLIENT_IP또는NONE)capacityScalerPercentbalancingMode: CONNECTIONmaxConnectionsPerEndpoint
다른 필드가 포함된
TCP정책이나TCP전용 필드(balancingMode: CONNECTION및maxConnectionsPerEndpoint)가 포함된HTTP정책을 만들 수 없습니다. Kubernetes API 서버는 생성 시 정책을 거부합니다. 자세한 내용은 정책을 사용하여 게이트웨이 리소스 구성을 참조하세요.HTTPRoute 및 TLSRoute 리소스가 모두 동일한 서비스 또는 ServiceImport를 참조하는 경우 HealthCheckPolicy 리소스를 해당 대상에 연결하면 별도의 기본 상태 점검이 대체되고 두 경로의 백엔드에 동일한 상태 점검 구성이 적용됩니다. 상태 점검을 독립적으로 구성하려면(예: HTTPRoute 백엔드의 경우
HTTP상태 점검, TLSRoute 백엔드의 경우SSL또는TCP상태 점검) 각 경로에 대해 별도의 서비스를 만들고 각 서비스에 HealthCheckPolicy 리소스를 연결합니다. 두 서비스 모두 동일한 포드를 선택할 수 있습니다.레이어 7 기능(예: URL 재작성, 경로 기반 라우팅, HTTP 헤더 변환)은 레이어 4 TCP 프록시 부하 분산기에 적용되지 않습니다.
프록시 전용 서브넷 구성
리전 게이트웨이를 배포하는 각 리전에 프록시 전용 서브넷(purpose=REGIONAL_MANAGED_PROXY)이 필요합니다. 하나의 프록시 전용 서브넷은 해당 리전의 모든 리전 Envoy 기반 부하 분산기를 지원합니다. 리전에 아직 없는 경우 프록시 전용 서브넷 구성을 참조하세요.
고정 IP 주소 예약
게이트웨이를 배포하기 전에 게이트웨이 주소가 변경되지 않고 샘플 호스트 이름을 확인할 수 있도록 리전 고정 IP 주소를 예약합니다. 고정 IP 주소를 만드는 방법은 리전 외부 HTTP(S) 게이트웨이 만들기를 참조하세요.
TLS 패스 스루 리스너를 사용하여 게이트웨이 배포
이 섹션의 게이트웨이는 443 포트를 공유하는 TLS 리스너 2개를 구성합니다. 각 리스너는 서로 다른 SNI 호스트 이름과 일치하며 연결을 패스 스루 모드로 연결된 TLSRoute 리소스로 전달합니다.
다음 매니페스트를
store-gateway.yaml로 저장합니다.kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-tls spec: gatewayClassName: gke-l7-regional-external-managed listeners: # Accept TLS connections for store.example.com without decrypting them. - name: store protocol: TLS port: 443 hostname: "store.example.com" tls: mode: Passthrough allowedRoutes: kinds: - kind: TLSRoute # A second listener on the same port, selected by a different SNI name. - name: store-german protocol: TLS port: 443 hostname: "store-de.example.com" tls: mode: Passthrough allowedRoutes: kinds: - kind: TLSRoute addresses: - type: NamedAddress value: IP_ADDRESS_NAMEIP_ADDRESS_NAME을 예약한 고정 IP 주소의 이름으로 바꿉니다.
tls블록에는certificateRefs필드가 없습니다.Passthrough모드에서 TLS 인증서는 부하 분산기가 아닌 백엔드 포드에 있습니다.게이트웨이 매니페스트를 적용합니다.
kubectl apply -f store-gateway.yaml게이트웨이가 프로그래밍되었는지 확인합니다.
kubectl get gateway store-tls부하 분산기를 프로비저닝하는 데 몇 분 정도 걸립니다. 출력은 다음과 비슷합니다.
NAME CLASS ADDRESS PROGRAMMED AGE store-tls gke-l7-regional-external-managed 35.118.32.224 True 53s
내부 게이트웨이 사용
VPC 네트워크 내에서 트래픽을 유지하려면 gatewayClassName 필드 값을 gke-l7-rilb로 변경하고 게이트웨이 매니페스트에서 addresses 필드를 삭제합니다. 그러면 GKE가 리전 내부 프록시 네트워크 부하 분산기를 만들고 클러스터 서브넷에서 내부 IP 주소를 할당합니다. 이 페이지의 나머지 단계는 변경되지 않습니다. 내부 IP 주소는 인터넷에서 연결할 수 없으므로 동일한 VPC 네트워크의 Compute Engine 인스턴스에서 테스트 요청을 전송합니다.
샘플 TLS 애플리케이션 배포
이 섹션에서는 포트 8443에서 TLS를 종료하는 두 개의 NGINX 배포(store-v1 및 store-german)를 배포합니다. 각 배포는 서로 다른 TLS 인증서를 제공하고 수신한 SNI 호스트 이름을 보고하므로 SNI를 기반으로 라우팅이 발생했는지 확인할 수 있습니다.
각 호스트 이름에 대해 자체 서명 TLS 인증서와 비공개 키를 생성합니다.
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 \ -keyout store.key -out store.crt \ -subj '/CN=store.example.com' \ -addext 'subjectAltName=DNS:store.example.com' openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 \ -keyout store-de.key -out store-de.crt \ -subj '/CN=store-de.example.com' \ -addext 'subjectAltName=DNS:store-de.example.com'프로덕션에서 인증 기관의 인증서를 사용합니다. 자체 서명 인증서는 이 예시를 독립적으로 유지합니다.
다음 명령어를 실행하여 각 인증서와 키를 Kubernetes 보안 비밀에 저장합니다.
kubectl create secret tls store-cert \ --cert=store.crt --key=store.key kubectl create secret tls store-de-cert \ --cert=store-de.crt --key=store-de.key다음 매니페스트를
store-tls-app.yaml로 저장합니다.apiVersion: v1 kind: ConfigMap metadata: name: store-nginx data: default.conf: | server { listen 8443 ssl; ssl_certificate /etc/nginx/ssl/tls.crt; ssl_certificate_key /etc/nginx/ssl/tls.key; default_type text/plain; # Report which Pod answered and which SNI name it received. return 200 "backend: $hostname\nsni: $ssl_server_name\n"; } --- apiVersion: apps/v1 kind: Deployment metadata: name: store-v1 spec: replicas: 2 selector: matchLabels: app: store-v1 template: metadata: labels: app: store-v1 spec: containers: - name: nginx image: nginx:1.27 ports: - containerPort: 8443 volumeMounts: - name: config mountPath: /etc/nginx/conf.d - name: cert mountPath: /etc/nginx/ssl readOnly: true volumes: - name: config configMap: name: store-nginx - name: cert secret: secretName: store-cert --- apiVersion: v1 kind: Service metadata: name: store-v1 spec: selector: app: store-v1 ports: - port: 443 targetPort: 8443 --- apiVersion: apps/v1 kind: Deployment metadata: name: store-german spec: replicas: 2 selector: matchLabels: app: store-german template: metadata: labels: app: store-german spec: containers: - name: nginx image: nginx:1.27 ports: - containerPort: 8443 volumeMounts: - name: config mountPath: /etc/nginx/conf.d - name: cert mountPath: /etc/nginx/ssl readOnly: true volumes: - name: config configMap: name: store-nginx - name: cert secret: secretName: store-de-cert --- apiVersion: v1 kind: Service metadata: name: store-german spec: selector: app: store-german ports: - port: 443 targetPort: 8443서비스에는
appProtocol필드가 필요하지 않습니다. GKE는 TLSRoute 트래픽을 백엔드로 TCP로 전달하므로 이 필드는 영향을 미치지 않습니다.매니페스트를 클러스터에 적용합니다.
kubectl apply -f store-tls-app.yamlpod가 실행 중인지 확인합니다.
kubectl get pods -l 'app in (store-v1,store-german)'출력은 다음과 비슷합니다.
NAME READY STATUS RESTARTS AGE store-german-7d9f8c5b47-2xqkd 1/1 Running 0 41s store-german-7d9f8c5b47-h6tzn 1/1 Running 0 41s store-v1-6c4b9d8f65-kp8vr 1/1 Running 0 41s store-v1-6c4b9d8f65-wm2ls 1/1 Running 0 41s
SNI 기반 라우팅을 위한 TLSRoute 리소스 배포
TLSRoute 리소스는 게이트웨이 리스너에 연결되고 호스트 이름과 일치하는 연결을 단일 백엔드 서비스로 라우팅합니다.
다음 매니페스트를
store-tls-routes.yaml로 저장합니다.kind: TLSRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store spec: parentRefs: - kind: Gateway name: store-tls sectionName: store hostnames: - "store.example.com" rules: - backendRefs: - name: store-v1 port: 443 --- kind: TLSRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-german spec: parentRefs: - kind: Gateway name: store-tls sectionName: store-german hostnames: - "store-de.example.com" rules: - backendRefs: - name: store-german port: 443sectionName필드는 게이트웨이에서 대상 리스너를 선택합니다.port필드는 컨테이너 포트가 아닌 서비스 포트(443)를 지정합니다.TLSRoute 매니페스트를 적용합니다.
kubectl apply -f store-tls-routes.yaml게이트웨이 컨트롤러가 경로를 수락했는지 확인합니다.
kubectl get tlsroute store -o yamlstatus필드는 다음과 비슷합니다.status: parents: - controllerName: networking.gke.io/gateway parentRef: name: store-tls sectionName: store conditions: - type: ResolvedRefs status: "True" reason: ResolvedRefs - type: Accepted status: "True" reason: Accepted - type: Reconciled status: "True" reason: ReconciliationSucceededReconciled조건은 게이트웨이 컨트롤러가 기본Google Cloud 리소스를 만들었는지 여부를 보고하는 GKE 관련 상태 조건입니다.게이트웨이 리스너가 경로를 수락했는지 확인합니다.
kubectl get gateway store-tls -o yamlstatus.listeners필드의 각 항목은 다음과 유사합니다.- name: store supportedKinds: - group: gateway.networking.k8s.io kind: TLSRoute attachedRoutes: 1 conditions: - type: ResolvedRefs status: "True" reason: ResolvedRefs - type: Accepted status: "True" reason: Accepted - type: Programmed status: "True" reason: Programmed
트래픽 라우팅 확인
GKE는 TLS 핸드셰이크를 완료하여 TLS 패스 스루 백엔드의 상태를 점검합니다. 포드가 초기 상태 점검을 통과하는 데 몇 분 정도 걸릴 수 있습니다.
게이트웨이 IP 주소를 검색합니다.
kubectl get gateway store-tls -o jsonpath='{.status.addresses[0].value}'GATEWAY_IP를 이전 단계의 IP 주소로 바꿔 각 호스트 이름에 요청을 보냅니다.
curl --resolve store.example.com:443:GATEWAY_IP \ --cacert store.crt https://store.example.com curl --resolve store-de.example.com:443:GATEWAY_IP \ --cacert store-de.crt https://store-de.example.com각 응답은 응답한 포드의 이름을 지정하고 도달한 SNI 호스트 이름을 에코합니다.
backend: store-v1-6c4b9d8f65-kp8vr sni: store.example.com backend: store-german-7d9f8c5b47-2xqkd sni: store-de.example.com각 요청에서 서로 다른 인증 기관 파일을 사용했고 둘 다 성공했으므로 각 백엔드는 자체 인증서를 제공했습니다. 부하 분산기는 암호화된 연결을 종료하지 않고 전달했습니다.
클라이언트가 HTTP 요청을 전송하기 전에 TLS 핸드셰이크 중에 라우팅이 발생하는지 확인합니다.
openssl s_client -connect GATEWAY_IP:443 \ -servername store-de.example.com </dev/null 2>/dev/null \ | openssl x509 -noout -subject출력에
store-german백엔드의 인증서가 표시됩니다.subject=CN=store-de.example.com-servername플래그의 값만 변경하면 반환되는 인증서가 변경되어 부하 분산기가 SNI만 기반으로 백엔드를 선택했음을 확인할 수 있습니다.일치하는 리스너가 없는 SNI 호스트 이름으로 요청을 보냅니다.
curl --resolve other.example.com:443:GATEWAY_IP \ https://other.example.com포트
443의 리스너가 SNI 호스트 이름other.example.com과 일치하지 않으므로 연결이 종료됩니다.
백엔드 연결 용량 구성
TLSRoute 리소스에서 참조하는 GKE 서비스의 경우 GKE 게이트웨이 컨트롤러는 CONNECTION 분산 모드를 사용하여 TCP 백엔드 서비스를 구성하고 maxConnectionsPerEndpoint 필드의 기본값을 100,000,000(1e8)로 설정합니다.
게이트웨이 컨트롤러는 컨테이너의 동시 연결 한도를 자동으로 결정할 수 없으므로 GCPBackendPolicy 리소스를 사용하여 maxConnectionsPerEndpoint 필드의 기본값을 재정의할 수 있습니다(1에서 1,000,000,000로). 백엔드 포드의 최적 연결 한도를 결정하려면 다음을 평가하세요.
- 소프트웨어 한도: Apache
MaxRequestWorkers지시문, NGINXworker_processes * worker_connections설정, TomcatmaxConnections속성, 데이터베이스 연결 풀 한도와 같은 서버 또는 애플리케이션 구성을 확인합니다. - 부하 테스트: CPU, 메모리, 지연 시간, 소켓 또는 파일 설명자 한도를 모니터링하면서 격리된 포드에 대한 동시 연결을 점진적으로 늘립니다.
커스텀 GCPBackendPolicy 적용
TLSRoute 백엔드 서비스에서 maxConnectionsPerEndpoint 필드의 기본값을 재정의하려면 spec.protocol 필드가 TCP로 설정되고 balancingMode 필드가 CONNECTION로 설정된 GCPBackendPolicy 리소스를 연결합니다.
다음 매니페스트를
backend-policy.yaml로 저장합니다.apiVersion: networking.gke.io/v1 kind: GCPBackendPolicy metadata: name: store-v1-backend-policy spec: protocol: TCP default: balancingMode: CONNECTION maxConnectionsPerEndpoint: 1000 targetRef: group: "" kind: Service name: store-v1정책을 적용합니다.
kubectl apply -f backend-policy.yaml
백엔드 정책 구성에 대한 자세한 내용은 정책을 사용하여 게이트웨이 리소스 구성을 참조하세요.
TLS 패스 스루의 상태 점검 구성
기본적으로 TLS 패스 스루 TLSRoute 리소스와 연결된 백엔드 서비스의 경우 GKE 게이트웨이 컨트롤러가 SSL 유형의 상태 점검을 자동으로 프로비저닝합니다.
프로브에서 SNI 확장 프로그램이 없는 경우 처리
TLS 패스 스루 백엔드의 상태 점검을 구성할 때는 Google Cloud 상태 점검 프로브가 TLS 엔드포인트와 상호작용하는 방식을 고려해야 합니다.
백엔드 애플리케이션에서 TLS 핸드셰이크를 완료하기 위해 유효한 SNI 호스트 이름이 필요한 경우 기본 SSL 상태 점검이 실패합니다. 이 문제를 해결하려면 다음 방법 중 하나를 사용하세요.
- 대체 인증서 구성: SNI 확장 프로그램 없이 TLS 연결이 도착할 때 기본 대체 TLS 인증서를 제공하도록 백엔드 서버 또는 포드를 구성합니다.
- HealthCheckPolicy와 함께 TCP 상태 점검 사용: HealthCheckPolicy 리소스(
config.type필드가TCP로 설정됨)를 서비스에 연결하여 원시 TCP 포트 연결을 확인하고 TLS 핸드셰이크를 방지합니다.
커스텀 HealthCheckPolicy 적용
커스텀 상태 점검 매개변수를 구성하거나 TCP 상태 점검으로 전환하려면 HealthCheckPolicy 리소스를 사용합니다.
다음 매니페스트를
health-check-policy.yaml로 저장합니다.apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: store-health-check spec: default: checkIntervalSec: 10 timeoutSec: 5 healthyThreshold: 2 unhealthyThreshold: 3 config: type: TCP tcpHealthCheck: port: 8443 targetRef: group: "" kind: Service name: store-service정책을 적용합니다.
kubectl apply -f health-check-policy.yaml
상태 점검 구성에 대한 자세한 내용은 정책을 사용하여 게이트웨이 리소스 구성을 참조하세요.
고급 구성
이 섹션에서는 TLS 패스 스루 게이트웨이 및 TLSRoute 리소스에서 지원되는 고급 라우팅 패턴, 멀티 테넌트 구성, 멀티 클러스터 배포를 설명합니다.
와일드 카드 호스트 이름 일치
TLSRoute 리소스는 호스트 이름에 대한 와일드 카드 프리픽스 일치를 지원하며 여러 경로가 동일한 수신 트래픽과 일치하는 경우 결정론적 우선순위 규칙을 따릅니다.
다음 매니페스트를 저장하여 와일드 카드 TLSRoute를 정의합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
name: wildcard-tls-route
spec:
parentRefs:
- name: store-tls
sectionName: store
hostnames:
- "*.example.com"
rules:
- backendRefs:
- name: store-v1
port: 443
우선순위 및 충돌 해결 규칙
여러 TLSRoute 리소스가 동일한 게이트웨이 리스너에 연결되고 겹치거나 동일한 호스트 이름을 요청하는 경우 GKE Gateway Controller는 다른 게이트웨이 경로와 동일한 호스트 이름 특수성 및 생성 타임스탬프 규칙을 사용하여 충돌을 해결합니다.
- 정확한 호스트 이름 일치(예:
store.example.com)는 와일드 카드 일치(예:*.example.com)보다 우선 적용되며, 더 긴 와일드 카드 일치는 더 광범위한 와일드 카드 일치(예:*.com)보다 우선 적용됩니다. - 두 개 이상의 TLSRoute 리소스가 정확히 동일한 호스트 이름을 선언하는 경우 생성 타임스탬프(
metadata.creationTimestamp)가 가장 오래된 경로가 우선 적용됩니다. 생성 타임스탬프가 일치하면 사전순으로 더 작은<namespace>/<name>식별자가 동률을 해소합니다. 게이트웨이 컨트롤러는Conflicted이유와 함께Accepted: False조건을 보고하는 충돌하는 경로를 허용하지 않습니다.
경로 우선순위에 대한 자세한 내용은 경로 병합, 우선순위, 검증을 참조하세요.
ReferenceGrant를 사용한 네임스페이스 간 라우팅
멀티 테넌트 환경에서 중앙 집중식 플랫폼팀은 인프라 네임스페이스(예: gateway-infra)에서 게이트웨이를 관리할 수 있고, 애플리케이션팀은 개발자 네임스페이스(예: store-ns)에서 TLSRoute 및 서비스 리소스를 관리할 수 있습니다.
게이트웨이 리스너에서 모든 네임스페이스(또는 선택한 네임스페이스)의 경로를 허용합니다.
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: shared-tls-gateway namespace: gateway-infra spec: gatewayClassName: gke-l7-regional-external-managed listeners: - name: tls-passthrough protocol: TLS port: 443 tls: mode: Passthrough allowedRoutes: namespaces: from: All kinds: - kind: TLSRoute애플리케이션 네임스페이스(
store-ns)에서gateway-infra네임스페이스의 게이트웨이가 TLSRoute 또는 서비스 리소스를 참조하도록 허용하는 ReferenceGrant 리소스를 만듭니다.apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: allow-gateway-infra namespace: store-ns spec: from: - group: gateway.networking.k8s.io kind: Gateway namespace: gateway-infra to: - group: "" kind: Service애플리케이션 네임스페이스(
store-ns)에서 공유 게이트웨이를 참조하는 TLSRoute 리소스를 만듭니다.apiVersion: gateway.networking.k8s.io/v1 kind: TLSRoute metadata: name: store-tls-route namespace: store-ns spec: parentRefs: - name: shared-tls-gateway namespace: gateway-infra sectionName: tls-passthrough hostnames: - "store.example.com" rules: - backendRefs: - name: store-service port: 443
멀티 클러스터 TLS 패스 스루 게이트웨이
Fleet의 여러 GKE 클러스터에서 TLS 패스 스루를 사용하여 멀티 클러스터 게이트웨이를 배포할 수 있습니다.
- 지원되는 멀티 클러스터 GatewayClass(
gke-l7-regional-external-managed-mc,gke-l7-rilb-mc또는gke-l7-cross-regional-internal-managed-mc)를 사용합니다. - ServiceExport 리소스를 사용하여 Fleet 전체에서 백엔드 서비스를 내보냅니다.
TLSRoute 리소스에서 ServiceImport 리소스를 사용하여 멀티 클러스터 백엔드를 참조합니다.
apiVersion: gateway.networking.k8s.io/v1 kind: TLSRoute metadata: name: mc-store-tls-route spec: parentRefs: - name: mc-tls-gateway sectionName: tls-passthrough hostnames: - "store.example.com" rules: - backendRefs: - group: net.gke.io kind: ServiceImport name: store-service port: 443
멀티 클러스터 게이트웨이의 여러 IP 주소
교차 리전 멀티 클러스터 게이트웨이를 배포할 때(예: gke-l7-cross-regional-internal-managed-mc GatewayClass를 사용하는 경우) spec.addresses 필드에 여러 IP 주소를 정의하여 여러 리전에 내부 VIP를 노출할 수 있습니다.
단일 게이트웨이에서 여러 IP 주소를 구성하면 GKE 게이트웨이 컨트롤러가 각 IP 주소를 별도의 전달 규칙으로 변환합니다. 동시에 컨트롤러는 공유 대상 프록시를 참조하고 동일한 기본 라우팅 구성을 재사용합니다. 컨트롤러는 기본 TLSRoute 리소스에 IP 주소 수를 곱하지 않으므로 경로 중복 및 할당량 소진을 방지할 수 있습니다.
다음 예시에서는 두 리전에 걸쳐 임시 IP 주소로 구성된 멀티 클러스터 게이트웨이를 보여줍니다.
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: internal-cross-region-tls-gateway
spec:
gatewayClassName: gke-l7-cross-regional-internal-managed-mc
addresses:
- type: networking.gke.io/ephemeral-ipv4-address/us-west1
value: "us-west1"
- type: networking.gke.io/ephemeral-ipv4-address/us-east1
value: "us-east1"
listeners:
- name: tls-passthrough
protocol: TLS
port: 443
tls:
mode: Passthrough
allowedRoutes:
kinds:
- kind: TLSRoute
내부 멀티 클러스터 게이트웨이 배포에 대한 자세한 내용은 내부 멀티 클러스터 게이트웨이 배포를 참조하세요.
HTTP 연결 통합
RFC 7540(섹션 9.1.1)에 따라 웹브라우저와 HTTP/2 클라이언트는 다음 두 조건이 모두 충족되는 경우 여러 요청에 대해 설정된 TLS 연결을 재사용할 수 있습니다.
- 대상 호스트 이름이 동일한 IP 주소로 확인됩니다.
- 서버에서 제공하는 TLS 인증서는 두 호스트 이름 모두에 대해 신뢰할 수 있습니다.
예를 들어
*.example.com과 같은 와일드 카드 인증서 또는 다중 도메인 주체 대체 이름(SAN)을 사용하는 경우 인증서가 여러 호스트 이름을 포함할 수 있습니다.
레이어 4 TCP 프록시 부하 분산기는 초기 TLS 핸드셰이크 후 HTTP 요청 헤더를 검사하지 않으므로 부하 분산기는 기존 연결을 통해 병합된 요청을 처음에 일치하는 백엔드 포드로 전달합니다.
연결 병합 문제를 방지하려면 다음 안내를 따르세요.
- 겹치지 않는 고유한 TLS 인증서 사용: 동일한 게이트웨이 IP 주소 뒤에서 멀티플렉싱된 여러 백엔드 서비스 간에 와일드 카드 인증서 또는 공통 SAN ID를 공유하지 마세요.
- HTTP 421 Misdirected Request 반환: HTTP
:authority(또는Host) 헤더를 확인하도록 백엔드 HTTPS 서버를 구성합니다. 요청된 호스트가 서버의 예상 도메인과 일치하지 않으면HTTP 421 Misdirected Request상태 코드를 반환하여 클라이언트가 새 연결을 열도록 합니다. - HTTP/2 ORIGIN 프레임 사용 설정: 원본 서버에서 RFC 8336 ORIGIN 프레임 지원을 채택하고 연결 재사용에 유효한 호스트 이름을 명시적으로 선언합니다.
삭제
이 페이지에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스를 삭제합니다.
TLSRoute 리소스를 삭제합니다.
kubectl delete tlsroute store store-german게이트웨이 리소스를 삭제합니다.
kubectl delete gateway store-tls샘플 배포, 서비스, 보안 비밀 리소스를 삭제합니다.
kubectl delete -f store-tls-app.yaml kubectl delete secret store-cert store-de-cert
다음 단계
- GatewayClass 기능 알아보기
- 게이트웨이 보안 알아보기
- 정책을 사용한 게이트웨이 리소스 구성 방법 알아보기