Istio 是由 Google、IBM 和 Lyft 开源的微服务管理、保护和监控框架。
官网:https://istio.io/latest/zh/
官方文档:https://istio.io/docs/
中文官方文档:https://istio.io/zh/docs
Github地址:https://github.com/istio/istio/releases
Service Mesh 服务网格:服务本身只用管理自己,不需要考虑网络连接,流量控制。
服务网格(Service Mesh)是处理服务间通信的基础设施层。它负责构成现代云原生应用程序的复杂服务拓扑来可靠地交付请求。在实践中,Service Mesh 通常以轻量级网络代理阵列的形式实现,这些代理与应用程序代码部署在一起,对应用程序来说无需感知代理的存在。服务网格有如下几个特点:
1、应用程序间通讯的中间层
2、轻量级网络代理
3、应用程序无感知
4、解耦应用程序的重试/超时、监控、追踪和服务发现
如果用一句话来解释什么是服务网格,可以将它比作是应用程序或者说微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控。对于编写应用程序来说一般无须关心 TCP/IP 这一层,同样使用服务网格也就无须关心服务之间那些原来是通过应用程序或者其他框架实现的事情,比如 Spring Cloud、GoZero等等,现在只要交给服务网格就可以了。
服务网格的架构如下图所示:
服务网格会在每个 pod 中注入一个 sidecar 代理,该代理对应用程序来说是透明,所有应用程序间的流量都会通过它,所以对应用程序流量的控制都可以在服务网格中实现。
服务网格service-mesh它描述了服务间的依赖形态,就像下面这张网一样:
深色的是我们平时工作中接触最多的业务微服务,旁边蓝色的被称为边车(sidecar)服务,sidecar作为业务微服务的“代理”,处理与其他业务微服务sidecar之间的非功能需求,如网络通信、安全、监控、流量控制等。多个sidecar之间的连接和交互组成了“网格(mesh)”。
istio架构,Istio 服务网格从逻辑上分为数据平面和控制平面。
数据平面:由一组智能代理(Envoy)以 sidecar 模式部署,协调和控制所有服务之间的网络通信。
控制平面:负责管理和配置代理路由流量,以及在运行时执行的政策。
下图展示了组成每个平面的不同组件:
Istio特性,使用istio的进行微服务管理有如下特性:
1、流量管理:控制服务间的流量和API调用流,使调用更可靠,增强不同环境下的网络鲁棒性。如果一个系统在内部和外部发生错误时仍能保持其基本功能,那么这个系统具有鲁棒性。
2、可观测性:了解服务之间的依赖关系和它们之间的性质和流量,提供快速识别定位问题的能力。
3、策略实施:通过配置mesh而不是以改变代码的方式来控制服务之间的访问策略。
4、服务识别和安全:提供在mesh里的服务可识别性和安全性保护。
Istio的一些组件:
Istio 使用 Envoy 代理的扩展版本,该代理是以 C++ 开发的高性能代理,用于调解服务网格中所有服务的所有入站和出站流量。Envoy 代理被部署为服务的 sidecar,在逻辑上为服务增加了 Envoy 的许多内置特性,例如:
1、动态服务发现
2、负载均衡
3、TLS 终端
4、HTTP/2 与 gRPC 代理
5、熔断器
6、健康检查
7、基于百分比流量分割的分阶段发布
8、故障注入
9、丰富的指标
Envoy 在 Pod 中以 sidecar 模式部署。这允许 Istio 将大量关于流量行为的信号作为属性提取出来,并发送给监控系统以提供有关整个服务网格的行为信息。Sidecar 代理模型还允许你将 Istio 功能添加到现有部署中,无需重新构建或重写代码。
Pilot 为 Envoy sidecar 提供服务发现、用于智能路由的流量管理功能(例如,A/B 测试、金丝雀发布等)以及弹性功能(超时、重试、熔断器等)。
Pilot 将控制流量行为的高级路由规则转换为特定于环境的配置,并在运行时将它们传播到 sidecar。Pilot 将特定于平台的服务发现机制抽象出来,并将它们合成为任何符合 Envoy API 的 sidecar 都可以使用的标准格式。
下图展示了平台适配器和 Envoy 代理如何交互。
1、平台启动一个服务的新实例,该实例通知其平台适配器。
2、平台适配器使用 Pilot 抽象模型注册实例。
3、Pilot 将流量规则和配置派发给 Envoy 代理,来传达此次更改。
版本选择说明,istio 对 Kubernetes v1.22.12 ( k8s版本v1.23.10也行)适配版本为 1.16 ,https://istio.io/latest/docs/releases/supported-releases/
安装步骤,https://istio.io/latest/zh/docs/setup/getting-started/
1、下载和安装istioctl 工具
tar -zxvf istio-1.16.6-linux-amd64.tar.gz,cd istio-1.16.6/,export PATH=$PWD/bin:$PATH
2、部署istio服务到k8s,采用 demo 配置组合
[root@master istio-1.16.6]# istioctl install --set profile=demo -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete Making this installation the default for injection and validation.
Thank you for installing Istio 1.16. Please take a few minutes to tell us about your install/upgrade experience! https://forms.gle/99uiMML96AmsXY5d6
[root@master istio-1.16.6]# kubectl get all -n istio-system
NAME READY STATUS RESTARTS AGE
pod/istio-egressgateway-7fb7666cd8-fdmvz 1/1 Running 0 84m
pod/istio-ingressgateway-7c46f85b68-bg47l 1/1 Running 0 84m
pod/istiod-7fc69785bc-q55p2 1/1 Running 0 86m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/istio-egressgateway ClusterIP 10.233.18.139 <none> 80/TCP,443/TCP 84m
service/istio-ingressgateway LoadBalancer 10.233.51.57 <pending> 15021:30317/TCP,80:30287/TCP,443:30935/TCP,31400:30496/TCP,15443:30783/TCP 84m
service/istiod ClusterIP 10.233.20.170 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 86m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/istio-egressgateway 1/1 1 1 84m
deployment.apps/istio-ingressgateway 1/1 1 1 84m
deployment.apps/istiod 1/1 1 1 86m
NAME DESIRED CURRENT READY AGE
replicaset.apps/istio-egressgateway-7fb7666cd8 1 1 1 84m
replicaset.apps/istio-ingressgateway-7c46f85b68 1 1 1 84m
replicaset.apps/istiod-7fc69785bc 1 1 1 86m
3、注入指定的命名空间,给命名空间添加标签,指示 Istio 在部署应用的时候,自动注入 Envoy 边车代理
[root@master istio-1.16.6]# kubectl label namespace default istio-injection=enabled
namespace/default labeled
[root@master istio-1.16.6]# kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 3d6h
部署bookinfo应用,应用说明:https://istio.io/latest/zh/docs/examples/bookinfo/
[root@master istio-1.16.6]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
[root@master istio-1.16.6]# kubectl get all
如果没有设置istio注入,这里的所有pod应该是一个,istio注入后,每个服务有一个边车服务,所以这里有2个pod
NAME READY STATUS RESTARTS AGE
pod/details-v1-6758dd9d8d-dhkvf 2/2 Running 0 16m
pod/productpage-v1-797d845774-twvkr 2/2 Running 0 16m
pod/ratings-v1-f849dc6d-tlcjn 2/2 Running 0 16m
pod/reviews-v1-74fb8fdbd8-jnkzq 2/2 Running 0 16m
pod/reviews-v2-58d564d4db-2ddtd 2/2 Running 0 16m
pod/reviews-v3-55545c459b-v5plw 2/2 Running 0 16m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/details ClusterIP 10.233.5.45 <none> 9080/TCP 16m
service/kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 3d6h
service/productpage ClusterIP 10.233.54.150 <none> 9080/TCP 16m
service/ratings ClusterIP 10.233.59.154 <none> 9080/TCP 16m
service/reviews ClusterIP 10.233.30.109 <none> 9080/TCP 16m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/details-v1 1/1 1 1 16m
deployment.apps/productpage-v1 1/1 1 1 16m
deployment.apps/ratings-v1 1/1 1 1 16m
deployment.apps/reviews-v1 1/1 1 1 16m
deployment.apps/reviews-v2 1/1 1 1 16m
deployment.apps/reviews-v3 1/1 1 1 16m
NAME DESIRED CURRENT READY AGE
replicaset.apps/details-v1-6758dd9d8d 1 1 1 16m
replicaset.apps/productpage-v1-797d845774 1 1 1 16m
replicaset.apps/ratings-v1-f849dc6d 1 1 1 16m
replicaset.apps/reviews-v1-74fb8fdbd8 1 1 1 16m
replicaset.apps/reviews-v2-58d564d4db 1 1 1 16m
replicaset.apps/reviews-v3-55545c459b 1 1 1 16m
测试访问,通过检查返回的页面标题来验证应用是否已在集群中运行
[root@master istio-1.16.6]# kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o ".* "
<title>Simple Bookstore App</title>
暴露服务到外网
1、把应用关联到 Istio 网关
[root@master istio-1.16.6]# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
[root@master istio-1.16.6]# kubectl get vs (vs指virtualservice)
NAME GATEWAYS HOSTS AGE
bookinfo ["bookinfo-gateway"] ["*"] 15s
2、判断k8s集群环境是否有外部负载均衡器
[root@master istio-1.16.6]# kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.233.51.57 <pending> 15021:30317/TCP,80:30287/TCP,443:30935/TCP,31400:30496/TCP,15443:30783/TCP 125m
3、k8s集群环境没有外部负载均衡器,那就选择一个节点端口来代替,设置入站的端口
[root@master istio-1.16.6]# export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
[root@master istio-1.16.6]# export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
[root@master istio-1.16.6]# export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
4、设置环境变量 GATEWAY_URL
[root@master istio-1.16.6]# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
[root@master istio-1.16.6]# echo "$GATEWAY_URL"
10.1.1.112:30287
或者在线修改svc为NodePort
[root@master istio-1.16.6]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.233.5.45 <none> 9080/TCP 42m
kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 3d7h
productpage ClusterIP 10.233.54.150 <none> 9080/TCP 42m
ratings ClusterIP 10.233.59.154 <none> 9080/TCP 42m
reviews ClusterIP 10.233.30.109 <none> 9080/TCP 42m
[root@master istio-1.16.6]# kubectl edit service/productpage
service/productpage edited
[root@master istio-1.16.6]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.233.5.45 <none> 9080/TCP 43m
kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 3d7h
productpage NodePort 10.233.54.150 <none> 9080:31550/TCP 43m
ratings ClusterIP 10.233.59.154 <none> 9080/TCP 43m
reviews ClusterIP 10.233.30.109 <none> 9080/TCP 43m
浏览器访问测试,http://10.1.1.112:30287/productpage,或http://10.1.1.113:31550/productpage
监控部署 kiali
1、安装 Kiali 和其他插件
kubectl apply -f samples/addons
kubectl rollout status deployment/kiali -n istio-system 检查kiali是否安装成功
Waiting for deployment "kiali" rollout to finish: 0 of 1 updated replicas are available...
deployment "kiali" successfully rolled out
2、暴露服务,浏览器访问 Kiali 仪表板
kubectl get svc -n istio -n istio-system
kubectl edit svc kiali -n istio-system 将type修改为NodePort
测试访问,http://10.1.1.113:31230/kiali
https://istio.io/latest/zh/docs/concepts/traffic-management/#virtual-services
Istio 的流量路由规则可以让您很容易的控制服务之间的流量和 API 调用。 Istio 简化了服务级别属性的配置,比如熔断器、超时和重试,并且能轻松的设置重要的任务, 如 A/B 测试、金丝雀发布、基于流量百分比切分的分阶段发布等。它还提供了开箱即用的故障恢复特性, 有助于增强应用的健壮性,从而更好地应对被依赖的服务或网络发生故障的情况。
Istio 的流量管理模型源于和服务一起部署的 Envoy 代理。 网格内服务发送和接收的所有 data plane 流量都经由 Envoy 代理, 这让控制网格内的流量变得异常简单,而且不需要对服务做任何的更改。
为了在网格中导流,Istio 需要知道所有的 endpoint 在哪以及它们属于哪些服务。 为了定位到 service registry(服务注册中心), Istio 会连接到一个服务发现系统。例如,如果您在 Kubernetes 集群上安装了 Istio, 那么它将自动检测该集群中的服务和 endpoint。
使用此服务注册中心,Envoy 代理可以将流量定向到相关服务。大多数基于微服务的应用程序, 每个服务的工作负载都有多个实例来处理流量,称为负载均衡池。默认情况下, Envoy 代理基于轮询调度模型在服务的负载均衡池内分发流量,按顺序将请求发送给池中每个成员, 一旦所有服务实例均接收过一次请求后,就重新回到第一个池成员。
Istio 基本的服务发现和负载均衡能力为您提供了一个可用的服务网格, 但它能做到的远比这多的多。在许多情况下,您可能希望对网格的流量情况进行更细粒度的控制。 作为 A/B 测试的一部分,您可能想将特定百分比的流量定向到新版本的服务, 或者为特定的服务实例子集应用不同的负载均衡策略。您可能还想对进出网格的流量应用特殊的规则, 或者将网格的外部依赖项添加到服务注册中心。
通过使用 Istio 的流量管理 API 将流量配置添加到 Istio, 就可以完成所有这些甚至更多的工作。和其他 Istio 配置一样,这些 API 也使用 Kubernetes 的自定义资源定义 (CRD)来声明,您可以像示例中看到的那样使用 YAML 进行配置。
3.1虚拟服务Virtual Service
虚拟服务(Virtual Service) 和目标规则(Destination Rule) 是 Istio 流量路由功能的核心构建模块。 基于 Istio 和您的平台提供的基本连通性及服务发现能力,虚拟服务允许您配置请求如何路由到特定的服务。 每个虚拟服务包含一组按顺序评估的路由规则,通过这些规则,Istio 将每个到虚拟服务的给定请求匹配到特定的、真实的目标地址。 根据您的使用场景,您的服务网格可以有多个虚拟服务或者不需要虚拟服务。
为什么使用虚拟服务?
虚拟服务在增强 Istio 流量管理的灵活性和有效性方面,发挥着至关重要的作用, 实现方式是解耦客户端请求的目标地址与实际响应请求的目标工作负载。 虚拟服务同时提供了丰富的方式,为发送至这些工作负载的流量指定不同的路由规则。
为什么这如此有用?就像在介绍中所说,如果没有虚拟服务, Envoy 会在所有的服务实例中使用轮询的负载均衡策略分发请求。 您可以用您对工作负载的了解来改善这种行为。例如,有些可能代表不同的版本。 这在 A/B 测试中可能有用,您可能希望在其中配置基于不同服务版本的流量百分比路由, 或指引从内部用户到特定实例集的流量。
使用虚拟服务,您可以为一个或多个主机名指定流量行为。在虚拟服务中使用路由规则, 告诉 Envoy 如何发送虚拟服务的流量到适当的目标。路由目标地址可以是同一服务的不同版本, 也可以是完全不同的服务。
一个典型的用例是将流量发送到被指定为服务子集的服务的不同版本。 客户端将虚拟服务视为一个单一实体,将请求发送至虚拟服务主机, 然后 Envoy 根据虚拟服务规则把流量路由到不同的版本。例如, “20% 的调用转发到新版本”或“将这些用户的调用转发到版本 2”。 这允许您创建一个金丝雀发布,逐步增加发送到新版本服务的流量百分比。 流量路由完全独立于实例部署,这意味着实现新版本服务的实例可以根据流量的负载来伸缩, 完全不影响流量路由。相比之下,像 Kubernetes 这样的容器编排平台只支持基于实例缩放的流量分发, 这会让情况变得复杂。
虚拟服务可以让您:和网关整合并配置流量规则来控制出入流量。
通过单个虚拟服务处理多个应用程序服务。如果您的网格使用 Kubernetes, 可以配置一个虚拟服务处理特定命名空间中的所有服务。映射单一的虚拟服务到多个“真实”服务特别有用, 可以在不需要客户适应转换的情况下,将单体应用转换为微服务构建的复合应用系统。 您的路由规则可以指定为“对 monolith.com 的 URI 调用转发到 microservice A” 等等。 您可以在下面的一个示例看到它是如何工作的。
在某些情况下,您还需要配置目标规则来使用这些特性,因为这是指定服务子集的地方。 在一个单独的对象中指定服务子集和其它特定目标策略,有利于在虚拟服务之间更简洁地重用这些规则。
虚拟服务示例,下面的虚拟服务根据请求是否来自特定的用户,把它们路由到服务的不同版本。
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
- route:
- destination:
host: reviews
subset: v1
3.2目标规则
与虚拟服务一样, 目标规则也是 Istio 流量路由功能的关键部分。您可以将虚拟服务视为将流量如何路由到给定目标地址, 然后使用目标规则来配置该目标的流量。在评估虚拟服务路由规则之后, 目标规则将应用于流量的“真实”目标地址。
特别是,您可以使用目标规则来指定命名的服务子集,例如按版本为所有给定服务的实例分组。 然后可以在虚拟服务的路由规则中使用这些服务子集来控制到服务不同实例的流量。
目标规则还允许您在调用整个目的地服务或特定服务子集时定制 Envoy 的流量策略, 比如您喜欢的负载均衡模型、TLS 安全模式或熔断器设置。 在目标规则参考中可以看到目标规则选项的完整列表。
负载均衡选项
默认情况下,Istio 使用轮询的负载均衡策略,实例池中的每个实例依次获取请求。Istio 同时支持如下的负载均衡模型, 可以在 DestinationRule 中为流向某个特定服务或服务子集的流量指定这些模型。
随机:请求以随机的方式转发到池中的实例。
权重:请求根据指定的百分比转发到池中的实例。
最少请求:请求被转发到最少被访问的实例。
目标规则示例,目标规则为 my-svc 目标服务配置了 3 个具有不同负载均衡策略的子集。
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
每个子集都是基于一个或多个 labels 定义的,在 Kubernetes 中它是附加到像 Pod 这种对象上的键/值对。这些标签应用于 Kubernetes 服务的 Deployment 并作为 metadata 来识别不同的版本。
除了定义子集之外,此目标规则对于所有子集都有默认的流量策略,而对于该子集, 则有特定于子集的策略覆盖它。定义在 subsets 上的默认策略,为 v1 和 v3 子集设置了一个简单的随机负载均衡器。在 v2 策略中,轮询负载均衡器被指定在相应的子集字段上。
3.3、网关
使用网关来管理网格的入站和出站流量, 可以让您指定要进入或离开网格的流量。网关配置被用于运行在网格边缘的独立 Envoy 代理, 而不是与服务工作负载一起运行的 Sidecar Envoy 代理。
与 Kubernetes Ingress API 这种控制进入系统流量的其他机制不同, Istio 网关让您充分利用流量路由的强大能力和灵活性。 您可以这么做的原因是 Istio 的网关资源可以配置 4-6 层的负载均衡属性, 如对外暴露的端口、TLS 设置等。然后,您无需将应用层流量路由 (L7) 添加到同一 API 资源, 而是将常规 Istio 虚拟服务绑定到网关。 这让您可以像管理网格中其他数据平面的流量一样去管理网关流量。
网关主要用于管理进入的流量,但您也可以配置出口网关。出口网关让您为离开网格的流量配置一个专用的出口节点, 这可以限制哪些服务可以或应该访问外部网络, 或者启用出口流量安全控制增强网格安全性。 您也可以使用网关配置一个纯粹的内部代理。
Istio 提供了一些预先配置好的网关代理部署(istio-ingressgateway 和 istio-egressgateway) 供您使用——如果使用 demo 配置文件安装它们都已经部署好了; 如果使用的是 default 配置文件则只部署了入口网关。 可以将您自己的网关配置应用到这些部署或配置您自己的网关代理。
Gateway 示例,下面的示例展示了一个外部 HTTPS 入口流量的网关配置:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: ext-host-gwy
spec:
selector:
app: my-gateway-controller
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- ext-host.example.com
tls:
mode: SIMPLE
credentialName: ext-host-cert
这个网关配置让 HTTPS 流量从 ext-host.example.com 通过 443 端口流入网格, 但没有为请求指定任何路由规则。要指定路由并让网关按预期工作,您必须把网关绑定到虚拟服务上。 正如下面的示例所示,使用虚拟服务的 gateways 字段进行设置:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtual-svc
spec:
hosts:
- ext-host.example.com
gateways:
- ext-host-gwy
3.4、服务入口
使用服务入口(Service Entry) 来添加一个入口到 Istio 内部维护的服务注册中心。添加了服务入口后,Envoy 代理可以向服务发送流量, 就好像它是网格内部的服务一样。配置服务入口允许您管理运行在网格外的服务的流量,它包括以下几种能力:
1、为外部目标重定向和转发请求,例如来自 Web 端的 API 调用,或者流向遗留老系统的服务。
2、为外部目标定义重试、超时和故障注入策略。
3、添加一个运行在虚拟机的服务来扩展您的网格。
您不需要为网格服务要使用的每个外部服务都添加服务入口。 默认情况下,Istio 配置 Envoy 代理将请求传递给未知服务。 但是,您不能使用 Istio 的特性来控制没有在网格中注册的目标流量。
服务入口示例,mesh-external 服务入口将 ext-svc.example.com 外部依赖项添加到 Istio 的服务注册中心:
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 字段。可以使用完全限定名或通配符作为前缀域名。
您可以配置虚拟服务和目标规则,以更细粒度的方式控制到服务入口的流量, 这与网格中的任何其他服务配置流量的方式相同。例如, 下面的目标规则调整了使用服务入口配置的 ext-svc.example.com 外部服务的连接超时:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ext-res-dr
spec:
host: ext-svc.example.com
trafficPolicy:
connectionPool:
tcp:
connectTimeout: 1s
3.5、Sidecar
默认情况下,Istio 让每个 Envoy 代理都可以访问来自和它关联的工作负载的所有端口的请求, 然后转发到对应的工作负载。您可以使用 Sidecar 配置去做下面的事情:
1、微调 Envoy 代理接受的端口和协议集。
2、限制 Envoy 代理可以访问的服务集合。
您可能希望在较庞大的应用程序中限制这样的 Sidecar 可达性, 配置每个代理能访问网格中的任意服务可能会因为高内存使用量而影响网格的性能。
您可以指定将 Sidecar 配置应用于特定命名空间中的所有工作负载,或者使用 workloadSelector 选择特定的工作负载。例如,下面的 Sidecar 配置将 bookinfo 命名空间中的所有服务配置为仅能访问运行在相同命名空间和 Istio 控制平面中的服务(Istio 的 Egress 和遥测功能需要使用):
apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
name: default
namespace: bookinfo
spec:
egress:
- hosts:
- "./*"
- "istio-system/*"
3.6、超时
超时是 Envoy 代理等待来自给定服务的答复的时间量,以确保服务不会因为等待答复而无限期的挂起, 并在可预测的时间范围内调用成功或失败。HTTP 请求的默认超时时间是 15 秒, 这意味着如果服务在 15 秒内没有响应,调用将失败。
对于某些应用程序和服务,Istio 的缺省超时可能不合适。例如,超时太长可能会由于等待失败服务的回复而导致过度的延迟; 而超时过短则可能在等待涉及多个服务返回的操作时触发不必要的失败。为了找到并使用最佳超时设置, Istio 允许您使用虚拟服务按服务轻松地动态调整超时,而不必修改您的业务代码。 下面的示例是一个虚拟服务,它对 ratings 服务的 v1 子集的调用指定 10 秒超时:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
timeout: 10s
3.7、重试
重试设置指定如果初始调用失败,Envoy 代理尝试连接服务的最大次数。 重试可以通过确保调用不会由于暂时性问题(例如临时过载的服务或网络)而永久失败, 从而提高服务可用性和应用程序性能。重试之间的间隔(25ms+)是可变的,由 Istio 自动确定, 防止被调用的服务被请求淹没。HTTP 请求的默认重试行为是在返回错误之前重试两次。
与超时一样,Istio 默认的重试行为在延迟方面可能不适合您的应用程序需求(对失败的服务进行过多的重试会降低速度)或可用性。 您可以在虚拟服务中按服务调整重试设置,而不必修改业务代码。 您还可以通过添加每次重试的超时来进一步细化重试行为,指定您希望等待每次重试成功连接到服务的时间量。 下面的示例配置了在初始调用失败后最多重试 3 次来连接到服务子集,每个重试都有 2 秒的超时。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
retries:
attempts: 3
perTryTimeout: 2s
3.8、熔断器
熔断器是 Istio 为创建具有弹性的微服务应用提供的另一个有用的机制。在熔断器中, 设置一个对服务中的单个主机调用的限制,例如并发连接的数量或对该主机调用失败的次数。 一旦限制被触发,熔断器就会“跳闸”并停止连接到该主机。 使用熔断模式可以快速失败而不必让客户端尝试连接到过载或有故障的主机。
熔断适用于在负载均衡池中的“真实”网格目标地址,您可以在目标规则中配置熔断器阈值, 让配置应用于服务中的每个主机。下面的示例将 v1 子集的 reviews 服务工作负载的并发连接数限制为 100:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
3.9、故障注入
在配置了网络,包括故障恢复策略之后,可以使用 Istio 的故障注入机制来为整个应用程序测试故障恢复能力。 故障注入是一种将错误引入系统以确保系统能够承受并从错误条件中恢复的测试方法。 使用故障注入特别有用,能确保故障恢复策略不至于不兼容或者太严格,这会导致关键服务不可用。
目前,故障注入配置不能与同一个虚拟服务上的重试或超时配置相结合.
与其他错误注入机制(如延迟数据包或在网络层杀掉 Pod)不同,Istio 允许在应用层注入错误。 这使您可以注入更多相关的故障,例如 HTTP 错误码,以获得更多相关的结果。
您可以注入两种故障,它们都使用虚拟服务配置:
1、延迟:延迟是时间故障。它们模拟增加的网络延迟或一个超载的上游服务。
2、终止:终止是崩溃失败。他们模仿上游服务的失败。终止通常以 HTTP 错误码或 TCP 连接失败的形式出现。
例如,下面的虚拟服务为千分之一的访问 ratings 服务的请求配置了一个 5 秒的延迟:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
delay:
percentage:
value: 0.1
fixedDelay: 5s
route:
- destination:
host: ratings
subset: v1
Istio 故障恢复功能对应用程序来说是完全透明的。在返回响应之前, 应用程序不知道 Envoy Sidecar 代理是否正在处理被调用服务的故障。这意味着, 如果在应用程序代码中设置了故障恢复策略,那么您需要记住这两个策略都是独立工作的, 否则会发生冲突。例如,假设您设置了两个超时,一个在虚拟服务中配置, 另一个在应用程序中配置。应用程序为服务的 API 调用设置了 2 秒超时。 而您在虚拟服务中配置了一个 3 秒超时和重试。在这种情况下,应用程序的超时会先生效, 因此 Envoy 的超时和重试尝试会失效。
虽然 Istio 故障恢复特性提高了网格中服务的可靠性和可用性, 但应用程序必须处理故障或错误并采取适当的回退操作。 例如,当负载均衡中的所有实例都失败时,Envoy 返回一个 HTTP 503 代码。 应用程序必须实现回退逻辑来处理 HTTP 503 错误代码。