Istio how to limit v1 projects always access v1 projects?

Viewed 88

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)?

2 Answers

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

  • ubu1 with label version v1
  • ubu2 with label version v2

Also there are 2 nginx pods

  • nginx1 with label nginx1
  • nginx2 with label nginx2

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.

Related