Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support direct response in VirtualService #29264

Closed
illidan80 opened this issue Nov 30, 2020 · 21 comments · Fixed by istio/api#2407 or #39776
Closed

Support direct response in VirtualService #29264

illidan80 opened this issue Nov 30, 2020 · 21 comments · Fixed by istio/api#2407 or #39776

Comments

@illidan80
Copy link

illidan80 commented Nov 30, 2020

For example, I would like to have something like this:

apiVersion: networking.istio.io/v1alpha3 
kind: VirtualService 
metadata:
  name: myservice-vs 
  namespace: mynamespace
spec:
  hosts:
  - "my.host"
  gateways:
  - mygateway
  http:
  - match:
    - uri:
        prefix: /mypath
    route:
     - response:
         code: 200
         body: "this is automatic response"
@hzxuzhonghu
Copy link
Member

Looks like a necessary feature

@esnible
Copy link
Contributor

esnible commented Nov 30, 2020

@howardjohn howardjohn changed the title Is it possible to configure VirtualService to "auto response" with specific http code? Support direct response in VirtualService Nov 30, 2020
@p53
Copy link

p53 commented Mar 9, 2021

this would be useful, can be done several ways but with workarounds would consume more resources than optimal

@mossad-zika
Copy link

I am still confused how I can implement this with istio (I am migrating from nginx ingress controller)

@esnible
Copy link
Contributor

esnible commented May 3, 2021

You can do this with WebAssembly code and sendLocalResponse(). I have tried it and it works.

A better way is to use Envoy's DirectResponseAction. I believe Istio can provide this configuration to Envoy using an EnvoyFilter RouteMatch.Action. I have not tried it myself nor was I able to locate an example to point you at.

@mossad-zika
Copy link

@esnible Hello! Actually I am also didn't find any proper example and noone answered me back there https://discuss.istio.io/t/please-assist-me-with-using-envoyfilter-routeconfigurationmatch-action-direct-response/10388

This is really not easy to undestand this EnvoyFilter entity without simple examples :(

@esnible
Copy link
Contributor

esnible commented May 3, 2021

I have tagged extensions and telemetry, you really have what the Istio developers would call an "extension" use case.

I will ask if anyone has examples as the next Telemetry and Extensions meeting.

@esnible
Copy link
Contributor

esnible commented May 5, 2021

I asked at T&E. I was pointed to https://github.com/istio/istio/wiki/EnvoyFilter-Samples which is where the EnvoyFilter samples are kept. My hope is that someone adds one. If not, I will see what I can do. (But not this week...)

@ostapio
Copy link

ostapio commented May 31, 2021

hey @esnible
im trying to figure out direct_response too...

kind: EnvoyFilter
metadata:
  name: direct-response
spec:
  configPatches:
  - applyTo: HTTP_ROUTE
    match:
      context: SIDECAR_OUTBOUND
      routeConfiguration:
        portNumber: 8080
        vhost:
          name: "demo.default.svc.cluster.local:8080"
    patch:
      operation: INSERT_FIRST
      value:
        name: "direct"
        decorator:
          operation: "demo.default.svc.cluster.local:8080/*"
        match:
          path: "/direct"
        directResponse:
          body:
            inlineString: 'hello world'
          status: 200

with this filter i get

"routes": [
    {
        "match": {
            "path": "/direct"
        },
        "decorator": {
            "operation": "demo.default.svc.cluster.local:8080/*"
        },
        "direct_response": {
            "status": 200,
            "body": {
                "inline_string": "hello world"
            }
        },
        "name": "direct"
    },
    {
        "match": {
            "prefix": "/"
        },
        "route": {
            "cluster": "outbound|8080||demo.default.svc.cluster.local",
            "timeout": "0s",
            "retry_policy": {
                "retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                "num_retries": 2,
                "retry_host_predicate": [
                    {
                        "name": "envoy.retry_host_predicates.previous_hosts"
                    }
                ],
                "host_selection_retry_max_attempts": "5",
                "retriable_status_codes": [
                    503
                ]
            },
            "max_stream_duration": {
                "max_stream_duration": "0s"
            }
        },
        "decorator": {
            "operation": "demo.default.svc.cluster.local:8080/*"
        },
        "name": "default"
    }
]

this config generated
but im still getting response from service...
istio 1.8.2 envoy 1.16.1

@mossad-zika
Copy link

this looks very complicated for me, I hope one day there will be just annotion for it (like in another ingress controllers)

@ostapio
Copy link

ostapio commented May 31, 2021

managed to get it working on gateway level
still not quite sure why filter doesnt work with sidecar_outbound. generated config looks exactly the same

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: direct
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: HTTP_ROUTE
    match:
      context: GATEWAY
      routeConfiguration:
        vhost:
          name: <domain_here>:443
    patch:
      operation: INSERT_FIRST
      value:
        name: direct
        match:
          path: /direct
        directResponse:
          body:
            inlineString: 'hello world'
          status: 200

@mossad-zika
Copy link

mossad-zika commented Jun 1, 2021

@ostapio could you please take a look at my setup, because I am getting HTTP ERROR 404

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: my-istio-gateway
  namespace: default
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - some.server
      tls:
        httpsRedirect: true
    - port:
        number: 443
        name: https-443
        protocol: HTTPS
      hosts:
        - some.server
      tls:
        mode: SIMPLE
        credentialName: full-chain-certificate

then I create your EnvoyFilter in default namespace with

      routeConfiguration:
        vhost:
          name: some.server:443

And https://some.server/direct returns 404

Am I missing something?

Could you share the rest of config. maybe I can try yours on empty cluster

@ostapio
Copy link

ostapio commented Jun 1, 2021

@Zeka13 do u have VirtualService created for that gataway/domain?
mine setup is following

envoy-filter (istio-system ns with workload selector istio: ingressgateway)
gateway resource (default ns)
vservice (default ns) (points to same gateway/domain and forwards traffic to demo with / prefix)
demo deployment (default ns)

@mossad-zika
Copy link

IMHAO this is too much for this purpose, anyway thx!

@robw-ca
Copy link

robw-ca commented Oct 18, 2021

The following attached to the sidecar worked well for me for fixed responses:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: direct-response
  namespace: namespace-of-sidecar
spec:
  workloadSelector:
    labels:
      app: myapp
  configPatches:
  - applyTo: HTTP_ROUTE
    match:
      context: SIDECAR_INBOUND
      routeConfiguration:
        vhost:
          name: inbound|http|1234
    patch:
      operation: INSERT_FIRST
      value:
        name: direct-response
        match:
          prefix: /somepath
        directResponse:
          body:
            inlineString: 'Inline body'
          status: 200

Adjust namespace, labels and listening port (above as 1234). Swap prefix to path for an exact match.

This seemed closer to the "VirtualService" goal.

@istio-policy-bot istio-policy-bot added the lifecycle/stale Indicates a PR or issue hasn't been manipulated by an Istio team member for a while label Nov 2, 2021
@p53
Copy link

p53 commented Nov 2, 2021

any work on this?

@istio-policy-bot istio-policy-bot added the lifecycle/automatically-closed Indicates a PR or issue that has been closed automatically. label Nov 17, 2021
@jiangshantao-dbg
Copy link

jiangshantao-dbg commented Dec 9, 2021

any work on this? i think this is an important feature, many cases will use this feature.

  1. gateway temporarily forbidden a route of the host
  2. service forbidden some route according to deployment environment
    etc...

envoy has implement three type of route, istio just support two of them. and it's difficult to use envoyfilter to implement and maintain the config in gateway situation, because http and https has different virtualhost name, the automate program must generated the name according to gateway config.

oneof action {
    option (validate.required) = true;

    // Route request to some upstream cluster.
    RouteAction route = 2;

    // Return a redirect.
    RedirectAction redirect = 3;

    // Return an arbitrary HTTP response directly, without proxying.
    DirectResponseAction direct_response = 7;

    // [#not-implemented-hide:]
    // If true, a filter will define the action (e.g., it could dynamically generate the
    // RouteAction).
    FilterAction filter_action = 17;
  }

@howardjohn can you reopen this issue ? thx

@vvatlin
Copy link

vvatlin commented Feb 23, 2022

+1

@zirain zirain reopened this Feb 24, 2022
@istio-policy-bot istio-policy-bot removed the lifecycle/stale Indicates a PR or issue hasn't been manipulated by an Istio team member for a while label Feb 24, 2022
@zirain zirain removed the lifecycle/automatically-closed Indicates a PR or issue that has been closed automatically. label Feb 24, 2022
@zirain
Copy link
Member

zirain commented Feb 24, 2022

not stale

@rverma-dev
Copy link

@robw-ca Thanks for the config. I wonder if we can apply this to the SIDECAR_OUTBOUND context in place of the INBOUND. I can observe that when using the inbound context the envoy filter will be processed on the proxy sidecar of the target service. However, I am trying to push this to the caller service's envoy sidecar to avoid the extra hop. Is that even possible?

@robw-ca
Copy link

robw-ca commented Jun 7, 2022

@robw-ca Thanks for the config. I wonder if we can apply this to the SIDECAR_OUTBOUND context in place of the INBOUND. I can observe that when using the inbound context the envoy filter will be processed on the proxy sidecar of the target service. However, I am trying to push this to the caller service's envoy sidecar to avoid the extra hop. Is that even possible?

I don't see why it couldn't work, but you'll probably need to match a different vhost. If you dump the outbound sidecar via https://www.envoyproxy.io/docs/envoy/latest/operations/admin#get--config_dump?include_eds you should be able to search the (Admittedly long) JSON for the relevant settings. Do post back your findings!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

13 participants