如何让 Istio VirtualService 通过 header 和 uri 来改变路由 [英] How to get an Istio VirtualService to vary routes by header along with uri

查看:64
本文介绍了如何让 Istio VirtualService 通过 header 和 uri 来改变路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍在与其他几个人一起在开发集群中试验 Istio.我们有一个示例虚拟服务、部署和目标规则,对指定 uri 的请求将发送到与部署关联的 pod.这工作正常.

I'm still experimenting with Istio in a dev cluster, along with a couple of other people. We have a sample virtualservice, deployment, and destinationrule, and requests to the specified uri are going to the pod associated with the deployment. This is working fine.

如果存在特定的标头和值,我正在尝试这种变体,该变体将转到备用部署.如果未设置标头,或指定的标头值不存在,则将转到原始部署,否则转到备用部署.我最终打算让它检查指定标头的几个不同值,每个值都用于不同的部署.

I am attempting a variation of this that goes to an alternate deployment if a particular header and value are present. If the header is not set, or the specified header value is not present, it will go to the original deployment, otherwise to the alternate deployment. I eventually intend for it to check for several different values of the specified header, each going to different deployments.

我创建了一个部署和目标规则,它们是原始规则的副本,具有一致的变化.我尝试使用此备用路由修改虚拟服务.到目前为止,它不能正常工作.我通过跟踪与每个部署关联的容器的容器日志来确定请求进入哪个部署.当我发送带有指定标头和值的请求时,它会转到备用部署.但是,当我发送没有指定标头或匹配值的请求时,它也会转到备用部署.事实上,我根本无法让它到达主部署.

I've created a deployment and destination rule that are copies of the original, with consistent variations. I attempted to modify the virtualservice with this alternate routing. Thus far, it isn't working properly. I determine which deployment a request goes to by tailing the container log of the container associated with each deployment. When I sent a request with the specified header and value, it does go to the alternate deployment. However, when I send the request without the specified header, or without the matching value, it ALSO goes to the alternate deployment. In fact, I can't get it to reach the main deployment at all.

请注意,我知道另一种方法是为默认"路由设置一个虚拟服务,并为每个备用路由设置一个额外的虚拟服务,指定不同的标头值.我见过基本上类似的东西.然而,这似乎有很多重复,以获得在单个 VirtualService 中设置应该更简单的东西.

Note that I understand that another way to do this is to have one virtualservice for the "default" route, and an additional virtualservice for each alternate route, specifying a different header value. I've seen something basically like that working. However, that seems like a lot of duplication to get something that should be simpler to set up in a single VirtualService.

以下是虚拟服务的当前状态,有一些省略:

The following is the current state of the virtualservice, with some elisions:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  annotations: {}
  name: fooms-vs-ingress
  namespace: com-example
spec:
  gateways:
  - ingress-gateway
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /msapi/foo
    - headers:
        ctx-debug-route-fooms:
          exact: myuid-1
    route:
    - destination:
        host: fooms.com-example.svc.cluster.local
        port:
          number: 80
        subset: myuid-1
  - route:
    - destination:
        host: fooms.com-example.svc.cluster.local
        port:
          number: 80
        subset: blue

我可以显示部署和目标规则,但我不知道这是否有帮助.

I could show the deployments and destinationrules, but I don't know if that will be helpful.

更新:

自从我写这篇文章以来,我发现为了在路由匹配中创建两个条件 AND,我必须在一个匹配规则中同时包含两个条件.我仍然习惯了 YAML 的工作方式.我将在此处提供虚拟服务的更新版本,以及网关、目标规则和大部分部署.部署中有很多可能没有帮助的东西.

Since I wrote this, I discovered that in order to make two conditions AND in a route match, I have to have both conditions in a single match rule. I'm still getting used to how YAML works. I'm going to provide here an updated version of the virtualservice, along with the gateway, destination rule, and much of the deployment. There's a lot of stuff in the deployment that probably isn't helpful.

当我从 Postman 向服务发送请求时,无论是否带有路由标头,我都会收到 503 返回.在我进行这些更改以检查路由标头之前,它正确地将请求路由到蓝色"实例(我正在拖尾两个 pod 的日志).当我第一次尝试进行这些更改时,我无意中定义了两个匹配块,一个带有 uri 条件,另一个带有标题匹配条件.当我这样做时,所有请求都将发送到备用 Pod.

When I sent a request to the service from Postman, with or without the routing header, I get a 503 back. Before I made these changes to check for the routing header, it was properly routing requests to the "blue" instance (I am tailing the logs for both pods). When I first tried making these changes, I inadvertently defined two match blocks, one with the uri condition, and one with the header match condition. When I did that, all of the requests were going to the alternate pod.

以下是可能相关的对象的省略版本,删除了一些瞬态属性.

Here are elided versions of the objects that might be relevant, with some transient properties removed.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  annotations: {}
  name: fooms-vs-ingress
  namespace: com-example
spec:
  gateways:
  - comp-ingress-gateway
  hosts:
  - '*'
  http:
  - match:
    - headers:
        compctx-debug-route-fooms:
          exact: myuid-1
      name: match-myuid-1
      uri:
        prefix: /msapi/foo
    route:
    - destination:
        host: fooms.com-example.svc.cluster.local
        port:
          number: 80
        subset: myuid-1
  - name: default
    route:
    - destination:
        host: fooms.com-example.svc.cluster.local
        port:
          number: 80
        subset: blue

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  annotations: {}
  name: comp-ingress-gateway
  namespace: com-example
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

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  labels:
    app: FooMS
    role: blue
    routeoffer: DEFAULT
    seed: COMPv2.2.0
    version: 2.2.0-myuid-1
  name: fooms-myuid-1
  namespace: com-example
spec:
  replicas: 1
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: FooMS
      role: blue
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true"
      creationTimestamp: null
      labels:
        app: FooMS
        role: blue
        routeoffer: DEFAULT
        seed: COMPv2.2.0
        version: 2.2.0-myuid-1
    spec:
      containers:
      - env:
        - name: SERVICE_NAME
          value: fooms
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: spec.nodeName
        envFrom:
        - configMapRef:
            name: global-config
        - secretRef:
            name: global-secrets
        image: dockercentral.it....
        imagePullPolicy: Always
        name: fooms
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
      - image: ...
        imagePullPolicy: IfNotPresent
        name: info
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: default
      serviceAccountName: default
      terminationGracePeriodSeconds: 30

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  annotations: {}
  name: fooms-destination-myuid-1
  namespace: com-example
spec:
  host: fooms.com-example.svc.cluster.local
  subsets:
  - labels:
      version: 2.2.0-myuid-1
    name: myuid-1
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL

推荐答案

因为我没有这个命令的所有信息 kubectl get pods,ep,svc -o wide 我不确定这是目标规则错误,因为我不了解有关您的 pod、ep、svc 的所有信息,并且您的目标规则适用于只有 1 个副本的相同部署.

Since I don't have all informations from this command kubectl get pods,ep,svc -o wide i'm not sure that's destination rule error because i don't know everything about your pods,ep,svc and your destination rule applies to same deployment with only 1 replica.

问题可能在于 destination rule 只有 1子集

Probably the problem there is destination rule with only 1 subset

根据您的虚拟服务,我认为这就是您的目标规则应该看起来

Based on your virtual service i think that's how your destination rule should look

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: fooms-destination-myuid-1
  namespace: com-example
spec:
  host: fooms.com-example.svc.cluster.local
  subsets:
  - labels:
      version: 2.2.0-myuid-1
    name: myuid-1
  subsets:
  - labels:
       role: blue
    name: blue
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL

我做了一些例子,下面需要做的一切

I made some example, everything needed to make this below

Kubernetes 版本 1.13.11-gke.14

Kubernetes version 1.13.11-gke.14

Istio 版本 1.4.1

kubectl label namespace default istio-injection=enabled

部署 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"]

部署 2

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx2
spec:
  selector:
    matchLabels:
      run: nginx2
  replicas: 1
  template:
    metadata:
      labels:
        run: nginx2
        app: frontend
    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"]

服务

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: frontend
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: frontend

网关

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: comp-ingress-gateway
  namespace: default
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

虚拟服务

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginxvirt
spec:
  gateways:
  - comp-ingress-gateway #outside cluster
  - mesh #inside cluster
  hosts:
  - nginx.default.svc.cluster.local #inside cluster
  - nginx.com #outside cluster
  http:
  - name: match-myuid
    match:
    - uri:
        prefix: /msapi
      headers:
        compctx:
          exact: myuid
    rewrite:
      uri: /
    route:
    - destination:
        host: nginx.default.svc.cluster.local
        port:
          number: 80
        subset: v1
  - name: default
    route:
    - destination:
        host: nginx.default.svc.cluster.local
        port:
          number: 80
        subset: v2

目的地规则

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: nginxdest
spec:
  host: nginx.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      run: nginx1
  - name: v2
    labels:
      run: nginx2
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL

用于测试的 Pod

apiVersion: v1
kind: Pod
metadata:
  name: ubu1
spec:
  containers:
  - name: ubu1
    image: ubuntu
    command: ["/bin/sh"]
    args: ["-c", "sleep 3000"]

卷曲的结果:

外部:

curl -H "host: nginx.com" -H "compctx: myuid" ingress_gateway_ip/msapi
Hello nginx1
curl -H "host: nginx.com" -H "compctx: myuid" ingress_gateway_ip/msapi
Hello nginx1
curl -H "host: nginx.com" -H "compctx: myuid" ingress_gateway_ip/msapi
Hello nginx1

curl -H "host: nginx.com" ingress_gateway_ip
Hello nginx2
curl -H "host: nginx.com" ingress_gateway_ip
Hello nginx2
curl -H "host: nginx.com" ingress_gateway_ip
Hello nginx2

内部:

kubectl exec -ti ubu1 -- /bin/bash

root@ubu1:/# curl -H "compctx: myuid " nginx/msapi
Hello nginx1
root@ubu1:/# curl -H "compctx: myuid " nginx/msapi
Hello nginx1
root@ubu1:/# curl -H "compctx: myuid " nginx/msapi
Hello nginx1

这篇关于如何让 Istio VirtualService 通过 header 和 uri 来改变路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆