第 5 章 Service Mesh 用户指南
5.1. 流量管理
您可以控制 Red Hat OpenShift Service Mesh 中服务间的流量和 API 调用。例如,服务网格中的一些服务可能需要在网格内进行通信,其他服务则需要隐藏。管理流量来隐藏特定后端服务、公开服务、创建测试或版本部署,或者在一组服务上添加安全层。
本指南使用 Bookinfo 示例应用程序来提供示例应用程序中的路由示例。安装 Bookinfo 应用程序 以了解这些路由示例如何工作。
5.1.1. 路由和管理流量
通过在 YAML 文件中使用自定义资源定义在 Red Hat OpenShift Service Mesh 中添加您自己的流量配置来配置服务网格。
5.1.1.1. 使用虚拟服务的流量管理
您可以使用虚拟服务通过 Red Hat OpenShift Service Mesh 将请求动态路由到微服务的不同版本。使用虚拟服务,您可以:
- 通过单一虚拟服务处理多个应用程序服务。如果网格使用 Kubernetes,您可以配置虚拟服务来处理特定命名空间中的所有服务。将单一虚拟服务映射到很多服务特别有助于将单个应用程序变成由不同微服务构建的复合服务,而无需该服务的使用者进行任何改变。
- 配置流量规则与网关相结合,以控制入口和出口流量。
5.1.1.1.1. 配置虚拟服务
使用虚拟服务将请求路由到服务网格中的服务中。每个虚拟服务由一组路由规则组成,并按顺序应用。Red Hat OpenShift Service Mesh 会将每个给定给虚拟服务的请求与网格内的特定实际目的地匹配。
如果没有虚拟服务,Red Hat OpenShift Service Mesh 会在所有服务实例间使用 round-robin 负载均衡分配流量。使用虚拟服务时,您可以指定一个或多个主机名的流量行为。虚拟服务的路由规则告知 Red Hat OpenShift Service Mesh 如何将虚拟服务的流量发送到适当的目的地。路由目的地可以是同一服务版本,也可以是完全不同的服务。
以下示例将请求路由到服务的不同版本,具体取决于用户连接到哪个应用程序。使用此命令来应用此示例 YAML 文件,或您创建的 YAML 文件。
$ oc apply -f - <<EOF 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 EOF
5.1.1.2. 配置您的虚拟主机
以下小节解释了 YAML 文件中的每个字段,并解释了如何在虚拟服务中创建虚拟主机。
5.1.1.2.1. Hosts
hosts
字段列出了这些路由规则应用到的虚拟服务的用户可访问的地址。这是向服务发送请求时使用的地址。
虚拟服务主机名可以是 IP 地址、DNS 名称,或者根据平台而定,可以被是解析为完全限定域名的简短名称。
spec: hosts: - reviews
5.1.1.2.2. 路由规则
http
项包含虚拟服务的路由规则,描述路由 HTTP/1.1、HTTP2 和 gRPC 流量与 hosts 字段中指定的目的地匹配的条件和动作。路由规则包含您希望流量访问的目的地,根据您的用例,可能有零个或更多匹配条件。
匹配条件
示例中的第一个路由规则有一个条件,并以 match 字段开头。在这个示例中,这个路由适用于来自用户 jason
的所有请求。添加 headers
、end-user
和 exact
项来选择适当的请求。
spec: hosts: - reviews http: - match: - headers: end-user: exact: jason
目的地
route 部分的 destination
字段指定与这个条件匹配的流量的实际目的地。与虚拟服务的主机不同,目的地的主机必须是 Red Hat OpenShift Service Mesh 服务 registry 中存在的真实目的地。这可以是带有代理的网格服务,或使用 service 条目添加的一个非网格服务。在本例中,主机名一个是 Kubernetes 服务名称:
spec: hosts: - reviews http: - match: - headers: end-user: exact: jason route: - destination: host: reviews subset: v2
5.1.1.2.3. 目的地规则
目的地规则在评估虚拟服务路由规则后应用,它们应用到流量的真实目的地。虚拟服务将流量路由到目的地。目的地规则配置该目的地的网络流量。
5.1.1.2.3.1. 负载平衡选项
默认情况下,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
5.1.1.2.4. 网关
您可以使用网关来管理入站和出站流量,以指定您想要进入或离开网格的流量。网关配置适用于在网格边缘运行的独立的 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 资源中。
网关主要用于管理入口流量,但您也可以配置出口网关。出口网关可让您为离开网格的流量配置专用退出节点,允许您限制哪些服务可访问外部网络,或者启用安全控制出口流量以为网格添加安全性。您还可以使用网关配置纯内部代理。
网关示例
以下示例显示了外部 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
然后,您可以使用外部流量的路由规则配置虚拟服务。
5.1.1.2.5. 服务条目
服务条目在由 Red Hat OpenShift Service Mesh 内部维护的服务 registry 中添加一个条目。添加服务条目后,Envoy 代理可将流量发送到该服务,就像在您的网格中是一个服务一样。配置服务条目可让您管理网格外运行的服务的流量,包括以下任务:
- 重定向和转发外部目的地的流量,如来自 web 的 API 调用,或转发到旧基础架构中服务的流量。
- 为外部目的地定义重新尝试、超时和错误注入策略。
- 在虚拟机 (VM) 中运行网格服务,方法是在网格中添加虚拟机。
- 在逻辑上,将服务从不同集群添加到网格,以便在 Kubernetes 上配置多集群 Red Hat OpenShift Service Mesh 网格。
- 您不需要为每个希望使用网格服务的外部服务添加服务条目。默认情况下,Red Hat OpenShift Service Mesh 配置 Envoy 代理,将请求传递给未知服务。但是,您无法使用 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
5.1.1.2.6. Sidecar
默认情况下,Red Hat OpenShift Service Mesh 配置每个 Envoy 代理,在其相关负载的所有端口上接收流量,并在转发流量时到达网格中的每个工作负载。您可以使用 sidecar 配置进行以下操作:
- 微调 Envoy 代理接受的端口和协议集合。
- 限制 Envoy 代理可访问的服务集合。
- 您可能想要限制大型应用程序中的 sidecar 可访问性,每个代理都配置为访问网格中的所有其他服务都可能会影响高内存用量的网格性能。
Sidecar 示例
您可以指定是否希望 sidecar 配置应用到特定命名空间中的所有工作负载,或使用 workloadSelector
选择特定工作负载。例如,以下 sidecar 配置将 bookinfo
命名空间中的所有服务配置为只访问在同一命名空间和 Red Hat OpenShift Service Mesh control plane 中运行的服务(当前需要使用 Red Hat OpenShift Service Mesh 策略和 telemetry 功能):
apiVersion: networking.istio.io/v1alpha3 kind: Sidecar metadata: name: default namespace: bookinfo spec: egress: - hosts: - "./*" - "istio-system/*"
5.1.2. 管理入口流量
在 Red Hat OpenShift Service Mesh 中,Ingress Gateway 启用了 Service Mesh 功能,如监控、安全和路由规则,用于进入集群的流量。将 Service Mesh 配置为使用 Service Mesh 网关在服务网格外公开服务。
5.1.2.1. 决定入口 IP 和端口
运行以下命令,以确定您的 Kubernetes 集群是否在支持外部负载均衡器的环境中运行:
$ oc get svc istio-ingressgateway -n istio-system
该命令会返回命名空间中每个项目的 NAME
、TYPE
、CLUSTER-IP
、EXTERNAL-IP
、PORT(S)
和 AGE
。
如果设置了 EXTERNAL-IP
值,您的环境会有一个外部负载均衡器,供您用于入口网关。
如果 EXTERNAL-IP
值是 <none>
,或 <pending>
,则您的环境不会为入口网关提供外部负载均衡器。您可以使用服务的 节点端口 访问网关。
选择您的环境说明:
使用负载均衡器配置路由
如果您的环境有外部负载均衡器,请按照以下步骤操作。
设置入口 IP 和端口:
$ export INGRESS_HOST=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
$ export SECURE_INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].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}')
在没有负载均衡器的情况下配置路由
如果您的环境没有外部负载均衡器,请按照以下步骤操作。您必须使用节点端口。
设置入口端口:
$ export INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
$ export SECURE_INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
5.1.3. 使用 bookinfo 应用程序的路由示例
Service Mesh Bookinfo 示例应用程序包含四个独立的微服务,每个服务都有多个版本。部署了三个不同的版本,一个名为 reviews
的微服务同时运行。
先决条件
- 部署 Bookinfo 示例应用程序以使用以下示例。
关于这个任务
要说明这个问题,请在浏览器中访问 bookinfo 应用的 /productpage
,并多次刷新。
有时,书的评论输出中会包含星号分级,有时则没有分级信息。如果没有可路由的显式默认服务版本,Service Mesh 会将请求路由到所有可用版本。
本教程可帮助您应用将所有流量路由到微服务的 v1
(版本 1)的规则。之后,您可以根据 HTTP 请求标头值应用一条规则来路由流量。
5.1.3.1. 应用虚拟服务
要只路由到一个版本,请应用为微服务设置默认版本的虚拟服务。在以下示例中,虚拟服务将所有流量路由到每个微服务的 v1
运行以下命令以应用虚拟服务:
$ oc apply -f https://raw.githubusercontent.com/Maistra/istio/maistra-1.1/samples/bookinfo/networking/virtual-service-all-v1.yaml
要测试该命令是否成功,请使用以下命令显示定义的路由:
$ oc get virtualservices -o yaml
该命令返回以下 YAML 文件。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: details ... spec: hosts: - details http: - route: - destination: host: details subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: productpage ... spec: gateways: - bookinfo-gateway - mesh hosts: - productpage http: - route: - destination: host: productpage subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: ratings ... spec: hosts: - ratings http: - route: - destination: host: ratings subset: v1 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: reviews ... spec: hosts: - reviews http: - route: - destination: host: reviews subset: v1
您已将 Service Mesh 配置为路由至 Bookinfo 微服务的
v1
版本,最重要的是reviews
服务版本 1。
5.1.3.2. 测试新的路由配置
您可以通过刷新 Bookinfo 应用程序的 /productpage
来轻松地测试新配置。
在浏览器中打开 Bookinfo 网站。URL 为
http://$GATEWAY_URL/productpage
,其中$GATEWAY_URL
是入口的外部 IP 地址。页面的评论部分显示没有分级星,无论您刷新多少次。这是因为您已将 Service Mesh 配置为将 reviews 服务的所有流量路由到版本
review:v1
,此版本的服务无法访问星表分级服务。您的服务网格现在将流量路由到服务的一个版本。
5.1.3.3. 基于用户身份的路由
接下来,修改路由配置,以便特定用户的所有流量都路由到特定的服务版本。在这种情况下,所有来自名为 Jason
的用户的流量都会被路由到服务的 review:v2
中。
请注意,Service Mesh 没有任何特殊的内置用户身份了解功能。这个示例是启用的,因为 productpage
服务为到 reviews 服务的所有传出 HTTP 请求都添加了一个自定义的 end-user
标头。
运行以下命令启用基于用户的路由:
$ oc apply -f https://raw.githubusercontent.com/Maistra/istio/maistra-1.1/samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
确认创建了规则:
$ oc get virtualservice reviews -o yaml
该命令返回以下 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: v1
-
在 Bookinfo 应用程序的
/productpage
中以用户Jason
的身份登陆。刷新浏览器。您会看到什么?星级分级会出现在每条评论旁。 -
以其他用户身份登录(选择任何名称)。刷新浏览器。现在就不会出现星级评分。这是因为除 Jason 外,所有用户的流量都会路由到
review:v1
。
您已成功配置了 Service Mesh,以根据用户身份路由流量。