2.7. 流量管理

警告

查看不再支持的 Red Hat OpenShift Service Mesh 发行版本的文档。

Service Mesh 版本 1.0 和 1.1 control plane 不再被支持。有关升级服务网格 control plane 的详情,请参阅 升级 Service Mesh

有关特定 Red Hat OpenShift Service Mesh 发行版本的支持状态的信息,请参阅产品生命周期页面

您可以控制 Red Hat OpenShift Service Mesh 中服务间的流量和 API 调用。例如,服务网格中的一些服务可能需要在网格内进行通信,其他服务则需要隐藏。管理流量来隐藏特定后端服务、公开服务、创建测试或版本部署,或者在一组服务上添加安全层。

2.7.1. 使用网关

您可以使用网关来管理入站和出站流量,以指定您想要进入或离开网格的流量。网关配置适用于在网格边缘运行的独立的 Envoy 代理,而不是与您的服务负载一同运行的 sidecar Envoy 代理。

与控制进入系统的其他流量的机制不同,如 Kubernetes Ingress API,Red Hat OpenShift Service Mesh 网关可让您获得流量路由的全部功能和灵活性。Red Hat OpenShift Service Mesh 网关资源可层 4-6 负载均衡属性,比如要公开和配置 Red Hat OpenShift Service Mesh TLS 设置的端口。您可以将常规 Red Hat OpenShift Service Mesh 虚拟服务绑定到网关,并像服务网格中的其它数据平面流量一样管理网关流量,而不将应用程序层流量路由(L7)添加到相同的 API 资源中。

网关主要用于管理入口流量,但您也可以配置出口网关。出口网关可让您为离开网格的流量配置专用退出节点。这可让您限制哪些服务可以访问外部网络,这会为您的服务网格增加安全控制。您还可以使用网关配置纯内部代理。

网关示例

网关资源描述了在网格边缘运行的负载均衡器,接收进入或传出的 HTTP/TCP 连接。该规范描述应当公开的一组端口,要使用的协议类型,以及负载均衡器的 SNI 配置等。

以下示例显示了外部 HTTPS 入口流量的网关配置示例:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: ext-host-gwy
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - ext-host.example.com
    tls:
      mode: SIMPLE
      serverCertificate: /tmp/tls.crt
      privateKey: /tmp/tls.key

这个网关配置允许来自 ext-host.example.com 的 HTTPS 流量通过端口 443 进入网格,但没有为流量指定路由。

要指定路由并让网关按预期工作,还必须将网关绑定到虚拟服务。您可以使用虚拟服务的网关字段进行此操作,如下例所示:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: virtual-svc
spec:
  hosts:
  - ext-host.example.com
  gateways:
    - ext-host-gwy

然后,您可以使用外部流量的路由规则配置虚拟服务。

2.7.2. 配置入口网关

入口网关是在网格边缘运行的负载均衡器,接收传入的 HTTP/TCP 连接。它配置公开的端口和协议,但不包括任何流量路由配置。入口流量的流量路由改为使用路由规则配置,这与内部服务请求相同。

以下步骤演示了如何创建网关并配置 VirtualService,以在 Bookinfo 示例应用程序中将服务公开给路径 /productpage/login 的外部流量。

流程

  1. 创建网关以接受流量。

    1. 创建 YAML 文件,并将以下 YAML 复制到其中:

      网关 gateway.yaml 示例

      apiVersion: networking.istio.io/v1alpha3
      kind: Gateway
      metadata:
        name: bookinfo-gateway
      spec:
        selector:
          istio: ingressgateway
        servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
          - "*"

    2. 应用 YAML 文件。

      $ oc apply -f gateway.yaml
  2. 创建 VirtualService 对象来重写主机标头。

    1. 创建 YAML 文件,并将以下 YAML 复制到其中:

      虚拟服务示例

      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        name: bookinfo
      spec:
        hosts:
        - "*"
        gateways:
        - bookinfo-gateway
        http:
        - match:
          - uri:
              exact: /productpage
          - uri:
              prefix: /static
          - uri:
              exact: /login
          - uri:
              exact: /logout
          - uri:
              prefix: /api/v1/products
          route:
          - destination:
              host: productpage
              port:
                number: 9080

    2. 应用 YAML 文件。

      $ oc apply -f vs.yaml
  3. 测试网关和 VirtualService 已正确设置。

    1. 设置网关 URL。

      export GATEWAY_URL=$(oc -n istio-system get route istio-ingressgateway -o jsonpath='{.spec.host}')
    2. 设置端口号。在本例中,istio-system 是 Service Mesh control plane 项目的名称。

      export TARGET_PORT=$(oc -n istio-system get route istio-ingressgateway -o jsonpath='{.spec.port.targetPort}')
    3. 测试已明确公开的页面。

      curl -s -I "$GATEWAY_URL/productpage"

      预期的结果为 200

2.7.3. 管理入口流量

在 Red Hat OpenShift Service Mesh 中,Ingress Gateway 允许监控、安全性和路由规则等功能应用到进入集群的流量。使用 Service Mesh 网关在服务网格外公开服务。

2.7.3.1. 决定入口 IP 和端口

入口配置根据您的环境是否支持外部负载均衡器而有所不同。在集群的入口 IP 和端口中设置一个外部负载均衡器。要确定是否为外部负载均衡器配置了集群的 IP 和端口,请运行以下命令。在本例中,istio-system 是 Service Mesh control plane 项目的名称。

$ oc get svc istio-ingressgateway -n istio-system

该命令会返回命名空间中每个项目的 NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE

如果设置了 EXTERNAL-IP 值,您的环境会有一个外部负载均衡器,供您用于入口网关。

如果 EXTERNAL-IP 值是 <none>,或 <pending>,则您的环境不会为入口网关提供外部负载均衡器。您可以使用服务的节点端口访问网关。

2.7.3.1.1. 使用负载均衡器确定入口端口

如果您的环境有外部负载均衡器,请按照以下步骤操作。

流程

  1. 运行以下命令来设置入口 IP 和端口。此命令在终端中设置变量。

    $ export INGRESS_HOST=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  2. 运行以下命令来设置入口端口。

    $ export INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
  3. 运行以下命令来设置安全入口端口。

    $ export SECURE_INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
  4. 运行以下命令来设置 TCP 入口端口。

    $ export TCP_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')
注意

在某些情况下,负载均衡器可能会使用主机名而不是 IP 地址公开。在这种情况下,入口网关的 EXTERNAL-IP 值不是一个 IP 地址。相反,这是一个主机名,上一命令无法设置 INGRESS_HOST 环境变量。

在这种情况下,使用以下命令更正 INGRESS_HOST 值:

$ export INGRESS_HOST=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
2.7.3.1.2. 确定没有负载均衡器的入口端口

如果您的环境没有外部负载均衡器,请确定入口端口并改用节点端口。

流程

  1. 设置入口端口。

    $ export INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
  2. 运行以下命令来设置安全入口端口。

    $ export SECURE_INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
  3. 运行以下命令来设置 TCP 入口端口。

    $ export TCP_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].nodePort}')

2.7.4. 自动路由创建

Istio 网关的 OpenShift 路由在 Red Hat OpenShift Service Mesh 中被自动管理。每次在 service mesh 中创建、更新或删除 Istio 网关时,都会自动创建、更新或删除 OpenShift 路由。

2.7.4.1. 启用自动路由创建

名为 Istio OpenShift Routing (IOR) 的 Red Hat OpenShift Service Mesh control plane 组件可以用来同步网关路由。作为 control plane 部署的一部分启用 IOR。

如果网关包含一个 TLS 部分,则 OpenShift Route 将被配置为支持 TLS。

  1. ServiceMeshControlPlane 资源中添加 ior_enabled 参数,并将其设置为 true。例如,请查看以下资源片断:
spec:
  istio:
    gateways:
     istio-egressgateway:
       autoscaleEnabled: false
       autoscaleMin: 1
       autoscaleMax: 5
     istio-ingressgateway:
       autoscaleEnabled: false
       autoscaleMin: 1
       autoscaleMax: 5
       ior_enabled: true

2.7.4.2. 子域

Red Hat OpenShift Service Mesh 使用子域创建路由,但必须配置 OpenShift Container Platform 才能启用它。子域,如 *.domain.com,被支持,但不是默认支持。在配置通配符主机网关前,请配置 OpenShift Container Platform 通配符策略。如需更多信息,请参阅"链接"部分。

如果创建了以下网关:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: gateway1
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - www.bookinfo.com
    - bookinfo.example.com

然后,会自动创建以下 OpenShift 路由。您可以使用以下命令来检查是否创建了路由:

$ oc -n <control_plane_namespace> get routes

预期输出

NAME           HOST/PORT             PATH  SERVICES               PORT  TERMINATION   WILDCARD
gateway1-lvlfn bookinfo.example.com        istio-ingressgateway   <all>               None
gateway1-scqhv www.bookinfo.com            istio-ingressgateway   <all>               None

如果删除了网关,Red Hat OpenShift Service Mesh 会删除路由。但是,手动创建的路由都不会被 Red Hat OpenShift Service Mesh 修改。

2.7.5. 了解服务条目

服务条目在由 Red Hat OpenShift Service Mesh 内部维护的服务 registry 中添加一个条目。添加服务条目后,Envoy 代理将流量发送到该服务,就像是网格中的服务一样。服务条目允许您进行以下操作:

  • 管理服务网格外运行的服务的流量。
  • 重定向和转发外部目的地的流量,如来自 web 的 API 调用,或转发到旧基础架构中服务的流量。
  • 为外部目的地定义重新尝试、超时和错误注入策略。
  • 在虚拟机 (VM) 中运行网格服务,方法是在网格中添加虚拟机。
注意

将服务从不同集群添加到网格,以便在 Kubernetes 上配置多集群 Red Hat OpenShift Service Mesh 网格。

服务条目示例

以下示例 mesh-external 服务条目将 ext-resource 外部依赖关系添加到 Red Hat OpenShift Service Mesh 服务 registry:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: svc-entry
spec:
  hosts:
  - ext-svc.example.com
  ports:
  - number: 443
    name: https
    protocol: HTTPS
  location: MESH_EXTERNAL
  resolution: DNS

使用 hosts 字段指定外部资源。您可以完全限定名,也可以使用通配符前缀域名。

您可以配置虚拟服务和目的地规则,以控制到服务条目的流量,其方式与您为网格中的任何其他服务配置流量相同。例如,以下目的地规则将流量路由配置为使用 mutual TLS 来保护到 ext-svc.example.com 外部服务的连接。它被配置为使用服务项:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: ext-res-dr
spec:
  host: ext-svc.example.com
  trafficPolicy:
    tls:
      mode: MUTUAL
      clientCertificate: /etc/certs/myclientcert.pem
      privateKey: /etc/certs/client_private_key.pem
      caCertificates: /etc/certs/rootcacerts.pem

2.7.6. 使用 VirtualServices

您可以使用虚拟服务通过 Red Hat OpenShift Service Mesh 将请求动态路由到微服务的不同版本。使用虚拟服务,您可以:

  • 通过单一虚拟服务处理多个应用程序服务。如果网格使用 Kubernetes,您可以配置虚拟服务来处理特定命名空间中的所有服务。虚拟服务使您能够将单体式应用转变为由具有无缝消费者体验的不同微服务组成的服务。
  • 配置流量规则与网关相结合,以控制入口和出口流量。

2.7.6.1. 配置 VirtualServices

使用虚拟服务将请求路由到服务网格中的服务。每个虚拟服务由一组路由规则组成,并按顺序应用。Red Hat OpenShift Service Mesh 会将每个给定给虚拟服务的请求与网格内的特定实际目的地匹配。

如果没有虚拟服务,Red Hat OpenShift Service Mesh 会在所有服务实例间使用 round-robin 负载均衡分配流量。使用虚拟服务时,您可以指定一个或多个主机名的流量行为。虚拟服务的路由规则告知 Red Hat OpenShift Service Mesh 如何将虚拟服务的流量发送到适当的目的地。路由目的地可以是同一服务版本,也可以是完全不同的服务。

流程

  1. 使用以下示例创建 YAML 文件,根据用户连接到应用程序的不同版本将请求路由到 Bookinfo 示例应用程序服务的不同版本。

    VirtualService.yaml 示例

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: reviews
    spec:
      hosts:
      - reviews
      http:
      - match:
        - headers:
            end-user:
              exact: jason
        route:
        - destination:
            host: reviews
            subset: v2
      - route:
        - destination:
            host: reviews
            subset: v3

  2. 运行以下命令以应用 VirtualService.yaml,其中 VirtualService.yaml 是文件的路径。

    $ oc apply -f <VirtualService.yaml>

2.7.6.2. VirtualService 配置参考

参数描述
spec:
  hosts:

hosts 字段列出了路由规则应用到的虚拟服务的目标地址。这是用于向服务发送请求的地址。虚拟服务主机名可以是解析为完全限定域名的 IP 地址、DNS 名称或简短名称。

spec:
  http:
  - match:

http 部分包含虚拟服务的路由规则,这些规则描述路由 HTTP/1.1、HTTP2 和 gRPC 流量与 hosts 字段中指定的目的地的匹配条件和操作。路由规则由您希望流量到达的目的地以及任何指定的匹配条件组成。示例中的第一个路由规则有一个以 match 字段开头的条件。在这个示例中,这个路由适用于来自用户 jason 的所有请求。添加 headersend-userexact 项来选择适当的请求。

spec:
  http:
  - match:
    - destination:

route 部分的 destination 字段指定与这个条件匹配的流量的实际目的地。与虚拟服务的主机不同,目的地的主机必须是 Red Hat OpenShift Service Mesh 服务 registry 中存在的真实目的地。这可以是带有代理的网格服务,或使用 service 条目添加的一个非网格服务。在本例中,主机名是一个 Kubernetes 服务名称:

2.7.7. 了解目的地规则

目的地规则在评估虚拟服务路由规则后应用,它们应用到流量的真实目的地。虚拟服务将流量路由到目的地。目的地规则配置该目的地的网络流量。

默认情况下,Red Hat OpenShift Service Mesh 使用 round-robin 负载均衡策略,其中实例池中的每个服务实例依次获得请求。Red Hat OpenShift Service Mesh 还支持以下模型,您可以在目的地规则中指定对特定服务或服务子集的请求。

  • Random: 请求会随机转发到池里的实例。
  • Weighted: 根据特定百分比将请求转发到池中的实例。
  • Least requests: 将请求转发到请求数量最少的实例。

目的地规则示例

以下目的地规则示例为 my-svc 目的地服务配置三个不同的子集,具有不同的负载均衡策略:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-destination-rule
spec:
  host: my-svc
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
  - name: v3
    labels:
      version: v3

本指南使用 Bookinfo 示例应用程序来提供示例应用程序中的路由示例。安装 Bookinfo 应用程序 以了解这些路由示例如何工作。

2.7.8. Bookinfo 路由指南

Service Mesh Bookinfo 示例应用程序包含四个独立的微服务,每个服务都有多个版本。安装 Bookinfo 示例应用程序后,reviews 微服务的三个不同版本同时运行。

当您在浏览器中访问 Bookinfo 应用 /product 页面并多次刷新时,有时书的评论输出中会包含星号分级,而其它时候则没有。如果没有可路由的显式默认服务版本,Service Mesh 会将请求路由到所有可用版本。

本教程可帮助您应用将所有流量路由到微服务的 v1 (版本 1)的规则。之后,您可以根据 HTTP 请求标头值应用一条规则来路由流量。

先决条件

  • 部署 Bookinfo 示例应用程序以使用以下示例。

2.7.8.1. 应用虚拟服务

在以下流程中,虚拟服务通过应用为微服务设定默认版本的虚拟服务,将所有流量路由到每个微服务的 v1

流程

  1. 应用虚拟服务。

    $ oc apply -f https://raw.githubusercontent.com/Maistra/istio/maistra-2.2/samples/bookinfo/networking/virtual-service-all-v1.yaml
  2. 要验证是否应用了虚拟服务,请使用以下命令显示定义的路由:

    $ oc get virtualservices -o yaml

    该命令返回一个 kind: VirtualService 资源,采用 YAML 格式。

您已将 Service Mesh 配置为路由到 Bookinfo 微服务的 v1 版本,包括 reviews 服务版本 1。

2.7.8.2. 测试新路由配置

通过刷新 Bookinfo 应用程序的 /productpage 来测试新配置。

流程

  1. 设置 GATEWAY_URL 参数的值。您可以在以后使用这个变量查找 Bookinfo 产品页面的 URL。在本例中,istio-system 是 control plane 项目的名称。

    export GATEWAY_URL=$(oc -n istio-system get route istio-ingressgateway -o jsonpath='{.spec.host}')
  2. 运行以下命令,以检索产品页面的 URL:

    echo "http://$GATEWAY_URL/productpage"
  3. 在浏览器中打开 Bookinfo 网站。

页面的评论部分显示没有分级星,无论您刷新多少次。这是因为您已将 Service Mesh 配置为将 reviews 服务的所有流量路由到版本 review:v1,此版本的服务无法访问星表分级服务。

您的服务网格现在将流量路由到服务的一个版本。

2.7.8.3. 基于用户身份的路由

更改路由配置,以便特定用户的所有流量都路由到特定的服务版本。在这种情况下,所有来自名为 Jason 的用户的流量都会被路由到服务的 review:v2 中。

Service Mesh 对用户身份没有任何特殊的内置了解。这个示例是启用的,因为 productpage 服务为到 reviews 服务的所有传出 HTTP 请求都添加了一个自定义的 end-user 标头。

流程

  1. 运行以下命令在 Bookinfo 示例应用程序中启用基于用户的路由。

    $ oc apply -f https://raw.githubusercontent.com/Maistra/istio/maistra-2.2/samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
  2. 运行以下命令,以确认创建了该规则。此命令返回 YAML 格式的所有 kind: VirtualService

    $ oc get virtualservice reviews -o yaml
  3. 在 Bookinfo 应用程序的 /productpage 中,以用户 jason 身份在无需密码的情况下进行登录。
  4. 刷新浏览器。星级分级会出现在每条评论旁。
  5. 以其他用户身份登录(选择任意名称)。刷新浏览器。现在就不会出现星级评分。现在,除 Jason 外,所有用户的流量都会被路由到 review :v1

您已成功配置了 Bookinfo 示例应用程序,以根据用户身份路由流量。

2.7.9. 其他资源

有关配置 OpenShift Container Platform 通配符策略的更多信息,请参阅使用通配符路由