Невозможно заставить EnvoyFilter на основе lua работать

#istio #envoyproxy

Вопрос:

Я пытаюсь заставить EnvoyFilters работать в моей установке. В целях тестирования я пытаюсь установить фильтр lua, который регистрирует немое сообщение и добавляет заголовок в резонанс.

Вот моя конфигурация:

 apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: dumb-filter
  namespace: istio-system
spec:
  # workloadSelector:
  #   labels:
  #     istio: ingressgateway
  configPatches:
  # - applyTo: VIRTUAL_HOST
  - applyTo: HTTP_ROUTE
    match:
      context: GATEWAY
      # context: ANY
      routeConfiguration:
        vhost:
          # name: "<domain>:443"
          route:
            #TODO: Understand name compose logic
            name: https.443.https.geth-dedicated.default
    patch:
      operation: MERGE
      value:
        name: envoy.filters.http.lua
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
          inlineCode: |
            function envoy_on_response(response_handle)
              response_handle:headers():add("dm3ch-test", "dm3ch")
              response_handle:logErr("Bye Bye.")
            end
 

На данный момент я не вижу сообщения журнала или заголовка теста в ответе.
Я уже пробовал:

  • создайте объект EnvoyFilter как в приложении, так и в пространстве имен istio-system (где находятся модули шлюза istio)
  • указание workloadSelector (я проверил, что модуль шлюза istio имеет istio: ingressgateway метку)
  • изменение контекста с «GATEWAY» на «ANY»
  • изменение applyTo на VIRTUAL_HOST и HTTP_ROUTE режимы
  • проверено, что имя маршрута на самом деле https.443.https.geth-dedicated.default использует istioctl proxy-config route <gateway_pod> command.
  • добавление vhost.name настроек и комментариев vhost.route.name

Информация о версии Istio:

 ❯ istioctl version
client version: 1.11.4
control plane version: 1.12.0-alpha.1
data plane version: 1.12.0-alpha.1 (1 proxies)
 

json конфигурации маршрута:

 ❯ istioctl proxy-config route istio-ingress-675cb54bc9-5r8cs.istio-system --name https.443.https.geth-dedicated.default -o json
[
    {
        "name": "https.443.https.geth-dedicated.default",
        "virtualHosts": [
            {
                "name": "<domain>:443",
                "domains": [
                    "<domain>",
                    "<domain>:*"
                ],
                "routes": [
                    {
                        "match": {
                            "prefix": "/",
                            "caseSensitive": true
                        },
                        "route": {
                            "cluster": "outbound|8545||geth-dedicated.default.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts"
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "hashPolicy": [
                                {
                                    "connectionProperties": {
                                        "sourceIp": true
                                    }
                                }
                            ],
                            "maxGrpcTimeout": "0s"
                        },
                        "metadata": {
                            "filterMetadata": {
                                "istio": {
                                    "config": "/apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/geth-dedicated"
                                }
                            }
                        },
                        "decorator": {
                            "operation": "geth-dedicated.default.svc.cluster.local:8545/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            }
        ],
        "validateClusters": false

 

Я был бы рад, если бы кто-нибудь мог посоветоваться со мной, что я делаю не так или как я могу лучше отладить, почему фильтр не применяется.

PS Моя цель — вызвать пользовательскую логику во время обработки запросов / ответов при развертывании ingressgateway istio только для конкретного виртуального сервиса

Ответ №1:

Ответ Криса был очень полезен, но, к сожалению, он не был неполным. 🙁

Вот что я нашел:

  • Невозможно использовать type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua filter on HTTP_ROUTE (но можно использовать LuaPerRoute)
  • type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute сам по себе не позволяет определять новый фильтр lua, он позволяет только отключить существующий фильтр Lua или переопределить его исходный код envoy docs

Итак, чтобы создать пользовательскую логику lua, которая применяется только к одному http-маршруту, вам нужно определить «глобальный» Lua фильтр и переопределить его код для определенного http-маршрута с помощью LuaPerRoute filter.

Вот мои манифесты, которые позволили мне заставить его работать:

 apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: geth-dedicated
  namespace: default
spec:
  gateways:
  - geth-dedicated # I'm ommiting gateway creation in this snippet
  hosts:
  - <domain>
  http:
  - match:
    - uri:
        prefix: /
    name: geth-public
    route:
    - destination:
        host: geth-dedicated
        port:
          number: 8545
---
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: dumb-filter
  namespace: istio-system # Namespace where istio gateway pods are actually running
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  # Patch that creates "global" lua filter that does nothing useful
  - applyTo: HTTP_FILTER
    match:
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
    patch:
      operation: INSERT_BEFORE
      value:
        name: envoy.lua
        typed_config:
          '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
          inlineCode: |
            function envoy_on_request(request_handle)
              -- Empty lua function
            end
  # Filter for http route that overrides "global" filter lua source code
  - applyTo: HTTP_ROUTE
    match:
      context: GATEWAY
      routeConfiguration:
        vhost:
          route:
            name: geth-public # Corresponds to http[0].name in VirtualService
    patch:
      operation: MERGE
      value:
        name: envoy.lua
        typed_per_filter_config:
          envoy.filters.http.lua:
            '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute
            source_code:
              inline_string: |
                function envoy_on_response(response_handle)
                  response_handle:logErr("Goodbye my brain.")
                  response_handle:headers():add("dm3ch-test", "dm3ch wins")
                end
 

Комментарии:

1. Хорошая работа! На самом деле я никогда не использовал LuaPerRoute без «глобального» фильтра lua, поэтому я не знал, что это требуется. Если мой ответ был полезен, пожалуйста, рассмотрите возможность голосования. TY!

2. Крис, да, я только что поддержал ваш ответ

Ответ №2:

Проблема в вашей задаче #TODO: Understand name compose logic . Вам нужно установить это значение name в имя маршрута VirtualService . Также вам нужно использовать a typed_per_filter_config с типом LuaPerRoute .

Если ваш VirtualService выглядит примерно так:

 apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews-route
spec:
  hosts:
  - reviews.prod.svc.cluster.local
  http:
  - name: "reviews-v2-routes"
    route:
    - destination:
        host: reviews.prod.svc.cluster.local
        subset: v2
  - name: "reviews-v1-route"
    route:
    - destination:
        host: reviews.prod.svc.cluster.local
        subset: v1
 

чем ваши EnvoyFilter потребности должны быть настроены следующим образом:

 apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: dumb-filter
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: HTTP_ROUTE
    match:
      routeConfiguration:
        vhost:
          route:
            # name from virtual service route that the filter should apply to
            name: reviews-v1-route
    patch:
      operation: MERGE
      value:
        # 'custom' as prefix, can be anything
        name: custom.dumb-filter
        # set lua per route filter
        typed_per_filter_config:
          envoy.filters.http.lua:
            "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute
            source_code:
              inline_string: |
                function envoy_on_response(response_handle)
                  response_handle:headers():add("dm3ch-test", "dm3ch")
                  response_handle:logErr("Bye Bye.")
                end
 

Примечание:

Для этого требуется фильтр lua, который уже применен, потому LuaPerRoute что он будет перезаписывать только существующий.

Комментарии:

1. В поисках ответа попробовал следующее, все еще безуспешно — pastebin.com/78nRpPzs

2. На самом деле я обнаружил, что это отображается в выводе маршрута proxy-config, но все равно никакого эффекта. Вот результат после некоторых экспериментов: pastebin.com/tfAjh1j0 Уже пробовал то же самое, но с фильтром LuaPerRoute, тоже безрезультатно

3. ТАЙ, я наконец-то нашел то, чего мне не хватало