L4 TCP路由

您可以使用ASM四层路由能力对TCP流量通过路由规则匹配进行路由。本文介绍ASM支持的所有TCP匹配规则和路由能力。

前提条件

已添加集群到ASM实例

部署示例应用

您可以通过部署示例应用并结合示例提供的VirtualService测试ASM的4层负载均衡能力。为了测试L4负载均衡,您可以按照以下步骤在数据面集群内部署echo-server和telnet-client两个应用。

  1. 创建foo命名空间。具体操作,请参见管理全局命名空间

  2. ASM控制台全局命名空间页面,确认default命名空间、foo命名空间都已启用Sidecar注入或切换为Ambient模式。

  3. 在数据平面集群对应的KubeConfig环境下,部署echo-server和telnet-client两个应用。

    1. 使用以下内容,分别创建echoserver.yaml、telnet.yaml文件。

      展开查看echoserver.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echo-server
        labels:
          app: echo-server
          version: prod
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: echo-server
            version: prod
        template:
          metadata:
            labels:
              app: echo-server
              version: prod
          spec:
            serviceAccountName: echo-server
            containers:
            - name: server
              image: istio/tcp-echo-server:1.2
              ports:
              - containerPort: 9000
              resources:
                limits:
                  cpu: "100m"
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: echo-server
        labels:
          app: echo-server
      spec:
        selector:
          app: echo-server
        ports:
        - protocol: TCP
          name: tcp
          port: 19000
          targetPort: 9000
        type: ClusterIP 
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: echo-server
      ---
      apiVersion: apps/v1 
      kind: Deployment
      metadata:
        name: echo-server-2 
        labels:
          app: echo-server-2
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: echo-server-2
        template:
          metadata:
            labels:
              app: echo-server-2
          spec:
            serviceAccountName: echo-server-2
            containers:
            - name: server 
              image: istio/tcp-echo-server:1.2 
              command:
              - "/bin/tcp-echo"
              - "9000"
              - "hello-2"
              ports:
              - containerPort: 9000
              resources:
                limits:
                  cpu: "100m"
      
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: echo-server-2
        labels:
          app: echo-server-2 
      spec:
        selector:
          app: echo-server-2
        ports:
        - protocol: TCP
          name: tcp
          port: 19000
          targetPort: 9000
        type: ClusterIP 
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: echo-server-2
      

      展开查看telnet.yaml

      apiVersion: apps/v1 
      kind: Deployment
      metadata:
        name: telnet-client 
        labels:
          app: telnet-client 
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: telnet-client 
        template:
          metadata:
            labels:
              app: telnet-client 
          spec:
            serviceAccountName: telnet-client 
            containers:
            - name: client 
              image: mikesplain/telnet:latest 
              command: 
              - "sleep"
              - "3600"
              resources:
                limits:
                  cpu: "100m"
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: telnet-client 
      ---
      apiVersion: apps/v1 
      kind: Deployment
      metadata:
        name: telnet-client-2 
        labels:
          app: telnet-client-2
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: telnet-client-2 
        template:
          metadata:
            labels:
              app: telnet-client-2 
          spec:
            serviceAccountName: telnet-client-2
            containers:
            - name: client 
              image: mikesplain/telnet:latest 
              command: 
              - "sleep"
              - "3600"
              resources:
                limits:
                  cpu: "100m"
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: telnet-client-2
      ---
      apiVersion: apps/v1 
      kind: Deployment
      metadata:
        name: telnet-client-foo 
        namespace: foo
        labels:
          app: telnet-client-foo
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: telnet-client-foo
        template:
          metadata:
            labels:
              app: telnet-client-foo
          spec:
            serviceAccountName: telnet-client-foo
            containers:
            - name: client 
              image: mikesplain/telnet:latest 
              command: 
              - "sleep"
              - "3600"
              resources:
                limits:
                  cpu: "100m"
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: telnet-client-foo
        namespace: foo
      

    2. 执行以下命令,部署echo-server和telnet-client两个应用。

      kubectl apply -f echoserver.yaml
      kubectl apply -f telnet.yaml

匹配规则

destinationSubnets

通过配置tcp.match[n].destinationSubnets属性可以为路由匹配目标网段,流量的目标网段与配置成功匹配将使用该路由规则进行路由。

支持情况

  • AmbientMode:不支持

  • SidecarMode:支持

部署示例资源

以下示例YAML匹配目标网段192.168.0.0/16,将去往该网段的TCP流量转发至echo-server-2.default.svc.cluster.local服务。您可以通过命令行或控制台的方式部署示例资源。下文以命令行方式为例进行说明。关于控制台的操作,请参见管理虚拟服务

  1. 使用以下内容,创建destinationSubnets.yaml文件。

    示例中echo-server.default.svc.cluster.local服务的地址在192.168.0.0/16网段下,请您根据实际情况进行修改。

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: echo
      namespace: default
    spec:
      hosts:
        - echo-server.default.svc.cluster.local
      tcp:
        - match:
            - destinationSubnets:
                - "192.168.0.0/16"
          route:
            - destination:
                host: echo-server-2.default.svc.cluster.local
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,部署VirtualService。

    kubectl apply -f destinationSubnets.yaml
  3. 执行以下命令,通过telnet-client Pod发起测试,输入test,向echo-server.default.svc.cluster.local 19000发起连接并传输数据。

    kubectl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test

    收到echo-server-2返回的hello2 test响应,说明流量命中了VirtualService中声明的匹配19000端口的规则,符合预期。

port

通过配置tcp.match[n].port属性可以为路由匹配目标端口。若流量的目标端口与配置的端口匹配成功,将使用该路由规则进行路由。

支持情况

  • AmbientMode:不支持

  • SidecarMode:支持

部署示例资源

以下示例YAML匹配目标端口19000,将发往该端口的TCP流量转发至echo-server-2.default.svc.cluster.local服务。您可以通过命令行或控制台的方式部署示例资源。下文以命令行方式为例进行说明。关于控制台的操作,请参见管理虚拟服务

  1. 使用以下内容,创建port.yaml文件。

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: echo
      namespace: default
    spec:
      hosts:
        - echo-server.default.svc.cluster.local
      tcp:
        - match:
            - port: 19000
          route:
            - destination:
                host: echo-server-2.default.svc.cluster.local
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,部署VirtualService。

    kubectl apply -f port.yaml
  3. 执行以下命令,通过telnet-client Pod发起测试,输入test,向echo-server.default.svc.cluster.local 19000发起连接并传输数据。

    kubectl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test

    收到echo-server-2返回的hello2 test响应,说明流量命中了VirtualService中声明的匹配19000端口的规则,符合预期。

sourceLabels

通过配置tcp.match[n].sourceLabels属性,可以匹配从特定工作负载发出的请求。

支持情况

  • AmbientMode:不支持

  • SidecarMode:支持

部署示例资源

以下示例YAML匹配从携带标签app: telnet-client的工作负载发出的请求。在示例应用中,telnet-client携带app: telnet-client标签,但telnet-client-2携带app: telnet-client-2标签,因此以下VirtualService将匹配来自telnet-client的TCP流量,但无法匹配来自telnet-client-2的TCP流量。您可以通过命令行或控制台的方式部署示例资源。下文以命令行方式为例进行说明。关于控制台的操作,请参见管理虚拟服务

  1. 使用以下内容,创建sourceLabels.yaml文件。

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: echo
      namespace: default
    spec:
      hosts:
        - echo-server.default.svc.cluster.local
      tcp:
        - match:
            - sourceLabels:
                app: telnet-client
          route:
            - destination:
                host: echo-server-2.default.svc.cluster.local
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,部署VirtualService。

    kubectl apply -f sourceLabels.yaml
  3. 执行以下命令,通过telnet-client Pod发起测试,输入test,向echo-server.default.svc.cluster.local 19000发起连接并传输数据。

    kubectl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test

    收到echo-server-2返回的hello2 test响应,说明经由telnet-client Pod发出的流量匹配到了VirtualService中声明的路由匹配规则。

  4. 执行以下命令,通过telnet-client-2 Pod发起测试,输入test,向echo-server.default.svc.cluster.local 19000发起连接并传输数据。

    kubectl exec -it telnet-client-2-c56db78bd-7**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test

    收到echo-server返回的hello test,说明流量未被转发到echo-server-2,经由telnet-client-2 Pod发出的流量未能匹配到VirtualService中声明的路由匹配规则,符合预期。

gateways

通过配置tcp.match[n].gateways可以匹配从特定网关发往服务的请求。

支持情况

  • AmbientMode:支持

  • SidecarMode:支持

部署示例资源

以下示例在本文前提条件的基础上,需要额外部署2个ASM网关,分别名为ingressgateway-1和ingressgateway-2。示例提供的VirtualService应用到这两个网关,网关ingressgateway-1的流量将被路由至echo-server服务,而ingressgateway-2的流量将被路由至echo-server-2服务。

  1. 创建ASM网关。具体操作,请参见创建入口网关

    ingressgateway-1和ingressgateway-2网关采用相同配置。配置端口映射时,单击添加端口协议选择TCP服务端口选择19000image.png

  2. 部署网关规则。

    下文以命令行方式为例进行说明。关于ASM控制台的具体操作,请参见管理网关规则

    1. 使用以下内容,分别创建ingressgateway-1.yaml、ingressgateway-2.yaml文件。

      以下网关规则定义了网关的监听端口,由于示例为TCP流量,所以Host配置为*

      展开查看ingressgateway-1.yaml

      apiVersion: networking.istio.io/v1beta1
      kind: Gateway
      metadata:
        name: ingressgateway-1
        namespace: istio-system
      spec:
        selector:
          istio: ingressgateway-1
        servers:
          - hosts:
              - '*'
            port:
              name: tcp
              number: 19000
              protocol: TCP

      展开查看ingressgateway-2.yaml

      apiVersion: networking.istio.io/v1beta1
      kind: Gateway
      metadata:
        name: ingressgateway-2
        namespace: istio-system
      spec:
        selector:
          istio: ingressgateway-2
        servers:
          - hosts:
              - '*'
            port:
              name: tcp
              number: 19000
              protocol: TCP
    2. 执行以下命令,部署网关规则。

      kubectl apply -f ingressgateway-1.yaml
      kubectl apply -f ingressgateway-2.yaml
  3. 为网关部署VirtualService。

    该虚拟服务定义了两条路由规则,第一条以网关匹配,如果当前网关是ingressgateway-2,则路由到echo-server-2.default.svc.cluster.local。您可以通过命令行或控制台的方式部署示例资源。下文以命令行方式为例进行说明。关于控制台的操作,请参见管理虚拟服务

    1. 使用以下内容,创建ingressgateway-vs.yaml文件。

      展开查看ingressgateway-vs.yaml

      apiVersion: networking.istio.io/v1beta1
      kind: VirtualService
      metadata:
        name: ingressgateway
        namespace: istio-system
      spec:
        gateways:
          - ingressgateway-1
          - ingressgateway-2
        hosts:
          - '*'
        tcp:
          - match:
              - gateways:
                  - ingressgateway-2
            route:
              - destination:
                  host: echo-server-2.default.svc.cluster.local
          - route:
              - destination:
                  host: echo-server.default.svc.cluster.local
      
  4. 在ASM实例对应的KubeConfig环境下,执行以下命令,部署VirtualService。

    kubectl apply -f ingressgateway-vs.yaml
  5. 执行以下命令,连接ingressgateway-1的IP地址并传输字符串test,按Enter发送。

    kubectl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test

    收到的返回信息为hello test。根据VirtualService定义,经过ingressgateway-1的流量应当被路由到echo-server.default.svc.cluster.local,符合预期。

  6. 执行以下命令,连接ingressgateway-2的IP地址并传输字符串test,按Enter发送。

    kubectl exec -it telnet-client-2-c56db78bd-7**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test

    收到的返回信息为hello-2 test。根据VirtualService定义,经过ingressgateway-2的流量应当被路由到echo-server-2.default.svc.cluster.local,符合预期。

sourceNamespace

通过配置sourceNamespace字段可以匹配流量的来源命名空间。

支持情况

  • AmbientMode:不支持

  • SidecarMode:支持

部署示例资源

以下YAML示例为将来自命名空间foo、发往echo-server.default.svc.cluster.local的流量路由至echo-server-2.default.svc.cluster.local。您可以通过命令行或控制台的方式部署示例资源。下文以命令行方式为例进行说明。关于控制台的操作,请参见管理虚拟服务

  1. 使用以下内容,创建source-namespace.yaml文件。

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: source-namespace
      namespace: default
    spec:
      hosts:
        - echo-server.default.svc.cluster.local
      http: []
      tcp:
        - match:
            - sourceNamespace: foo
          route:
            - destination:
                host: echo-server-2.default.svc.cluster.local
        - route:
            - destination:
                host: echo-server.default.svc.cluster.local
    
  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,部署VirtualService。

    kubectl apply -f source-namespace.yaml
  3. 执行以下命令,通过foo/telnet-client-foo Pod发起测试,然后输入test

    kubectl -n foo exec -it telnet-client-foo-7c94569bfd-h**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test

    收到echo-server-2返回的hello2 test响应,说明经由foo/telnet-client-foo Pod发出的流量匹配到了VirtualService中声明的路由匹配规则。

  4. 执行以下命令,通过default/telnet-client Pod发起测试,然后输入test

    kubectl exec -it telnet-client-c56db78bd-7**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test

    收到echo-server返回的hello test,流量未被转发到echo-server-2,说明经由default/telnet-client Pod发出的流量使用了VirtualService中的默认匹配规则被路由至echo-server.default.svc.cluster.local,符合预期。

路由

weight

配置weight字段可以使多个子集之间按照流量比例进行路由。

支持情况

  • AmbientMode:不支持

  • SidecarMode:支持

部署示例资源

  1. 部署Deployment。

    1. 使用以下内容,创建echo-server-backup.yaml文件。

      以下YAML将部署echo-server服务的gray版本。

      展开查看echo-server-backup.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echo-server-gray
        labels:
          app: echo-server
          version: gray
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: echo-server
            version: gray
        template:
          metadata:
            labels:
              app: echo-server
              version: gray
          spec:
            serviceAccountName: echo-server
            containers:
            - name: server
              image: istio/tcp-echo-server:1.2
              command:
              - "/bin/tcp-echo"
              - "9000"
              - "hello-gray"
              ports:
              - containerPort: 9000
              resources:
                limits:
                  cpu: "100m"
    2. 在数据平面集群对应的KubeConfig环境下,执行以下命令,部署Deployment。

      kubectl apply -f echo-server-backup.yaml
  2. 部署DestinationRule。

    下文以命令行方式为例进行说明。关于ASM控制台的具体操作,请参见管理目标规则

    1. 使用以下内容,创建echoserver-dr.yaml文件。

      以下YAML将使用DestinationRule为echo-server服务分别创建prod和gray两个子集。

      apiVersion: networking.istio.io/v1beta1
      kind: DestinationRule
      metadata:
        name: echo
        namespace: default
      spec:
        host: echo.default.svc.cluster.local
        subsets:
          - labels:
              version: prod
            name: prod
          - labels:
              version: gray
            name: gray
    2. 在ASM实例对应的KubeConfig环境下,执行以下命令,部署DestinationRule。

      kubectl apply -f echoserver-dr.yaml
  3. 部署VirtualService。

    下文以命令行方式为例进行说明。关于ASM控制台的具体操作,请参见管理虚拟服务

    1. 使用以下内容,创建echoserver-vs.yaml文件。

      以下YAML将使用VirtualService为echo-server服务的两个子集prod和gray配置80:20的流量权重。

      apiVersion: networking.istio.io/v1beta1
      kind: VirtualService
      metadata:
        name: echo
      spec:
        hosts:
        - echo-server.default.svc.cluster.local
        http:
          - route:
            - destination:
                host: echo-server.default.svc.cluster.local
                subset: gray
              weight: 20
            - destination:
                host: echo-server.default.svc.cluster.local
                subset: prod
              weight: 80
    2. 在ASM实例对应的KubeConfig环境下,执行以下命令,部署VirtualService。

      kubectl apply -f echoserver-vs.yaml
  4. 执行以下命令,通过telnet-client Pod发起测试,输入test,收到echo-server返回的hello test响应,按Ctrl + D退出。将此操作重复执行五次。

    $ ackctl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test
    #预期输出:
    hello-gray test
    
    $ ackctl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test
    #预期输出:
    hello test
    
    $ ackctl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test
    #预期输出:
    hello test
    
    $ ackctl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test
    #预期输出:
    hello test
    
    $ ackctl exec -it telnet-client-5786fc744f-9**** -c client -- telnet echo-server.default.svc.cluster.local:19000
    test
    #预期输出:
    hello test

    由于TCP负载均衡为连接级别负载均衡,可以看到五次连接被按照VirtualService设置的比例被路由到echo-server服务的prod和version子集(该比例不一定严格准确)。