I have two services running and 4 different headers. I want to direct requests with headers a and c to one service and b and d to another service. What is the best way to achieve that in a virtual service manifests?
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: sample_virtualservice
namespace: sample_namespace
spec:
hosts:
- sample_service.sample_namespace.svc.cluster.local
http:
- match:
- headers:
x-test:
exact: "a" OR "c" //This doesn't work but I want to achieve.
route:
- destination:
host: service_1.sample_namespace.svc.cluster.local
port:
number: 80
- route:
- destination:
host: service_2.sample_namespace.svc.cluster.local
port:
number: 80
I believe there must be a better way instead of mentioning the same route destination multiple times in a manifest file.
I found a clean solution of using regex instead of exact which allows us to send requests to the same destination for different headers without mentioning the same route destination multiple times in a manifest file.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: sample_virtualservice
namespace: sample_namespace
spec:
hosts:
- sample_service.sample_namespace.svc.cluster.local
http:
- match:
- headers:
x-test:
regex: "a|c"
route:
- destination:
host: service_1.sample_namespace.svc.cluster.local
port:
number: 80
- route:
- destination:
host: service_2.sample_namespace.svc.cluster.local
port:
number: 80
As far as I know there are not logical operators in istio virtual service.
They are only available in rules and mixer expression language.
As you mentioned for now the only option is to use the same route multiple times.
So virtual service would look like this.
http:
- name: "a"
match:
- headers:
x-test:
exact: "a"
route:
- destination:
host: service_1.sample_namespace.svc.cluster.local
port:
number: 80
- name: "b"
match:
- headers:
x-test:
exact: "b"
route:
- destination:
host: service_1.sample_namespace.svc.cluster.local
port:
number: 80
- name: "c"
match:
- headers:
x-test:
exact: "c"
route:
- destination:
host: service_2.sample_namespace.svc.cluster.local
port:
number: 80
- name: "d"
match:
- headers:
x-test:
exact: "d"
route:
- destination:
host: service_2.sample_namespace.svc.cluster.local
port:
number: 80
Additional info, I see you have virtual service deployed in sample_namespace, remember that gateway should be deployed in the same namespace. If it´s not, you should add it like in below example.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-gateway
namespace: some-config-namespace
Check the spec.gateways section
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo-Mongo
namespace: sample_namespace
spec:
gateways:
- some-config-namespace/my-gateway
Related
I have two different micro-services running in same name space, both have same context path (ex - my/context/path), further controllers are different in both of them, for example service one supports - my/context/path/service1 and service2 supports my/context/path/service2
now when i defined vs like this, its always redirecting to the service1, is there a possible way to achieve this?
below is my VS:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-service
namespace: ns-ns
spec:
gateways:
- gateway.ns-ns
hosts:
- '*'
http:
- match:
- uri:
prefix: /my/context/path
route:
- destination:
host: service1.ns-ns.svc.cluster.local
port:
number: 9000
- route:
- destination:
host: service2.ns-ns.svc.cluster.local
port:
number: 9000
I also tried below VS, but this also seems to redirect to first service.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-service
namespace: ns-ns
spec:
gateways:
- gateway.ns-ns
hosts:
- '*'
http:
- match:
- uri:
prefix: /my/context/path
route:
- destination:
host: service1.ns-ns.svc.cluster.local
port:
number: 9000
- match:
- uri:
prefix: /my/context/path/service2
route:
- destination:
host: service2.ns-ns.svc.cluster.local
port:
number: 9000
i am not sure if this is achievable or not, or do i need to separate the context part of both the services?
The routes are matched in order. Thus you need to start from the most specific to the most generic. e.g.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-service
namespace: ns-ns
spec:
gateways:
- gateway.ns-ns
hosts:
- '*'
http:
- match:
- uri:
prefix: /my/context/path/service2
route:
- destination:
host: service2.ns-ns.svc.cluster.local
port:
number: 9000
- match:
- uri:
prefix: /my/context/path
route:
- destination:
host: service1.ns-ns.svc.cluster.local
port:
number: 9000
I have three service that I need to expose via istio ingress gateway, i have setup those services dns records to point to the ingress gateway load balancer but i have not succeded to make it work.
The gateway and virtual service config file :
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: test-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*.mywebsite.io"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtualservice
spec:
hosts:
- "*.mywebsite.io"
gateways:
- test-gateway
http:
- name: "api-gateway"
match:
- uri:
exact: "gateway.mywebsite.io"
route:
- destination:
host: gateway.default.svc.cluster.local
port:
number: 8080
- name: "visitor-service"
match:
- uri:
exact: "visitor-service.mywebsite.io"
route:
- destination:
host: visitor-service.default.svc.cluster.local
port:
number: 8000
- name: "auth-service"
match:
- uri:
exact: "auth-service.mywebsite.io"
route:
- destination:
host: auth-service.default.svc.cluster.local
port:
number: 3004
I guess the URI part of the HttpMatchRequest does not work that way. Try to add VirtualServices for each subdomain, i.e. something like.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: gateway-virtualservice
spec:
hosts:
- "gateway.mywebsite.io"
gateways:
- test-gateway
http:
- name: "api-gateway"
match:
- uri:
exact: "/" #or prefix
route:
- destination:
host: gateway.default.svc.cluster.local
port:
number: 8080
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: visitor-virtualservice
spec:
hosts:
- "visitor-service.mywebsite.io"
gateways:
- test-gateway
http:
- name: "visitor-service"
match:
- uri:
exact: "/"
route:
- destination:
host: visitor-service.default.svc.cluster.local
port:
number: 8000
I’m working on setting up an Egress Gateway. I have a simple one that handles traffic for one host configured based on the Istio docs, so that part is fine. But when I look at how to handle multiple hosts, I find this verbiage:
To direct multiple hosts through an egress gateway, you can include a
list of hosts, or use * to match all, in the Gateway. The subset
field in the DestinationRule should be reused for the additional
hosts.
On this Istio docs page.
Unfortunately I have no idea what the second part of that actually means: "The subset field in the DestinationRule should be reused for the additional hosts." To be honest, I don't entirely understand how DR's work with EgressGateway's in general. I'm more used to a DR that specifies a set of pods as it's target in the "subset" field. So I don't quite get how the DR connections a specific host to the Gateway. I tried the following, but this doesn't work:
egress-gateway.yml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-egressgateway
namespace: env-specific-egress-experiments
spec:
selector:
istio: egressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- news.ycombinator.com
- www.slashdot.org
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: env-specific-egressgateway-dr
namespace: env-specific-egress-experiments
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: hn
- name: slashdot
service-entries.yml
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: news-ycombinator-com
namespace: env-specific-egress-experiments
spec:
hosts:
- news.ycombinator.com
ports:
- number: 80
name: http-port-hn
protocol: HTTP
- number: 443
name: https-port-hn
protocol: HTTPS
resolution: DNS
---
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: www-slashdot-org
namespace: env-specific-egress-experiments
spec:
hosts:
- www.slashdot.org
ports:
- number: 80
name: http-port-slashdot
protocol: HTTP
- number: 443
name: https-port-slashdot
protocol: HTTPS
resolution: DNS
virtual-service.yml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: external-service-vs-hn
namespace: env-specific-egress-experiments
spec:
hosts:
- news.ycombinator.com
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
- port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: hn
port:
number: 80
rewrite:
authority: news.ycombinator.com
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: news.ycombinator.com
port:
number: 80
weight: 100
rewrite:
authority: news.ycombinator.com
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: external-service-vs-slash
namespace: env-specific-egress-experiments
spec:
hosts:
- www.slashdot.org
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
- port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: slashdot
port:
number: 80
rewrite:
authority: www.slashdot.org
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: www.slashdot.org
port:
number: 80
weight: 100
rewrite:
authority: www.slashdot.org
If I try to curl one of the hosts with this configuration, I get
/ # curl http://news.ycombinator.com
/ # curl -SsL -D - http://news.ycombinator.com
HTTP/1.1 503 Service Unavailable
date: Tue, 23 Feb 2021 19:27:49 GMT
server: envoy
x-envoy-upstream-service-time: 45
content-length: 0
Also, just as an FYI, a few additional points:
This is just a simulation of part of what I'm trying to accomplish. Obviously I don't really care about connecting to HN or /. Those are just stand-ins for external sites in general
Long-term, the goal is to put an abstract name in front of a external service that can vary in terms of the actual host, based on the deployment. Eg, if I deploy qa-deployment.yml, then "mongodatabase" actually points to mongo.qa.mycompany.com, and if I deploy int-deployment.yml, "mongodatabase" points to mongo.int.mycompany.com, and so on. I think I can accomplish this part with an ExternalName service, and/or a ClusterIP that "floats" and doesn't point to any pods, but is just there for DNS resolution so the VirtualService can trigger.
Ultimately I want all outgoing traffic to go through an EgressGateway. But there will be multiple "things" that need to go through it, hence the particular point I'm stuck on now, which is getting the EgressGateway to work with multiple hosts.
My Gateway and VirtualService for the sample BookInfo looks like this:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
tls:
httpsRedirect: true
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "*"
tls:
mode: SIMPLE
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
privateKey: /etc/istio/ingressgateway-certs/tls.key
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
route:
- destination:
host: productpage
port:
number: 9080
- match:
- uri:
regex: "v1"
route:
- destination:
host: productpage
port:
number: 9080
I am terminating TLS at the gateway and in the HTTP route, I have configured a regex match on "v1" for HTTP and routing it the productpage service.
I am testing this by sending a request to http://External-IP/api/v1/products (the sample application's productpage service is configured to return a text body on this endpoint), but the request fails with HTTP 404. I am not sure what I am doing wrong here, any help is highly appreciated.
I think I found the mistake here, the regex : "v1" does not do partial match.
- match:
- uri:
regex: v1
route:
- destination:
host: productpage
port:
number: 9080
Instead I had to specify regex : .*v1.* to make it work. I am able to route now.
- match:
- uri:
regex: .*v1.*
route:
- destination:
host: productpage
port:
number: 9080
Well, unless I'm reading this wrong your path filters dont match your request, your request is /api and your filters dont have that
I know istio is supporting route to different service by static rule as below:
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtualservice
spec:
hosts:
- "*"
gateways:
- my-gateway
http:
- match:
- uri:
prefix: /applications/app-a
route:
- destination:
host: app-a
port:
number: 9080
But i have the requirement that, I have dynamically created services when there is new user or new configuration is coming. If i use the "static" way, then I have to create new virtual service every time or update existing virtual service.
I don't find any documentation mentioned this kind of usage, but can i use something like "regex" or some other way to create one rule to apply to all those new created services without updating virtual service every time? Below is something not work, but try to demonstrate my idea:
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtualservice
spec:
hosts:
- "*"
gateways:
- my-gateway
http:
- match:
- uri:
regex: /applications/(?<appname>.*)
route:
- destination:
host: $('appname')--svc
port:
number: 9080
Of course, any suggestion would be greatly appreciated. Thanks.
I do not think Istio can do what you ask. The good side of it is that you must control all the entry points into your cluster - which application is accessible and how it is accessible - less security holes.
I am not sure but on github they use regexp in VirtualService:
- match:
- headers:
cookie:
regex: "^(.*?;)?(user=dev-123)(;.*)?"
so you could try to use something like:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-virtualservice
spec:
hosts:
- "*"
gateways:
- my-gateway
http:
- match:
- uri:
prefix:
regex: "/applications/(?<appname>.*)"
route:
- destination:
host: match_group['appname']
port:
number: 9080
instead of regix