I have 3 projects: A,B,C.
Each project have 2 versions: v1,v2.
How to config istio to limit A(v1) only send request to B(v1) and C(v1)?
I have 3 projects: A,B,C.
Each project have 2 versions: v1,v2.
How to config istio to limit A(v1) only send request to B(v1) and C(v1)?
This is Istio's Request Routing, as described in this tutorial: https://istio.io/latest/docs/tasks/traffic-management/request-routing/
Basically, you need first to define some DestinationRules to create some subsets based on your versions, e.g.:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: v1
labels:
version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
Then, you create some VirtualServices to define the routing rules. Here, you want to use sourceLabels matching, so it's going to be like:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
...
spec:
hosts:
- reviews
http:
- match:
- sourceLabels:
version: v2
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
It reads as: if any incoming traffic to service reviews comes from a service that has a label version: v2, it is routed to reviews v2; else as a default rule, it is routed to v1. You can add any number of route rules in that VirtualService, and can repeat the operation for all your services.
Additionally to what @Joel already told, I wanted to clarify how this works inside the mesh. Also added an example for testing.
If I understand correctly you're looking for a way to use Istio Virtual Service from inside the mesh to make calls from specific versions of projects to the same versions of another projects.
In that case you can use mesh gateway for that.
According to documentation:
The reserved word mesh is used to imply all the sidecars in the mesh. When this field is omitted, the default gateway (mesh) will be used, which would apply the rule to all sidecars in the mesh. If a list of gateway names is provided, the rules will apply only to the gateways. To apply the rules to both gateways and sidecars, specify mesh as one of the gateway names.
So there are 2 options.
You can either use mesh gateway as one of the gateways:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-mesh-gateway
spec:
gateways:
- "mesh"
hosts:
- "service.default.svc.cluster.local"
http:
route:
- destination:
host: service.default.svc.cluster.local
Or you can create Virtual Service without the gateways list, so the default gateway will be mesh gateway.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-mesh-gateway
spec:
hosts:
- "service.default.svc.cluster.local"
http:
route:
- destination:
host: service.default.svc.cluster.local
I've made an example with 2 ubuntu pods
Also there are 2 nginx pods
We're gonna change it later accordingly to v1 and v2 with Destination Rule.
There are all the yamls.
apiVersion: v1
kind: Pod
metadata:
name: ubu1
labels:
version: v1
spec:
containers:
- name: ubu2
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "apt-get update && apt-get install curl -y && sleep 3000"]
---
apiVersion: v1
kind: Pod
metadata:
name: ubu2
labels:
version: v2
spec:
containers:
- name: ubu1
image: ubuntu
command: ["/bin/sh"]
args: ["-c", "apt-get update && apt-get install curl -y && sleep 3000"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx1
spec:
selector:
matchLabels:
run: nginx1
replicas: 1
template:
metadata:
labels:
run: nginx1
app: projectA
spec:
containers:
- name: nginx1
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo This is version 1 of project A > /usr/share/nginx/html/index.html"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx2
spec:
selector:
matchLabels:
run: nginx2
replicas: 1
template:
metadata:
labels:
run: nginx2
app: projectA
spec:
containers:
- name: nginx2
image: nginx
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo This is version 2 of project A > /usr/share/nginx/html/index.html"]
---
apiVersion: v1
kind: Service
metadata:
name: project-a
labels:
app: projectA
spec:
ports:
- port: 80
protocol: TCP
selector:
app: projectA
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: project-a-vs
spec:
hosts:
- project-a.default.svc.cluster.local
http:
- name: v1-match-v1
match:
- sourceLabels:
version: v1
route:
- destination:
host: project-a.default.svc.cluster.local
port:
number: 80
subset: v1
- name: v2-match-v2
match:
- sourceLabels:
version: v2
route:
- destination:
host: project-a.default.svc.cluster.local
port:
number: 80
subset: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: project-a-dr
spec:
host: project-a.default.svc.cluster.local
subsets:
- name: v1
labels:
run: nginx1
- name: v2
labels:
run: nginx2
And some tests:
ubu1 pod have v1 version label, so it should call version v1 of the nginx deployment.
kubectl exec -ti ubu1 -- /bin/bash
root@ubu1:/# curl project-a
This is version 1 of project A
root@ubu1:/# curl project-a
This is version 1 of project A
root@ubu1:/# curl project-a
This is version 1 of project A
ubu1 pod have v2 version label, so it should call version v2 of the nginx deployment.
kubectl exec -ti ubu2 -- /bin/bash
root@ubu2:/# curl project-a
This is version 2 of project A
root@ubu2:/# curl project-a
This is version 2 of project A
root@ubu2:/# curl project-a
This is version 2 of project A
As @Joel mentioned
You can add any number of route rules in that VirtualService, and can repeat the operation for all your services.
So I hope with above example you can change it for your use case.