I have deployed eight services on Kubernetes with Istio sidecar injection. I want to set-up routing rules in VirtualService where three services have same rule. Rules:-
- match:
- headers:
location:
exact: pune
uri:
prefix: /wagholi
route:
- destination:
host: wagholi
port:
number: 8080
uri:
prefix: /yerwada
route:
- destination:
host: yerwada
port:
number: 8080
uri:
prefix: /hadapsar
route:
- destination:
host: hadapsar
port:
number: 8080
- match:
- headers:
location:
exact: mumbai
uri:
prefix: /chatraparishivajiterminal
route:
- destination:
host: chatraparishivajiterminal
port:
number: 8080
uri:
prefix: /kalyan
route:
- destination:
host: kalyan
port:
number: 8080
- match:
- headers:
location:
exact: Pimpari
uri:
prefix: /akurdi
route:
- destination:
host: akurdi
port:
number: 8080
uri:
prefix: /ravet
route:
- destination:
host: ravet
port:
number: 8080
In this scenario, If I set location pune in headers and then try to call service with name wagholi it should call wagholi and if I hit hadapsar then hadapsar. If I set the location as Pimpri and call ravet then it should call ravet only. Is there any scenario to do so !!!!!
I have made a reproduction of your question with 3 simple nginx pods, the problem is I couldn't make it work with just 1 header and 3 uri.
So i made it another way, every match of virtual service has it's own header and uri.
Check below example.
We have 3 pods -> 3 services -> virtual service -> gateway -> ingressgateway
Deployment 1
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx1
spec:
selector:
matchLabels:
run: nginx1
replicas: 1
template:
metadata:
labels:
run: nginx1
app: frontend
spec:
containers:
- name: nginx1
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello nginx1 > /usr/share/nginx/html/index.html"]
Deployment 2
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx2
spec:
selector:
matchLabels:
run: nginx2
replicas: 1
template:
metadata:
labels:
run: nginx2
app: frontend2
spec:
containers:
- name: nginx2
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello nginx2 > /usr/share/nginx/html/index.html"]
Deployment 3
piVersion: apps/v1
kind: Deployment
metadata:
name: nginx3
spec:
selector:
matchLabels:
run: nginx3
replicas: 1
template:
metadata:
labels:
run: nginx3
app: frontend3
spec:
containers:
- name: nginx3
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello nginx3 > /usr/share/nginx/html/index.html"]
Service 1
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: frontend
spec:
ports:
- name: http
port: 80
protocol: TCP
selector:
app: frontend
Service 2
apiVersion: v1
kind: Service
metadata:
name: nginx2
labels:
app: frontend2
spec:
ports:
- port: 80
protocol: TCP
selector:
app: frontend2
Service 3
apiVersion: v1
kind: Service
metadata:
name: nginx3
labels:
app: frontend3
spec:
ports:
- port: 80
protocol: TCP
selector:
app: frontend3
Virtual Service
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginxvirt
spec:
gateways:
- mesh # traffic inside cluster
- comp-ingress-gateway # traffic from outside cluster
hosts:
- nginx.default.svc.cluster.local
- nginx.com # outside cluster
- nginx3.default.svc.cluster.local
- nginx2.default.svc.cluster.local
http:
- name: a
match:
- uri:
prefix: /wagholi
headers:
location:
exact: pune
rewrite:
uri: /
route:
- destination:
host: nginx.default.svc.cluster.local
port:
number: 80
- name: b
match:
- uri:
prefix: /yerwada
headers:
location:
exact: pune
rewrite:
uri: /
route:
- destination:
host: nginx2.default.svc.cluster.local
port:
number: 80
- name: c
match:
- uri:
prefix: /hadasapar
headers:
location:
exact: pune
rewrite:
uri: /
route:
- destination:
host: nginx3.default.svc.cluster.local
port:
number: 80
Gateway
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: comp-ingress-gateway
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: http
number: 80
protocol: HTTP
- hosts:
- '*'
port:
name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
Some ubuntu pod to test inside traffic
apiVersion: v1
kind: Pod
metadata:
name: ubu1
spec:
containers:
- name: ubu1
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "apt-get update && apt-get install curl -y && sleep 3000"]
And the results:
Inside:
root@ubu1:/# curl -H "location: pune" nginx/wagholi
Hello nginx1
root@ubu1:/# curl -H "location: pune" nginx/hadasapar
Hello nginx3
root@ubu1:/# curl -H "location: pune" nginx/yerwada
Hello nginx2
Outside:
curl -H "location: pune" -H "host: nginx.com" ingress_gateway_ip/hadasapar
Hello nginx3
curl -H "location: pune" -H "host: nginx.com" ingress_gateway_ip/wagholi
Hello nginx1
curl -H "location: pune" -H "host: nginx.com" ingress_gateway_ip/yerwada
Hello nginx2
EDIT
How Can I find ingress_gateway_ip?
You Can use
kubectl get svc istio-ingressgateway -n istio-system
And it's istio-ingressgateway EXTERNAL-IP
If the EXTERNAL-IP value is set, your environment has an external load balancer that you can use for the ingress gateway. If the EXTERNAL-IP value is (or perpetually ), your environment does not provide an external load balancer for the ingress gateway. In this case, you can access the gateway using the service’s node port.
Can I do differently Ingress for each service and then map to VirtualService.
I'm not sure about that but i think it's possible. Check below links
I hope it will help You. Let me know if You have any more questions.