EnvoyFilter를 사용한 데이터 영역 확장성

EnvoyFilter API를 사용하면 다른 Istio API를 사용하여 달성할 수 없는 Cloud Service Mesh의 데이터 영역 기능을 확장할 수 있습니다. EnvoyFilter API를 사용하면 HTTP 필터 체인에 필터를 추가하는 것과 같이 워크로드에 적용된 다른 정책에서 생성된 Envoy 구성을 맞춤설정할 수 있습니다.

중요 고려사항

  • API 노출 영역은 내부 구현 세부정보와 연결되어 있으므로 잘못된 구성으로 인해 메시가 불안정해질 수 있으므로 이 기능을 사용할 때는 특별히 주의해야 합니다. 다른 Istio API가 요구사항에 맞지 않는 경우에만 EnvoyFilter API를 사용하세요.
  • EnvoyFilter API는 안정성 및 지원 가능성을 위해 사용할 수 있는 필드 및 확장 프로그램에 특정 제한사항이 적용되어 지원됩니다. EnvoyFilter API에서 지원되는 기능의 전체 목록은 Istio API를 사용하는 지원 기능 (관리형 컨트롤 플레인)을 참조하세요.
  • Google에서 제공하는 지원 범위는 Envoy 사이드카가 있는 워크로드에 사용자가 제공한 구성을 전파하는 것으로 제한되며 확장 프로그램별 API를 사용하여 지정된 구성의 정확성에는 적용되지 않습니다.

지원되는 API 필드

EnvoyFilter API는 다음과 같이 제한된 지원만으로 TRAFFIC_DIRECTOR 컨트롤 플레인 구현에서만 지원됩니다.

  • targetRefs: 지원되지 않음
  • configPatches[].applyTo : HTTP_FILTER만 지원됨
  • configPatches[].patch.operation: 경로 필터와 함께 사용되는 경우 INSERT_FIRSTINSERT_BEFORE만 지원됨
  • configPatches[].patch.value.type_url: 지원되는 확장 프로그램 참조
  • configPatches[].patch.filterClass: 지원되지 않음
  • configPatches[].match.proxy: 지원되지 않음
  • configPatches[].match.routeConfiguration: 지원되지 않음
  • configPatches[].match.cluster: 지원되지 않음
  • 다음 필드는 INSERT_BEFORE 작업에만 지원됩니다.
    • configPatches[].match.listener: filter만 지원됨
    • configPatches[].match.listener.filter.name: envoy.filters.network.http_connection_manager만 지원됨
    • configPatches[].match.listener.filter.subFilter.name: envoy.filters.http.router만 지원됨

지원되는 확장 프로그램

다음은 다양한 출시 채널에서 지원되는 API 필드와 함께 지원되는 확장 프로그램 목록입니다. API 정의 및 의미는 공식 Envoy 문서에서 확인할 수 있습니다.

type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit

필드 신속 일반 정식
stat_prefix
status
token_bucket
filter_enabled
filter_enforced
response_headers_to_add
request_headers_to_add_when_not_enforced
local_rate_limit_per_downstream_connection
enable_x_ratelimit_headers

type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb

필드 신속 일반 정식
(필드 없음)

사용 예시

이 튜토리얼에서는 Envoy의 기본 제공 로컬 비율 제한을 사용하여 EnvoyFilter API를 통해 서비스로의 트래픽을 동적으로 제한하는 방법을 알아봅니다.

비용

이 튜토리얼에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud구성요소를 사용합니다.

이 튜토리얼을 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않도록 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

인그레스 게이트웨이 배포

  1. kubectl의 현재 컨텍스트를 클러스터로 설정합니다.

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  2. 인그레스 게이트웨이에 대해 네임스페이스를 만듭니다.

    kubectl create namespace asm-ingress
    
  3. 네임스페이스의 삽입을 사용 설정합니다. 이 단계는 컨트롤 플레인 구현에 따라 다릅니다.

    기본 삽입 라벨을 네임스페이스에 적용합니다.

    kubectl label namespace asm-ingress \
        istio.io/rev- istio-injection=enabled --overwrite
    
  4. anthos-service-mesh-samples 저장소에 게이트웨이 예시를 배포합니다.

    kubectl apply -n asm-ingress \
        -f docs/shared/asm-ingress-gateway
    

    예상 출력:

    serviceaccount/asm-ingressgateway configured
    service/asm-ingressgateway configured
    deployment.apps/asm-ingressgateway configured
    gateway.networking.istio.io/asm-ingressgateway configured
    

Online Boutique 샘플 애플리케이션 배포

  1. 아직 설정하지 않은 경우 kubectl의 현재 컨텍스트를 클러스터로 설정합니다.

    gcloud container clusters get-credentials CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION 
    
  2. 샘플 애플리케이션의 네임스페이스를 만듭니다.

    kubectl create namespace onlineboutique
    
  3. Envoy 프록시를 자동으로 주입하도록 onlineboutique 네임스페이스에 라벨을 지정합니다.

    kubectl label namespace onlineboutique \
       istio.io/rev- istio-injection=enabled --overwrite
    
  4. 샘플 앱, 프런트엔드용 VirtualService, 워크로드의 서비스 계정을 배포합니다. 이 튜토리얼에서는 마이크로서비스 데모 앱인 Online Boutique를 배포합니다.

    kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/virtual-service.yaml
    
    kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/service-accounts
    

서비스 보기

  1. onlineboutique 네임스페이스의 포드를 확인합니다.

    kubectl get pods -n onlineboutique
    

    예상 출력:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    애플리케이션의 모든 포드가 작동되고 READY 열의 2/2를 사용해서 실행됩니다. 이것은 포드에 Envoy 사이드카 프록시가 성공적으로 주입된 것을 나타냅니다. 몇 분 후에도 2/2가 표시되지 않는다면 문제 해결 가이드를 방문하세요.

  2. 외부 IP를 가져오고 이를 변수로 설정합니다.

    kubectl get services -n asm-ingress
    export FRONTEND_IP=$(kubectl --namespace asm-ingress \
    get service --output jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}' \
    )
    

    다음과 비슷한 출력이 표시됩니다.

    NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
    asm-ingressgateway   LoadBalancer   10.19.247.233   35.239.7.64   80:31380/TCP,443:31390/TCP,31400:31400/TCP   27m
    
    
  3. 웹브라우저에서 EXTERNAL-IP 주소를 방문합니다. 브라우저에 Online Boutique 매장이 표시될 것으로 예상됩니다.

    Online Boutique 프런트엔드

비율 제한 구성 적용

이 섹션에서는 EnvoyFilter 리소스를 적용하여 frontend 서비스로의 모든 트래픽을 분당 5개의 요청으로 제한합니다.

  1. frontend 서비스에 CR을 적용합니다.

    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: frontend-local-ratelimit
      namespace: onlineboutique
    spec:
      workloadSelector:
        labels:
          app: frontend
      configPatches:
        - applyTo: HTTP_FILTER
          match:
            context: SIDECAR_INBOUND
            listener:
              filterChain:
                filter:
                  name: "envoy.filters.network.http_connection_manager"
                  subFilter:
                    name: "envoy.filters.http.router"
          patch:
            operation: INSERT_BEFORE
            value:
              name: envoy.filters.http.local_ratelimit
              typed_config:
                "@type": type.googleapis.com/udpa.type.v1.TypedStruct
                type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
                value:
                  stat_prefix: http_local_rate_limiter
                  token_bucket:
                    max_tokens: 5
                    tokens_per_fill: 5
                    fill_interval: 60s
                  filter_enabled:
                    runtime_key: local_rate_limit_enabled
                    default_value:
                      numerator: 100
                      denominator: HUNDRED
                  filter_enforced:
                    runtime_key: local_rate_limit_enforced
                    default_value:
                      numerator: 100
                      denominator: HUNDRED
    EOF
    

    예상 출력:

    envoyfilter.networking.istio.io/frontend-local-ratelimit created
    
  2. CR 상태에 오류가 보고되지 않는지 확인합니다.

    kubectl get envoyfilter -n onlineboutique frontend-local-ratelimit -o yaml
    

    예상 출력:

    ...
    status:
      conditions:
      - lastTransitionTime: "2025-06-30T14:29:25.467017594Z"
        message: This resource has been accepted. This does not mean it has been propagated
          to all proxies yet
        reason: Accepted
        status: "True"
        type: Accepted
    
  3. 토큰을 사용하는 서비스를 여러 번 호출하므로 loadgenerator 배포를 삭제합니다.

    kubectl delete -n onlineboutique deployment loadgenerator
    

    예상 출력:

    deployment.apps/loadgenerator deleted
    
  4. curl을 사용하여 60초 이내에 5개 이하의 요청이 허용되는지 확인합니다. 429 코드는 비율 제한이 적용되고 있음을 나타냅니다.

    for i in {1..10}; do curl -s http://${FRONTEND_IP} -o /dev/null -w "%{http_code}\n"; sleep 1; done
    

    예상 출력:

    200
    200
    200
    200
    200
    429
    429
    429
    429
    429
    

삭제

이 튜토리얼에서 사용된 리소스 비용이 계정에 청구되지 않도록 하려면 프로젝트를 삭제하거나 개별 리소스를 삭제하면 됩니다. Google Cloud

프로젝트 삭제

Cloud Shell에서 프로젝트를 삭제합니다.

  gcloud projects delete PROJECT_ID

리소스 삭제

  • 클러스터를 유지하고 Online Boutique를 삭제하려면 다음 안내를 따르세요.

    1. 애플리케이션 네임스페이스를 삭제합니다.

      kubectl delete namespace onlineboutique
      

      예상 출력:

      namespace "onlineboutique" deleted
      
    2. 인그레스 게이트웨이 네임스페이스를 삭제합니다.

      kubectl delete namespace asm-ingress
      

      예상 출력:

      namespace "asm-ingress" deleted
      
  • 추가 요금이 청구되지 않도록 하려면 클러스터를 삭제하세요.

    gcloud container clusters delete CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION 
    

문제 해결

데이터 영역 확장성 문제 해결을 참조하세요.