如何获得Istio VirtualService来通过标头和uri

时间:2019-12-08 18:32:56

标签: kubernetes istio

我仍在与其他几个人一起在开发集群中尝试Istio。我们有一个示例虚拟服务,部署和destinationrule,对指定uri的请求将转到与该部署关联的pod。一切正常。

如果存在特定的标头和值,我尝试将其更改为备用部署。如果未设置标头,或者不存在指定的标头值,则它将转到原始部署,否则转到备用部署。我最终打算让它检查指定标头的几个不同值,每个值去不同的部署。

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

请注意,我知道执行此操作的另一种方法是为“默认”路由提供一个虚拟服务,为每个备用路由提供一个附加虚拟服务,并指定不同的标头值。我基本上看到了类似的东西。但是,要获得在单个VirtualService中设置起来应该更简单的东西,这似乎有很多重复。

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

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

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

更新

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

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

以下是可能相关的对象的省略版本,其中删除了一些临时属性。

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

1 个答案:

答案 0 :(得分:0)

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

可能是存在destination rule只有一个子集的问题

根据您的virtual service,我认为您的目标规则应该是这样

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

我举了一个例子,下面做了所有说明

Kubernetes版本 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