게이트웨이 배포


이 페이지에서는 인그레스 트래픽의 부하 분산을 위해 단일 Google Kubernetes Engine(GKE) 클러스터에 Kubernetes 게이트웨이 리소스를 배포하는 방법을 설명합니다.

여러 클러스터(또는 Fleet)에 인그레스 트래픽을 부하 분산하기 위한 게이트웨이를 배포하려면 멀티 클러스터 게이트웨이 배포를 참조하세요.

시작하기 전에

시작하기 전에 다음 태스크를 수행했는지 확인합니다.

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우 gcloud components update를 실행하여 최신 버전을 가져옵니다.

GKE Gateway Controller 요구사항

  • 표준인 경우 GKE 버전 1.24 이상
  • Autopilot의 경우 GKE 버전 1.26 이상
  • Google Cloud CLI 버전 407.0.0 이상
  • Gateway API는 VPC 기반 클러스터에서만 지원됩니다.
  • 내부 GatewayClasses를 사용하는 경우 프록시 전용 서브넷을 사용 설정해야 합니다.
  • 클러스터에 HttpLoadBalancing 부가기능이 사용 설정되어 있어야 합니다.
  • Istio를 사용하는 경우 Istio를 다음 버전 중 하나로 업그레이드해야 합니다.
    • 1.15.2 이상
    • 1.14.5 이상
    • 1.13.9 이상
  • 공유 VPC를 사용하는 경우 호스트 프로젝트에서 서비스 프로젝트에 대해 GKE 서비스 계정에 Compute Network User 역할을 할당해야 합니다.

제한 및 한도

  • GKE GatewayClasses는 사용하는 부하 분산기에 따라 다양한 기능을 지원합니다. 각 GatewayClass에서 지원되는 다양한 기능에 대한 자세한 내용은 GatewayClass 기능을 참조하세요.

  • 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 게이트웨이 컨트롤러가 지원하는 필드 목록을 보려면 GatewayClass 기능을 참조하세요.

  • GKE 게이트웨이는 와일드 카드, 정규 표현식, 동적 URL을 지원하지 않습니다.

  • 리전별 외부 게이트웨이 클래스로 게이트웨이를 지정하면 컨트롤러는 외부 주소 대신 내부 IP 주소를 프로비저닝합니다. 리전 외부 애플리케이션 부하 분산기에서 이름이 지정된 주소를 사용하는 방법은 리전 외부 게이트웨이 배포를 참조하세요.

  • 게이트웨이는 독립형 NEG를 활용하여 네트워크 엔드포인트 그룹을 프로비저닝합니다. 게이트웨이 컨트롤러가 부하 분산기 구성을 적절히 조정해야 하므로 게이트웨이에 포함된 서비스의 cloud.google.com/neg 주석을 수정할 수는 없습니다.

  • GKE 게이트웨이는 GKE 인그레스에서도 참조되는 서비스 참조를 지원하지 않습니다.

  • IP 주소를 프로비저닝하도록 Gateway를 구성한 경우 Gateway.spec.gatewayClass 변경이 지원되지 않습니다. 게이트웨이 컨트롤러가 부하 분산기를 적절히 조정할 수 있도록 기존 게이트웨이를 삭제하고 gatewayClass 값을 업데이트하여 매니페스트를 다시 배포하세요.

  • networking.gke.io/app-protocols 주석은 지원되지 않습니다. 동일한 결과를 얻으려면 대신 appProtocol 필드를 사용하세요.

클러스터에서 Gateway API 사용 설정

GKE에서 게이트웨이 리소스를 사용하려면 클러스터에서 Gateway API를 사용 설정해야 합니다.

Gateway API가 사용 설정된 새 클러스터 만들기

GKE는 GKE 버전 1.26부터 Autopilot 클러스터에서 Gateway API를 지원합니다. GKE 1.26 이상에서 새 Autopilot 클러스터를 만드는 경우 기본적으로 Gateway API가 사용 설정됩니다. GKE 버전 1.25 이하의 기존 클러스터의 경우 기본적으로 Gateway API가 사용 중지됩니다.

Autopilot

Gateway API가 사용 설정된 새 GKE Autopilot 클러스터 만들기:

  gcloud container clusters create-auto CLUSTER_NAME \
      --location=CLUSTER_LOCATION \
      --release-channel=RELEASE_CHANNEL \
      --cluster-version=VERSION

다음을 바꿉니다.

  • CLUSTER_NAME: 클러스터의 이름
  • CLUSTER_LOCATION: 새 클러스터의 Compute Engine 리전 또는 영역
  • RELEASE_CHANNEL: 출시 채널의 이름
  • VERSION: GKE 버전이며 1.26 이상이어야 함. --release-channel 플래그를 사용하여 출시 채널을 선택할 수도 있습니다. 출시 채널은 기본 버전이 1.26 이상이어야 합니다.

스탠더드

GKE Standard를 사용하면 Gateway API는 --gateway-api 플래그로 제어됩니다. 사용 설정 시 및 사용 중지 시 가치 표준을 사용할 수 있습니다.

Gateway API가 사용 설정된 새 VPC 기반 GKE 클러스터를 만듭니다.

  gcloud container clusters create CLUSTER_NAME \
    --gateway-api=standard \
    --cluster-version=VERSION \
    --location=CLUSTER_LOCATION

다음을 바꿉니다.

  • RELEASE_CHANNEL: 출시 채널의 이름
  • CLUSTER_NAME: 클러스터의 이름
  • VERSION: GKE 버전. 1.24 이상이어야 합니다. --release-channel 플래그를 사용하여 출시 채널을 선택할 수도 있습니다. 출시 채널은 기본 버전이 1.24 이상이어야 합니다.
  • CLUSTER_LOCATION: 새 클러스터의 Compute Engine 리전 또는 영역

--gateway-api=standard 플래그를 사용하면 GKE에서 클러스터에 v1beta1 CRD를 설치합니다.

기존 클러스터에서 Gateway API 사용 설정

Autopilot 클러스터 버전이 1.26 이상이고 Standard 클러스터 버전이 1.24 이상인지 확인합니다.

기존 GKE 클러스터(Autopilot 또는 Standard)에서 Gateway API를 사용 설정하려면 다음을 사용합니다.

gcloud container clusters update CLUSTER_NAME \
    --location=CLUSTER_LOCATION\
    --gateway-api=standard

다음을 바꿉니다.

--gateway-api=standard 플래그를 사용하면 GKE에서 클러스터에 v1beta1 CRD를 설치합니다.

클러스터 확인

클러스터를 만들거나 업그레이드한 후 GKE Gateway 컨트롤러에서 GatewayClasses를 자동으로 설치합니다. 컨트롤러가 CRD를 인식하고 GatewayClasses를 설치하는 데 몇 분 정도 걸릴 수 있습니다.

  1. Gateway API가 GKE 제어 영역에서 사용 설정되었는지 확인합니다.

    gcloud container clusters describe CLUSTER_NAME \
      --location=CLUSTER_LOCATION \
      --format json
    

    출력은 다음과 비슷합니다. 이 출력이 비어 있는 경우 클러스터 업데이트 명령어를 다시 실행합니다.

    "networkConfig": {
      ...
      "gatewayApiConfig": {
        "channel": "CHANNEL_STANDARD"
      },
      ...
    },
    
  2. 클러스터에 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 기능을 참조하세요.

내부 게이트웨이 배포

내부 게이트웨이는 VPC 내에서 또는 VPC에 연결된 네트워크에서만 연결할 수 있는 애플리케이션을 노출합니다.

리전 내부 게이트웨이 배포

다음 예시에서는 특정 지역 리전 내의 서비스 간에 효율적이고 안전한 통신을 사용 설정하는 리전 내부 게이트웨이를 배포하는 방법을 보여줍니다.

프록시 전용 서브넷 구성

내부 애플리케이션 부하 분산기를 사용하는 게이트웨이를 만들기 전에 프록시 전용 서브넷을 구성해야 합니다. 내부 애플리케이션 부하 분산기를 사용하는 VPC의 각 리전에는 프록시 전용 서브넷이 있어야 합니다. 이 서브넷은 부하 분산기 프록시에 내부 IP 주소를 제공합니다.

  1. 프록시 전용 서브넷을 만듭니다.

    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 네트워크의 이름입니다.
    • CIDR_RANGE: 서브넷의 기본 IP 주소 범위입니다. 리전의 프록시에서 64개 이상의 IP 주소를 사용할 수 있도록 /26 이하의 서브넷 마스크를 사용해야 합니다. 권장 서브넷 마스크는 /23입니다.
  2. 프록시 전용 서브넷을 확인합니다.

    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 클러스터의 관리자가 애플리케이션을 내부적으로 노출하기 위해 다른 팀에서 사용될 수 있는 게이트웨이를 만듭니다. 관리자가 게이트웨이를 배포한 후 애플리케이션 팀은 해당 경로를 독립적으로 배포하고 이를 이 게이트웨이에 연결합니다.

  1. 다음 게이트웨이 매니페스트를 gateway.yaml이라는 파일에 저장합니다.

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-http
    spec:
      gatewayClassName: gke-l7-rilb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
    

    이 매니페스트에는 다음 필드가 포함됩니다.

    • gatewayClassName: gke-l7-rilb: 이 게이트웨이가 파생된 GatewayClass를 지정합니다. gke-l7-rilb는 내부 애플리케이션 부하 분산기에 해당합니다.
    • port: 80: 게이트웨이가 HTTP 트래픽을 리슨하기 위해 포트 80만 노출하도록 지정합니다.
  2. 클러스터에 게이트웨이를 배포합니다.

    kubectl apply -f gateway.yaml
    
  3. 게이트웨이가 올바르게 배포되었는지 확인합니다. 모든 리소스를 배포하려면 몇 분 정도 걸릴 수 있습니다.

    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:  1970-01-01T00:00:00Z
        Message:               Waiting for controller
        Reason:                NotReconciled
        Status:                False
        Type:                  Scheduled
    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
    

    이 시점에서는 부하 분산기 및 IP 주소를 프로비저닝한 클러스터에 게이트웨이가 배포됩니다. 게이트웨이에는 경로가 포함되지 않습니다. 하지만 따라서 백엔드에 트래픽을 전송하는 방법을 아직 알 수 없습니다. 경로가 없으면 모든 트래픽이 기본 백엔드로 이동하고, 이것이 HTTP 404를 반환합니다. 그런 후 애플리케이션 및 경로를 배포합니다. 이것은 게이트웨이에 애플리케이션 백엔드를 가져오는 방법을 알려줍니다.

데모 애플리케이션 배포

애플리케이션팀은 게이트웨이의 배포와 독립적으로 해당 애플리케이션 및 경로를 배포할 수 있습니다. 일부 경우에 애플리케이션팀은 게이트웨이도 소유하고, 애플리케이션 전용 리소스로 이를 직접 배포해야 할 수 있습니다. 게이트웨이 및 경로의 서로 다른 소유 모델은 경로 바인딩을 참조하세요. 하지만 이 예시에서 스토어팀은 이전 섹션에서 만든 internal-http 게이트웨이를 통해 앱을 노출하기 위해 해당 애플리케이션 및 수반되는 HTTPRoute를 배포합니다.

HTTPRoute 리소스에는 트래픽 일치를 위한 많은 구성 가능한 필드가 포함됩니다. HTTPRoute의 필드에 대한 설명은 API 사양을 참조하세요.

  1. 스토어 애플리케이션(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개 배포가 생성됩니다.

  2. 애플리케이션이 성공적으로 배포되었는지 확인합니다.

    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
    
  3. 서비스도 배포되었는지 확인합니다.

    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를 배포하여, 스토어 애플리케이션에 연결하기 위해 필요한 라우팅 규칙으로 게이트웨이를 프로그래밍합니다.

  1. 다음 HTTPRoute 매니페스트를 store-route.yaml이라는 파일에 저장합니다.

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 8080
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
        - name: store-v2
          port: 8080
      - matches:
        - path:
            value: /de
        backendRefs:
        - name: store-german
          port: 8080
    
  2. 클러스터에 HTTProute를 배포합니다.

    kubectl apply -f store-route.yaml
    

    store HTTPRoute는 parentRefs 속성을 사용하여 internal-http 게이트웨이에 바인딩됩니다. 이러한 라우팅 규칙은 다음 다이어그램과 같이 기본 부하 분산기에서 구성됩니다.

    저장소 HTTPRoute로 구성된 라우팅 규칙

    이러한 라우팅 규칙은 다음과 같은 방식으로 HTTP 트래픽을 처리합니다.

    • store.example.com/de에 대한 트래픽은 store-german 서비스로 이동합니다.
    • HTTP 헤더 "env: canary"가 있는 store.example.com에 대한 트래픽은 store-v2 서비스로 이동합니다.
    • store.example.com에 대한 나머지 트래픽은 store-v1 서비스로 이동합니다.
  3. HTTPRoute가 배포되었는지 확인합니다.

    kubectl describe httproute store
    

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

    Name:         store
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         HTTPRoute
    <...>
    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",
      <...>
    
  4. 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
          <...>
    

애플리케이션에 트래픽 보내기

이제 게이트웨이, 경로, 애플리케이션이 클러스터에 배포되었으므로, 트래픽을 애플리케이션에 전달할 수 있습니다.

  1. 애플리케이션에 트래픽을 전송할 수 있도록 게이트웨이에서 IP 주소를 검색합니다.

    kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}"
    

    출력은 IP 주소입니다.

  2. 클러스터 연결을 사용하여 가상 머신(VM) 인스턴스에 대해 셸에서 이 IP 주소로 트래픽을 전송합니다. 이 용도로 VM을 만들 수 있습니다. 이것은 게이트웨이에 내부 IP 주소가 포함되었고 VPC 네트워크 내에서만 액세스할 수 있기 때문에 필요합니다. internal-http가 리전 부하 분산기이기 때문에 클라이언트 셸이 GKE 클러스터와 동일한 리전 내에 있어야 합니다.

    example.com 호스트 이름을 소유하지 않기 때문에, 트래픽 라우팅을 관찰할 수 있도록 호스트 헤더를 수동으로 설정합니다. 먼저 store.example.com 요청을 시도합니다.

    curl -H "host: store.example.com" VIP
    

    VIP를 이전 단계의 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"
    }
    
  3. store.example.com/de에서 스토어 서비스의 독일어 버전으로 이동하여 경로 일치를 테스트합니다.

    curl -H "host: store.example.com" VIP/de
    

    요청이 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"
    }
    
  4. 마지막으로 env: canary HTTP 헤더를 사용하여 스토어 서비스의 카나리아 버전으로 트래픽을 전송합니다.

    curl -H "host: store.example.com" -H "env: canary " VIP
    

    요청이 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 주소)를 모든 Google Cloud 컴퓨팅 리전에서 공지된 게이트웨이의 프런트엔드로 사용합니다. 이 Anycast IP 주소로 트래픽을 전송하는 클라이언트는 IP가 공지되는 가장 가까운 Google 위치로 라우팅됩니다. 전역 외부 게이트웨이는 프리미엄 네트워크 서비스 등급에서만 사용할 수 있습니다.

리전 외부 게이트웨이는 리전 외부 게이트웨이가 배포된 로컬 Google Cloud Compute 리전에서만 공지되는 게이트웨이의 프런트엔드로 리전 IP를 사용합니다. 이 리전 IP 주소로 트래픽을 전송하는 클라이언트는 IP가 공지된 Google 리전에 도달하기 전에 해당 로컬 ISP와 인터넷을 통해 라우팅됩니다. 리전 외부 게이트웨이는 표준 네트워크 서비스 등급에서만 사용할 수 있습니다.

전역 외부 게이트웨이 배포

다음 예시에서는 전역 외부 게이트웨이에 연결되고 인증서 관리자와 HTTPRoute를 사용하여 인증서 맵에 그룹화된 여러 인증서가 있는 스토어 애플리케이션을 노출하는 방법을 보여줍니다.

인증서 맵 만들기

게이트웨이당 15개 이상의 인증서가 필요하거나 와일드 카드 인증서를 사용해야 하는 경우 인증서 관리자를 사용하여 인증서를 관리하는 것이 좋습니다.

Kubernetes 보안 비밀 또는 Google 관리형 SSL 인증서를 사용하여 외부 게이트웨이를 보호할 수도 있습니다. 자세한 내용은 게이트웨이 보안을 참조하세요.

이 섹션에서는 인증서 관리자를 사용하여 클러스터에서 실행되는 애플리케이션을 보호하는 인증서를 만듭니다.

  1. Certificate Manager API를 사용 설정합니다.

    gcloud services enable certificatemanager.googleapis.com
    
  2. 인증서 맵을 만듭니다.

    gcloud beta certificate-manager maps create store-example-com-map
    
  3. 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: 비공개 키 파일의 이름입니다.

    자세한 내용은 비공개 키 및 인증서 만들기를 참조하세요.

  4. 인증서 맵에 인증서를 할당하는 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 사양을 참조하세요.

이 섹션에서는 게이트웨이를 만듭니다. 애플리케이션팀은 게이트웨이를 사용하여 경로를 독립적으로 배포하고 해당 경로를 게이트웨이에 안전하게 연결하여 인터넷에 애플리케이션을 노출할 수 있습니다.

  1. 다음 매니페스트를 gateway.yaml이라는 파일에 저장합니다.

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: external-http
      annotations:
        networking.gke.io/certmap: store-example-com-map
    spec:
      gatewayClassName: gke-l7-global-external-managed
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
    
    

    이 매니페스트는 다음 필드를 사용해서 게이트웨이를 기술합니다.

    • gatewayClassName: gke-l7-global-external-managed: 이 게이트웨이에 GatewayClass를 지정합니다. 이 게이트웨이 클래스는 전역 외부 애플리케이션 부하 분산기를 사용합니다.
    • protocol: HTTPSport: 443: 게이트웨이가 HTTPS 트래픽에 대해 포트 443을 노출하도록 지정합니다. 이러한 필드는 TLS를 사용 설정합니다.
    • networking.gke.io/certmap: store-example-com-map: 인증서 관리자에서 인증서 맵 이름을 지정합니다.

    TLS가 networking.gke.io/certmap 주석을 사용하여 인증서 관리자에서 구성되므로 TLS 섹션이 없습니다.

  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f gateway.yaml
    

    GKE에서 리소스를 배포하는 데 몇 분 정도 걸릴 수 있습니다.

  3. 게이트웨이가 성공적으로 배포되었는지 확인합니다.

    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 사양을 참조하세요.

  1. 클러스터에 샘플 애플리케이션을 배포합니다.

    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개의 서비스를 만듭니다.

  2. 애플리케이션이 성공적으로 배포되었는지 확인합니다.

    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
    
  3. 서비스가 성공적으로 배포되었는지 확인합니다.

    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를 배포합니다.

  1. 다음 매니페스트를 store-route-external.yaml이라는 파일에 저장합니다.

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-external
    spec:
      parentRefs:
      - kind: Gateway
        name: external-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 8080
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
        - name: store-v2
          port: 8080
      - matches:
        - path:
            value: /de
        backendRefs:
        - name: store-german
          port: 8080
    

    이 매니페스트는 external-http 게이트웨이를 참조하는 HTTPRoute를 설명합니다.

  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f store-route-external.yaml
    

    store HTTPRoute는 parentRefs 속성을 사용하여 external-http 게이트웨이에 바인딩됩니다. 다음 다이어그램은 기본 부하 분산기에 구성된 라우팅 규칙을 보여줍니다.

    저장소 HTTPRoute로 구성된 라우팅 규칙

    라우팅 규칙은 다음과 같이 HTTP 트래픽을 처리합니다.

    • store.example.com/de에 대한 트래픽은 store-german 서비스로 라우팅됩니다.
    • HTTP 헤더 "env: canary"가 있는 store.example.com에 대한 트래픽은 store-v2 서비스로 라우팅됩니다.
    • store.example.com에 대한 나머지 트래픽은 store-v1 서비스로 라우팅됩니다.
  3. HTTPRoute가 배포되었는지 확인합니다.

    kubectl describe httproute store-external
    

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

    Name:         store-external
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         HTTPRoute
    <...>
    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:
        Conditions:
          Last Transition Time:  2022-11-01T05:42:31Z
          Message:
          Reason:                Accepted
          Status:                True
          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",
      ...
    
  4. HTTPRoute가 게이트웨이에 바인딩되었는지 확인합니다.

    kubectl describe gateway external-http
    

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

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    <...>
    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
          <...>
    

애플리케이션에 트래픽 보내기

이제 게이트웨이, 경로, 애플리케이션이 클러스터에 배포되었으므로, 트래픽을 애플리케이션에 전달할 수 있습니다.

  1. 게이트웨이의 IP 주소를 가져옵니다.

    kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}"
    

    출력은 IP 주소입니다.

  2. VM을 만듭니다.

    gcloud cloud-shell ssh
    
  3. VM에서 게이트웨이 IP 주소로 트래픽을 전송합니다. example.com 호스트 이름을 소유하지 않으므로 호스트 헤더를 수동으로 설정해야 합니다.

    curl -H "host: store.example.com" https://GATEWAY_IP_ADDRESS --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -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-09-25T13:31:17",
      "zone": "us-central1-a"
    }
    
  4. store.example.com/de에서 store 서비스의 독일어 버전으로 이동하여 경로 일치를 테스트합니다.

    curl -H "host: store.example.com" https://GATEWAY_IP_ADDRESS/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"
    }
    
  5. env: canary HTTP 헤더를 사용하여 store 서비스의 카나리아 버전으로 트래픽을 전송합니다.

    curl -H "host: store.example.com" -H "env: canary " https://GATEWAY_IP_ADDRESS/de --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 보안 비밀에 인증서 저장을 참조하세요.

리전 외부 HTTP(S) 게이트웨이 만들기

  1. 외부 부하 분산기의 리전 고정 IP 주소를 만듭니다.

    gcloud compute addresses create IP_ADDRESS_NAME \
      --region=COMPUTE_REGION \
      --network-tier=STANDARD
    

    다음을 바꿉니다.

    • IP_ADDRESS_NAME: 새 고정 IP 주소의 이름
    • COMPUTE_REGION: 클러스터가 실행되는 Compute Engine 리전
  2. 다음과 같이 자체 관리형 인증서를 사용하여 리전 외부 애플리케이션 부하 분산기 게이트웨이를 만들고 매니페스트를 regional-gateway.yaml로 저장합니다.

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-regional-http
      spec:
        gatewayClassName: gke-l7-regional-external-managed
        listeners:
        - name: https
          protocol: HTTPS
          port: 443
          tls:
            mode: Terminate
            certificateRefs:
            - name: store-example-com
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
    
  3. regional-gateway 매니페스트를 적용합니다.

      kubectl apply -f regional-gateway.yaml
    
  4. 구성을 확인합니다.

      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에는 부하 분산기 및 라우팅 규칙을 배포하기 위해 개별 리소스, 게이트웨이, 경로 리소스가 사용됩니다. 이것은 모든 것을 하나의 리소스로 결합하는 인그레스와 다릅니다. 리소스 간 책임을 분할함으로써 게이트웨이는 부하 분산기 및 해당 라우팅 규칙이 개별적으로 배포되고 서로 다른 사용자 또는 팀에 의해 배포될 수 있게 합니다. 이렇게 해서 게이트웨이는 서로 다른 네임스페이스 간에도 독립적인 팀에 의해 완전히 소유되고 관리될 수 있는 여러 다른 경로로 연결되는 공유 게이트웨이가 될 수 있습니다.

공유 게이트웨이에 경로 배포

이 예시는 내부 게이트웨이 배포에 배포된 internal-http 게이트웨이를 기반으로 합니다.

이 예시에서 사이트팀은 게이트웨이에서 해당 서비스로 일치하는 트래픽을 선택하기 위해 자신의 애플리케이션, 서비스, HTTPRoute를 배포합니다.

  1. 예시 애플리케이션 배포:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml
    
  2. 다음 매니페스트를 site-route-internal.yaml이라는 파일에 저장합니다.

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: site-internal
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "site.example.com"
      rules:
      - backendRefs:
        - name: site-v1
          port: 8080
    

    이 매니페스트는 site.example.com의 모든 트래픽과 일치하고 site-v1 서비스로 라우팅하는 HTTPRoute를 기술합니ㅏㄷ.

  3. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f site-route-internal.yaml
    
  4. 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가 게이트웨이에 성공적으로 바인딩된 것입니다. 상태 필드에 대한 자세한 내용은 경로 상태를 참조하세요.

  5. 게이트웨이에 대한 트래픽이 올바르게 라우팅되는지 확인합니다.

    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"
    }
    

게이트웨이 기본 백엔드 구성

모든 gke-l7-* GatewayClasses는 일치하지 않는 트래픽에 HTTP 404를 반환합니다. 일치하지 않는 트래픽을 사용자가 제공한 서비스로 전송하는 명시적인 기본 경로를 사용하여 기본 백엔드를 구성할 수 있습니다.

다음 HTTPRoute는 기본 백엔드를 맞춤설정하는 방법에 대한 예시입니다. 다음과 유사한 HTTPRoute를 적용하면 암시적 기본 백엔드보다 우선 적용됩니다.

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
  name: custom-default-backend
spec:
  parentRefs:
  - kind: Gateway
    name: my-internal-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 주소 풀
  • gke-l7-rilb
  • gke-l7-rilb-mc
  • 기본 노드 IPv4/IPv6 주소 범위의 리전 비공개 IP 주소
  • gke-l7-regional-external-managed
  • gke-l7-regional-external-managed-mc
  • Google 리전 외부 IPv4/IPv6 범위의 리전 공개 IP 주소
  • gke-l7-global-external-managed
  • gke-l7-global-external-managed-mc
  • gke-l7-gxlb
  • gke-l7-gxlb-mc
  • Google 전역 외부 IPv4/IPv6 범위의 전역 공개 IP 주소

    addresses.NamedAddress 필드를 사용하면 게이트웨이와 독립적으로 IP 주소를 지정할 수 있습니다. 게이트웨이 배포 전 고정 IP 주소 리소스를 만들 수 있으며, 리소스는 NamedAddress로 참조됩니다. 게이트웨이가 삭제된 경우에도 고정 IP 주소를 다시 사용할 수 있습니다.

    이름이 지정된 IP 주소 사용

    NamedAddress를 지정하여 IP 주소를 구성할 수 있습니다. 게이트웨이를 만들기 전에 고정 IP 주소를 프로비저닝해야 합니다.

    1. 고정 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 클러스터가 실행되는 프로젝트입니다.
    2. 다음 매니페스트를 named-ip-gateway.yaml이라는 파일에 저장합니다.

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: internal-http
      spec:
        gatewayClassName: gke-l7-rilb
        listeners:
        - name: http
          protocol: HTTP
          port: 80
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
      

      이 매니페스트는 명명된 IP 주소를 참조하는 게이트웨이를 설명합니다.

    3. 매니페스트를 클러스터에 적용합니다.

      kubectl apply -f named-ip-gateway.yaml
      
    4. 게이트웨이 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 트래픽 리디렉션

    다음 예시에서 게이트웨이는 HTTP 리스너가 Same(동일한 네임스페이스의 연결)을 허용하도록 구성되며 HTTPS 리스너는 모든 네임스페이스에 열립니다. 이 구성을 사용할 때는 리디렉션 HTTPRoute만 게이트웨이와 동일한 네임스페이스에 있어야 합니다.

    이 구성은 추가 HTTPRoute가 게이트웨이의 HTTP 리스너에 바인딩될 수 없도록 보장합니다. 이를 위해서는 애플리케이션팀의 HTTPRoute가 gateway-infra 네임스페이스에서 허용되지 않아야 합니다.

    1. 게이트웨이의 네임스페이스 gateway-infra를 만듭니다. 매니페스트를 gateway-namespace.yaml로 저장하세요.

      apiVersion: v1
      kind: Namespace
      metadata:
        name: gateway-infra
      
    2. 매니페스트를 적용합니다.

      kubectl apply -f gateway-namespace.yaml
      
    3. 다음 매니페스트를 사용하여 게이트웨이를 만들고 매니페스트를 external-gateway.yaml로 저장하세요.

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-http
        namespace: gateway-infra
      spec:
        gatewayClassName: gke-l7-global-external-managed
        listeners:
        - name: http
          protocol: HTTP
          port: 80
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: Same
        - name: https
          protocol: HTTPS
          port: 443
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: All
          tls:
            mode: Terminate
            options:
              networking.gke.io/pre-shared-certs: store-example-com
      
      • allowedRoutes 섹션의 namespaces 필드는 http 리스너를 게이트웨이의 네임스페이스 gateway-infra로만 제한합니다.

      • https 리스너에는 허용된 네임스페이스에 대한 제한이 포함되지 않으므로 모든 네임스페이스는 HTTPRoute에서 https 리스너를 사용합니다.

    4. 매니페스트를 적용합니다.

      kubectl apply -f external-gateway.yaml
      
    5. HTTPS 리디렉션을 강제 적용하려면 다음 매니페스트를 사용하여 기본 HTTPRoute를 만들고 매니페스트를 redirect-httproute.yaml로 저장하세요.

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: redirect
        namespace: gateway-infra
      spec:
        parentRefs:
        - namespace: gateway-infra
          name: external-http
          sectionName: http
        rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
      
      • sectionName 필드는 게이트웨이가 http 리스너에서만 일치하도록 지시합니다. RequestRedirect 필터는 https 리스너로 강제 리디렉션합니다.

      이 구성은 게이트웨이의 포트 80에서 수신된 모든 트래픽을 포트 443의 리스너로 리디렉션하여 클라이언트와 부하 분산기 간의 보안 통신을 적용합니다.

    6. 매니페스트를 적용합니다.

      kubectl apply -f redirect-httproute.yaml
      
    7. 다음 매니페스트를 사용하여 애플리케이션 서비스를 만듭니다. 매니페스트를 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.2.20
              ports:
              - containerPort: 8080
              env:
              - name: METADATA
                value: "store-v1"
      
    8. 매니페스트를 적용합니다.

      kubectl apply -f service-deployment.yaml
      
    9. HTTPS만 허용하는 애플리케이션에 대한 HTTPRoute를 만듭니다. 매니페스트를 httproute.yaml로 저장합니다.

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: store-external
        labels:
          gateway: external-http
      spec:
        parentRefs:
        - name: external-http
          namespace: gateway-infra
          sectionName: https
        hostnames:
        - "store.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
      
    10. 매니페스트를 적용합니다.

      kubectl apply -f httproute.yaml
      

    인프라 네임스페이스에서 HTTP 트래픽 리디렉션

    일부 경우에는 인프라 또는 플랫폼 관리팀과 애플리케이션팀 사이에 명확한 차이가 없으므로 게이트웨이의 오용을 방지하는 것이 어려울 수 있습니다.

    다음 예시에서는 애플리케이션 팀이 비보안 프로토콜을 의도치 않게 사용하는 것을 방지하기 위해 HTTP 리스너 사용을 추가로 제한합니다. 이 예시에서는 지정된 네임스페이스(http-redirect)에 경로가 있는 경우에만 HTTPRoute가 HTTP 리스너를 사용하도록 하는 한편, HTTPS 네임스페이스가 모든 네임스페이스에 열리도록 게이트웨이를 구성합니다. Kubernetes RBAC를 통해 http-redirect 네임스페이스를 제한하여 애플리케이션팀이 실수로 이 네임스페이스에 HTTPRoute를 생성하지 못하게 할 수 있습니다.

    1. 게이트웨이의 네임스페이스를 만듭니다. 매니페스트를 gateway-namespace.yaml로 저장하세요.

      apiVersion: v1
      kind: Namespace
      metadata:
        name: gateway-infra
      
    2. 매니페스트를 적용합니다.

      kubectl apply -f gateway-namespace.yaml
      
    3. 게이트웨이의 네임스페이스를 만들고 매니페스트를 redirect-namespace.yaml으로 저장합니다.

      apiVersion: v1
      kind: Namespace
      metadata:
        name: http-redirect
        labels:
          otherInfra: httpToHttps
      
      • 이 네임스페이스에는 특정 라벨이 설정되어 있습니다.
    4. 매니페스트를 적용합니다.

      kubectl apply -f redirect-namespace.yaml
      
    5. http 리스너 사용을 제한하려면 다음 매니페스트를 사용하여 게이트웨이를 만듭니다. 매니페스트를 external-gateway.yaml로 저장합니다.

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-http
        namespace: gateway-infra
      spec:
        gatewayClassName: gke-l7-global-external-managed
        listeners:
        - name: http
          protocol: HTTP
          port: 80
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: selector
              selector:
                matchLabels:
                  otherInfra: httpToHttps
        - name: https
          protocol: HTTPS
          port: 443
          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 라벨과 일치하는 네임스페이스로 제한합니다.

    6. 매니페스트를 적용합니다.

      kubectl apply -f external-gateway.yaml
      
    7. HTTPS 리디렉션을 강제 적용하려면 다음 매니페스트를 사용하여 기본 HTTPRoute를 만드세요. 매니페스트를 http-redirect.yaml로 저장합니다.

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: redirect
        namespace: http-redirect
      spec:
        parentRefs:
        - namespace: gateway-infra
          name: external-http
          sectionName: http
        rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
      
      • sectionName 필드는 게이트웨이가 http 리스너에서만 일치하도록 지시합니다. RequestRedirect 필터는 https 리스너로 강제 리디렉션합니다.
    8. 매니페스트를 적용합니다.

      kubectl apply -f http-redirect.yaml
      
    9. 다음 매니페스트를 사용하여 애플리케이션 서비스를 만듭니다. 매니페스트를 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.2.20
              ports:
              - containerPort: 8080
              env:
              - name: METADATA
                value: "store-v1"
      
    10. 매니페스트를 적용합니다.

      kubectl apply -f service-deployment.yaml
      
    11. 다음 매니페스트를 사용하여 HTTPS만 허용하는 애플리케이션에 대한 HTTPRoute를 만듭니다. 매니페스트를 http-route.yaml로 저장합니다.

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: store-external
        labels:
          gateway: external-http
      spec:
        parentRefs:
        - name: external-http
          namespace: gateway-infra
          sectionName: https
        hostnames:
        - "store.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
      
    12. 매니페스트를 적용합니다.

      kubectl apply -f http-route.yaml
      

    경로 리디렉션 및 URL 재작성 구성

    경로 리디렉션에는 한 URL 경로에서 다른 URL 경로로 들어오는 요청을 리디렉션하는 작업이 포함됩니다. 경로 리디렉션을 사용하면 오래되었거나 지원 중단된 URL을 처리해야 할 때 URL 구조를 변경할 수 있습니다.

    URL 재작성은 수신 URL을 서버에서 처리하기 전에 수정하는 데 도움이 됩니다. 기본 콘텐츠나 파일 구조를 실제로 변경하지 않고도 URL의 구조나 형식을 변경할 수 있습니다. URL 재작성은 기억하기 쉽고 이해하기 쉬운 사용자 친화적이고 검색엔진 최적화 친화적인 URL을 만드는 데 유용합니다. 기본적으로 경로 리디렉션 및 URL 재작성은 구성되지 않으므로 HTTPRoute의 필터를 사용하여 해당 리디렉션 또는 재작성을 명시적으로 구성해야 합니다.

    GKE 게이트웨이는 경로 리디렉션 및 URL 재작성을 지원합니다. 자세한 내용은 HTTP 경로 리디렉션 및 재작성을 참조하세요.

    경로 리디렉션 구성

    경로 리디렉션을 구성하여 전체 경로를 바꾸거나 URL에서 프리픽스만 바꿀 수 있습니다.

    전체 경로 바꾸기

    1. 전체 경로를 바꾸려면 URL 경로에 프리픽스 /any-path가 포함된 모든 URL을 엄격한 값 /new-path로 바꾸는 HTTPRoute에서 필터를 구성합니다.

    2. 다음과 같이 HTTPRoute 매니페스트를 만들고 이름을 store.yaml으로 지정합니다.

        apiVersion: gateway.networking.k8s.io/v1beta1
        kind: HTTPRoute
        metadata:
          name: store
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - store.example.com
          rules:
          - matches:
            - path:
                type: PathPrefix
                value: /any-path
            filters:
            - type: RequestRedirect
              requestRedirect:
                path:
                  type: ReplaceFullPath
                  replaceFullPath: /new-path
                statusCode: 302
      

      예를 들어 이 매니페스트는 HTTPRoute에 대한 라우팅 규칙을 다음과 같이 설정합니다. URL https://store.example.com/any-path/...에 대한 모든 경로는 새 위치인 https://store.example.com/new-path/(엄격)로 리디렉션되어야 합니다.

    3. 매니페스트를 적용합니다.

      kubectl apply -f store.yaml
      

    이 라우팅 규칙은 엄격한 리디렉션 규칙을 따릅니다. 즉, 브라우저가 리디렉션을 캐시하려고 시도하지 않고 대신 최신 버전으로 리디렉션합니다.

    프리픽스만 바꾸기

    1. 프리픽스만 바꾸려면 URL 경로의 프리픽스 /any-prefix가 포함된 모든 URL을 엄격한 값 /new-prefix로 바꾸는 HTTPRoute에서 필터를 구성합니다.

    2. 다음과 같이 HTTPRoute 매니페스트를 만들고 이름을 store.yaml으로 지정합니다.

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
        - matches:
            - path:
                type: PathPrefix
                value: /any-prefix
          filters:
          - type: RequestRedirect
            requestRedirect:
              path:
                type: ReplacePrefixMatch
                replacePrefixMatch: /new-prefix
              statusCode: 302
      

      예를 들어 이 매니페스트는 HTTPRoute에 대한 라우팅 규칙을 다음과 같이 설정합니다. URL https://store.example.com/any-path/v1/..에 대한 모든 경로는 새 위치인 https://store.example.com/new-path/v1/...로 리디렉션되어야 합니다 (전용).

    3. 매니페스트를 적용합니다.

        kubectl apply -f store.yaml
      

    이 라우팅 규칙은 리디렉션 규칙만 따르므로 브라우저에서 항상 사용자를 동일한 의도된 페이지로 리디렉션합니다.

    URL 재작성 구성

    URL 재작성을 설정하여 사용자에게 URL이 표시되는 방식을 변경할 수 있습니다. URL 재작성을 사용하여 URL을 더 사용자 친화적으로 만들거나 검색엔진 최적화를 개선하거나 사용자를 새 페이지로 리디렉션할 수 있습니다.

    전체 호스트 이름 재작성

    전체 호스트 이름을 재작성하려면 다음 안내를 따르세요.

    1. 요청을 백엔드 서비스로 전달하기 전에 요청 헤더에 있는 Host 정보를 www.example.com에서 store.example.com으로 바꾸도록 게이트웨이에 지시하는 HTTPRoute에서 필터를 구성합니다.

    2. 다음과 같이 HTTPRoute 매니페스트를 만들고 이름을 www.yaml로 지정합니다.

        apiVersion: gateway.networking.k8s.io/v1beta1
        kind: HTTPRoute
        metadata:
          name: www
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - www.example.com
          rules:
          - filters:
            - type: URLRewrite
              urlRewrite:
                hostname: store.example.com
            backendRefs:
            - name: store-v1
              port: 8080
      

      예를 들어 위의 구성에서 https://www.example.com에 대한 모든 요청은 Host: www.example.com 대신 Host: store.example.com 헤더와 함께 백엔드 서비스로 전달됩니다.

    3. 매니페스트를 적용합니다.

        kubectl apply -f www.yaml
      

    경로 수정자를 사용하여 재작성

    재작성을 경로 수정자와 결합하여 백엔드 서비스에 요청을 릴레이하기 전에 고급 URL 및 경로 수정을 제공할 수 있습니다.

    경로 수정자를 사용하여 재작성하려면 다음 안내를 따르세요.

    1. 요청을 백엔드 서비스로 전달하기 전에 요청 헤더에 있는 '호스트' 정보를 www.example.com에서 store.example.com으로 바꾸고 /store 값을 /로 바꾸도록 게이트웨이에 지시하는 HTTPRoute의 필터를 구성합니다.

    2. 다음과 같이 HTTPRoute 매니페스트를 만들고 이름을 www.yaml로 지정합니다.

        apiVersion: gateway.networking.k8s.io/v1beta1
        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
              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로 재작성합니다.

    3. 매니페스트를 적용합니다.

      kubectl apply -f www.yaml
      

    구성을 확인합니다

    URL 재작성 또는 경로 리디렉션 필터를 사용하여 HTTPRoute를 만든 후 필터가 적용되었는지 확인하려면 다음을 수행합니다.

    kubectl get httproute www -o yaml
    

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

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"gateway.networking.k8s.io/v1beta1","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/v1beta1
      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/v1beta1
    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/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
          - matches:
            - path:
                type: PathPrefix
                value: /fr
            filters:
              - 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/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
          - matches:
            - path:
                type: PathPrefix
                value: /de
            filters:
              - type: ResponseHeaderModifier
                responseHeaderModifier:
                  add:
                    - name: Strict-Transport-Security
                      value: max-age=63072000
            backendRefs:
              - name: store-german
                port: 8080
    

    구성을 확인합니다

    1. 커스텀 요청 및 응답 헤더를 구성한 후 구성을 확인하려면 다음 안내를 따르세요.

        kubectl get httproute
      

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

        NAME    HOSTNAMES               AGE
        store   ["store.example.com"]   4d23h
      
    2. 더 많은 세부정보를 확인하려면 describe 명령어를 사용합니다.

        kubectl describe httproute
      

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

        Name:         store
        Namespace:    default
        Labels:       <none>
        Annotations:  <none>
        API Version:  gateway.networking.k8s.io/v1beta1
        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 사이의 우선순위는 다음과 같습니다.

    1. 호스트 이름 병합: 가장 길고 가장 구체적인 호스트 이름이 선택됩니다.
    2. 경로 병합: 가장 길고 가장 구체적인 경로가 선택됩니다.
    3. 헤더 병합: 일치하는 가장 큰 수의 HTTP 헤더입니다.
    4. 충돌: 위 3개 규칙에 따라 우선순위가 결정되지 않으면 가장 오래된 타임스탬프의 HTTPRoute 리소스가 우선 적용됩니다.

    경로 병합

    gke-l7 GatewayClass의 경우 지정된 게이트웨이에 대한 모든 HTTPRoute가 동일한 URL 맵 리소스에 병합됩니다. HTTPRoute가 병합되는 방법은 HTTPRoute 사이의 겹침 유형에 따라 달라집니다. 이전 예시의 HTTPRoute를 3개의 개별 HTTPRoute로 분할하여 경로 병합 및 우선순위를 나타낼 수 있습니다.

    1. 경로 병합: 3개 HTTPRoute 모두 동일한 internal-http 게이트웨이와 연결되어 함께 병합됩니다.
    2. 호스트 이름 병합: 3개 경로 모두 store.example.com과 일치하여, 해당 호스트 이름 규칙이 병합됩니다.
    3. 경로 병합: store-german-route에 보다 구체적인 경로 /de가 포함되므로, 이것은 추가로 병합되지 않습니다. store-v1-route 및 store-v2-route는 모두 동일한 /* 경로에서 일치하므로, 해당 경로로 병합됩니다.
    4. 헤더 병합: store-v2-route는 store-v1-route보다 더 구체적인 HTTP 헤더 일치 집합을 가지므로, 추가로 병합되지 않습니다.
    5. 충돌: 경로가 호스트 이름, 경로, 헤더로 병합될 수 있기 때문에 충돌이 없고, 모든 경로 규칙이 트래픽에 적용됩니다.

    앞의 예시에 사용된 단일 HTTPRoute는 이러한 3개의 개별 경로와 동일합니다.

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    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/v1beta1
    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/v1beta1
    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
    

    이유:

    이 오류 메시지는 프록시 전용 서브넷이 이미 있는 리전에서 리전 프록시 전용 서브넷을 만들려고 했음을 나타냅니다.

    해결 방법:

    이 문제를 해결하려면 다음을 단계를 사용해 보세요.

    1. 프록시 전용 서브넷이 리전에 이미 있는지 확인하고 올바른 목적을 가지고 있는지 확인합니다.

      1. 서브넷을 나열하여 해당 리전의 프록시 전용 서브넷을 찾습니다.

        gcloud compute networks subnets list --regions=COMPUTE_REGION
        

        COMPUTE_REGION을 리전 게이트웨이를 만들려는 Compute Engine 리전으로 바꿉니다.

      2. 해당 리전의 프록시 전용 서브넷을 설명하여 그 용도를 찾습니다.

        gcloud compute networks subnets describe PROXY_ONLY_SUBNET \
            --region COMPUTE_REGION | grep -E 'name|purpose'
        

        PROXY_ONLY_SUBNET을 프록시 전용 서브넷으로 바꿉니다.

      GKE 게이트웨이는 리전 게이트웨이(내부 또는 리전)에 대해 REGIONAL_MANAGED_PROXY 프록시 전용 서브넷만 지원합니다.

    2. 리전의 기존 프록시 전용 서브넷이 INTERNAL_HTTPS_LOAD_BALANCER 목적으로 생성된 경우 해당 목적을 REGIONAL_MANAGED_PROXY로 마이그레이션합니다.

    다음 단계