이 페이지에서는 인그레스 트래픽의 부하 분산을 위해 단일 Google Kubernetes Engine(GKE) 클러스터에 Kubernetes 게이트웨이 리소스를 배포하는 방법을 설명합니다.
다중 클러스터(또는 Fleet)에 인그레스 트래픽을 부하 분산하기 위한 게이트웨이를 배포하려면 멀티 클러스터 게이트웨이 배포를 참조하세요.
네임스페이스 간 라우팅 및 HTTP 트래픽 분할과 같은 보다 구체적인 게이트웨이 구성이 필요한 경우 Gateway API 사용자 가이드를 참조하세요.
시작하기 전에
시작하기 전에 다음 태스크를 수행했는지 확인합니다.
- Google Kubernetes Engine API를 사용 설정합니다. Google Kubernetes Engine API 사용 설정
- 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우
gcloud components update
명령어를 실행하여 최신 버전을 가져옵니다. 이전 gcloud CLI 버전에서는 이 문서의 명령어를 실행하지 못할 수 있습니다.
- 기존 Autopilot 또는 Standard 클러스터가 있는지 확인합니다. 새 클러스터를 만들려면 Autopilot 클러스터 만들기를 참조하세요.
GKE Gateway Controller 요구사항
- Gateway API는 VPC 기반 클러스터에서만 지원됩니다.
- 내부 GatewayClasses를 사용하는 경우 프록시 전용 서브넷을 사용 설정해야 합니다.
- 클러스터에
HttpLoadBalancing
부가기능이 사용 설정되어 있어야 합니다. - Istio를 사용하는 경우 Istio를 다음 버전 중 하나로 업그레이드해야 합니다.
- 1.15.2 이상
- 1.14.5 이상
- 1.13.9 이상
- 공유 VPC를 사용하는 경우 호스트 프로젝트에서 서비스 프로젝트에 대해 GKE 서비스 계정에
Compute Network User
역할을 할당해야 합니다.
제한 및 한도
GKE 게이트웨이를 사용할 때는 다음과 같은 제한과 한도에 유의하세요.
GKE GatewayClasses는 사용하는 부하 분산기에 따라 다양한 기능을 지원합니다. 각 GatewayClass에서 지원되는 다양한 기능에 대한 자세한 내용은 GatewayClass 기능을 참조하세요.
권장사항: 최적 성능을 위해 게이트웨이 수를 최대 100으로 제한합니다. 이 한도를 초과하면 성능에 영향을 주거나 지연 시간이 늘어날 수 있습니다.
FrontendConfig 또는 BackendConfig를 사용하여 게이트웨이를 구성할 수 없습니다. 정책을 사용해야 합니다.
GKE 게이트웨이는 해당 게이트웨이가 상태 점검 매개변수를 추론하지 않는다는 점에서 인그레스와 다르게 작동합니다. 서비스가
GET /
요청에 대해 200을 반환하지 않거나 다른 조정된 포드 준비 점검이 있는 경우 서비스에 HealthCheckPolicy를 구성해야 합니다.트래픽 라우팅을 위해 호스트 이름(예: web.example.com:80)에 포트 번호를 직접 지정할 수 없습니다.
Google Cloud 콘솔에서 GKE가 게이트웨이에 대해 만드는 부하 분산기 리소스를 볼 수 있지만 이러한 리소스는 연결된 게이트웨이 또는 GKE 클러스터를 참조하지 않습니다.
게이트웨이를 사용하여 Google 관리형 SSL 인증서를 자동으로 생성할 수는 없지만 수동으로 Google 관리형 SSL 인증서를 만들고 참조할 수 있습니다. 자세한 내용은 게이트웨이 보안을 참조하세요.
HTTPRoute는 유일하게 지원되는 경로 유형입니다. TCPRoutes, UDPRoutes, TLSRoutes는 지원되지 않습니다. GKE Gateway Controller가 지원하는 필드 목록을 보려면 GatewayClass 기능을 참조하세요.
게이트웨이 또는 경로 리디렉션 및 URL 재작성이 포함된 커스텀 요청 및 응답 헤더는 GKE 버전 1.27 이상에서만 사용할 수 있습니다.
게이트웨이, 경로 리디렉션 및 URL 재작성이 포함된 커스텀 요청 및 응답 헤더의 경우 GatewayClass
gke-l7-gxlb
는 지원되지 않습니다.HTTPRoute 커스텀 요청 및 응답 헤더를 구성할 때 다음 Google Cloud 변수는 지원되지 않습니다.
cdn_cache_id
(Cloud CDN은 GKE 게이트웨이에서 지원되지 않음)cdn_cache_status
(Cloud CDN은 GKE 게이트웨이에서 지원되지 않음)origin_request_header
(CORS 정책은 GKE 게이트웨이에서 지원되지 않음)
GKE 게이트웨이는 Cloud CDN 부하 분산 기능을 지원하지 않습니다.
상호 TLS 커스텀 헤더는 지원되지 않습니다(GKE 게이트웨이를 사용하는 mTLS는 지원되지 않음).
Google Cloud 클래식 애플리케이션 부하 분산기 제한사항은 GKE 게이트웨이에 적용됩니다. 또한 백엔드 서비스에서 커스텀 호스트 응답 헤더를 구성할 수 없습니다.
경로 리디렉션과 URL 재작성은 상호 배타적이므로 동일한 규칙에서 두 필터를 동시에 사용할 수 없습니다.
다른 포트로 트래픽 리디렉션은 Cloud Load Balancing에서 지원되지 않습니다. GKE Gateway Controller가 지원하는 필드 목록을 보려면 GatewayClass 기능을 참조하세요.
GKE 게이트웨이는 와일드 카드, 정규 표현식, 동적 URL을 지원하지 않습니다.
리전별 외부 게이트웨이 클래스로 게이트웨이를 지정하면 컨트롤러는 외부 주소 대신 내부 IP 주소를 프로비저닝합니다. 리전 외부 애플리케이션 부하 분산기에서 이름이 지정된 주소를 사용하는 방법은 리전 외부 게이트웨이 배포를 참조하세요.
게이트웨이는 독립형 NEG를 활용하여 네트워크 엔드포인트 그룹을 프로비저닝합니다. 게이트웨이 컨트롤러가 부하 분산기 구성을 적절히 조정해야 하므로 게이트웨이에 포함된 서비스의
cloud.google.com/neg
주석을 수정할 수는 없습니다.GKE 게이트웨이는 GKE 인그레스에서도 참조되는 서비스 참조를 지원하지 않습니다.
IP 주소를 프로비저닝하도록
Gateway
를 구성한 경우Gateway.spec.gatewayClass
변경이 지원되지 않습니다. 게이트웨이 컨트롤러가 부하 분산기를 적절히 조정할 수 있도록 기존 게이트웨이를 삭제하고gatewayClass
값을 업데이트하여 매니페스트를 다시 배포하세요.networking.gke.io/app-protocols
주석은 지원되지 않습니다. 동일한 결과를 얻으려면 대신appProtocol
필드를 사용하세요.external-dns
에 GKE 게이트웨이를 사용하고 게이트웨이 상태가 비정상이면 기본적으로 게이트웨이와 연결된 모든 DNS 레코드가 DNS 영역에서 삭제됩니다.권장사항: external-dns
를 실행할 때policy=upsert-only
플래그를 설정합니다. 이 구성은 기존 DNS 레코드가 삭제되지 않도록 방지하는 데 도움이 됩니다.GKE 게이트웨이에서 경로를 통해 참조되는
Service
에서 포트를 삭제한 경우, 해당 포트를 서비스의 독립형 NEG 주석에서도 함께 삭제해야 합니다. 그렇지 않으면 NEG 컨트롤러가 이 서비스의 포드 엔드포인트를 동기화하지 않게 될 수 있습니다. 자세한 내용은 서비스에서 포트가 삭제되면 NEG 컨트롤러가 엔드포인트 관리를 중지함을 참조하세요.영역 클러스터를 사용하는 멀티 클러스터 게이트웨이 (MCG)를 사용하는 배포는 클러스터 업그레이드 중에 서비스 중단이 발생할 수 있습니다. 이 문제는 영역 클러스터의 제어 영역을 일시적으로 사용할 수 없을 때 기존 네트워크 엔드포인트 그룹 (NEG) 검색 메커니즘이 백엔드를 0으로 잘못 보고할 수 있기 때문에 발생합니다. 장기적인 해결책을 마련하고 있습니다. 이러한 단일 장애점을 방지하려면 MCG가 포함된 리전 GKE 클러스터를 사용하세요.
클러스터에서 Gateway API 사용 설정
GKE에서 게이트웨이 리소스를 사용하려면 클러스터에서 Gateway API를 사용 설정해야 합니다.
Gateway API를 사용 설정하기 위해 기존 GKE 클러스터를 업데이트하려면 먼저 업데이트를 진행하기 전에 최소 요구사항이 충족되었는지 확인합니다.
기존 GKE 클러스터(Autopilot 또는 Standard)에서 Gateway API를 사용 설정하려면 다음 명령어를 사용합니다. 클러스터가 CRD를 조정하고 설치하는 데 최대 45분이 걸릴 수 있습니다.
gcloud container clusters update CLUSTER_NAME \
--location=CLUSTER_LOCATION\
--gateway-api=standard
다음을 바꿉니다.
CLUSTER_NAME
: 기존 클러스터의 이름CLUSTER_LOCATION
: 클러스터의 Compute Engine 리전 또는 영역
--gateway-api=standard
플래그를 사용하면 GKE에서 클러스터에 v1beta1
CRD를 설치합니다.
클러스터 확인
클러스터를 만들거나 업그레이드한 후 GKE Gateway Controller에서 GatewayClasses를 자동으로 설치합니다. 컨트롤러가 CRD를 인식하고 GatewayClasses를 설치하는 데 몇 분 정도 걸릴 수 있습니다.
GKE 컨트롤 플레인에서 Gateway API가 사용 설정되었는지 확인합니다.
gcloud container clusters describe CLUSTER_NAME \ --location=CLUSTER_LOCATION \ --format json
출력은 다음과 비슷합니다. 이 출력이 비어 있는 경우 클러스터 업데이트 명령어를 다시 실행합니다.
"networkConfig": { ... "gatewayApiConfig": { "channel": "CHANNEL_STANDARD" }, ... },
클러스터에 GatewayClasses가 설치되어 있는지 확인합니다.
kubectl get gatewayclass
출력은 다음과 비슷합니다.
NAME CONTROLLER ACCEPTED AGE gke-l7-global-external-managed networking.gke.io/gateway True 16h gke-l7-regional-external-managed networking.gke.io/gateway True 16h gke-l7-gxlb networking.gke.io/gateway True 16h gke-l7-rilb networking.gke.io/gateway True 16h
각 GatewayClass의 기능을 이해하기 위해서는 GatewayClass 기능을 참조하세요.
단일 클러스터 GatewayClass만 자동으로 설치됩니다. 내부 및 외부 멀티 클러스터 부하 분산을 위해 멀티 클러스터 GatewayClasses를 설치하고 사용하려면 멀티 클러스터 게이트웨이 사용 설정을 참조하세요.
내부 게이트웨이 배포
내부 게이트웨이는 VPC 내에서 또는 VPC에 연결된 네트워크에서만 연결할 수 있는 애플리케이션을 노출합니다.
리전 내부 게이트웨이 배포
다음 예시에서는 특정 지역 리전 내의 서비스 간에 효율적이고 안전한 통신을 사용 설정하는 리전 내부 게이트웨이를 배포하는 방법을 보여줍니다.
프록시 전용 서브넷 구성
내부 애플리케이션 부하 분산기를 사용하는 게이트웨이를 만들기 전에 프록시 전용 서브넷을 구성해야 합니다. 내부 애플리케이션 부하 분산기를 사용하는 VPC의 각 리전에는 프록시 전용 서브넷이 있어야 합니다. 이 서브넷은 부하 분산기 프록시에 내부 IP 주소를 제공합니다.
프록시 전용 서브넷을 만듭니다.
gcloud compute networks subnets create SUBNET_NAME \ --purpose=REGIONAL_MANAGED_PROXY \ --role=ACTIVE \ --region=COMPUTE_REGION \ --network=VPC_NETWORK_NAME \ --range=CIDR_RANGE
다음을 바꿉니다.
SUBNET_NAME
: 프록시 전용 서브넷의 이름입니다.COMPUTE_REGION
: 프록시 전용 서브넷의 리전입니다.VPC_NETWORK_NAME
: 이 프록시 전용 서브넷을 만드는 VPC 네트워크의 이름입니다. 이 네트워크가 GKE 클러스터가 있고 게이트웨이를 배포하는 VPC 네트워크와 동일한지 확인합니다. 이는 부하 분산기와 백엔드 서비스 사이의 원활한 통신을 위해 중요합니다.CIDR_RANGE
: 서브넷의 기본 IP 주소 범위입니다. 리전의 프록시에서 64개 이상의 IP 주소를 사용할 수 있도록/26
이하의 서브넷 마스크를 사용해야 합니다. 권장 서브넷 마스크는/23
입니다.
프록시 전용 서브넷을 확인합니다.
gcloud compute networks subnets describe SUBNET_NAME \ --region=COMPUTE_REGION
출력은 다음과 비슷합니다.
... gatewayAddress: 10.1.1.1 ipCidrRange: 10.1.1.0/24 kind: compute#subnetwork name: proxy-subnet network: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/global/networks/default privateIpGoogleAccess: false privateIpv6GoogleAccess: DISABLE_GOOGLE_ACCESS purpose: REGIONAL_MANAGED_PROXY region: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION role: ACTIVE selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION/subnetworks/proxy-subnet state: READY
게이트웨이 만들기
게이트웨이 리소스는 Kubernetes에서 트래픽을 라우팅하는 데이터 영역을 나타냅니다. 게이트웨이는 파생된 GatewayClass에 따라 여러 종류의 부하 분산 및 라우팅을 나타낼 수 있습니다. 게이트웨이 리소스에 대한 자세한 내용은 게이트웨이 리소스 설명 또는 API 사양을 참조하세요.
여기에서는 GKE 클러스터의 관리자가 애플리케이션을 내부적으로 노출하기 위해 다른 팀에서 사용될 수 있는 게이트웨이를 만듭니다. 관리자가 게이트웨이를 배포한 후 애플리케이션 팀은 해당 경로를 독립적으로 배포하고 이를 이 게이트웨이에 연결합니다.
다음 게이트웨이 매니페스트를
gateway.yaml
이라는 파일에 저장합니다.kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-http spec: # Specify an existing GatewayClass. gatewayClassName: gke-l7-rilb listeners: # Listen for HTTP traffic on port 80. - name: http protocol: HTTP port: 80
이 매니페스트에는 다음 필드가 포함됩니다.
gatewayClassName: gke-l7-rilb
: 이 게이트웨이가 파생된 GatewayClass를 지정합니다.gke-l7-rilb
는 내부 애플리케이션 부하 분산기에 해당합니다.port: 80
: 게이트웨이가 HTTP 트래픽을 리슨하기 위해 포트 80만 노출하도록 지정합니다.
이 게이트웨이는 포트 80에서만 HTTP 트래픽을 처리하도록 구성되어 있습니다. 기본적으로 HTTPS(포트 443)를 지원하지 않으며 HTTPS를 통해 연결하려고 하면 요청이 실패할 수 있습니다.
클러스터에 게이트웨이를 배포합니다.
kubectl apply -f gateway.yaml
게이트웨이가 올바르게 배포되었는지 확인합니다. 모든 리소스를 배포하려면 몇 분 정도 걸릴 수 있습니다.
kubectl describe gateways.gateway.networking.k8s.io internal-http
출력은 다음과 비슷합니다.
Name: internal-http Namespace: default Spec: Gateway Class Name: gke-l7-rilb Listeners: Allowed Routes: Kinds: Group: gateway.networking.k8s.io Kind: HTTPRoute Namespaces: From: Same Name: http Port: 80 Protocol: HTTP Status: Addresses: Type: IPAddress Value: 192.168.1.14 Conditions: Last Transition Time: 2025-03-19T19:53:46Z Message: The OSS Gateway API has deprecated this condition, do not depend on it. Observed Generation: 1 Reason: Scheduled Status: True Type: Scheduled Last Transition Time: 2025-03-19T19:53:46Z Message: Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2025-03-19T19:53:46Z Message: Observed Generation: 1 Reason: Programmed Status: True # Indicates that the Gateway is ready. Type: Programmed Last Transition Time: 2025-03-19T19:53:46Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reserved it for future use. GKE Gateway will stop emitting it in a future update, use "Programmed" instead. Observed Generation: 1 Reason: Ready Status: True Type: Ready Last Transition Time: 2025-03-19T19:53:46Z Message: Observed Generation: 1 Reason: Healthy Status: True Type: networking.gke.io/GatewayHealthy Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 92s networking.gke.io/gateway test/internal-http Normal UPDATE 45s (x3 over 91s) networking.gke.io/gateway test/internal-http Normal SYNC 45s networking.gke.io/gateway SYNC on test/internal-http was a success
이 출력에서
Programmed
조건의True
상태는 게이트웨이가 준비되었음을 나타냅니다.이 시점에서는 부하 분산기 및 IP 주소를 프로비저닝한 클러스터에 게이트웨이가 배포됩니다. 게이트웨이에는 경로가 포함되지 않습니다. 하지만 따라서 백엔드에 트래픽을 전송하는 방법을 아직 알 수 없습니다. 경로가 없으면 모든 트래픽이 기본 백엔드로 이동하고, 이것이 HTTP 404를 반환합니다. 그런 후 애플리케이션 및 경로를 배포합니다. 이것은 게이트웨이에 애플리케이션 백엔드를 가져오는 방법을 알려줍니다.
데모 애플리케이션 배포
애플리케이션팀은 게이트웨이의 배포와 독립적으로 해당 애플리케이션 및 경로를 배포할 수 있습니다. 일부 경우에 애플리케이션팀은 게이트웨이도 소유하고, 애플리케이션 전용 리소스로 이를 직접 배포해야 할 수 있습니다. 게이트웨이 및 경로의 서로 다른 소유 모델은 경로 바인딩을 참조하세요. 하지만 이 예시에서 스토어팀은 이전 섹션에서 만든 internal-http
게이트웨이를 통해 앱을 노출하기 위해 해당 애플리케이션 및 수반되는 HTTPRoute를 배포합니다.
HTTPRoute 리소스에는 트래픽 일치를 위한 많은 구성 가능한 필드가 포함됩니다. HTTPRoute의 필드에 대한 설명은 API 사양을 참조하세요.
스토어 애플리케이션(store-v1, store-v2, store-german 배포)을 클러스터에 배포합니다.
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
이렇게 하면 이름이 store-v1, store-v2, store-german인 3개 서비스와 3개 배포가 생성됩니다.
애플리케이션이 성공적으로 배포되었는지 확인합니다.
kubectl get pod
애플리케이션이 실행된 후에는 출력이 다음과 비슷합니다.
NAME READY STATUS RESTARTS AGE store-german-66dcb75977-5gr2n 1/1 Running 0 38s store-v1-65b47557df-jkjbm 1/1 Running 0 14m store-v2-6856f59f7f-sq889 1/1 Running 0 14m
서비스도 배포되었는지 확인합니다.
kubectl get service
출력에 각 저장소 배포에 대한 서비스가 표시됩니다.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE store-german ClusterIP 10.48.3.183 <none> 8080/TCP 4s store-v1 ClusterIP 10.48.2.224 <none> 8080/TCP 5s store-v2 ClusterIP 10.48.4.48 <none> 8080/TCP 5s
HTTPRoute 배포
경로 리소스는 게이트웨이에서 Kubernetes 백엔드로 트래픽을 매핑하기 위한 프로토콜 특정 규칙을 정의합니다. HTTPRoute 리소스는 HTTP 및 HTTPS 트래픽 일치 및 필터링을 수행하며, 모든 gke-l7
GatewayClass에서 지원됩니다.
이 섹션에서는 HTTPRoute를 배포하여, 스토어 애플리케이션에 연결하기 위해 필요한 라우팅 규칙으로 게이트웨이를 프로그래밍합니다.
다음 HTTPRoute 매니페스트를
store-route.yaml
이라는 파일에 저장합니다.kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store spec: # Attach the HTTPRoute to a Gateway. parentRefs: - kind: Gateway name: internal-http # Route requests that have `store.example.com` in the Host header. hostnames: - "store.example.com" rules: # Send requests with the `env: canary` header to the `store-v2` Service. - matches: - headers: - name: env value: canary backendRefs: - name: store-v2 port: 8080 # Send requests with `/de` in the path to the `store-german` Service. - matches: - path: value: /de backendRefs: - name: store-german port: 8080 # Send unmatched requests to the store-v1 Service. - backendRefs: - name: store-v1 port: 8080
클러스터에 HTTProute를 배포합니다.
kubectl apply -f store-route.yaml
store
HTTPRoute는parentRefs
속성을 사용하여internal-http
게이트웨이에 바인딩됩니다. 이러한 라우팅 규칙은 다음 다이어그램과 같이 기본 부하 분산기에서 구성됩니다.이러한 라우팅 규칙은 다음과 같은 방식으로 HTTP 트래픽을 처리합니다.
store.example.com/de
에 대한 트래픽은store-german
서비스로 이동합니다.- HTTP 헤더
"env: canary"
가 있는store.example.com
에 대한 트래픽은store-v2
서비스로 이동합니다. store.example.com
에 대한 나머지 트래픽은store-v1
서비스로 이동합니다.
HTTPRoute가 배포되었는지 확인합니다.
kubectl describe httproute store
출력은 다음과 비슷합니다.
Name: store Namespace: default Labels: <none> Annotations: <none> API Version: gateway.networking.k8s.io/v1 Kind: HTTPRoute # Multiple lines are omitted here. Spec: Hostnames: store.example.com Parent Refs: Group: gateway.networking.k8s.io Kind: Gateway Name: internal-http Rules: Backend Refs: Group: Kind: Service Name: store-v1 Port: 8080 Weight: 1 Matches: Path: Type: PathPrefix Value: / Backend Refs: Group: Kind: Service Name: store-v2 Port: 8080 Weight: 1 Matches: Headers: Name: env Type: Exact Value: canary Path: Type: PathPrefix Value: / Backend Refs: Group: Kind: Service Name: store-german Port: 8080 Weight: 1 Matches: Path: Type: PathPrefix Value: /de Status: Parents: Conditions: Last Transition Time: 2022-11-01T04:18:52Z Message: Reason: Accepted Status: True Type: Accepted Last Transition Time: 2022-11-01T04:18:52Z Message: Reason: ReconciliationSucceeded Status: True Type: Reconciled Controller Name: networking.gke.io/gateway Parent Ref: Group: gateway.networking.k8s.io Kind: Gateway Name: internal-http Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 24m sc-gateway-controller default/store Normal SYNC 16m (x4 over 23m) sc-gateway-controller Bind of HTTPRoute "default/store" to ParentRef {Group: gateway.networking.k8s.io", # Multiple lines are omitted here.
HTTPRoute가 게이트웨이에 바인딩되었는지 확인합니다.
kubectl describe gateway
출력은 다음과 비슷합니다.
Name: internal-http Namespace: default Labels: <none> <...> Status: Addresses: Type: IPAddress Value: 10.128.15.203 Conditions: Last Transition Time: 2022-11-01T03:47:01Z Message: Reason: Scheduled Status: True Type: Scheduled Last Transition Time: 2022-11-01T03:47:01Z Message: Reason: Ready Status: True Type: Ready Listeners: Attached Routes: 1 Conditions: Last Transition Time: 2022-11-01T03:47:01Z Message: Reason: Ready Status: True Type: Ready Name: http Supported Kinds: Group: gateway.networking.k8s.io Kind: HTTPRoute <...>
애플리케이션에 트래픽 보내기
이제 게이트웨이, 경로, 애플리케이션이 클러스터에 배포되었으므로, 트래픽을 애플리케이션에 전달할 수 있습니다. 게이트웨이는 포트 80에서만 HTTP 트래픽을 서빙하도록 구성됩니다. TLS가 별도로 구성되지 않았으면 HTTPS를 사용하는 요청이 실패할 수 있습니다.
애플리케이션에 트래픽을 전송할 수 있도록 게이트웨이에서 IP 주소를 검색합니다.
kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}"
출력은 IP 주소입니다.
클러스터 연결을 사용하여 가상 머신(VM) 인스턴스에 대해 셸에서 이 IP 주소로 트래픽을 전송합니다. 이 용도로 VM을 만들 수 있습니다. 이것은 게이트웨이에 내부 IP 주소가 포함되었고 VPC 네트워크 내에서만 액세스할 수 있기 때문에 필요합니다.
internal-http
가 리전 부하 분산기이기 때문에 클라이언트 셸이 GKE 클러스터와 동일한 리전 내에 있어야 합니다.store.example.com에 요청을 수행합니다.
curl http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
GATEWAY_IP_ADDRESS
를 이전 단계의 IP 주소로 바꿉니다.데모 앱의 출력에 앱이 실행되는 위치에 대한 정보가 표시됩니다.
{ "cluster_name": "gke1", "host_header": "store.example.com", "metadata": "store-v1", "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal", "pod_name": "store-v1-84b47c7f58-pmgmk", "pod_name_emoji": "💇🏼♀️", "project_id": "gateway-demo-243723", "timestamp": "2022-10-25T13:31:17", "zone": "ZONE_NAME" }
store.example.com/de
에서 스토어 서비스의 독일어 버전으로 이동하여 경로 일치를 테스트합니다.curl http://store.example.com/de --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
요청이
store-german
포드로 제공되는 것이 출력에 확인됩니다.{ "cluster_name": "gke1", "host_header": "store.example.com", "metadata": "Gutentag!", "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal", "pod_name": "store-german-5cb6474c55-lq5pl", "pod_name_emoji": "🧞♀", "project_id": "gateway-demo-243723", "timestamp": "2022-10-25T13:35:37", "zone": "ZONE_NAME" }
마지막으로
env: canary
HTTP 헤더를 사용하여 스토어 서비스의 카나리아 버전으로 트래픽을 전송합니다.curl -H "env: canary" http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
요청이
store-v2
포드로 제공되는 것이 출력에 확인됩니다.{ "cluster_name": "gke1", "host_header": "store.example.com", "metadata": "store-v2", "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal", "pod_name": "store-v2-5788476cbd-s9thb", "pod_name_emoji": "🦰", "project_id": "gateway-demo-243723", "timestamp": "2022-10-25T13:38:26", "zone": "ZONE_NAME" }
외부 게이트웨이 배포
외부 게이트웨이는 인터넷이나 VPC 네트워크 외부의 네트워크에서 액세스할 수 있는 애플리케이션을 노출합니다. 게이트웨이를 공개 인터넷에서 액세스할 수 있으므로 애플리케이션을 보호해야 한다는 점을 제외하면 내부 게이트웨이 배포와 유사합니다.
외부 게이트웨이 만들기에는 외부 게이트웨이 또는 리전 외부 게이트웨이 두 가지 옵션이 있습니다.
- 전역 외부 게이트웨이: 이 게이트웨이는 전역 IP 주소 (또는 Anycast IP 주소)를 게이트웨이의 프런트엔드로 사용합니다. 이 IP 주소는 모든 Google Cloud 컴퓨팅 리전에서 광고됩니다. 이 Anycast IP 주소로 트래픽을 전송하는 클라이언트는 IP 주소가 공지되는 가장 가까운 Google 위치로 라우팅됩니다. 전역 외부 게이트웨이는 프리미엄 네트워크 서비스 등급에서만 사용할 수 있습니다.
- 리전 외부 게이트웨이: 이 게이트웨이는 리전 IP 주소를 게이트웨이의 프런트엔드로 사용합니다. 이 게이트웨이의 동작은 선택한 네트워크 서비스 등급에 따라 다릅니다.
- Standard 네트워크 서비스 등급 (기본값)을 선택하면 리전 IP 주소가 리전 외부 게이트웨이가 배포된 로컬 Google Cloud Compute 리전 내에서만 공지됩니다. 이 IP 주소로 트래픽을 전송하는 클라이언트는 IP 주소가 공지된 Google 리전에 도달하기 전에 해당 로컬 ISP와 공개 인터넷을 통해 라우팅됩니다.
- 프리미엄 네트워크 서비스 등급을 선택하면 리전 IP 주소가 Google의 글로벌 네트워크에 공지됩니다. 즉, 대상이 리전 IP 주소인 경우에도 클라이언트 트래픽이 클라이언트와 최대한 가까운 Google 에지 피어링 지점에서 Google의 고품질 글로벌 백본으로 들어갑니다. 이 위치는 공개 인터넷을 통해 이동하는 트래픽 거리를 최소화하여 지연 시간을 크게 줄이고 성능을 향상합니다.
전역 외부 게이트웨이 배포
다음 예시에서는 전역 외부 게이트웨이에 연결되고 인증서 관리자와 HTTPRoute를 사용하여 인증서 맵에 그룹화된 여러 인증서가 있는 스토어 애플리케이션을 노출하는 방법을 보여줍니다.
인증서 맵 만들기
게이트웨이당 15개 이상의 인증서가 필요하거나 와일드 카드 인증서를 사용해야 하는 경우 인증서 관리자를 사용하여 인증서를 관리하는 것이 좋습니다.
Kubernetes 보안 비밀 또는 Google 관리형 SSL 인증서를 사용하여 외부 게이트웨이를 보호할 수도 있습니다. 자세한 내용은 게이트웨이 보안을 참조하세요.
이 섹션에서는 인증서 관리자를 사용하여 클러스터에서 실행되는 애플리케이션을 보호하는 인증서를 만듭니다.
Certificate Manager API를 사용 설정합니다.
gcloud services enable certificatemanager.googleapis.com
인증서 맵을 만듭니다.
gcloud beta certificate-manager maps create store-example-com-map
Google 관리 인증서와 키를 인증서에 로드합니다.
gcloud beta certificate-manager certificates create store-example-com-cert \ --certificate-file="CERTIFICATE_FILE" \ --private-key-file="PRIVATE_KEY_FILE"
다음을 바꿉니다.
CERTIFICATE_FILE
: 인증서 파일의 이름입니다. 파일 확장자는.pem
이어야 합니다. 예를 들면cert.pem
입니다.PRIVATE_KEY_FILE
: 비공개 키 파일의 이름입니다.
자세한 내용은 비공개 키 및 인증서 만들기를 참조하세요.
인증서 맵에 인증서를 할당하는
CertificateMapEntry
를 만듭니다.gcloud beta certificate-manager maps entries create store-example-com-map-entry \ --map=store-example-com-map \ --hostname=store.example.com \ --certificates=store-example-com-cert
Kubernetes 보안 비밀 또는 SSL 인증서와 같은 다른 인증서 소스를 사용하여 게이트웨이를 보호하는 방법은 게이트웨이 보호를 참조하세요.
게이트웨이 만들기
게이트웨이 리소스는 Kubernetes에서 트래픽을 라우팅하는 데이터 영역을 나타냅니다. 게이트웨이는 사용하는 GatewayClass에 따라 다양한 종류의 부하 분산 및 라우팅을 나타낼 수 있습니다.
게이트웨이 리소스에 대한 자세한 내용은 게이트웨이 리소스 설명 또는 API 사양을 참조하세요.
이 섹션에서는 게이트웨이를 만듭니다. 애플리케이션팀은 게이트웨이를 사용하여 경로를 독립적으로 배포하고 해당 경로를 게이트웨이에 안전하게 연결하여 인터넷에 애플리케이션을 노출할 수 있습니다.
다음 매니페스트를
gateway.yaml
이라는 파일에 저장합니다.kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http annotations: networking.gke.io/certmap: store-example-com-map spec: # This GatewayClass uses a global external Application Load Balancer. gatewayClassName: gke-l7-global-external-managed listeners: - name: https protocol: HTTPS port: 443
이 매니페스트는 다음 필드를 사용해서 게이트웨이를 기술합니다.
gatewayClassName: gke-l7-global-external-managed
: 이 게이트웨이에 GatewayClass를 지정합니다. 이 게이트웨이 클래스는 전역 외부 애플리케이션 부하 분산기를 사용합니다.protocol: HTTPS
및port: 443
: 게이트웨이가 HTTPS 트래픽에 대해 포트 443을 노출하도록 지정합니다. 이 필드는 TLS를 사용 설정합니다.networking.gke.io/certmap: store-example-com-map
: 인증서 관리자의 인증서 맵 이름을 지정합니다.
TLS가
networking.gke.io/certmap
주석을 사용하여 인증서 관리자에서 구성되므로 TLS 섹션이 없습니다.매니페스트를 클러스터에 적용합니다.
kubectl apply -f gateway.yaml
GKE에서 리소스를 배포하는 데 몇 분 정도 걸릴 수 있습니다.
게이트웨이가 성공적으로 배포되었는지 확인합니다.
kubectl describe gateway
출력은 다음과 비슷합니다.
Name: external-http Namespace: default Labels: <none> ... Spec: Gateway Class Name: gke-l7-global-external-managed Listeners: Allowed Routes: Namespaces: From: Same Name: https Port: 443 Protocol: HTTPS Tls: Certificate Refs: Group: Kind: Secret Name: store-example-com Mode: Terminate ...
이 출력은 클러스터에 배포된 게이트웨이에 부하 분산기와 공개 IP 주소가 있음을 보여줍니다. 게이트웨이에 경로가 없으므로 백엔드로 트래픽을 전송할 수 없습니다. 경로가 없으면 모든 트래픽이 기본 백엔드로 이동하고, 이것이 HTTP 404 응답을 반환합니다. 다음 섹션에서는 게이트웨이에 트래픽을 백엔드로 전송하도록 지시하는 경로를 배포합니다.
데모 애플리케이션 배포
애플리케이션팀은 게이트웨이의 배포와 독립적으로 해당 애플리케이션 및 경로를 배포할 수 있습니다. 일부 경우에 애플리케이션팀은 게이트웨이도 소유하고, 애플리케이션 전용 리소스로 이를 직접 배포해야 할 수 있습니다. 게이트웨이 및 경로의 서로 다른 소유 모델은 경로 바인딩을 참조하세요. 이 예시에서 스토어팀은 이전 섹션에서 만든 external-http
게이트웨이를 통해 앱을 노출하기 위해 해당 애플리케이션 및 수반되는 HTTPRoute를 배포합니다.
HTTPRoute 필드에 대한 자세한 내용은 API 사양을 참조하세요.
클러스터에 샘플 애플리케이션을 배포합니다.
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
이 샘플 애플리케이션은 이름이
store-v1
,store-v2
,store-german
인 3개의 배포와 3개의 서비스를 만듭니다.애플리케이션이 성공적으로 배포되었는지 확인합니다.
kubectl get pod
출력은 다음과 비슷합니다.
NAME READY STATUS RESTARTS AGE store-german-66dcb75977-5gr2n 1/1 Running 0 38s store-v1-65b47557df-jkjbm 1/1 Running 0 14m store-v2-6856f59f7f-sq889 1/1 Running 0 14m
서비스가 성공적으로 배포되었는지 확인합니다.
kubectl get service
출력은 다음과 비슷합니다.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE store-german ClusterIP 10.48.3.183 <none> 8080/TCP 4s store-v1 ClusterIP 10.48.2.224 <none> 8080/TCP 5s store-v2 ClusterIP 10.48.4.48 <none> 8080/TCP 5s
HTTPRoute 만들기
경로 리소스는 게이트웨이에서 Kubernetes 백엔드로 트래픽을 매핑하기 위한 프로토콜 특정 규칙을 정의합니다. HTTPRoute 리소스는 HTTP 및 HTTPS 트래픽 일치 및 필터링을 수행하며, 모든 gke-l7-*
GatewayClass에서 지원됩니다.
이 섹션에서는 샘플 애플리케이션에 도달하는 데 필요한 라우팅 규칙이 있는 게이트웨이를 구성하는 HTTPRoute를 배포합니다.
다음 매니페스트를
store-route-external.yaml
이라는 파일에 저장합니다.kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-external spec: parentRefs: # Bind the route to the 'external-http' Gateway. - kind: Gateway name: external-http hostnames: - "store.example.com" rules: # Default rule for store.example.com that sends traffic to the store-v1 service. - backendRefs: - name: store-v1 port: 8080 # Match requests with the "env: canary" header and send them to the store-v2 service. - matches: - headers: - name: env value: canary backendRefs: - name: store-v2 port: 8080 # Match requests with the path "/de" and sends them to the store-german service. - matches: - path: value: /de backendRefs: - name: store-german port: 8080
이 매니페스트는
external-http
게이트웨이를 참조하는 HTTPRoute를 설명합니다.매니페스트를 클러스터에 적용합니다.
kubectl apply -f store-route-external.yaml
store
HTTPRoute는parentRefs
속성을 사용하여external-http
게이트웨이에 바인딩됩니다. 다음 다이어그램은 기본 부하 분산기에 구성된 라우팅 규칙을 보여줍니다.라우팅 규칙은 다음과 같이 HTTP 트래픽을 처리합니다.
store.example.com/de
에 대한 트래픽은store-german
서비스로 라우팅됩니다.- HTTP 헤더
"env: canary"
가 있는store.example.com
에 대한 트래픽은store-v2
서비스로 라우팅됩니다. store.example.com
에 대한 나머지 트래픽은store-v1
서비스로 라우팅됩니다.
HTTPRoute가 배포되었는지 확인합니다.
kubectl describe httproute store-external
출력은 다음과 비슷합니다.
Name: store-external Namespace: default Labels: <none> Annotations: <none> API Version: gateway.networking.k8s.io/v1 Kind: HTTPRoute # Multiple lines are omitted here. Spec: Hostnames: store.example.com Parent Refs: Group: gateway.networking.k8s.io Kind: Gateway Name: external-http Rules: Backend Refs: Group: Kind: Service Name: store-v1 Port: 8080 Weight: 1 Matches: Path: Type: PathPrefix Value: / Backend Refs: Group: Kind: Service Name: store-v2 Port: 8080 Weight: 1 Matches: Headers: Name: env Type: Exact Value: canary Path: Type: PathPrefix Value: / Backend Refs: Group: Kind: Service Name: store-german Port: 8080 Weight: 1 Matches: Path: Type: PathPrefix Value: /de Status: Parents: # This section shows the status of this route in relation to each Gateway attached. Conditions: Last Transition Time: 2022-11-01T05:42:31Z Message: Reason: Accepted Status: True # Means that the Gateway has validated and accepted this route's configuration. Type: Accepted Last Transition Time: 2022-11-01T05:43:18Z Message: Reason: ReconciliationSucceeded Status: True Type: Reconciled Controller Name: networking.gke.io/gateway Parent Ref: Group: gateway.networking.k8s.io Kind: Gateway Name: external-http Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 2m48s sc-gateway-controller default/store-external Normal SYNC 61s (x3 over 2m27s) sc-gateway-controller Bind of HTTPRoute "default/store-external" to ParentRef Group: "gateway.networking.k8s.io", ...
HTTPRoute가 게이트웨이에 바인딩되었는지 확인합니다.
kubectl describe gateway external-http
출력은 다음과 비슷합니다.
Name: external-http Namespace: default Labels: <none> # Multiple lines are omitted here. Status: Addresses: Type: IPAddress Value: 34.149.207.45 Conditions: Last Transition Time: 2022-11-01T05:37:21Z Message: Reason: Scheduled Status: True Type: Scheduled Last Transition Time: 2022-11-01T05:43:18Z Message: Reason: Ready Status: True Type: Ready Listeners: Attached Routes: 1 Conditions: Last Transition Time: 2022-11-01T05:43:18Z Message: Reason: Ready Status: True Type: Ready Name: https Supported Kinds: Group: gateway.networking.k8s.io Kind: HTTPRoute # Multiple lines are omitted here.
애플리케이션에 트래픽 보내기
이제 게이트웨이, 경로, 애플리케이션이 클러스터에 배포되었으므로, 트래픽을 애플리케이션에 전달할 수 있습니다.
게이트웨이의 IP 주소를 가져옵니다.
kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}"
출력은 IP 주소입니다.
VM을 만듭니다.
gcloud cloud-shell ssh
VM에서 게이트웨이 IP 주소로 트래픽을 전송합니다.
example.com
호스트 이름을 소유하지 않으므로 호스트 헤더를 수동으로 설정해야 합니다.curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
GATEWAY_IP_ADDRESS
를 이전 단계의 게이트웨이 IP 주소로 바꿉니다.cacert.pem: 생성한 인증서 파일입니다. 게이트웨이에 연결하기 위해 사하는 머신에 이 파일을 저장해야 합니다.
출력에 앱이 실행되는 위치에 대한 데모 앱의 정보가 표시됩니다.
{ "cluster_name": "gke1", "host_header": "store.example.com", "metadata": "store-v1", "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal", "pod_name": "store-v1-84b47c7f58-pmgmk", "pod_name_emoji": "💇🏼♀️", "project_id": "gateway-demo-243723", "timestamp": "2022-09-25T13:31:17", "zone": "us-central1-a" }
store.example.com/de
에서store
서비스의 독일어 버전으로 이동하여 경로 일치를 테스트합니다.curl https://store.example.com/de --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
요청이
store-german
포드로 제공되는 것이 출력에 확인됩니다.{ "cluster_name": "gke1", "host_header": "store.example.com", "metadata": "Gutentag!", "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal", "pod_name": "store-german-5cb6474c55-lq5pl", "pod_name_emoji": "🧞♀", "project_id": "gateway-demo-243723", "timestamp": "2022-09-25T13:35:37", "zone": "us-central1-a" }
env: canary
HTTP 헤더를 사용하여store
서비스의 카나리아 버전으로 트래픽을 전송합니다.curl -H "env: canary" https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
요청이
store-v2
포드로 제공되는 것이 출력에 확인됩니다.{ "cluster_name": "gke1", "host_header": "store.example.com", "metadata": "store-v2", "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal", "pod_name": "store-v2-5788476cbd-s9thb", "pod_name_emoji": "👩🏿", "project_id": "gateway-demo-243723", "timestamp": "2022-09-25T13:38:26", "zone": "us-central1-a" }
리전 외부 게이트웨이 배포
다음 예시에서는 자체 관리형 인증서 및 HTTPRoute를 사용하여 리전 외부 게이트웨이에 연결된 여러 인증서가 있는 매장 애플리케이션을 노출하는 방법을 보여줍니다.
리전 게이트웨이의 프록시 서브넷 만들기
리전 외부 애플리케이션 부하 분산기를 사용하는 게이트웨이를 만들기 전에 프록시 전용 서브넷을 구성해야 합니다. 리전 외부 애플리케이션 부하 분산기를 사용하는 VPC의 각 리전에는 external_managed_proxy
서브넷이 있어야 합니다. 이 서브넷은 부하 분산기 프록시에 내부 IP 주소를 제공합니다.
클라이언트 트래픽을 보호하기 위한 인증서 만들기
인증 기관(CA)에서 발급되고 검증된 인증서를 사용하거나 자체 서명된 인증서를 만들 수 있습니다. 인증서를 만드는 방법에 대한 자세한 내용은 Kubernetes 보안 비밀에 인증서 저장을 참조하세요.
클라이언트와 리전 게이트웨이 간의 트래픽을 보호하려면 다음 방법을 사용하면 됩니다.
- Google 관리형 또는 자체 관리형 인증서 관리자 인증서
- 자체 관리형 지역 SSL 인증서
- Kubernetes 보안 비밀
CertificateMap
또는 Google 관리 SSL 인증서는 리전 게이트웨이에서 지원되지 않습니다.
자세한 내용은 인증서 및 Google Cloud 부하 분산기를 참고하세요.
리전 외부 HTTP(S) 게이트웨이 만들기
외부 부하 분산기에 대한 리전 고정 IP 주소를 만듭니다.
gcloud compute addresses create IP_ADDRESS_NAME \ --region=COMPUTE_REGION \ --network-tier=STANDARD
다음을 바꿉니다.
IP_ADDRESS_NAME
: 새 고정 IP 주소의 이름COMPUTE_REGION
: 클러스터가 실행되는 Compute Engine 리전
다음과 같이 자체 관리형 인증서를 사용하여 리전 외부 애플리케이션 부하 분산기 게이트웨이를 만들고 매니페스트를
regional-gateway.yaml
로 저장합니다.kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-regional-http spec: # Name of an existing GatewayClass. gatewayClassName: gke-l7-regional-external-managed # Listen for HTTPS traffic on port 443 listeners: - name: https protocol: HTTPS port: 443 tls: # Terminate the TLS session with the client at the Gateway. mode: Terminate # Certificates for the Gateway to use to create a new TLS session. certificateRefs: - name: store-example-com # The name of the static IP address of the external load balancer. # You can also use the `IPAddress` type to specify the actual IP address. addresses: - type: NamedAddress value: IP_ADDRESS_NAME
regional-gateway
매니페스트를 적용합니다.kubectl apply -f regional-gateway.yaml
구성을 확인합니다.
kubectl get gateway
출력은 다음과 비슷합니다.
NAME CLASS ADDRESS READY AGE external-http gke-l7-regional-external-managed 35.118.32.224 True 49s
더 많은 세부정보를 가져오려면 describe 명령어를 사용합니다.
kubectl describe gateway
출력은 다음과 비슷합니다.
Name: external-regional-http Namespace: default Labels: <none> ... Spec: Gateway Class Name: gke-l7-regional-external-managed Listeners: Allowed Routes: Namespaces: From: Same Name: https Port: 443 Protocol: HTTPS Tls: Certificate Refs: Group: Kind: Secret Name: store-example-com Mode: Terminate ...
데모 애플리케이션 배포
게이트웨이 배포와 독립적으로 애플리케이션 및 경로를 배포할 수 있습니다.
데모 애플리케이션을 배포하는 방법은 데모 애플리케이션 배포를 참조하세요.
HTTPRoute 만들기
HTTP 및 HTTPS 트래픽을 매칭하고 필터링하려면 HTTPRoute를 생성해야 합니다.
애플리케이션에 트래픽 보내기
애플리케이션을 배포하고 HTTPRoute를 만든 후 애플리케이션으로 트래픽을 전달할 수 있습니다.
애플리케이션으로 트래픽을 전송하는 방법은 애플리케이션으로 트래픽 전송을 참조하세요.
공유 게이트웨이 사용
Gateway API는 부하 분산기 및 라우팅 규칙을 배포하기 위해 게이트웨이 리소스와 경로 리소스를 별도로 사용합니다. 반면, 인그레스는 이 모든 구성을 하나의 리소스에 결합합니다. Gateway API는 이러한 역할을 리소스별로 분리함으로써, 부하 분산기와 라우팅 규칙을 각각 독립적으로 배포하고 서로 다른 사용자나 팀이 각각 관리할 수 있도록 합니다. 이를 통해 Gateway API는 여러 개의 경로 리소스가 연결되는 공유 게이트웨이로 구성될 수 있으며, 각 경로는 서로 다른 팀이나 네임스페이스에서 독립적으로 소유하고 관리할 수 있습니다.
공유 게이트웨이에 경로 배포
이 예시는 내부 게이트웨이 배포에 배포된 internal-http
게이트웨이를 기반으로 합니다.
이 예시에서 사이트팀은 게이트웨이에서 해당 서비스로 일치하는 트래픽을 선택하기 위해 자신의 애플리케이션, 서비스, HTTPRoute를 배포합니다.
예시 애플리케이션 배포:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml
다음 매니페스트를
site-route-internal.yaml
이라는 파일에 저장합니다.kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: site-internal spec: # Attach the HTTPRoute to the `internal-http` Gateway. parentRefs: - kind: Gateway name: internal-http # Route requests that have `site.example.com` in the Host header. hostnames: - "site.example.com" # Send all requests to the `site-v1` Service. rules: - backendRefs: - name: site-v1 port: 8080
이 매니페스트는
site.example.com
의 모든 트래픽과 일치하고site-v1
서비스로 라우팅하는 HTTPRoute를 기술합니ㅏㄷ.매니페스트를 클러스터에 적용합니다.
kubectl apply -f site-route-internal.yaml
HTTPRoute가 게이트웨이에 연결되었는지 확인합니다.
kubectl describe httproute.gateway.networking.k8s.io site-internal
출력은 다음과 비슷합니다.
Status: Parents: Conditions: Last Transition Time: 2023-01-09T15:05:43Z Message: Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-01-09T15:05:43Z Message: Reason: ReconciliationSucceeded Status: True Type: Reconciled Controller Name: networking.gke.io/gateway Parent Ref: Group: gateway.networking.k8s.io Kind: Gateway Name: internal-http ...
게이트웨이의
Accepted
조건이True
이면 HTTPRoute가 게이트웨이에 성공적으로 바인딩된 것입니다. 상태 필드에 관한 자세한 내용은 경로 상태를 참조하세요.게이트웨이에 대한 트래픽이 올바르게 라우팅되는지 확인합니다.
curl -H "host: site.example.com" GATEWAY_IP_ADDRESS curl -H "host: store.example.com" GATEWAY_IP_ADDRESS
GATEWAY_IP_ADDRESS
를 내부 게이트웨이의 IP 주소로 바꿉니다.게이트웨이와 동일한 VPC에서 가상 머신(VM)을 사용해야 합니다.
출력은 다음과 비슷합니다.
{ "cluster_name": "CLUSTER_NAME", "host_header": "site.example.com", "metadata": "site-v1", "pod_name": "site-v1-5d64fc4d7d-fz6f6", "pod_name_emoji": "👩🏼🍳", "project_id": "PROJECT_ID", "timestamp": "2022-11-02T19:07:01", "zone": "ZONE_NAME" } ... { "cluster_name": "CLUSTER_NAME", "host_header": "store.example.com", "metadata": "store-v1", "pod_name": "store-v1-6d8d58d78-vz8pn", "pod_name_emoji": "🧝🏻♂️", "project_id": "PROJECT_ID", "timestamp": "2022-11-02T19:07:01", "zone": "ZONE_NAME" }
이 출력은
site.example.com
호스트 헤더가 있는 요청이site-v1
서비스에 도달하고store.example.com
호스트 헤더가 있는 요청이store-v1
서비스에 도달함을 나타냅니다.
네트워크 등급 구성
게이트웨이 정의의 addresses[]
배열 내에서 type
필드를 사용하여 리전 외부 애플리케이션 부하 분산기의 리스너 주소에 대한 네트워크 등급을 지정할 수 있습니다. 네트워크 등급을 지정하지 않으면 게이트웨이는 기본적으로 표준 등급 임시 IP 주소를 사용합니다.
type
필드에는 다음 값을 사용합니다.
networking.gke.io/premium-ephemeral-ipv4-address
: Premium 등급 IP 주소를 할당합니다.networking.gke.io/standard-ephemeral-ipv4-address
: 표준 등급 IP 주소를 할당합니다.
두 네트워크 계층에서 IP 주소를 할당하려면 addresses
필드에 두 유형을 모두 지정합니다.
다음 예시에서는 게이트웨이에 프리미엄 등급 IP 주소를 할당하는 방법을 보여줍니다. Google Cloud 표준 등급 IP 주소를 프로비저닝하려면 networking.gke.io/standard-ephemeral-ipv4-address
를 사용하세요.
다음 샘플 매니페스트를
external-regional-http.yaml
로 저장합니다.kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-regional-http spec: # Name of an existing GatewayClass. gatewayClassName: gke-l7-regional-external-managed # Listen for HTTPS traffic on port 443. listeners: - name: https protocol: HTTPS port: 443 tls: # Terminate the TLS session with the client at the Gateway. mode: Terminate # Certificates for the Gateway to use to create a new TLS session. certificateRefs: - name: store-example-com addresses: # Request a Premium Tier ephemeral IPv4 address for the Gateway. - type: networking.gke.io/premium-ephemeral-ipv4-address
샘플 매니페스트를 적용합니다.
kubectl apply -f external-regional-http.yaml
게이트웨이 기본 백엔드 구성
모든 gke-l7-*
GatewayClasses는 일치하지 않는 트래픽에 HTTP 404를 반환합니다. 일치하지 않는 트래픽을 사용자가 제공한 서비스로 전송하는 명시적인 기본 경로를 사용하여 기본 백엔드를 구성할 수 있습니다.
게이트웨이는 명시적 백엔드 정의 없이 404(찾을 수 없음) 및 500(서버 오류)과 같은 오류 코드를 처리하도록 구성됩니다. 기본 동작은 게이트웨이 구현마다 다를 수 있습니다. 오류 처리를 더 세부적으로 제어하기 위해서는 커스텀 백엔드 구성을 고려하세요.
다음 HTTPRoute는 기본 백엔드를 맞춤설정하는 방법에 대한 예시입니다. 다음과 유사한 HTTPRoute를 적용하면 암시적 기본 백엔드보다 우선 적용됩니다.
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: custom-default-backend
spec:
parentRefs:
- kind: Gateway
name: my-internal-gateway
# Omit the `hostnames` field to route all unmatched traffic from the
# attached Gateway.
rules:
- backendRefs:
- name: my-custom-default-backend-service
port: 8080
이 HTTPRoute는 특정 게이트웨이에서 모든 일치하는 트래픽을 선택합니다. 게이트웨이마다 이러한 규칙 하나만 포함할 수 있습니다. 그렇지 않으면 규칙이 충돌하여 우선순위 순서가 적용됩니다.
기본 백엔드를 사용하여 누군가 모든 게이트웨이 트래픽을 라우팅하는 기본 경로 백엔드를 만들지 못하게 할 수 있습니다. 명시적 HTTPRoute는 라우팅 규칙이 충돌하는 새 HTTPRoute보다 항상 우선 적용됩니다.
게이트웨이의 고정 IP 주소 구성
모든 게이트웨이에는 트래픽을 리슨하는 데 사용하는 IP 주소가 있습니다. 게이트웨이에 IP 주소를 지정하지 않으면 게이트웨이 컨트롤러가 자동으로 IP 주소를 제공합니다. 또한 IP 주소가 게이트웨이 수명 주기와 독립적으로 존재하도록 고정 IP 주소를 만들 수도 있습니다.
게이트웨이가 배포된 다음에는 해당 IP 주소가 상태 필드에 표시됩니다.
kind: Gateway
...
status:
addresses:
- value: 10.15.32.3
GatewayClass에 따라 IP 주소가 다음 서브넷에서 할당됩니다.
GatewayClass | 기본 IP 주소 풀 |
---|---|
|
기본 노드 IPv4/IPv6 주소 범위의 리전 비공개 IP 주소 |
|
Google 리전 외부 IPv4/IPv6 범위의 리전 공개 IP 주소 |
|
Google 전역 외부 IPv4/IPv6 범위의 전역 공개 IP 주소 |
addresses.NamedAddress
필드를 사용하면 게이트웨이와 독립적으로 IP 주소를 지정할 수 있습니다. 게이트웨이 배포 전 고정 IP 주소 리소스를 만들 수 있으며, 리소스는 NamedAddress
로 참조됩니다. 게이트웨이가 삭제된 경우에도 고정 IP 주소를 다시 사용할 수 있습니다.
이름이 지정된 IP 주소 사용
NamedAddress
를 지정하여 IPv4 또는 IPv6 주소를 구성할 수 있습니다. 게이트웨이를 만들기 전에 고정 IP 주소를 프로비저닝해야 합니다.
고정 IP 주소 리소스를 만듭니다.
gcloud compute addresses create IP_ADDRESS_NAME \ --purpose=SHARED_LOADBALANCER_VIP \ --region=COMPUTE_REGION \ --subnet=SUBNET \ --project=PROJECT_ID
다음을 바꿉니다.
IP_ADDRESS_NAME
: 새 고정 IP 주소의 이름입니다.COMPUTE_REGION
: 리전 게이트웨이의 경우 클러스터가 실행되는 Compute Engine 리전입니다. 전역 외부 게이트웨이에는 이 플래그가 필요하지 않습니다.SUBNET
: IP 주소의 서브넷입니다. 전역 외부 게이트웨이에는 이 플래그가 필요하지 않습니다.PROJECT_ID
: GKE 클러스터가 실행되는 프로젝트입니다.
다음 매니페스트를
named-ip-gateway.yaml
이라는 파일에 저장합니다.kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-http spec: gatewayClassName: gke-l7-rilb listeners: - name: http protocol: HTTP port: 80 addresses: - type: NamedAddress value: IP_ADDRESS_NAME
이 매니페스트는 명명된 IP 주소를 참조하는 게이트웨이를 설명합니다.
매니페스트를 클러스터에 적용합니다.
kubectl apply -f named-ip-gateway.yaml
게이트웨이 IP 주소를 확인합니다.
kubectl describe gateway internal-http
출력은 다음과 비슷합니다.
Name: internal-http Namespace: default Labels: <none> ... Spec: Addresses: Type: NamedAddress Value: IP_ADDRESS_NAME Gateway Class Name: gke-l7-rilb Listeners: Allowed Routes: Namespaces: From: Same Name: http Port: 80 Protocol: HTTP Status: Addresses: Type: IPAddress Value: 10.15.32.103
HTTP-HTTPS 간 리디렉션 구성
Cloud Load Balancing은 HTTP-HTTPS 간 리디렉션 기능을 제공합니다. 외부 애플리케이션 부하 분산기는 암호화되지 않은 HTTP 요청을 동일한 IP 주소를 사용하는 HTTPS 부하 분산기로 리디렉션할 수 있습니다. HTTP-HTTPS 간 리디렉션을 사용 설정한 게이트웨이를 만들면 두 부하 분산기 모두 자동으로 생성됩니다. 포트 80에서 게이트웨이의 외부 IP 주소에 대한 요청은 포트 443에서 동일한 외부 IP 주소로 자동 리디렉션됩니다.
기본적으로 HTTP-HTTPS 간의 리디렉션은 게이트웨이에 정의되지 않습니다.
HTTP 트래픽을 HTTPS로 리디렉션하려면 HTTP 및 HTTPS 트래픽을 모두 처리하도록 게이트웨이를 구성합니다. HTTP 또는 HTTPS를 사용 중지할 경우 게이트웨이가 트래픽을 리디렉션하지 않습니다.
다음 예시에서는 클라이언트에서 웹 애플리케이션으로 이동하는 트래픽이 항상 보안 페이지로 리디렉션되도록 하는 수단으로 HTTP-HTTPS 간 리디렉션을 사용하는 방법을 보여줍니다.
HTTP-HTTPS 간 리디렉션은 gke-l7-gxlb
및 gke-l7-gxlb-mc
GatewayClass에서 지원되지 않습니다. 각 GatewayClass에서 지원되는 다양한 기능에 대한 자세한 내용은 GatewayClass 기능을 참조하세요.
인프라 네임스페이스에서 HTTP 트래픽 리디렉션
경우에 따라 인프라 또는 플랫폼 관리팀과 애플리케이션팀 간의 역할 구분이 명확하지 않아, 게이트웨이 오용을 방지하는 데 어려움이 있을 수 있습니다.
다음 예시에서는 애플리케이션 팀이 비보안 프로토콜을 의도치 않게 사용하는 것을 방지하기 위해 HTTP 리스너 사용을 추가로 제한합니다. 이 예시에서는 otherInfra: httpToHttps
라벨이 있는 네임스페이스에 경로가 있는 경우에만 HTTPRoute가 HTTP 리스너를 사용하도록 게이트웨이를 구성합니다. 하지만 게이트웨이는 모든 네임스페이스의 HTTPRoute가 HTTPS 리스너를 사용하도록 허용합니다. Kubernetes RBAC를 통해 http-redirect 네임스페이스를 제한하여 애플리케이션팀이 실수로 이 네임스페이스에 HTTPRoute를 생성하지 못하게 할 수 있습니다.
게이트웨이의 네임스페이스를 만듭니다. 매니페스트를
gateway-namespace.yaml
로 저장합니다.apiVersion: v1 kind: Namespace metadata: name: gateway-infra
매니페스트를 적용합니다.
kubectl apply -f gateway-namespace.yaml
게이트웨이의 네임스페이스를 만들고 매니페스트를
redirect-namespace.yaml
으로 저장합니다.apiVersion: v1 kind: Namespace metadata: name: http-redirect labels: otherInfra: httpToHttps
이
http-redirect
네임스페이스에는otherInfra: httpToHttps
라벨이 있습니다.매니페스트를 적용합니다.
kubectl apply -f redirect-namespace.yaml
http 리스너 사용을 제한하려면 다음 매니페스트를 사용하여 게이트웨이를 만듭니다. 매니페스트를
external-gateway.yaml
로 저장합니다.kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http namespace: gateway-infra spec: # Name of an existing GatewayClass. gatewayClassName: gke-l7-global-external-managed listeners: - name: http protocol: HTTP port: 80 # Allow only HTTPRoutes from namespaces that have the # `otherInfra: httpToHttps` label to use this listener. allowedRoutes: kinds: - kind: HTTPRoute namespaces: from: Selector selector: matchLabels: otherInfra: httpToHttps - name: https protocol: HTTPS port: 443 # Allow HTTPRoutes from any namespace to use this listener. allowedRoutes: kinds: - kind: HTTPRoute namespaces: from: All tls: mode: Terminate options: networking.gke.io/pre-shared-certs: store-example-com
namespace
필드는 게이트웨이가gateway-infra
네임스페이스에 생성되도록 지정합니다.allowedRoutes
섹션의namespaces
필드는 http 리스너를otherInfra: httpToHttps
라벨과 일치하는 네임스페이스로 제한합니다.
매니페스트를 적용합니다.
kubectl apply -f external-gateway.yaml
HTTPS 리디렉션을 강제 적용하려면 다음 매니페스트를 사용하여 기본 HTTPRoute를 만드세요. 매니페스트를
http-redirect.yaml
로 저장합니다.kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: redirect # Create the HTTPRoute in the `http-redirect` namespace. namespace: http-redirect spec: # Attach the HTTPRoute to the `http` listener in the `external-http` # Gateway. parentRefs: - namespace: gateway-infra name: external-http sectionName: http rules: # Respond to the request with an HTTPS redirection. - filters: - type: RequestRedirect requestRedirect: scheme: https
sectionName
필드는 게이트웨이가 http 리스너에서만 일치하도록 지시합니다.RequestRedirect
필터는 https 리스너로 강제 리디렉션합니다.
매니페스트를 적용합니다.
kubectl apply -f http-redirect.yaml
다음 매니페스트를 사용하여 애플리케이션의 서비스를 만듭니다. 매니페스트를
service-deployment.yaml
로 저장합니다.apiVersion: v1 kind: Service metadata: name: store-v1 spec: selector: app: store version: v1 ports: - port: 8080 targetPort: 8080 --- apiVersion: apps/v1 kind: Deployment metadata: name: store-v1 spec: replicas: 2 selector: matchLabels: app: store version: v1 template: metadata: labels: app: store version: v1 spec: containers: - name: whereami image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1 ports: - containerPort: 8080 env: - name: METADATA value: "store-v1"
매니페스트를 적용합니다.
kubectl apply -f service-deployment.yaml
다음 매니페스트를 사용하여 HTTPS만 허용하는 애플리케이션에 대한 HTTPRoute를 만듭니다. 매니페스트를
http-route.yaml
로 저장합니다.kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-external labels: gateway: external-http spec: # Attach the HTTPRoute to the HTTPS listener in the `external-http` # Gateway. parentRefs: - name: external-http namespace: gateway-infra sectionName: https # Match requests that have the `store.example.com` Host header. hostnames: - "store.example.com" # Route requests to the `store-v1` Service. rules: - backendRefs: - name: store-v1 port: 8080
매니페스트를 적용합니다.
kubectl apply -f http-route.yaml
경로 리디렉션 및 URL 재작성 구성
경로 리디렉션에는 한 URL 경로에서 다른 URL 경로로 들어오는 요청을 리디렉션하는 작업이 포함됩니다. 경로 리디렉션을 사용하면 오래되었거나 지원 중단된 URL을 처리해야 할 경우에 URL 구조를 변경할 수 있습니다.
URL 재작성을 사용하면 서버에서 처리하기 전 수신 URL을 수정할 수 있습니다. 기본 콘텐츠나 파일 구조를 실제로 변경하지 않고도 URL의 구조나 형식을 변경할 수 있습니다. URL 재작성은 기억하기 쉽고 이해하기 쉬운 사용자 친화적이고 검색엔진 최적화 친화적인 URL을 만드는 데 유용합니다. 기본적으로 경로 리디렉션 및 URL 재작성은 구성되지 않으므로 HTTPRoute의 필터를 사용하여 해당 리디렉션 또는 재작성을 명시적으로 구성해야 합니다.
GKE 게이트웨이는 경로 리디렉션과 URL 재작성을 지원합니다. 자세한 내용은 HTTP 경로 리디렉션 및 재작성을 참조하세요.
경로 리디렉션 구성
전체 경로를 바꾸거나 URL에서 프리픽스만 바꾸도록 경로 리디렉션을 구성할 수 있습니다.
전체 경로 바꾸기
전체 경로를 바꾸려면 URL 경로에 프리픽스
/any-path
가 포함된 모든 URL을 엄격한 값/new-path
로 바꾸는 HTTPRoute에서 필터를 구성합니다.다음과 같이
HTTPRoute
매니페스트를 만들고 이름을store.yaml
로 지정합니다.apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: store spec: parentRefs: - kind: Gateway name: external-http hostnames: - store.example.com rules: - matches: - path: # Match requests by a prefix, like `/any-path` and `/any-path/home`. type: PathPrefix value: /any-path filters: - type: RequestRedirect requestRedirect: path: # Replace the full path with `/new-path`. For example, both # `/any-path/home` and `/any-path` become `/new-path`. type: ReplaceFullPath replaceFullPath: /new-path statusCode: 302
예를 들어 이 매니페스트는 HTTPRoute의 라우팅 규칙을 다음과 같이 설정합니다.
https://store.example.com/any-path/...
URL 경로로 들어오는 모든 요청은 새 위치인https://store.example.com/new-path/
로 엄격(stric)하게 리디렉션됩니다.매니페스트를 적용합니다.
kubectl apply -f store.yaml
이 라우팅 규칙은 엄격한 리디렉션 규칙을 따릅니다. 즉, 브라우저가 리디렉션을 캐시하려고 시도하지 않고 대신 최신 버전으로 리디렉션합니다.
프리픽스만 바꾸기
프리픽스만 바꾸려면 URL 경로의 프리픽스
/any-prefix
가 포함된 모든 URL을 엄격한 값/new-prefix
로 바꾸는 HTTPRoute에서 필터를 구성합니다.다음과 같이
HTTPRoute
매니페스트를 만들고 이름을store.yaml
로 지정합니다.apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: store spec: parentRefs: - kind: Gateway name: external-http hostnames: - store.example.com rules: - matches: - path: # Match requests by prefix, like `/any-prefix` and # `/any-prefix/home`. type: PathPrefix value: /any-prefix filters: - type: RequestRedirect requestRedirect: path: # Replace the matched prefix with `/new-prefix`. For example, # `/any-prefix` becomes `/new-prefix` and `/any-prefix/home` # becomes `/new-prefix/home`. type: ReplacePrefixMatch replacePrefixMatch: /new-prefix statusCode: 302
예를 들어 이 매니페스트는 HTTPRoute의 라우팅 규칙을 다음과 같이 설정합니다.
https://store.example.com/any-path/v1/...
URL로 들어오는 모든 요청은 새 위치인https://store.example.com/new-path/v1/...
으로만(only) 리디렉션됩니다.매니페스트를 적용합니다.
kubectl apply -f store.yaml
이 라우팅 규칙은 리디렉션 규칙만 따르므로 브라우저에서 항상 사용자를 동일한 의도된 페이지로 리디렉션합니다.
URL 재작성 구성
URL이 사용자에게 표시되는 방법을 변경하도록 URL 재작성을 설정합니다. URL 재작성을 사용하여 URL을 더 사용자 친화적으로 만들거나 검색엔진 최적화를 개선하거나 사용자를 새 페이지로 리디렉션할 수 있습니다.
전체 호스트 이름 재작성
전체 호스트 이름을 재작성하려면 다음 안내를 따르세요.
요청을 백엔드 서비스로 전달하기 전 요청 헤더의
Host
정보를www.example.com
에서store.example.com
으로 바꾸도록 게이트웨이에 지시하는 HTTPRoute 필터를 구성합니다.다음과 같이
HTTPRoute
매니페스트를 만들고 이름을www.yaml
로 지정합니다.apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: www spec: parentRefs: - kind: Gateway name: external-http hostnames: - www.example.com rules: - filters: - type: URLRewrite # Replace the hostname in the URL with `store.example.com`. urlRewrite: hostname: store.example.com backendRefs: - name: store-v1 port: 8080
예를 들어 위 구성에서는
https://www.example.com
으로 들어오는 모든 요청이Host: www.example.com
대신Host: store.example.com
헤더와 함께 백엔드 서비스로 전달됩니다.매니페스트를 적용합니다.
kubectl apply -f www.yaml
경로 수정자를 사용하여 재작성
재작성을 경로 수정자와 결합하여 백엔드 서비스에 요청을 릴레이하기 전에 고급 URL 및 경로 수정을 제공할 수 있습니다.
경로 수정자를 사용하여 재작성하려면 다음 안내를 따르세요.
HTTPRoute에 필터를 구성하여, 게이트웨이가 요청 헤더의 "Host" 정보를 www.example.com에서
to store.example.com
으로 변경하고, 요청 경로에서/store
를/
로 바꾼 뒤 백엔드 서비스로 전달하도록 설정합니다.다음과 같이
HTTPRoute
매니페스트를 만들고 이름을www.yaml
로 지정합니다.apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: www spec: parentRefs: - kind: Gateway name: external-http hostnames: - www.example.com rules: - matches: - path: type: PathPrefix value: /store filters: - type: URLRewrite # For URLs that have `/store` in the path, replace the hostname with # store.example.com and replace the `/store` prefix with `/de`. urlRewrite: hostname: store.example.com path: type: ReplacePrefixMatch replacePrefixMatch: /de backendRefs: - name: store-german port: 8080
예를 들어 위 구성에서는
https://www.example.com/store/...
로 들어오는 모든 요청이 요청 헤더에Host: www.example.com
대신Host: store.example.com
이 설정된 상태로 백엔드 서비스로 전달되며, 경로의/store
는/de
로 재작성됩니다.매니페스트를 적용합니다.
kubectl apply -f www.yaml
구성을 확인합니다
URL 재작성 또는 경로 리디렉션 필터를 사용하여 HTTPRoute를 만든 후 필터가 적용되었는지 확인하려면 다음을 수행합니다.
kubectl get httproute www -o yaml
출력은 다음과 비슷합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"gateway.networking.k8s.io/v1","kind":"HTTPRoute","metadata":{"annotations":{},"name":"www","namespace":"default"},"spec":{"hostnames":["www.example.com"],"parentRefs":[{"kind":"Gateway","name":"external-http"}],"rules":[{"backendRefs":[{"name":"store-german","port":8080}],"filters":[{"type":"URLRewrite","urlRewrite":{"hostname":"store.example.com","path":{"replacePrefixMatch":"/de","type":"ReplacePrefixMatch"}}}],"matches":[{"path":{"type":"PathPrefix","value":"/store"}}]}]}}
creationTimestamp: "2023-06-22T01:00:42Z"
generation: 3
name: www
namespace: default
resourceVersion: "51268631"
uid: e516493e-806d-44d6-ae0d-1c9ff25682cf
spec:
hostnames:
- www.example.com
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: external-http
rules:
- backendRefs:
- group: ""
kind: Service
name: store-german
port: 8080
weight: 1
filters:
- type: URLRewrite
urlRewrite:
hostname: store.example.com
path:
replacePrefixMatch: /de
type: ReplacePrefixMatch
matches:
- path:
type: PathPrefix
value: /store
status:
parents:
- conditions:
- lastTransitionTime: "2023-06-22T01:11:26Z"
message: ""
observedGeneration: 2
reason: Accepted
status: "True"
type: Accepted
- lastTransitionTime: "2023-06-22T01:11:26Z"
message: ""
observedGeneration: 2
reason: ReconciliationSucceeded
status: "True"
type: Reconciled
controllerName: networking.gke.io/gateway
parentRef:
group: gateway.networking.k8s.io
kind: Gateway
name: external-http
더 많은 세부정보를 확인하려면 describe 명령어를 사용합니다.
kubectl describe httproute
커스텀 요청 및 응답 헤더 구성
커스텀 요청 및 응답 헤더를 사용하면 HTTP(S) 요청 및 응답에 대해 추가 헤더를 지정할 수 있습니다. 부하 분산기에서 감지된 정보에 따라 헤더에는 다음 정보가 포함될 수 있습니다.
- 클라이언트에 대한 지연 시간
- 클라이언트 IP 주소의 지리적 위치
- TLS 연결 매개변수
기본적으로 백엔드 서비스와 주고받는 요청에 추가된 커스텀 헤더가 없으므로 HTTPRoute의 필터를 사용하여 커스텀 헤더를 명시적으로 구성해야 합니다.
다음과 같이 HTTPRoute 규칙에 필터 섹션을 추가하여 커스텀 헤더를 구성할 수 있습니다.
커스텀 요청 헤더 구성
RequestHeaderModifier 필터로 HTTPRoute 매니페스트를 만들고 http-route-request.yaml:
로 저장합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: store
spec:
<...>
rules:
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
<...>
매니페스트를 적용합니다.
kubectl apply -f http-route-request.yaml
커스텀 응답 헤더 구성
ResponseHeaderModifier 필터를 사용하여 HTTPRoute 매니페스트를 만들고 이를 http-route-response.yaml:
로 저장합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: store
spec:
<...>
rules:
filters:
- type: ResponseHeaderModifier
responseHeaderModifier:
<...>
매니페스트를 적용합니다.
kubectl apply -f http-route-response.yaml
Gateway API 구현에 설명된 대로 헤더를 추가, 설정, 삭제할 수 있습니다. Google Cloud 지원 변수를 사용하여 커스텀 헤더로 HTTPRoute를 구성할 수 있습니다.
예시 1:
클라이언트 위치 정보를 백엔드 서비스로 보내기 전에 HTTP 요청에 추가하는 HTTPRoute를 구성하려면 HTTPRoute 매니페스트를 만들고 이름을 external-http-request.yaml
로 지정합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: store
spec:
parentRefs:
- kind: Gateway
name: external-http
hostnames:
- store.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /fr
filters:
# Add custom headers to requests that have `/fr` in the path.
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: X-Client-Geo-Location
value: "{client_region},{client_city}"
backendRefs:
- name: store-french
port: 8080
예를 들어 프랑스 스트라스부르에 있는 클라이언트의 경우 게이트웨이는 헤더를 X-Client-Geo-Location:FR,Strasbourg
로 추가합니다.
예시 2:
HTTP Strict Transport Security를 지원하기 위해 커스텀 응답 헤더를 추가하는 HTTPRoute를 구성하려면 HTTPRoute 매니페스트를 만들고 이름을 external-http-response.yaml
로 지정합니다.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: store
spec:
parentRefs:
- kind: Gateway
name: external-http
hostnames:
- store.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /de
filters:
# Add custom headers to responses to requests that have `/de` in the
# path.
- type: ResponseHeaderModifier
responseHeaderModifier:
add:
- name: Strict-Transport-Security
value: max-age=63072000
backendRefs:
- name: store-german
port: 8080
구성을 확인합니다
커스텀 요청 및 응답 헤더를 구성한 후 구성을 확인하려면 다음을 수행합니다.
kubectl get httproute
출력은 다음과 비슷합니다.
NAME HOSTNAMES AGE store ["store.example.com"] 4d23h
더 많은 세부정보를 확인하려면 describe 명령어를 사용합니다.
kubectl describe httproute
출력은 다음과 비슷합니다.
Name: store Namespace: default Labels: <none> Annotations: <none> API Version: gateway.networking.k8s.io/v1 Kind: HTTPRoute Metadata: Creation Timestamp: 2023-05-27T00:51:01Z Generation: 5 Resource Version: 25418887 UID: 2e07a1b8-420b-41b4-acd1-cecbfcd39f42 Spec: Hostnames: store.example.com Parent Refs: Group: gateway.networking.k8s.io Kind: Gateway Name: external-http Rules: Backend Refs: Group: Kind: Service Name: store-v1 Port: 8080 Weight: 1 Matches: Path: Type: PathPrefix Value: / Backend Refs: Group: Kind: Service Name: store-v2 Port: 8080 Weight: 1 Matches: Headers: Name: env Type: Exact Value: canary Path: Type: PathPrefix Value: / Backend Refs: Group: Kind: Service Name: store-german Port: 8080 Weight: 1 Filters: Request Header Modifier: Add: Name: X-Client-Geo-Location Value: {client_region},{client_city} Type: RequestHeaderModifier Matches: Path: Type: PathPrefix Value: /de Status: <...>
경로 상태
HTTPRoute 리소스는 HTTPRoute가 하나 이상의 게이트웨이와 성공적으로 바인딩되었는지 또는 거부되었는지를 사용자가 이해할 수 있도록 조건 및 이벤트를 방출합니다.
HTTPRoute 조건
HTTPRoute 조건은 경로가 바인딩된 게이트웨이와 경로의 상태를 나타냅니다. 경로를 여러 게이트웨이에 바인딩할 수 있기 때문에 이것은 경로와 각 게이트웨이 사이의 개별 조건과 게이트웨이 목록입니다.
Accepted=True
는 HTTPRoute가 게이트웨이에 성공적으로 바인딩되었음을 나타냅니다.Accepted=False
는 HTTPRoute가 이 게이트웨이와의 바인딩에서 거부되었음을 나타냅니다.
Gateway bindings
제목 아래에 게이트웨이가 없으면 HTTPRoute 라벨과 게이트웨이 라벨 선택기가 일치하지 않을 수 있습니다. 이 문제는 게이트웨이에서 경로를 선택하지 않은 경우에 발생할 수 있습니다.
HTTPRoute 이벤트
HTTPRoute 이벤트는 HTTPRoute 상태에 대한 세부정보를 제공합니다. 이벤트는 다음과 같은 이유로 그룹화됩니다.
ADD
이벤트는 추가되는 리소스에 의해 트리거됩니다.UPDATE
이벤트는 업데이트되는 리소스에 의해 트리거됩니다.SYNC
이벤트는 정기적인 조정으로 트리거됩니다.
경로 병합, 우선순위, 검증
경로 우선순위
Gateway API는 겹쳐진 라우팅 규칙을 갖는 경로에서 트래픽이 선택되는 방법에 대해 엄격한 우선순위 규칙을 정의합니다. 두 가지 겹치는 HTTPRoute 사이의 우선순위는 다음과 같습니다.
- 호스트 이름 병합: 가장 길고 가장 구체적인 호스트 이름이 선택됩니다.
- 경로 병합: 가장 길고 가장 구체적인 경로가 선택됩니다.
- 헤더 병합: 일치하는 가장 큰 수의 HTTP 헤더입니다.
- 충돌: 위 3개 규칙에 따라 우선순위가 결정되지 않으면 가장 오래된 타임스탬프의 HTTPRoute 리소스가 우선 적용됩니다.
경로 병합
gke-l7
GatewayClass의 경우 지정된 게이트웨이에 대한 모든 HTTPRoute가 동일한 URL 맵 리소스에 병합됩니다. HTTPRoute가 병합되는 방법은 HTTPRoute 사이의 겹침 유형에 따라 달라집니다. 이전 예시의 HTTPRoute를 3개의 개별 HTTPRoute로 분할하여 경로 병합 및 우선순위를 나타낼 수 있습니다.
- 경로 병합: 3개 HTTPRoute 모두 동일한
internal-http
게이트웨이와 연결되어 함께 병합됩니다. - 호스트 이름 병합: 3개 경로 모두
store.example.com
과 일치하여, 해당 호스트 이름 규칙이 병합됩니다. - 경로 병합: store-german-route에 보다 구체적인 경로
/de
가 포함되므로, 이것은 추가로 병합되지 않습니다. store-v1-route 및 store-v2-route는 모두 동일한/*
경로에서 일치하므로, 해당 경로로 병합됩니다. - 헤더 병합: store-v2-route는 store-v1-route보다 더 구체적인 HTTP 헤더 일치 집합을 가지므로, 추가로 병합되지 않습니다.
- 충돌: 경로가 호스트 이름, 경로, 헤더로 병합될 수 있기 때문에 충돌이 없고, 모든 경로 규칙이 트래픽에 적용됩니다.
앞의 예시에 사용된 단일 HTTPRoute는 이러한 3개의 개별 경로와 동일합니다.
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: store-v1-route
spec:
parentRefs:
- kind: Gateway
name: internal-http
hostnames:
- "store.example.com"
rules:
- backendRefs:
- kind: Service
name: store-v1
port: 8080
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: store-v2-route
spec:
parentRefs:
- kind: Gateway
name: internal-http
hostnames:
- "store.example.com"
rules:
- matches:
- headers:
- type: Exact
name: env
value: canary
backendRefs:
- kind: Service
name: store-v2
port: 8080
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: store-german-route
spec:
parentRefs:
- kind: Gateway
name: internal-http
hostnames:
- "store.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /de
backendRefs:
- kind: Service
name: store-german
port: 8080
Kubernetes 게이트웨이 및 Istio 게이트웨이
Kubernetes Gateway API와 Istio API에는 모두 Gateway
라는 리소스가 있습니다. 비슷한 기능을 실행하지만 동일한 리소스는 아닙니다. Istio와 Gateway API를 동일한 Kubernetes 클러스터에서 사용하는 경우 이러한 이름은 명령줄에서 kubectl을 사용할 때 겹칠 수 있습니다.
kubectl get gateway
는 Istio 게이트웨이 리소스가 아닌 Kubernetes 게이트웨이 리소스를 반환할 수 있으며 그 반대의 경우도 마찬가지입니다.
$ kubectl api-resources
NAME SHORTNAMES APIGROUP NAMESPACED KIND
gateways gw networking.istio.io/v1beta1 true Gateway
gateways gtw networking.k8s.io/v1beta1 true Gateway
Istio를 사용하고 GKE 1.20 이상으로 업그레이드하는 경우 게이트웨이 리소스 별칭 사용하거나 API 그룹을 지정하는 것이 좋습니다. Kubernetes 게이트웨이의 별칭은 gtw
이며 Istio 게이트웨이의 별칭은 gw
입니다. 다음 명령어는 각각 Kubernetes 게이트웨이 및 Istio 게이트웨이 리소스를 반환합니다.
# Kubernetes Gateway
$ kubectl get gtw
NAME CLASS
multi-cluster-gateway gke-l7-global-external-managed-mc
$ kubectl get gateway.networking.x-k8s.io
NAME CLASS
multi-cluster-gateway gke-l7-global-external-managed-mc
# Istio Gateway
$ kubectl get gw
NAME AGE
bookinfo-gateway 64m
$ kubectl get gateway.networking.istio.io
NAME AGE
bookinfo-gateway 64m
문제 해결
리전에서 프록시 전용 서브넷 누락
증상:
리전 게이트웨이(내부 또는 외부)를 만들 때 다음 문제가 발생할 수 있습니다.
generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/[REGION_NAME]/targetHttpProxies/gkegw-x5vt-default-internal-http-[ID]'. A reserved managed proxy subnetwork with purpose REGIONAL_MANAGED_PROXY is required.
이유:
이 오류 메시지는 게이트웨이에 대한 리전에 프록시 전용 서브넷이 없음을 나타냅니다.
해결 방법:
이 문제를 해결하려면 프록시 전용 서브넷을 배포합니다.
프록시 전용 서브넷이 잘못된 용도로 리전에 이미 있습니다.
증상:
리전 게이트웨이(내부 또는 외부)에 대한 프록시 전용 서브넷을 만들 때 다음 문제가 발생할 수 있습니다.
ERROR: (gcloud.compute.networks.subnets.create) Could not fetch resource:
- The resource 'projects/[PROJECT_NAME]/regions/[REGION_NAME]/subnetworks/[PROXY_ONLY_SUBNET_NAME]' already exists
이유:
이 오류 메시지는 프록시 전용 서브넷이 이미 있는 리전에 리전별 프록시 전용 서브넷을 만들려고 시도했음을 나타냅니다.
해결 방법:
이 문제를 해결하려면 다음을 단계를 사용해 보세요.
프록시 전용 서브넷이 리전에 이미 있는지 확인하고 올바른 목적을 가지고 있는지 확인합니다.
서브넷을 나열하여 리전에 있는 프록시 전용 서브넷을 찾습니다.
gcloud compute networks subnets list --regions=COMPUTE_REGION
COMPUTE_REGION
을 리전 게이트웨이를 만들려는 Compute Engine 리전으로 바꿉니다.해당 리전의 프록시 전용 서브넷을 설명하여 그 용도를 찾습니다.
gcloud compute networks subnets describe PROXY_ONLY_SUBNET \ --region COMPUTE_REGION | grep -E 'name|purpose'
PROXY_ONLY_SUBNET
을 프록시 전용 서브넷으로 바꿉니다.
GKE 게이트웨이는 리전 게이트웨이(내부 또는 리전)에 대해
REGIONAL_MANAGED_PROXY
프록시 전용 서브넷만 지원합니다.리전의 기존 프록시 전용 서브넷이
INTERNAL_HTTPS_LOAD_BALANCER
목적으로 생성된 경우 해당 목적을REGIONAL_MANAGED_PROXY
로 마이그레이션합니다.
정상 업스트림 없음
증상:
게이트웨이를 만들 때 백엔드 서비스에 액세스할 수 없는 경우 다음 문제가 발생할 수 있습니다(503 응답 코드).
no healthy upstream
이유:
이 오류 메시지는 상태 점검 프로버가 정상 백엔드 서비스를 찾을 수 없음을 나타냅니다. 백엔드 서비스가 정상일 수 있지만 상태 점검을 맞춤설정해야 할 수도 있습니다.
해결 방법:
이 문제를 해결하려면 HealthCheckPolicy
를 사용하여 애플리케이션 요구사항(예: /health
)에 따라 상태 점검을 맞춤설정합니다.
다음 단계
- 게이트웨이 컨트롤러 자세히 알아보기
- 정책을 사용한 게이트웨이 리소스 구성 방법 알아보기
- Gateway API 문서에서 다른 게이트웨이 구성 알아보기