Istio 如何限制 v1 项目总是访问 v1 项目?

Istio how to limit v1 projects always access v1 projects?

我有 3 个项目:A、B、C。
每个项目有两个版本:v1,v2.
如何配置istio来限制A(v1)只向B(v1)和C(v1)发送请求?

这是 Istio 的请求路由,如本教程所述:https://istio.io/latest/docs/tasks/traffic-management/request-routing/

基本上,您需要先定义一些 DestinationRules 以根据您的版本创建一些子集,例如:

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

然后,您创建一些 VirtualServices 来定义路由规则。在这里,你想使用 sourceLabels 匹配,所以它会像:

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

它的意思是:如果服务 reviews 的任何传入流量来自具有标签 version: v2 的服务,它会被路由到 reviews v2;否则作为默认规则,它被路由到 v1。您可以在该 VirtualService 中添加任意数量的路由规则,并且可以为您的所有服务重复该操作。

除了@Joel 已经讲过的内容之外,我想澄清一下它在网格内部的工作原理。还添加了一个测试示例。


如果我理解正确的话,您正在寻找一种方法来从网格内部使用 Istio 虚拟服务来从特定版本的项目调用另一个项目的相同版本。

在这种情况下,您可以使用 网状网关

根据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.

所以有2个选项。

您可以使用 网状网关 作为网关之一:

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

  

或者您可以在没有网关列表的情况下创建虚拟服务,因此默认网关将是 网状网关

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

我用 2 ubuntu pods

做了一个例子
  • ubu1 标签版本为 v1
  • ubu2 标签版本为 v2

还有2个nginxpods

  • 带有标签 nginx1 的 nginx1
  • 带有标签 nginx2 的 nginx2

我们稍后会根据目标规则将其更改为 v1 和 v2。


所有的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

还有一些测试:

ubu1 pod 有 v1 版本标签,所以它应该调用 nginx 部署的版本 v1。

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 有 v2 版本标签,所以它应该调用 nginx 部署的 v2 版本。

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

正如@Joel 提到的那样

You can add any number of route rules in that VirtualService, and can repeat the operation for all your services.

所以我希望您可以根据您的用例更改上面的示例。