流量管理基础概念

  • 在 Istio 服务网格中定义路由规则,控制流量路由到服务上的各种行为。
  • VirtualService 路由生效后,配置应用与请求的策略集。
  • ServiceEntry 通常用于在 Istio 服务网格之外启用的服务请求。
  • 为 HTTP/TCP 流量配置负载均衡器,最常见的是在网格边缘的操作,以启用应用程序的入口流量。
  • EnvoyFilter 描述了针对代理服务的过滤器,用来定制由 Istio Pilot 生成的代理配置。一定要谨慎使用此功能。错误的配置内容一旦完成传播,可能会令整个服务网格陷入瘫痪状态。这一配置是用于对 Istio 网络系统内部实现进行变更的。

:本文中的示例引用自 Istio 官方 Bookinfo 示例,见:,且对于配置的讲解都以在 Kubernetes 中部署的服务为准。

VirtualService 故名思义,就是虚拟服务,在 Istio 1.0 以前叫做 RouteRule。VirtualService 中定义了一系列针对指定服务的流量路由规则。每个路由规则都是针对特定协议的匹配规则。如果流量符合这些特征,就会根据规则发送到服务注册表中的目标服务(或者目标服务的子集或版本)。VirtualService 的详细定义和配置请参考通信路由

注意VirtualService 中的规则是按照在 YAML 文件中的顺序执行的,这就是为什么在存在多条规则时,需要慎重考虑优先级的原因。

配置说明

下面是 VirtualService 的配置说明。

示例

下面的例子中配置了一个名为 reviewsVirtualService,该配置的作用是将所有发送给 reviews 服务的流量发送到 v1 版本的子集。

  • 该配置中流量的目标主机是 reviews,如果该服务和规则部署在 Kubernetes 的 default namespace 下的话,对应于 Kubernetes 中的服务的 DNS 名称就是 reviews.default.svc.cluster.local
  • 我们在 hosts 配置了服务的名字只是表示该配置是针对 reviews.default.svc.cluster.local 的服务的路由规则,但是具体将对该服务的访问的流量路由到哪些服务的哪些实例上,就是要通过 destination 的配置了。
  • 我们看到上面的 VirtualService 的 HTTP 路由中还定义了一个 destinationdestination 用于定义在网络中可寻址的服务,请求或连接在经过路由规则的处理之后,就会被发送给 destinationdestination.host 应该明确指向服务注册表中的一个服务。Istio 的服务注册表除包含平台服务注册表中的所有服务(例如 Kubernetes 服务、Consul 服务)之外,还包含了 资源所定义的服务。VirtualService 中只定义流量发送给哪个服务的路由规则,但是并不知道要发送的服务的地址是什么,这就需要 DestinationRule 来定义了。
  • subset 配置流量目的地的子集,下文会讲到。VirtualService 中其实可以除了 hosts 字段外其他什么都不配置,路由规则可以在 DestinationRule 中单独配置来覆盖此处的默认规则。

Subset

subset 不属于 Istio 创建的 CRD,但是它是一条重要的配置信息,有必要单独说明下。subset 是服务端点的集合,可以用于 A/B 测试或者分版本路由等场景。参考 文档,其中会有更多这方面应用的例子。另外在 subset 中可以覆盖服务级别的即 VirtualService 中的定义的流量策略。

以下是subset 的配置信息。对于 Kubernetes 中的服务,一个 subset 相当于使用 label 的匹配条件选出来的 service

DestinationRule 所定义的策略,决定了经过路由处理之后的流量的访问策略。这些策略中可以定义负载均衡配置、连接池大小以及外部检测(用于在负载均衡池中对不健康主机进行识别和驱逐)配置。

配置说明

示例

下面是一条对 productpage 服务的流量目的地策略的配置。

  1. apiVersion: networking.istio.io/v1alpha3
  2. kind: DestinationRule
  3. metadata:
  4. name: reviews
  5. spec:
  6. host: reviews
  7. subsets:
  8. - name: v1
  9. labels:
  10. version: v1

该路由策略将所有对 reviews 服务的流量路由到 v1 的 subset。

Istio 服务网格内部会维护一个与平台无关的使用通用模型表示的服务注册表,当你的服务网格需要访问外部服务的时候,就需要使用 ServiceEntry 来添加服务注册。

EnvoyFilter 描述了针对代理服务的过滤器,用来定制由 Istio Pilot 生成的代理配置。一定要谨慎使用此功能。错误的配置内容一旦完成传播,可能会令整个服务网格陷入瘫痪状态。这一配置是用于对 Istio 网络系统内部实现进行变更的,属于高级配置,用于扩展 Envoy 中的过滤器的。

为 HTTP/TCP 流量配置了一个负载均衡,多数情况下在网格边缘进行操作,用于启用一个服务的入口(ingress)流量,相当于前端代理。与 Kubernetes 的 Ingress 不同,Istio Gateway 只配置四层到六层的功能(例如开放端口或者 TLS 配置),而 Kubernetes 的 Ingress 是七层的。将 VirtualService 绑定到 Gateway 上,用户就可以使用标准的 Istio 规则来控制进入的 HTTP 和 TCP 流量。

Gateway 设置了一个集群外部流量访问集群中的某些服务的入口,而这些流量究竟如何路由到那些服务上则需要通过配置 VirtualServcie 来绑定。下面仍然以 这个服务来说明。

  1. apiVersion: networking.istio.io/v1alpha3
  2. kind: Gateway
  3. metadata:
  4. name: bookinfo-gateway
  5. spec:
  6. selector:
  7. istio: ingressgateway # 使用默认的控制器
  8. servers:
  9. - port:
  10. number: 80
  11. name: http
  12. protocol: HTTP
  13. hosts:
  14. - "*"
  15. ---
  16. apiVersion: networking.istio.io/v1alpha3
  17. kind: VirtualService
  18. metadata:
  19. name: bookinfo
  20. spec:
  21. hosts:
  22. - "*"
  23. gateways:
  24. - bookinfo-gateway
  25. http:
  26. - match:
  27. - uri:
  28. exact: /productpage
  29. - uri:
  30. exact: /login
  31. - uri:
  32. exact: /logout
  33. - uri:
  34. prefix: /api/v1/products
  35. route:
  36. - destination:
  37. host: productpage
  38. port:
  39. number: 9080

上面的例子中 bookinfo 这个 VirtualService 中绑定到了 bookinfo-gatewaybookinfo-gateway 使用了标签选择器选择对应的 Kubernetes pod,即下图中的 pod。

我们再看下 istio-ingressgateway 的 YAML 安装配置。

我们看到 ingressgateway 使用的是 proxyv2 镜像,该镜像容器的启动命令入口是 /usr/local/bin/pilot-agent,后面跟参数 proxy 就会启动一个 Envoy 进程,因此 Envoy 既作为 sidecar 也作为边缘代理,egressgateway 的情况也是类似,只不过它控制的是集群内部对外集群外部的请求。这正好验证了本文开头中所画的 Istio Pilot 架构图。请求 /productpage/login/logout/api/v1/products 这些 URL 的流量转发给 productpage 服务的 9080 端口,而这些流量进入集群内又是经过 ingressgateway pod 代理的,通过访问 ingressgateway pod 所在的宿主机的 31380 端口进入集群内部的。

VirtualSerivce 和 DestimationRule 示意图

在前提条件中我部署了该示例,并列出了该示例中的所有 pod,现在我们使用 istioctl 命令来启动查看 productpage-v1-745ffc55b7-2l2lw pod 中的流量配置。

查看 pod 中 Envoy sidecar 的启动配置信息

消息是 Envoy 配置的根本来源,Bootstrap 消息的一个关键的概念是静态和动态资源的之间的区别。例如 或 Cluster 这些资源既可以从 静态的获得也可以从 dynamic_resources 中配置的 LDS 或 CDS 之类的 xDS 服务获取。关于 xDS 服务的详解请参考 。

  1. $ istioctl proxy-config bootstrap productpage-v1-745ffc55b7-2l2lw -o json
  2. {
  3. "bootstrap": {
  4. "node": {
  5. "id": "sidecar~172.33.78.10~productpage-v1-745ffc55b7-2l2lw.default~default.svc.cluster.local",
  6. "cluster": "productpage",
  7. "metadata": {
  8. "INTERCEPTION_MODE": "REDIRECT",
  9. "ISTIO_PROXY_SHA": "istio-proxy:6166ae7ebac7f630206b2fe4e6767516bf198313",
  10. "ISTIO_PROXY_VERSION": "1.0.0",
  11. "ISTIO_VERSION": "1.0.0",
  12. "POD_NAME": "productpage-v1-745ffc55b7-2l2lw",
  13. },
  14. "buildVersion": "0/1.8.0-dev//RELEASE"
  15. },
  16. "staticResources": { # Envoy 的静态配置,除非销毁后重设,否则不会改变,配置中会明确指定每个上游主机的已解析网络名称( IP 地址、端口、unix 域套接字等)。
  17. "clusters": [
  18. {
  19. "name": "xds-grpc",
  20. "type": "STRICT_DNS",
  21. "connectTimeout": "10.000s",
  22. "hosts": [
  23. { # istio-pilot 的地址,指定控制平面地址,这个必须是通过静态的方式配置的
  24. "socketAddress": {
  25. "address": "istio-pilot.istio-system",
  26. "portValue": 15010
  27. }
  28. }
  29. ],
  30. "circuitBreakers": { # 断路器配置
  31. "thresholds": [
  32. {
  33. "maxConnections": 100000,
  34. "maxPendingRequests": 100000,
  35. "maxRequests": 100000
  36. },
  37. {
  38. "priority": "HIGH",
  39. "maxConnections": 100000,
  40. "maxPendingRequests": 100000,
  41. "maxRequests": 100000
  42. }
  43. ]
  44. },
  45. "http2ProtocolOptions": {
  46. },
  47. "upstreamConnectionOptions": { # 上游连接选项
  48. "tcpKeepalive": {
  49. "keepaliveTime": 300
  50. }
  51. }
  52. },
  53. { # zipkin 分布式追踪地址配置
  54. "name": "zipkin",
  55. "type": "STRICT_DNS",
  56. "connectTimeout": "1.000s",
  57. "hosts": [
  58. {
  59. "socketAddress": {
  60. "address": "zipkin.istio-system",
  61. "portValue": 9411
  62. }
  63. ]
  64. }
  65. ]
  66. }, # 以下是动态配置
  67. "dynamicResources": {
  68. "ldsConfig": { # Listener Discovery Service 配置,直接使用 ADS 配置,此处不用配置
  69. "ads": {
  70. }
  71. },
  72. "cdsConfig": { # Cluster Discovery Service 配置,直接使用 ADS 配置,此处不用配置
  73. "ads": {
  74. }
  75. },
  76. "adsConfig": { # Aggregated Discovery Service 配置,ADS 中集成了 LDS、RDS、CDS
  77. "apiType": "GRPC",
  78. "grpcServices": [
  79. {
  80. "envoyGrpc": {
  81. "clusterName": "xds-grpc"
  82. }
  83. }
  84. ],
  85. "refreshDelay": "1.000s"
  86. }
  87. "statsSinks": [ # metric 汇聚的地址
  88. {
  89. "name": "envoy.statsd",
  90. "config": {
  91. "address": {
  92. "socket_address": {
  93. "address": "10.254.109.175",
  94. "port_value": 9125
  95. }
  96. }
  97. }
  98. }
  99. ],
  100. "statsConfig": {
  101. "useAllDefaultTags": false
  102. },
  103. "tracing": { # zipkin 地址
  104. "http": {
  105. "name": "envoy.zipkin",
  106. "config": {
  107. "collector_cluster": "zipkin"
  108. }
  109. }
  110. },
  111. "admin": {
  112. "accessLogPath": "/dev/stdout",
  113. "address": {
  114. "socketAddress": {
  115. "address": "127.0.0.1",
  116. "portValue": 15000
  117. }
  118. }
  119. }
  120. },
  121. "lastUpdated": "2018-09-04T03:38:45.645Z"
  122. }

以上为初始信息。

创建一个名为 reviewsVirtualService

  1. $ cat<<EOF | istioctl create -f -
  2. kind: VirtualService
  3. metadata:
  4. name: reviews
  5. spec:
  6. hosts:
  7. - reviews
  8. http:
  9. - route:
  10. - destination:
  11. host: reviews
  12. subset: v1
  13. EOF

上面的 VirtualService 定义只是定义了访问 reviews 服务的流量要全部流向 reviews服务的 v1子集,至于哪些实例是 v1 子集,VirtualService 中并没有定义,这就需要再创建个 DestinationRule

同时还可以为每个 subset 设置负载均衡规则。这里面也可以同时创建多个子集,例如同时创建3个 subset 分别对应3个版本的实例。

  1. $ cat <<EOF | istioctl create -f -
  2. apiVersion: networking.istio.io/v1alpha3
  3. kind: DestinationRule
  4. metadata:
  5. name: reviews
  6. spec:
  7. host: reviews
  8. subsets:
  9. - name: v1
  10. labels:
  11. version: v1
  12. - name: v2
  13. labels:
  14. version: v2
  15. - name: v3
  16. labels:
  17. version: v3
  18. EOF

同时配置了三个 subset 当你需要切分流量时可以直接修改 VirtualServicedestination 里的 subset 即可,还可以根据百分比拆分流量,配置超时和重试,进行错误注入等,详见流量管理

当然上面这个例子中只是简单的将流量全部导到某个 VirtualServicesubset 中,还可以根据其他限定条件如 HTTP headers、pod 的 label、URL 等。

此时再查询 productpage-v1-745ffc55b7-2l2lw pod 的配置信息。

  1. $ istioctl proxy-config clusters productpage-v1-8d69b45c-bcjqv|grep reviews
  2. reviews.default.svc.cluster.local 9080 - outbound EDS
  3. reviews.default.svc.cluster.local 9080 v1 outbound EDS
  4. reviews.default.svc.cluster.local 9080 v2 outbound EDS
  5. reviews.default.svc.cluster.local 9080 v3 outbound EDS

参考