当配置一个生产级别的Istio时,须要解决一些问题:如网格是单集群使用,仍是跨集群使用?全部的服务会放到一个彻底可达的网络中,仍是须要网关来链接跨网络的服务?使用一个控制面(可能会跨集群共享一个控制面),仍是使用多个控制面来实现高可用(HA)?全部的集群都链接到一个多集群服务网格,仍是联合成一个多网格形态。git
全部这些问题,以及他外因素,都表明了Istio部署的各个配置维度。github
上述条件能够任意组合(虽然有些组合相比其余更加广泛,有些则不那么受欢迎,如单集群中的多网格场景)。shell
在一个涉及多集群的生产环境中,能够混合使用部署模型。例如,可使用多个控制面来作到HA。在一个3集群环境中,能够将两个集群共享一个控制面,而后给第三个集群在不一样的网络中添加另一个控制面。而后配置三个集群共享各自的控制面,这样全部的集群就可使用2个控制面来作到HA。json
实际使用中,须要根据隔离性,性能,以及HA要求来选择合适的部署模型。本章将描述部署Istio时的各类选择和考量。缓存
该模式下,应用的负载会运行在多个集群中。为了隔离,性能或高可用,能够限定集群的可用zone和region。安全
取决于具体要求,生产系统能够跨多个zone或region的多个集群运行,利用云负载均衡器来处理诸如本地性,zonal 或regional故障转移之类的事情。网络
大多数场景下,集群表示配置和终端发现的边界。例如,每一个kubernetes集群都有一个API Server来管理集群的配置,以及提供服务终端的信息,如pod的启停等。因为kubernetes的这种配置行为是基于单个集群的,所以会将潜在的错误(如配置错误)限制在其所在的集群中。app
使用Istio能够在任意个集群上配置一个服务网格。负载均衡
在最简单的场景中,能够在单个集群中部署单Istio网格。一个集群一般会运行在一个独立的网络中,但具体取决于基础设施提供商。包含一个网络的单集群模型会包含一个控制面,这就是istio最简单的部署模型:dom
单集群的部署比较简单,但同时也缺乏一些特性,如故障隔离和转移。若是须要高可用,则应该使用多集群模式。
一个网格能够包含多个集群。使用多集群部署能够在一个网格中提供以下功能。
cluster-1
宕机后,使用cluster-2
多集群部署提供了更大的隔离性和可靠性,但同时也增长了复杂性。若是系统须要高可用,则集群可能会跨多个zone和region。
能够经过金丝雀配置来在单个集群中修改或使用新的二进制版本,这样配置变动仅会影响一小部分的用户流量。若是一个集群出现问题,能够临时把流量路由到临近的集群(直到问题解决)。
此外,能够根据网络和云提供商支持的选项配置集群间的通讯。例如,若是两个集群使用了相同的底层网络,那么就能够经过简单的防火墙规则实现集群间的通讯。
不少生产系统须要多个网络或子网来实现隔离和高可用。Istio支持将一个服务网格部署到多种类型的网络拓扑中。经过这种方式选择符合现有网络拓扑的网络模型。
在最简单场景下,服务网格会运行在一个彻底链接的网络上,在单网络模型下,全部的负载示例可以在没有Istio网格的状况下实现互联。
单个网络使Istio可以在网格中以统一的方式配置服务使用者,并具备直接处理工做负载实例的能力。
多网络提供了以下新功能:
这种模式下,不一样网络中的负载实例只能经过一个或多个Istio网关进行互联。Istio使用分区服务发现来为使用者提供service endpoints的不一样视图。视图取决于使用者的网络。
Istio网格使用控制面来配置网格内负载实例之间的通讯。经过复制控制面,工做负载能够链接到任何控制面来获取配置。
最简单的场景下,可在单集群中运行网格的控制面:
像这样具备本身的本地控制平面的集群被称为主集群。
多集群部署能够共享相同的控制面实例。这种状况下,控制面实例能够位于一个或多个主集群中。没有本身的控制面的集群称为远端集群。
一个彻底由远程集群组成的服务网格能够经过外部控制面进行控制,而不须要经过运行在主集群中的控制面进行控制。经过这种方式将istio在管理上进行了隔离,即将控制面和数据面服务进行了彻底分割。
云提供商的
Managed Control Plane
实际上就是一个外部控制面。
为了高可用,控制面可能须要跨多集群,zone和region来部署。下图中的服务网格在每一个region中都使用了一个控制面。
使用上述模型具备以下优点:
能够经过故障转移来提高控制面的可靠性。当一个控制面实例变为不可用时,负载实例能够链接到其余可用的控制面实例上。集群,zone和region中均可能发生故障迁移。下图能够看到,当左侧的控制面出问题后,由右侧的控制面托管了Envoy代理(虚线)。
如下列表按可用性对控制平面的部署进行了排序:
当在一个服务网格中建立负载实例时,istio会赋予该负载一个身份。
CA( certificate authority)会为网格中使用的身份建立和颁发证书,后续就可使用CA为该身份建立和颁发证书时使用的公钥对消息发送端进行校验。trust bundle是Istio网格使用的全部CA公钥的集合。任何人均可以使用网格的trust bundle校验来自网格的服务。
在单istio网格中,istio保证每一个负载实例都有一个标识其身份的证书,使用trust bundle来识别网格和联邦网格中的全部身份。CA仅负责为这些身份建立和签发证书。该模型容许网格中的负载实例互联。下图展现了一个具备 certificate authority的服务网格。
若是一个网格中的服务须要调用另一个网格中的服务,此时须要在两个网格之间使用联邦身份。为了实现联邦身份的信任,须要交换网格的trust buncles(能够经过手动或自动方式,如SPIFFE Trust Domain Federation来交换trust bundles)
Istio支持在一个网格或联邦网格(也被称为多网格)中部署全部的应用。
单网格是部署Istio的最简单的方式。在一个网格中,服务名是惟一的。例如,一个foo
命名空间中,只能存在一个名为mysvc
的服务。此外,负载实例共享同一个身份service account,由于该资源在命名空间内是惟一的。
单网格能够部署在一个或多个集群中,以及一个或多个网络上。在一个网格中,命名空间用于tenancy(见下)。
多网格是网格联邦的结果。
多网格提供了以下功能:
default
命名空间能够用于多种用途可使用中间网格来链接网格联邦。当使用联邦时,每一个网格均可以暴露一组全部参与的网格都能识别的服务和身份。
为了不服务名冲突,能够给每一个网格分配一个全局惟一的网格ID,来保证每一个服务的fully qualified domain name (FQDN)是有效的。
当联邦中两个网格没有使用相同的信任域时,必须对这两个网格的身份和trust bundles进行联邦。查看Multiple Trust Domains。
在Istio中,租户是一个共享用户组,共享一组已部署的工做负载的访问权限和特权。一般须要从网络配置和策略层面来为不一样的租户隔离负载实例。
能够配置租户模式来知足组织的隔离需求:
Istio支持两种类型的租户:
在一个网格中,Istio使用命名空间做为租户的单位。Istio也能够运行在没有实现命名空间租户的环境中。在实现命名空间租户的环境中,能够保证仅容许一个团队将负载部署在一个给定的命名空间或一组命名空间中。默认状况下,多个租户命名空间中的服务均可以互联。
为了提高隔离性,能够选择暴露到其余命名空间中的服务。经过受权策略来暴露服务或限制访问。
当使用多集群时,每一个集群中的相同名称的命名空间被看做是相同的命名空间。例如,cluster-1
中的foo
命名空间中的Service B
,以及cluster-2
中的foo
命名空间中的Service B
被认为是相同的服务,且Istio会在服务发现时合并endpoints,并在这些endpoints间执行负载均衡。下图展现了具备相同命名空间的两个集群
Istio支持以集群做为租户的单位。这种状况下,能够给每一个团队指定特定的集群或一组集群来部署负载,并受权团队成员。能够给成员分配不一样的角色,如:
为了在Istio中使用集群租户,须要将每一个集群做为独立的网格。此外,可使用Istio将一组集群做为单租户。这样每一个团队就能够拥有一个或多个集群,而不是将全部的集群配置为单网格。为了链接不一样团队的网格,能够将这些将这些网格联邦为多网格。下图展现了使用两个集群和命名空间来隔离服务网格。
因为网格由不一样的团队或组织进行操做,所以服务命名不多会不一样。例如,cluster-1
的foo
命名空间中的mysvc
和cluster-2
的foo
命名空间中的mysvc
服务并非相同的服务。最多见的示例是Kubernetes中的场景,许多团队将工做负载部署到default
命名空间。
当每一个团队都有各自的网格后,就可使用多网格模型跨网格进行通讯。
Istio使用丰富的路由,负载均衡,服务到服务的认证,监控等简化了部署服务的网络,且不须要修改应用代码。Istio力争使用最少的资源开销来提供这些便利,以及在增长最小的延迟下支撑更大规模的网格和更高的请求率。
Istio数据面组件,Envoy代理会处理流经系统的数据。Istio的控制面组件,Pilot,Galley和Citadel来配置数据面。数据面和控制面都有明显的性能问题。
Istio负载测试网格包含1000个服务和2000个sidecar,每秒70000个网格范围的请求。在对Istio1.7测试以后,得出以下结果:
istio-telemetry
服务会使用0.6 vCPUPilot会根据用户的配置文件和系统的当前状态配置sidecar代理。在Kubernetes环境中,CRD和deployment构成了配置和系统状态。Istio配置对象,如gateway和virtual service等提供了用户可编辑的配置。为了生成代理的配置,Pilot处理来自Kubernetes环境和用户配置的组合配置以及系统状态。
控制平面支持成千上万的服务,这些服务分布在成千上万个Pod中,并使用相似数量的由用户编写的virtual services和其余配置对象。Pilot的CPU和内存会随着配置数据的变化和系统状态而变化。CPU的使用包含以下因素:
但这部分是支持水平扩展的。
当启用命名空间租户时,使用1vCPU和1.5GB内存的单个Pilot能够支持1000个服务,2000个sidecar。能够经过增长Pilot的数量来下降配置全部代理的时间。
数据面性能依赖不少因素,如:
延迟,吞吐量以及代理的CPU和内存消耗均根据上述因素进行衡量。
因为sidecar代理会在数据路径上作一些额外的工做,所以会消耗CPU和内存。如Istio 1.1中,在每秒1000个请求的状况下,一个代理会消耗0.6 vCPU。
代理的内存消耗取决于代理保存的总配置状态。大量listeners,clusters和routes可能会增长内存消耗。Istio 1.1引入了命名空间隔离来限制发送到一个代理的配置。在一个大的命名空间中,一个代理大概会消耗50 MB的内存。
因为代理一般不会缓存经过的数据,所以请求率不会影响内存消耗。
命名空间的隔离是经过sidecar资源实现的。如何使用能够参见istio-namespace-isolation-tricks。
因为Istio在数据路径上注入了sidecar代理,所以延迟是一个须要重点考虑的因素。Istio会将身份验证和Mixer过滤器添加到代理,每一个额外的过滤器都会增长代理内部的路径长度,并影响到延迟。
Envoy代理会收在客户端接收到响应以后采集原始的遥测数据。对采集请求的遥测数据的时间不会计算在总的完成请求所须要的时间内。但因为worker忙于处理请求,所以worker可能不会当即处理下一个请求。这种处理会增长请求在队列中等待的时间,并影响到平均值和尾部延迟。实际的尾部延迟取决于流量情况。
在网格中,请求会经过客户端的代理,而后到达服务端。1.7的默认配置中(即,telemetry V2),这两个代理在基准数据平面延迟的90百分位和99百分位延迟上分别增长了大约3.12ms 和3.13ms。经过Istio benchmarks的http/1.1
协议得出如上结论,使用两个代理worker,并启用mutual TLS,经过16个客户端链接来发送每秒1000个请求,每一个请求1KB。
在即将发布的Istio版本中,将把Istio策略和Istio遥测功能做为TelemetryV2添加到代理中。经过这种方式来减小流经系统的数据量,从而减小CPU使用量和延迟。
P90 latency vs client connections without jitter
P99 latency vs client connections without jitter
P90 latency vs client connections with jitter
P99 latency vs client connections with jitter
baseline
客户端Pod直接调用服务端Pod,不通过sidecarnone_both
使用Istio代理,但不配置Istio过滤器v2-stats-wasm_both
客户端和服务端的sidecar都配置彷佛用telemetry v2 v8
v2-stats-nullvm_both
客户端和服务端的sidecar默认都配置彷佛用telemetry v2 nullvm
v2-sd-full-nullvm_both
使用配置的 telemetry v2 nullvm
暴露Stackdriver metrics,访问日志v2-sd-nologging-nullvm_both
与上面系统,但不暴露访问日志Istio使用以下工具来进行benchmarking:
fortio.org
- 恒定吞吐量的负载测试工具blueperf
- 真实的云原生应用程序isotope
- 具备可配置拓扑的合成应用程序做为网格的一部分,kubernetes的pod和service必须知足以下要求:
NET_ADMIN
和NET_RAW
capabilities:若是集群强制使用pod安全策略,则必须给pod添加 NET_ADMIN
和NET_RAW
capabilities。若是使用了Istio CNI 插件,则能够不遵照该要求。app
和version
labels。app
和version
labels会给istio采集的metrics和遥测数据添加上下文信息
app
label:每一个deployment应该包含不一样的app
label。app
label用于在分布式跟踪中添加上下文信息。version
label:指定特定deployment对应的应用版本。若是集群使用了pod安全策略,除非使用了Istio CNI插件,不然pod必须容许NET_ADMIN
和NET_RAW
capabilities。Envoy代理的initialization容器会使用这些capabilities。
为了校验pod是否容许NET_ADMIN
和NET_RAW
capabilities,须要校验pod对应的service account是否可使用pod安全策略来容许NET_ADMIN
和NET_RAW
capabilities。若是没有在pod的deployment中指定service account,那么pod会使用其所在命名空间的default
service account。
使用以下命令能够列出一个service accout的capabilities,替换<your namespace>
和<your service account>
# for psp in $(kubectl get psp -o jsonpath="{range .items[*]}{@.metadata.name}{'\n'}{end}"); do if [ $(kubectl auth can-i use psp/$psp --as=system:serviceaccount:<your namespace>:<your service account>) = yes ]; then kubectl get psp/$psp --no-headers -o=custom-columns=NAME:.metadata.name,CAPS:.spec.allowedCapabilities; fi; done
例如可使用以下命令来校验default
命名空间中的default
service account。
# for psp in $(kubectl get psp -o jsonpath="{range .items[*]}{@.metadata.name}{'\n'}{end}"); do if [ $(kubectl auth can-i use psp/$psp --as=system:serviceaccount:default:default) = yes ]; then kubectl get psp/$psp --no-headers -o=custom-columns=NAME:.metadata.name,CAPS:.spec.allowedCapabilities; fi; done
若是在capabilities列表中看到 NET_ADMIN
和 NET_ADMIN
或*
,则说明该pod容许运行Isti init容器,不然须要配置权限。