Service Extensions을 사용하여 GKE 게이트웨이 트래픽 맞춤설정

이 페이지에서는 Google Kubernetes Engine (GKE)이 서비스 확장 프로그램을 사용하여 Cloud Load Balancing에 맞춤 로직을 추가하는 방법을 설명합니다.

이 페이지는 서비스 확장 프로그램을 사용하여 맞춤 트래픽 관리 로직을 구성해야 하는 GKE ID 및 계정 관리자와 개발자를 대상으로 합니다.

이 페이지를 읽기 전 다음 내용을 숙지해야 합니다.

개요

GKE는 서비스 확장 프로그램을 사용하여 Cloud Load Balancing에 맞춤 로직을 추가합니다. 고급 트래픽 분할, 맞춤 인증, 요청 로깅과 같은 작업에 서비스 확장 프로그램을 사용할 수 있습니다.

GKE Gateway Controller는 다음 서비스 확장 프로그램을 지원합니다.

  • GCPRoutingExtension: 이 확장 프로그램은 Cloud Load Balancing에 커스텀 로직을 추가하여 트래픽 라우팅을 제어합니다.
  • GCPTrafficExtension: 이 확장 프로그램은 트래픽을 수정하기 위해 Cloud Load Balancing에 맞춤 로직을 삽입합니다. 이 로직은 서비스가 선택된 후 트래픽에 적용됩니다. 부하 분산기는 HTTP 요청 및 응답의 헤더와 페이로드를 추가하거나 변경할 수 있습니다. GCPTrafficExtension는 서비스 선택이나 서비스 보안 정책에 영향을 미치지 않습니다.

확장 프로그램은 게이트웨이에 연결되고 Service, GCPWasmPlugin 또는 googleAPIServiceName를 참조합니다.

  • 서비스 참조: 이 모델에서는 커스텀 로직을 별도의 백엔드 애플리케이션으로 배포하고 Kubernetes 서비스로 노출합니다. 부하 분산기는 트래픽을 처리하기 위해 이 서비스에 콜아웃을 만듭니다. 이 접근 방식은 다재다능하며 맞춤 라우팅 로직을 구현하거나 헤더 수정 또는 페이로드 검사와 같은 트래픽 조작을 실행할 수 있습니다. GCPRoutingExtension 또는 GCPTrafficExtension로 서비스를 참조합니다.

  • GCPWasmPlugin 리소스 참조: 고성능 사용 사례의 경우 WebAssembly (Wasm) 모듈을 사용하여 맞춤 사용자 작성 로직을Google Cloud 부하 분산기의 데이터 경로에 직접 삽입할 수 있습니다. Artifact Registry에서 Wasm 모듈의 이미지를 가리키는 GCPWasmPlugin 리소스를 정의합니다. 이 메서드는 GCPTrafficExtension 및 전역 외부 애플리케이션 부하 분산기에서만 사용됩니다.

  • Google API 서비스 참조: GCPTrafficExtension 내에서 googleAPIServiceName 필드를 사용하여 Google API 서비스를 직접 참조할 수도 있습니다.

다음 다이어그램에서 GCPRoutingExtension 리소스는 게이트웨이에 연결되어 있으며 여러 서비스를 참조합니다. 확장 프로그램은 서비스로의 트래픽 라우팅을 제어합니다.

`GCPRoutingExtension` 리소스는 게이트웨이에 연결되고 서비스를 참조합니다. 확장 프로그램이 트래픽 라우팅을 제어합니다.
그림: GCPRoutingExtension이 게이트웨이와 작동하는 방식

다음 다이어그램에서 GCPTrafficExtension 리소스는 게이트웨이에 연결되어 있으며 서비스, GoogleAPIServiceName 또는 GCPWasmPlugin를 참조합니다. 확장 프로그램은 요청 및 응답의 헤더와 페이로드를 변경합니다.

`GCPTrafficExtension` 리소스는 게이트웨이에 연결되고 서비스, `GoogleAPIServiceName` 또는 `GCPWasmPlugin`을 참조합니다. 확장 프로그램은 요청 및 응답의 헤더와 페이로드를 변경합니다.
그림: GCPTrafficExtension이 게이트웨이와 작동하는 방식

시작하기 전에

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

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우 gcloud components update 명령어를 실행하여 최신 버전을 가져옵니다. 이전 gcloud CLI 버전에서는 이 문서의 명령어를 실행하지 못할 수 있습니다.

GKE Gateway Controller 요구사항

  • 클러스터는 GKE 버전 1.33 이상을 사용해야 합니다.
  • GCPWasmPlugin를 사용하려면 클러스터에서 GKE 버전 1.33.3 이상을 사용해야 합니다.
  • 클러스터에서 Gateway API가 사용 설정되어 있어야 합니다.
  • 구성된 게이트웨이 리소스가 있어야 합니다. 이 리소스는 전역 외부 애플리케이션 부하 분산기, 리전 외부 애플리케이션 부하 분산기 또는 리전 내부 애플리케이션 부하 분산기 게이트웨이일 수 있습니다. GCPWasmPlugin 리소스를 사용하는 경우 전역 외부 애플리케이션 부하 분산기 게이트웨이만 배포해야 합니다.
  • 구성된 HTTPRoute 리소스가 있어야 합니다.

제한 및 한도

다음 표에는 GKE의 게이트웨이 서비스 확장 프로그램 구성과 관련된 제한사항이 나와 있습니다.

카테고리 제한 및 한도
부하 분산기 GCPRoutingExtension는 다음 부하 분산기에서 지원됩니다.
  • 리전 외부 애플리케이션 부하 분산기 (gke-l7-regional-external-managed 게이트웨이 클래스)
  • 리전 내부 애플리케이션 부하 분산기(gke-l7-rilb 게이트웨이 클래스)
GCPTrafficExtension는 다음 부하 분산기에서 지원됩니다.
  • 리전 외부 애플리케이션 부하 분산기 (gke-l7-regional-external-managed 게이트웨이 클래스)
  • 리전 내부 애플리케이션 부하 분산기 (gke-l7-rilb 게이트웨이 클래스)
  • 전역 외부 애플리케이션 부하 분산기 (gke-l7-global-external-managed 게이트웨이 클래스)
확장 프로그램 체인 및 사양
  • GCPTrafficExtension의 경우 각 ExtensionChain에는 최대 3개의 Extensions가 있을 수 있습니다.
  • GCPRoutingExtension의 경우 각 ExtensionChainExtension 1개로 제한됩니다.
  • GCPTrafficExtensionSpecGCPRoutingExtensionSpec는 각각 최대 5개의 ExtensionChains를 가질 수 있습니다.
타이밍 및 매칭
  • 확장 프로그램 내 스트림의 개별 메시지 제한 시간은 10~10,000밀리초여야 합니다. 이 1초 제한은 경로 및 트래픽 확장 프로그램에 적용됩니다.
  • ExtensionChain 내의 각 MatchCondition는 최대 10개의 CELExpressions로 제한됩니다.
  • GCE로 전송되는 결과 MatchCondition 문자열의 문자 제한은 512입니다.
  • CELExpression 내의 CELMatcher 문자열의 최대 길이는 512자(영문 기준)이며 특정 패턴을 따라야 합니다. CELExpressionBackendRefs 필드는 지원되지 않습니다.
헤더 및 메타데이터
  • ExtensionForwardHeaders 목록에는 최대 50개의 HTTP 헤더 이름이 포함될 수 있습니다.
  • ExtensionMetadata 맵에는 최대 16개의 속성이 있을 수 있습니다.
  • Metadata 맵 내의 키는 1~63자(영문 기준)여야 합니다.
  • Metadata 맵의 값은 1~1,023자(영문 기준)여야 합니다.
이벤트
  • GCPRoutingExtension의 경우 requestBodySendMode이 설정되지 않으면 supportedEvents 목록에 RequestHeaders 이벤트만 포함될 수 있습니다.
  • GCPRoutingExtension의 경우 requestBodySendModeFullDuplexStreamed로 설정되면 supportedEvents 목록에는 RequestHeaders, RequestBody, RequestTrailers 이벤트만 포함될 수 있습니다.
GCPTrafficExtension
  • responseBodySendMode 필드는 GCPTrafficExtension에만 지원됩니다.
  • googleAPIServiceName 필드는 GCPTrafficExtension에만 지원됩니다.
  • GCPWasmPlugin 필드는 GCPTrafficExtension에만 지원됩니다.
GCPWasmPlugin
  • GCPWasmPlugin가 있는 확장 프로그램은 다음 필드를 지원하지 않습니다.
    • authority
    • timeout
    • metadata
    • requestBodySendMode
    • responseBodySendMode
  • GCPWasmPlugin 지원이 있는 확장 프로그램은 RequestHeaders, RequestBody, ResponseHeaders, ResponseBody 이벤트만 지원합니다.
googleAPIServiceNamebackendRef 확장 프로그램에서 backendRef을 사용하는 서비스를 참조하는 경우 다음 조건을 충족해야 합니다.
  • HTTP2를 appProtocol로 사용해야 합니다.
  • 확장 프로그램 및 확장 프로그램에서 참조하는 게이트웨이와 동일한 네임스페이스에 있어야 합니다.
  • IAP를 사용할 수 없습니다.
  • Google Cloud Armor 보안 정책 ( GCPBackendPolicyConfigsecurityPolicy 필드)을 사용할 수 없습니다.
  • Cloud CDN을 사용할 수 없습니다.
  • Extension의 경우 backendRef 또는 googleAPIServiceName 중 하나만 설정해야 합니다.
  • backendRef가 설정되고 kindService인 경우 authority를 설정해야 합니다.
  • googleAPIServiceName가 설정된 경우 authority를 설정하면 안 됩니다.
  • backendRefService만 사용하여 확장 프로그램용 requestBodySendMode를 구성합니다.
  • backendRefService만 사용하여 확장 프로그램용 responseBodySendMode를 구성합니다.

서비스 참조

서비스 확장 프로그램에서 부하 분산기가 실행할 맞춤 로직을 호스팅하는 서비스를 참조할 수 있습니다. 게이트웨이에는 기본적으로 서비스 확장 프로그램이 없습니다.

GKE Service Extensions를 구성하려면 다음 단계를 따르세요.

  1. 백엔드 콜아웃 서비스 배포: 맞춤 로직 실행을 위한 백엔드 서비스를 나타내는 Kubernetes 서비스를 만듭니다. 부하 분산기가 이 서비스를 호출합니다.

  2. 서비스 확장 프로그램 구성: 부하 분산기 유형에 따라 적절한 확장 프로그램을 사용합니다.

    1. 리전 게이트웨이의 GCPRoutingExtension: 리전 외부 애플리케이션 부하 분산기 및 리전 내부 애플리케이션 부하 분산기에서 이 확장 프로그램을 사용하여 리전 내에서 맞춤 라우팅 로직을 구현합니다.

    2. 전역 외부, 리전 외부, 내부 게이트웨이의 경우 GCPTrafficExtension: 이 확장 프로그램을 사용하여 전역 외부 애플리케이션 부하 분산기, 리전 외부 애플리케이션 부하 분산기, 리전 내부 애플리케이션 부하 분산기에서 다양한 부하 분산기 유형에 걸쳐 헤더 수정 또는 페이로드 검사와 같은 트래픽 조작을 실행합니다.

백엔드 콜아웃 서비스 배포

콜아웃 서비스는 GKE의 게이트웨이 서비스 확장 프로그램에 대한 맞춤 로직을 구현합니다. 게이트웨이는 GCPTrafficExtension 또는 GCPRoutingExtension 구성에 따라 이러한 백엔드 애플리케이션을 호출하여 트래픽을 수정하거나 라우팅합니다.

콜아웃 서비스를 배포하여 게이트웨이에 커스텀 로직을 추가합니다. 이 별도의 서비스는 헤더 조작, 페이로드 변환, 트래픽 라우팅과 같은 맞춤 처리를 처리합니다.

게이트웨이의 콜아웃으로 작동할 수 있는 서비스를 배포하려면 다음 단계를 따르세요.

  1. (선택사항) TLS용 보안 비밀 만들기: 이 명령어는 TLS 인증서와 비공개 키가 포함된 TLS 유형의 Kubernetes 보안 비밀을 만듭니다.

    호출 서비스의 TLS 보안 비밀을 만들려면 다음을 바꿉니다.

    • SECRET_NAME: 콜아웃 서비스의 보안 비밀 이름
    • path-to-cert: 인증서의 파일 경로
    • path-to-key: 키의 파일 경로
  2. 시크릿이 추가되었는지 확인하려면 다음 명령어를 실행합니다.

    kubectl get secrets SECRET_NAME
    

    SECRET_NAME을 콜아웃 서비스의 보안 비밀 이름으로 바꿉니다.

    출력은 다음과 비슷하게 표시됩니다.

    NAME            TYPE                DATA   AGE
    SECRET_NAME     kubernetes.io/tls   2      12s
    
  3. 배포 및 서비스 리소스를 정의합니다.

    다음을 정의해야 합니다.

    • 배포: 서비스 확장 프로그램의 맞춤 로직이 포함된 애플리케이션 포드를 관리합니다.
    • 서비스: Deployment에서 관리하는 애플리케이션 포드를 네트워크 서비스로 노출합니다.
    1. 배포 및 서비스 정의가 있는 샘플 매니페스트 extension-service-app.yaml를 만듭니다.

      apiVersion: apps/v1
      kind: Deployment
      metadata:
      name: extension-service-app
      spec:
      selector:
          matchLabels:
            app: store
        replicas: 1
        template:
          metadata:
            labels:
              app: store
          spec:
            containers:
            - name: serviceextensions
              image: us-docker.pkg.dev/service-extensions-samples/callouts/python-example-basic:main
              ports:
              - containerPort: 8080
              - containerPort: 443
              volumeMounts:
              - name: certs
                mountPath: "/etc/certs/"
                readOnly: true
              env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              - name: NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
              - name: TLS_SERVER_CERT
                value: "/etc/certs/path-to-cert"
              - name: TLS_SERVER_PRIVKEY
                value: "/etc/certs/path-to-key"
                resources:
                requests:
                  cpu: 10m
            volumes:
            - name: certs
              secret:
                secretName: SECRET_NAME
                optional: false
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: extension-service
      spec:
        ports:
        - port: 443
          targetPort: 443
          appProtocol: HTTP2
        selector:
          app: store
      
    2. extension-service-app.yaml 매니페스트를 적용합니다.

      kubectl apply -f extension-service-app.yaml
      
  4. 구성을 확인합니다

    1. 애플리케이션이 배포되었는지 확인합니다.

      kubectl get pod --selector app=store
      

      애플리케이션이 실행되면 출력은 다음과 비슷합니다.

      NAME                                     READY   STATUS    RESTARTS   AGE
      extension-service-app-85f466bc9b-b5mf4   1/1     Running   0          7s
      
    2. 서비스가 배포되었는지 확인합니다.

      kubectl get service extension-service
      

      각 스토어 배포에 대해 서비스를 보여주는 출력이 다음과 같이 표시됩니다.

      NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
      extension-service   ClusterIP   34.118.225.9   <none>        443/TCP   2m40s
      

서비스 확장 프로그램 구성

GCPRoutingExtension 또는 GCPTrafficExtension을 구성하여 트래픽 흐름을 맞춤설정할 수 있습니다.

리전 게이트웨이의 GCPRoutingExtension 구성

GCPRoutingExtension를 사용하여 트래픽을 리라우팅할 수 있습니다. GCPRoutingExtension를 구성하려면 service-extensions.com 호스트에 대한 요청을 지정하도록 HTTPRoute를 업데이트합니다.

  1. HTTPRoute를 업데이트합니다. 라우팅 확장 프로그램을 트리거하는 호스트 이름 또는 경로를 포함하도록 HTTPRoute를 수정합니다.

    1. 다음 샘플 매니페스트를 store-route.yaml 파일로 저장합니다.

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: store
      spec:
        parentRefs:
        - kind: Gateway
          name:GATEWAY_NAME
        hostnames:
        - "store.example.com"
        - "service-extensions.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
      

      GATEWAY_NAME을 게이트웨이 이름으로 바꿉니다.

    2. store-route.yaml 매니페스트를 적용합니다.

      kubectl apply -f store-route.yaml
      
  2. GCPRoutingExtension을 정의합니다.

    1. 샘플 gcp-routing-extension.yaml 파일에 GCPRoutingExtension 구성을 저장합니다.

      kind: GCPRoutingExtension
      apiVersion: networking.gke.io/v1
      metadata:
        name: my-gateway-extension
        namespace: default
      spec:
        targetRefs:
        - group: "gateway.networking.k8s.io"
          kind: Gateway
          name: GATEWAY_NAME
        extensionChains:
        - name: chain1
          matchCondition:
            celExpressions:
            - celMatcher: request.path.contains("serviceextensions")
          extensions:
          - name: ext1
            authority: "myext.com"
            timeout: 1s
              backendRef:
                group: ""
              kind: Service
              name: extension-service
              port: 443
      

      GATEWAY_NAME을 게이트웨이 이름으로 바꿉니다.

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

      kubectl apply -f gcp-routing-extension.yaml
      
  3. GCPRoutingExtension 구성과 게이트웨이와의 바인딩을 확인합니다.

    1. GCPRoutingExtension 배포를 확인합니다.

      kubectl describe gcproutingextension my-gateway-extension
      

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

      Name:         my-gateway-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPRoutingExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:        1
        Resource Version:  31283253
        UID:               ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:    myext.com
            Backend Ref:
              Group:
              Kind: Service
              Name: extension-service
              Port: 443
            Name:       ext1
            Timeout:    1s
          Match Condition:
            Cel Expressions:
              Cel Matcher: request.path.contains("serviceextensions")
          Name:  chain1
        Target Refs:
          Group: gateway.networking.k8s.io
          Kind: Gateway
          Name: GATEWAY_NAME
      Events:  <none>
      

      출력에는 기본 네임스페이스 내에 있으며 my-gateway-extension이라는 이름이 지정된 GCPRoutingExtension의 세부정보가 표시됩니다. 출력에는 확장 프로그램의 동작 방식을 정의하는 Spec 필드가 표시됩니다.

    2. 게이트웨이 바인딩을 확인합니다.

      1. GCPRoutingExtension이 게이트웨이에 바인딩되었는지 확인합니다. 이 작업은 몇 분 정도 소요될 수 있습니다.

        kubectl describe gateway GATEWAY_NAME
        

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

        Name:         GATEWAY_NAME
        Namespace:    default
        Labels:       none
        Annotations:  networking.gke.io/addresses: /projects/1234567890/regions/us-central1/addresses/test-hgbk-default-internal-http-5ypwen3x2gcr
                      networking.gke.io/backend-services:
                        /projects/1234567890/regions/us-central1/backendServices/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/re...
                      networking.gke.io/firewalls: /projects/1234567890/global/firewalls/test-hgbk-l7-default-us-central1
                      networking.gke.io/forwarding-rules: /projects/1234567890/regions/us-central1/forwardingRules/test-hgbk-default-internal-http-qn7dk9i9zm73
                      networking.gke.io/health-checks:
                        /projects/1234567890/regions/us-central1/healthChecks/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/regio...
                      networking.gke.io/last-reconcile-time: 2025-03-02T17:15:02Z
                      networking.gke.io/lb-route-extensions:
                        /projects/1234567890/locations/us-central1/lbRouteExtensions/test-hgbk-default-internal-http-lwh0op4qorb0
                      networking.gke.io/lb-traffic-extensions:
                      networking.gke.io/ssl-certificates:
                      networking.gke.io/target-http-proxies:
                        /projects/1234567890/regions/us-central1/targetHttpProxies/test-hgbk-default-internal-http-2jzr7e3xclhj
                      networking.gke.io/target-https-proxies:
                      networking.gke.io/url-maps: /projects/1234567890/regions/us-central1/urlMaps/test-hgbk-default-internal-http-2jzr7e3xclhj
        API Version:  gateway.networking.k8s.io/v1
        Kind:         Gateway
        Metadata:
          Creation Timestamp:  2025-03-02T16:37:50Z
          Finalizers:
          gateway.finalizer.networking.gke.io
          Generation:        1
          Resource Version:  31284863
          UID:               fd512611-bad2-438e-abfd-5619474fbf31
        ...
        

        출력에는 GKE가 게이트웨이와 기본Google Cloud 리소스 간의 링크를 저장하는 데 사용하는 주석이 표시됩니다. networking.gke.io/lb-route-extensions 주석은 게이트웨이와 GCPRoutingExtension의 바인딩을 확인합니다.

      2. GCPRoutingExtensionProgrammingSucceeded 이유와 함께 Programmed 상태가 있는지 확인하여 확장 프로그램 상태를 확인합니다. 이 명령어는 몇 분 정도 걸릴 수 있습니다.

        kubectl describe gcproutingextension my-gateway-extension
        

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

        Name:         my-gateway-extension
        Namespace:    default
        Labels:       <none>
        Annotations:  <none>
        API Version:  networking.gke.io/v1
        Kind:         GCPRoutingExtension
        Metadata:
          Creation Timestamp:  2025-03-02T17:12:30Z
          Generation:          1
          Resource Version:    31284378
          UID:                 ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
        Spec:
          Extension Chains:
            Extensions:
              Authority:  myext.com
              Backend Ref:
                Group:
                Kind:   Service
                Name:   extension-service
                Port:   443
              Name:     ext1
              Timeout:  1s
            Match Condition:
              Cel Expressions:
                Cel Matcher:  request.path.contains("serviceextensions")
            Name:             chain1
          Target Refs:
            Group:  gateway.networking.k8s.io
            Kind:   Gateway
            Name:   GATEWAY_NAME
        Status:
          Ancestors:
            Ancestor Ref:
              Group:      gateway.networking.k8s.io
              Kind:       Gateway
              Name:       GATEWAY_NAME
              Namespace:  default
            Conditions:
              Last Transition Time:  2025-03-02T17:14:15Z
              Message:
              Reason:                Accepted
              Status:                True
              Type:                  Accepted
              Last Transition Time:  2025-03-02T17:14:15Z
              Message:
              Reason:                ProgrammingSucceeded
              Status:                True
              Type:                  Programmed
            Controller Name:         networking.gke.io/gateway
        Events:
          Type    Reason  Age                From                   Message
          ----    ------  ----               ----                   -------
          Normal  ADD     2m31s              sc-gateway-controller  default/my-gateway-extension
        Normal  SYNC    51s (x2 over 98s)  sc-gateway-controller  Attachment of GCPRoutingExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        "GATEWAY_NAME",
        SectionName: nil,
        Port:        nil} was a success
          Normal  SYNC    23s           sc-gateway-controller  Reconciliation of GCPRoutingExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        "GATEWAY_NAME",
        SectionName: nil,
        Port:        nil} was a success
        

        Status.Conditions 필드에는 Status: TrueReason: ProgrammingSucceeded이 있는 Programmed 조건이 표시됩니다. 이 정보는 확장 프로그램이 성공적으로 적용되었음을 확인해 줍니다.

  4. 애플리케이션에 트래픽을 보냅니다.

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

    1. 애플리케이션에 액세스하려면 게이트웨이의 IP 주소를 찾아야 합니다.

      터미널에서 다음 명령어를 사용합니다.

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

      GATEWAY_NAME을 게이트웨이 이름으로 바꿉니다.

      이 명령어는 게이트웨이의 IP 주소를 출력합니다. 후속 명령어에서 GATEWAY_IP_ADDRESS을 출력의 IP 주소로 바꿉니다.

    2. store.example.com/serviceextensions에서 스토어 서비스의 serviceextensions 버전으로 이동하여 경로 업데이트를 테스트합니다.

      curl http://store.example.com/serviceextensions --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
      

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

      {
      "cluster_name": "gke1",
      "host_header": "service-extensions.com",
      "metadata": "store-v1",
      "pod_name": "store-v1-5d9554f847-cvxpd",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo",
      "timestamp": "2025-03-15T12:00:00",
      "zone": "us-central1-c"
      }
      

GCPTrafficExtension 구성

GCPTrafficExtension를 사용하여 Google Cloud 환경 내에서 고급 트래픽 관리 기능을 사용할 수 있습니다. 전역 외부 애플리케이션 부하 분산기, 리전 외부 애플리케이션 부하 분산기, 리전 내부 애플리케이션 부하 분산기에서 이 확장 프로그램을 구성할 수 있습니다. GCPTrafficExtension를 사용하여 맞춤 HTTP 요청 및 응답 로직, 정교한 라우팅, 변환, 보안 정책을 구현할 수 있습니다.

  1. HTTPRoute를 업데이트합니다. 트래픽 확장을 트리거하는 호스트 이름 또는 경로를 포함하도록 HTTPRoute를 수정합니다.

    1. 다음 샘플 매니페스트를 store-route.yaml 파일로 저장합니다.

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: store
      spec:
        parentRefs:
        - kind: Gateway
          name: GATEWAY_NAME
        hostnames:
        - "store.example.com"
        - "service-extensions.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
      

      GATEWAY_NAME을 게이트웨이 이름(예: internal-http, external-http, global-external-http)으로 바꿉니다.

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

      kubectl apply -f store-route.yaml
      
  2. GCPTrafficExtension을 정의합니다.

    1. GCPTrafficExtension 구성을 샘플 gcp-traffic-extension.yaml 파일에 저장합니다.

      kind: GCPTrafficExtension
      apiVersion: networking.gke.io/v1
      metadata:
        name: my-traffic-extension
        namespace: default
      spec:
        targetRefs:
        - group: "gateway.networking.k8s.io"
          kind: Gateway
          name: GATEWAY_NAME
        extensionChains:
        - name: chain1
          matchCondition:
            celExpressions:
            - celMatcher: request.path.contains("serviceextensions")
          extensions:
          - name: ext1
            authority: "myext.com"
            timeout: 1s
            backendRef:
              group: ""
              kind: Service
              name: extension-service
              port: 443
      

      GATEWAY_NAME을 게이트웨이 이름(internal-http, external-http, global-external-http)으로 바꿉니다.

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

      kubectl apply -f gcp-traffic-extension.yaml
      
  3. GCPTrafficExtension 구성과 게이트웨이와의 바인딩을 확인합니다.

    1. GCPTrafficExtension 배포를 확인합니다.

      kubectl describe gcptrafficextension my-traffic-extension
      

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

      Name:         my-traffic-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:        1
        Resource Version:  31283253
        UID:               ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:    myext.com
            Backend Ref:
              Group:
              Kind: Service
              Name: extension-service
              Port: 443
            Name:       ext1
            Timeout:    1s
          Match Condition:
            Cel Expressions:
              Cel Matcher: request.path.contains("serviceextensions")
          Name:  chain1
        Target Refs:
          Group: gateway.networking.k8s.io
          Kind: Gateway
          Name: GATEWAY_NAME
      Events:  <none>
      

      출력에 기본 네임스페이스 내 my-traffic-extension이라는 이름의 GCPTrafficExtension 세부정보가 표시됩니다. 확장 프로그램이 작동하는 방식을 정의하는 Spec 필드가 표시됩니다.

    2. 게이트웨이 바인딩을 확인합니다.

      GCPTrafficExtension이 게이트웨이에 바인딩되었는지 확인합니다. 이 명령어를 완료하는 데 몇 분이 걸릴 수 있습니다.

      kubectl describe gateway GATEWAY_NAME
      

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

      Name:         GATEWAY_NAME
      Namespace:    default
      Labels:       <none>
      Annotations:  networking.gke.io/addresses: /projects/1234567890/regions/us-central1/addresses/test-hgbk-default-internal-http-5ypwen3x2gcr
                    networking.gke.io/backend-services:
                      /projects/1234567890/regions/us-central1/backendServices/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/re...
                    networking.gke.io/firewalls: /projects/1234567890/global/firewalls/test-hgbk-l7-default-us-central1
                    networking.gke.io/forwarding-rules: /projects/1234567890/regions/us-central1/forwardingRules/test-hgbk-default-internal-http-qn7dk9i9zm73
                    networking.gke.io/health-checks:
                      /projects/1234567890/regions/us-central1/healthChecks/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/regio...
                    networking.gke.io/last-reconcile-time: 2025-03-02T17:15:02Z
                    networking.gke.io/lb-traffic-extensions:
                      /projects/1234567890/locations/us-central1/lbTrafficExtensions/test-hgbk-default-internal-http-lwh0op4qorb0
                    networking.gke.io/ssl-certificates:
                    networking.gke.io/target-http-proxies:
                      /projects/1234567890/regions/us-central1/targetHttpProxies/test-hgbk-default-internal-http-2jzr7e3xclhj
                    networking.gke.io/target-https-proxies:
                    networking.gke.io/url-maps: /projects/1234567890/regions/us-central1/urlMaps/test-hgbk-default-internal-http-2jzr7e3xclhj
      API Version:  gateway.networking.k8s.io/v1
      Kind:         Gateway
      Metadata:
        Creation Timestamp:  2025-03-02T16:37:50Z
        Finalizers:
          gateway.finalizer.networking.gke.io
        Generation:        1
        Resource Version:  31284863
        UID:               fd512611-bad2-438e-abfd-5619474fbf31
      ...
      

      출력에는 게이트웨이와 기본 Google Cloud 리소스 간의 링크를 저장하는 데 GKE가 사용하는 주석이 표시됩니다. networking.gke.io/lb-traffic-extensions 주석으로 바인딩을 확인할 수 있습니다.

    3. 확장 프로그램 상태를 확인합니다.

      GCPTrafficExtension의 상태가 ProgrammingSucceeded 이유로 Programmed인지 확인합니다. 명령어를 완료하는 데 몇 분이 걸릴 수 있습니다.

      GCPTrafficExtension의 확장 프로그램 상태를 확인하려면 다음 명령어를 실행합니다.

      kubectl describe gcptrafficextension my-traffic-extension
      

      GCPTrafficExtension 리소스 출력은 다음과 비슷합니다.

      Name:         my-traffic-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:          1
        Resource Version:    31284378
        UID:                 ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:  myext.com
            Backend Ref:
              Group:
              Kind:   Service
              Name:   extension-service
              Port:   443
            Name:     ext1
            Timeout:  1s
          Match Condition:
            Cel Expressions:
              Cel Matcher:  request.path.contains("serviceextensions")
          Name:             chain1
        Target Refs:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   GATEWAY_NAME
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       GATEWAY_NAME
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-03-02T17:14:15Z
            Message:
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-03-02T17:14:15Z
            Message:
            Reason:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                From                   Message
        ----    ------  ----               ----                   -------
        Normal  ADD     2m31s              sc-gateway-controller  default/my-traffic-extension
        Normal  SYNC    51s (x2 over 98s)  sc-gateway-controller  Attachment of GCPTrafficExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        "GATEWAY_NAME",
        SectionName: nil,
        Port:        nil} was a success
        Normal  SYNC    23s           sc-gateway-controller  Reconciliation of GCPTrafficExtension "default/my-traffic-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        "GATEWAY_NAME",
        SectionName: nil,
        Port:        nil} was a success
      

      Status.Conditions 필드에는 Status: TrueReason: ProgrammingSucceeded이 있는 Programmed 조건이 표시됩니다. 이 정보는 확장 프로그램이 성공적으로 적용되었음을 확인해 줍니다.

  4. 애플리케이션에 트래픽을 보냅니다.

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

    1. 애플리케이션에 액세스하려면 게이트웨이의 IP 주소를 찾아야 합니다.

      터미널에서 다음 명령어를 사용합니다.

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

      GATEWAY_NAME을 게이트웨이 이름으로 바꿉니다.

      이 명령어는 게이트웨이의 IP 주소를 출력합니다. 후속 명령어에서 GATEWAY_IP_ADDRESS을 출력의 IP 주소로 바꿉니다.

    2. store.example.com/serviceextensions에서 스토어 서비스의 serviceextensions 버전으로 이동하여 경로 업데이트를 테스트합니다.

      curl http://store.example.com/serviceextensions --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
      

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

      {
      *   Request completely sent off
      < HTTP/1.1 200 OK
      < server: Werkzeug/2.3.7 Python/3.11.3
      < date: Sun, 02 Mar 2025 16:58:10 GMT
      < content-type: application/json
      < access-control-allow-origin: *
      < hello: service-extensions
      < via: 1.1 google
      < transfer-encoding: chunked
      }
      

GCPWasmPlugin 리소스 참조

GCPTrafficExtension이 있는 GCPWasmPlugin를 사용하여 부하 분산기의 데이터 경로에 직접 커스텀 로직을 삽입할 수 있습니다. 이 방법을 사용하면 Wasm 모듈로 패키징된 맞춤 트래픽 관리 기능을 배포할 수 있습니다.

GKE Service Extensions를 구성하려면 다음 단계를 따르세요.

  1. GCPWasmPlugin 배포: Wasm 모듈의 맞춤 코드가 포함된 GCPWasmPlugin 커스텀 리소스 정의 (CRD)를 만들고 배포합니다. gke-l7-global-external-managed GatewayClass의 경우 GCPTrafficExtension에만 GCPWasmPlugin를 사용할 수 있습니다.

  2. 서비스 확장 프로그램 구성: 전역 외부 애플리케이션 부하 분산기에 GCPTrafficExtension 사용

GCPWasmPlugin 배포

GCPWasmPlugin를 사용하면 사용자 작성 커스텀 로직을 Google Cloud 부하 분산기의 데이터 경로에 직접 삽입할 수 있습니다. GCPWasmPlugin 리소스는 Artifact Registry의 Wasm 모듈 이미지를 가리키며, 이 이미지는 로드 밸런서에 의해 실행됩니다.

다음 단계를 계속하기 전에 Wasm 모듈을 Artifact Registry 저장소에 업로드했는지 확인합니다. 자세한 내용은 플러그인 코드 준비를 참고하세요.

GCPWasmPlugin 리소스를 배포하려면 다음 단계를 완료하세요.

  1. 다음 매니페스트를 wasm-plugin.yaml로 저장합니다.

    kind: GCPWasmPlugin
    apiVersion: networking.gke.io/v1
    metadata:
      name: gcp-wasm-plugin
    spec:
      versions:
      - name: wasm-plugin-version
        description: "Test wasm plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 1000000
      logConfig:
        enabled: true
        # Configures the sampling rate of activity logs.
        # The value of the field must be in range [0, 1e6].
        sampleRate: 1000000
        # Specifies the lowest level of logs that are exported to Cloud Logging.
        minLogLevel: INFO
    

    다음에 유의하세요.

    • spec.versions.name: 버전 이름은 GCPWasmPlugin 리소스 내에서 고유해야 합니다. 최대 10개의 버전을 나열할 수 있으며, 하나의 버전만 0이 아닌 가중치를 가져야 합니다.
    • spec.versions.image: Artifact Registry에 저장된 플러그인 코드가 포함된 이미지를 참조합니다.
    • spec.versions.weight: 플러그인 버전의 가중치를 지정합니다. 가중치는 0 이상 1,000,000 이하의 숫자여야 합니다.
    • spec.logConfig: 이 플러그인에 Cloud Logging을 사용 설정할지 여부를 지정합니다. 값을 지정하지 않으면 기본적으로 Cloud Logging이 사용 중지됩니다.
    • spec.logConfig.sampleRate: 활동 로그의 샘플링 레이트를 구성합니다. 비율은 0 이상 1,000,000 이하여야 합니다. Cloud Logging이 사용 설정된 경우 지정하지 않으면 기본값은 1,000,000(요청의 100% 가 로깅됨)입니다.
    • spec.logConfig.minLogLevel: Cloud Logging으로 내보내지는 로그의 최저 수준을 지정합니다. Cloud Logging이 사용 설정된 경우 값을 지정하지 않으면 필드가 기본적으로 INFO로 설정됩니다.
  2. wasm-plugin.yaml 매니페스트를 적용합니다.

    kubectl apply -f wasm-plugin.yaml
    
  3. 플러그인이 배포되었는지 확인합니다.

    kubectl describe gcpwasmplugins.networking.gke.io gcp-wasm-plugin
    

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

    Name:         gcp-wasm-plugin
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  networking.gke.io/v1
    Kind:         GCPWasmPlugin
    Metadata:
      Creation Timestamp:  2025-08-08T19:54:18Z
      Generation:          1
      Resource Version:    44578
      UID:                 549a12c7-91d1-43ad-a406-d6157a799b79
    Spec:
      Log Config:
        Enabled: true
        Min Log Level: INFO
        Sample Rate: 1000000
      Versions:
        Description:  Test wasm plugin version
        Image:        us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main
        Name:         wasm-plugin-version
        Weight:       1000000
      Events:     <none>
    

서비스 확장 프로그램 구성

전역 외부 애플리케이션 부하 분산기에 맞춤 로직을 추가하려면 GCPWasmPlugin을 사용하도록 GCPTrafficExtension를 구성하면 됩니다. GCPTrafficExtension를 사용하여 Google Cloud 환경 내에서 고급 트래픽 관리 기능을 사용할 수 있습니다. 전역 외부 애플리케이션 부하 분산기에서 이 확장 프로그램을 구성할 수 있습니다.

GCPWasmPlugin을 사용하도록 GCPTrafficExtension을 구성하려면 다음 단계를 완료하세요.

  1. GCPTrafficExtension을 정의합니다.

    1. GCPTrafficExtension 구성을 gcp-traffic-extension-with-plugin.yaml로 저장합니다.

      kind: GCPTrafficExtension
      apiVersion: networking.gke.io/v1
      metadata:
        name: gcp-traffic-extension-with-plugin
        namespace: default
      spec:
        targetRefs:
        - group: "gateway.networking.k8s.io"
          kind: Gateway
          name: GATEWAY_NAME
        extensionChains:
        - name: chain1
          matchCondition:
            celExpressions:
            - celMatcher: request.path.contains("serviceextensions")
          extensions:
          - name: ext1
            supportedEvents:
            - RequestHeaders
            - ResponseHeaders
            backendRef:
              group: "networking.gke.io"
              kind: GCPWasmPlugin
              name: gcp-wasm-plugin
      

      GATEWAY_NAME을 게이트웨이 이름으로 바꿉니다(예: global-external-http).

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

      kubectl apply -f gcp-traffic-extension-with-plugin.yaml
      
  2. GCPTrafficExtension 구성과 게이트웨이와의 바인딩을 확인합니다.

    1. GCPTrafficExtension 배포를 확인합니다.

      kubectl describe gcptrafficextensions.networking.gke.io gcp-traffic-extension-with-plugin
      

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

      Name:         gcp-traffic-extension-with-plugin
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:        1
        Resource Version:  31283253
        UID:               ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Backend Ref:
              Group: networking.gke.io
              Kind: GCPWasmPlugin
              Name: gcp-wasm-plugin
            Name:       ext1
            Supported Events:
              RequestHeaders
              ResponseHeaders
          Match Condition:
            Cel Expressions:
              Cel Matcher: request.path.contains("serviceextensions")
          Name:  chain1
        Target Refs:
          Group: gateway.networking.k8s.io
          Kind: Gateway
          Name: GATEWAY_NAME
      Events:  <none>
      

      출력에 기본 네임스페이스 내 gcp-traffic-extension-with-plugin이라는 이름의 GCPTrafficExtension 세부정보가 표시됩니다. 확장 프로그램이 작동하는 방식을 정의하는 Spec 필드가 표시됩니다.

    2. 게이트웨이 바인딩을 확인합니다.

      GCPTrafficExtension이 게이트웨이에 바인딩되었는지 확인합니다. 이 명령어를 완료하는 데 몇 분이 걸릴 수 있습니다.

      kubectl describe gateway GATEWAY_NAME
      

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

      Name:         GATEWAY_NAME
      Namespace:    default
      Labels:       <none>
      Annotations:  networking.gke.io/addresses: /projects/922988411345/global/addresses/test-k18j-default-external-http-2jfqxrkgd0fm
                    networking.gke.io/backend-services:
                      /projects/922988411345/global/backendServices/test-k18j-default-gw-serve404-80-8zjp3d8cqfsu, /projects/922988411345/global/backendServices...
                      networking.gke.io/certmap: store-example-com-map
                      networking.gke.io/firewalls: /projects/922988411345/global/firewalls/test-k18j-l7-default-global
                      networking.gke.io/forwarding-rules: /projects/922988411345/global/forwardingRules/test-k18j-default-external-http-wt1tl0cwi6zr
                      networking.gke.io/health-checks:
                        /projects/922988411345/global/healthChecks/test-k18j-default-gw-serve404-80-8zjp3d8cqfsu, /projects/922988411345/global/healthChecks/test-...
                      networking.gke.io/last-reconcile-time: 2025-08-08T20:27:35Z
                      networking.gke.io/lb-route-extensions:
                      networking.gke.io/lb-traffic-extensions:
                        projects/922988411345/locations/global/lbTrafficExtensions/test-k18j-default-external-http-0tdum40yts35
                      networking.gke.io/ssl-certificates:
                      networking.gke.io/target-http-proxies:
                      networking.gke.io/target-https-proxies: /projects/922988411345/global/targetHttpsProxies/test-k18j-default-external-http-jy9mc97xb5yh
                      networking.gke.io/url-maps: /projects/922988411345/global/urlMaps/test-k18j-default-external-http-jy9mc97xb5yh
                      networking.gke.io/wasm-plugin-versions:
                        projects/922988411345/locations/global/wasmPlugins/test-k18j-default-gcp-wasm-plugin-itle20jj9nyk/versions/test-k18j-wasm-plugin-version-i...
                      networking.gke.io/wasm-plugins: projects/922988411345/locations/global/wasmPlugins/test-k18j-default-gcp-wasm-plugin-itle20jj9nyk
      API Version:  gateway.networking.k8s.io/v1
      Kind:         Gateway
      Metadata:
        Creation Timestamp:  2025-03-02T16:37:50Z
        Finalizers:
          gateway.finalizer.networking.gke.io
        Generation:        1
        Resource Version:  31284863
        UID:               fd512611-bad2-438e-abfd-5619474fbf31
      Spec:
        Gateway Class Name:  gke-l7-global-external-managed
        Listeners:
          Allowed Routes:
            Namespaces:
              From:  Same
          Name:      https
          Port:      443
          Protocol:  HTTPS
      ...
      

      출력에는 GKE가 게이트웨이와 기본 Google Cloud리소스 간의 링크를 저장하는 데 사용하는 주석이 표시됩니다. networking.gke.io/lb-traffic-extensions, networking.gke.io/wasm-plugin-versions, networking.gke.io/wasm-plugins 주석은 바인딩을 확인합니다.

    3. 확장 프로그램 상태를 확인합니다.

      GCPTrafficExtension의 상태가 ProgrammingSucceeded 이유로 Programmed인지 확인합니다. 명령어를 완료하는 데 몇 분이 걸릴 수 있습니다.

      kubectl describe gcptrafficextensions.networking.gke.io gcp-traffic-extension-with-plugin
      

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

      Name:         gcp-traffic-extension-with-plugin
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-08-08T20:08:09Z
        Generation:          1
        Resource Version:    56528
        UID:                 1389f790-9663-45ca-ac4e-a2c082f43359
      Spec:
        Extension Chains:
          Extensions:
            Backend Ref:
              Group:  networking.gke.io
              Kind:   GCPWasmPlugin
              Name:   gcp-wasm-plugin
            Name:     ext1
            Supported Events:
              RequestHeaders
              ResponseHeaders
          Match Condition:
            Cel Expressions:
              Cel Matcher:  request.path.contains("serviceextensions")
          Name:             chain1
        Target Refs:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   external-http
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       external-http
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                ResolvedRefs
            Status:                True
            Type:                  ResolvedRefs
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                  From                   Message
        ----    ------  ----                 ----                   -------
        Normal  ADD     19m                  sc-gateway-controller  default/gcp-traffic-extension-with-plugin
        Normal  SYNC    3m25s (x4 over 11m)  sc-gateway-controller  Attachment of GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
        Normal  SYNC  3m25s (x4 over 11m)  sc-gateway-controller  All the object references were able to be resolved for GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" bound to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil}
        Normal  SYNC  3m25s (x4 over 11m)  sc-gateway-controller  Programming of GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
      
    4. 플러그인 상태를 확인합니다.

      GCPWasmPlugin 리소스의 상태가 ProgrammingSucceeded 이유로 Programmed인지 확인합니다. 명령어를 완료하는 데 몇 분이 걸릴 수 있습니다.

      kubectl describe gcpwasmplugins.networking.gke.io gcp-wasm-plugin
      

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

      Name:         gcp-wasm-plugin
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPWasmPlugin
      Metadata:
        Creation Timestamp:  2025-08-08T19:54:18Z
        Generation:          1
        Resource Version:    44578
        UID:                 549a12c7-91d1-43ad-a406-d6157a799b79
      Spec:
        Log Config:
          Enabled: true
          Min Log Level: INFO
          Sample Rate: 1000000
        Versions:
          Description:  Test wasm plugin version
          Image:        us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main
          Name:         wasm-plugin-version
          Weight:       1000000
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       external-http
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                ResolvedRefs
            Status:                True
            Type:                  ResolvedRefs
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                 From                   Message
        ----    ------  ----                ----                   -------
        Normal  ADD     31m                 sc-gateway-controller  default/gcp-wasm-plugin
        Normal  SYNC    2m1s (x7 over 26m)  sc-gateway-controller  Attachment of WasmPlugin "default/gcp-wasm-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
        Normal  SYNC  2m1s (x7 over 26m)  sc-gateway-controller  All the object references were able to be resolved for WasmPlugin "default/gcp-wasm-plugin" bound to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil}
        Normal  SYNC  2m1s (x7 over 26m)  sc-gateway-controller  Programming of WasmPlugin "default/gcp-wasm-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
      
  3. 애플리케이션에 트래픽을 보냅니다.

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

    1. 애플리케이션에 액세스하려면 게이트웨이의 IP 주소를 찾아야 합니다.

      터미널에서 다음 명령어를 사용합니다.

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

      GATEWAY_NAME을 게이트웨이 이름으로 바꿉니다.

      이 명령어는 게이트웨이의 IP 주소를 출력합니다. 후속 명령어에서 GATEWAY_IP_ADDRESS을 출력의 IP 주소로 바꿉니다.

    2. store.example.com/serviceextensions에서 스토어 서비스의 serviceextensions 버전으로 이동하여 경로 업데이트를 테스트합니다.

      curl https://store.example.com/serviceextensions --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
      

      출력은 Hello World을 반환합니다.

GCPWasmPlugin 리소스 관리

GCPWasmPlugin CRD를 업데이트하고 플러그인을 모니터링할 수 있습니다.

GCPWasmPlugin 업데이트

GCPWasmPlugin 리소스를 업데이트하려면 다음 단계를 따르세요.

  1. GCPWasmPlugin 매니페스트를 변경하고 GCPWasmPlugin 배포에 설명된 단계를 따릅니다.

    예를 들어 한 버전은 트래픽을 처리하고 다른 버전은 트래픽을 처리하지 않는 두 버전의 플러그인이 있는 경우 wasm-plugin.yaml 파일을 다음과 같이 업데이트합니다.

    kind: GCPWasmPlugin
    apiVersion: networking.gke.io/v1
    metadata:
      name: gcp-wasm-plugin
    spec:
      versions:
      - name: wasm-plugin-version-v1
        description: "Serving Wasm Plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 1000000
      - name: wasm-plugin-version-v2
        description: "Non serving Wasm Plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 0
      logConfig:
        enabled: true
        sampleRate: 1000000
        minLogLevel: INFO
    

    이 예에서는 다음이 적용됩니다.

    • wasm-plugin-version-v1weight1000000이므로 모든 트래픽을 처리합니다.
    • wasm-plugin-version-v2weight0이므로 트래픽을 제공하지 않습니다.
  2. 게이트웨이가 업데이트되었는지 확인하려면 다음 명령어를 실행합니다. 이 명령어를 완료하는 데 몇 분이 걸릴 수 있습니다.

    kubectl describe gateway GATEWAY_NAME
    

    GATEWAY_NAME을 게이트웨이 이름으로 바꿉니다.

GCPWasmPlugin 모니터링하기

Google Cloud 콘솔에서 GCPWasmPlugin의 측정항목을 보려면 플러그인 관점에서 모니터링을 참고하세요.

가이드에서 플러그인 버전 필터 목록에서 값을 선택해야 하는 단계에 도달하면 prefix−WASM_PLUGIN_VERSION_NAME_FROM_FILE−suffix 형식을 찾습니다. 여기서 WASM_PLUGIN_VERSION_NAME_FROM_FILEGCPWasmPlugin 구성 파일에 정의한 특정 버전 이름입니다.

게이트웨이의 트래픽 확장 문제 해결

이 섹션에서는 게이트웨이에서 트래픽 확장 프로그램을 구성하는 데 도움이 되는 문제 해결 팁을 제공합니다.

게이트웨이를 찾을 수 없음

다음 오류는 GCPTrafficExtension 또는 GCPRoutingExtension 리소스의 targetRefs 필드에 지정된 게이트웨이 리소스가 존재하지 않음을 나타냅니다.

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.gatewayRef: gateway "my-gateway" not found in namespace "default"

이 문제를 해결하려면 GCPTrafficExtension 또는 GCPRoutingExtension 리소스의 targetRefs 필드에 지정된 게이트웨이 리소스가 지정된 네임스페이스에 있는지 확인합니다.

서비스 또는 서비스 포트를 찾을 수 없음

다음 오류는 GCPTrafficExtension 또는 GCPRoutingExtension 리소스의 backendRef 필드에 지정된 서비스 또는 서비스 포트가 존재하지 않음을 나타냅니다.

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.service: service "callout-service" not found in namespace "default"

이 문제를 해결하려면 GCPTrafficExtension 또는 GCPRoutingExtension 리소스의 backendRef 필드에 지정된 서비스와 서비스 포트가 지정된 네임스페이스에 있는지 확인합니다.

NEG에 네트워크 엔드포인트가 없음

다음 오류는 NEG에 GCPTrafficExtension 또는 GCPRoutingExtension 리소스의 backendRef 필드에 지정된 서비스와 연결된 네트워크 엔드포인트가 없음을 나타냅니다.

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.service: no network endpoints found for service "callout-service"

이 문제를 해결하려면 GCPTrafficExtension 또는 GCPRoutingExtension 리소스의 backendRef 필드에 지정된 서비스에 네트워크 엔드포인트가 있는지 확인합니다.

요청을 보낼 때 답장이 없거나 오류가 포함된 답장이 전송됨

요청을 보낼 때 답장을 받지 못하거나 오류가 포함된 답장을 받는 경우 콜아웃 서비스가 올바르게 작동하지 않는 것일 수 있습니다.

이 문제를 해결하려면 콜아웃 서비스의 로그에서 오류를 확인하세요.

JSON 페이로드의 오류 코드 404

다음 오류는 콜아웃 서비스를 찾을 수 없거나 요청에 응답하지 않음을 나타냅니다.

{
  "error": {
    "code": 404,
    "message": "Requested entity was not found.",
    "status": "NOT_FOUND"
  }
}

이 문제를 해결하려면 콜아웃 서비스가 실행 중이고, 올바른 포트에서 수신 대기 중이며, 서비스가 GCPTrafficExtension 또는 GCPRoutingExtension 리소스에서 올바르게 구성되어 있는지 확인합니다.

JSON 페이로드의 오류 코드 500

다음 오류는 콜아웃 서비스에 내부 서버 오류가 발생했음을 나타냅니다.

{
  "error": {
    "code": 500,
    "message": "Internal server error.",
    "status": "INTERNAL"
  }
}

이 문제를 해결하려면 콜아웃 서비스의 로그를 확인하여 내부 서버 오류의 원인을 파악하세요.

GCPWasmPlugin 없음

다음 오류는 프로젝트에 GCPWasmPlugin 리소스가 없음을 나타냅니다.

Status:
  Ancestors:
    Ancestor Ref:
      Group:      gateway.networking.k8s.io
      Kind:       Gateway
      Name:       external-http
      Namespace:  default
    Conditions:
      Last Transition Time:  2025-03-06T16:27:57Z
      Message:
      Reason:                Accepted
      Status:                True
      Type:                  Accepted
      Last Transition Time:  2025-03-06T16:27:57Z
      Message:               error cause: invalid-wasm-plugin: GCPWasmPlugin default/my-wasm-plugin in GCPTrafficExtension default/my-gateway-plugin-extension does not exist
      Reason:                GCPWasmPluginNotFound
      Status:                False
      Type:                  ResolvedRefs
    Controller Name:         networking.gke.io/gateway

이 문제를 해결하려면 Google Cloud 프로젝트에서 해당 GCPWasmPlugin를 만들거나 기존 GCPWasmPlugin확장 프로그램을 연결하세요.

다음 단계