目录
1.Istio介绍?
1.1 Istio是什么?
1.2 Istio流量管理
1.2.1 熔断
1.2.2 超时
1.2.3 重试
2.Istio架构
3.istio组件详解
3.1 Pilot
3.2 Envoy
3.3 Citadel
3.4 Galley
3.5 Ingressgateway
3.5 egressgateway
扩展、k8s1.23及1.23以下版本安装istio微服务
4.1 准备安装Istio是要的压缩包
4.2 安装istio
4、k8s1.24及1.24以上版本安装istio最新版微服务
4.1 准备安装Istio是要的压缩包
4.2 安装istio
4.3 卸载istio
5、在k8s集群部署在线书店,启动istio功能
5.1 在线书店功能介绍
5.2 部署应用
5.3 启动应用服务
5.4理解Istio的各组件的功能及相互之间的协作方式
6、通过Istio实现灰度发布
6.1 什么是灰度发布?
6.2 使用istio进行金丝雀发布
7、istio核心功能演示
7.1 熔断
7.2 超时
7.3 故障注入和重试
备注:关闭istio功能,创建pod不让自动注入代理容器:
文档中的YAML文件配置直接复制粘贴可能存在格式错误,故实验中所需要的YAML文件以及本地包均打包至网盘
链接:https://pan.baidu.com/s/1Pl_McyPC3z32_Xyt6g3PUg
提取码:5a4l
实验环境:
Istio安装在已经存在的k8s集群上即可
k8s集群: k8s的控制节点
ip:192.168.40.180
主机名:xianchaomaster1
配置:6vCPU/6Gi内存
k8s的工作节点:
ip:192.168.40.181
主机名:xianchaonode1
配置:12vCPU/8Gi内存
1.Istio介绍?
官方文档:Istio / The Istio service mesh
Github地址:https://github.com/istio/istio/
1.1 Istio是什么?
Istio是一个开源的服务网格(Service Mesh),为Kubernetes和其他平台上的微服务架构提供了一种统一的、灵活的网络通信和管理方式。具有服务发现、负载均衡、流量管理、故障恢复和安全性等功能。
以下是Istio的一些基本特性:
- 代理注入:Istio使用Envoy作为其数据面代理,通过注入Envoy代理到每个微服务的Pod中,实现对流量的控制和管理。这种代理注入的方式无需修改应用代码,提供了一种非侵入式的部署方式。
- 服务发现:Istio通过在代理中集成服务注册和发现机制,实现对微服务实例的自动发现和路由。它能够动态地将流量转发到可用的服务实例,并支持多种服务发现的机制
- 负载均衡:Istio提供了丰富的负载均衡策略,可以根据不同的需求进行流量的分发和负载均衡,包括轮询、加权轮询、故障感知等。
- 流量管理:Istio可以实现对流量的灵活管理和控制,支持流量切分、A/B测试、金丝雀发布等高级流量管理功能。它可以帮助开发人员更好地控制和管理微服务架构中的流量。
- 故障恢复:Istio提供了故障恢复机制,包括超时控制、重试、断路器和熔断等。它能够自动检测和处理微服务中的故障,并提供弹性和可靠性。
- 安全性:Istio提供了丰富的安全功能,包括流量加密、身份认证和授权、访问控制等。它可以通过自动注入代理,对服务间的通信进行加密和验证,提供了更高层次的安全保障。
1.2 Istio流量管理
1.2.1 熔断
互动1:举个生活中的例子解释熔断
当电路发生故障或异常时,伴随着电流不断升高,并且升高的电流有可能能损坏电路中的某些重要器件,也有可能烧毁电路甚至造成火灾。若电路中正确地安置了保险丝,那么保险丝就会在电流异常升高到一定的高度和热度的时候,自身熔断切断电流,从而起到保护电路安全运行的作用。
很多技术都是来源生活的,随着社会进步,科技发展
当在 Kubernetes(K8s)集群中使用 Istio 时,可以通过 Istio 提供的熔断功能来增加微服务架构的稳定性和可靠性。熔断是一种故障保护机制,用于在服务之间的通信中防止故障扩散,并提供更好的容错能力。
在微服务架构中,一个应用通常由许多小型的、相互协作的服务组成。当某个服务发生故障或变得不可用时,如果不采取措施,可能会导致连锁反应,影响到整个系统的可用性。熔断机制旨在解决这个问题,其核心思想是在服务之间设置阈值和超时时间,并对请求进行监控。当服务的错误率或响应时间超过预设的阈值时,熔断器会打开,拒绝向该服务发送更多请求,并快速失败返回错误,而不是等待超时。
应用场景如下:
- 快速失败返回: 当目标服务不可用时,不再尝试等待请求超时,而是快速返回错误,从而避免资源浪费和潜在的长时间等待。
- 故障隔离: 熔断机制阻止故障扩散,使问题局限在出现故障的服务,而不会影响到整个应用程序。
- 恢复机制: 熔断器会定期尝试发起一些请求到目标服务,以检查其是否已经恢复。如果服务恢复正常,则熔断器会逐渐关闭,允许流量再次流向目标服务。
- 自动重试: 一旦目标服务恢复,熔断器会逐渐允许一部分流量通过,如果没有再次出现问题,会逐渐恢复到正常状态,否则继续保持熔断状态。
在微服务架构中,在高并发情况下,如果请求数量达到一定极限(可以自己设置阈值),超出了设置的阈值,断路器会自动开启服务保护功能,然后通过服务降级的方式返回一个友好的提示给客户端。假设当10个请求中,有10%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到10s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。
1.2.2 超时
在 Kubernetes(K8s)集群中结合 Istio,可以使用 Istio 的流量管理功能来控制服务之间的请求超时。超时是指在一定时间内,如果某个请求没有得到及时响应,就会被认为是超时。通过设置请求超时时间,可以对服务之间的通信进行控制,确保请求在合理的时间内得到响应,避免请求无限期地等待导致资源浪费或影响整体系统的响应性能。
Istio 的超时控制允许你为每个服务之间的请求设置最大的等待时间。当某个请求在指定的超时时间内没有得到响应时,Istio 会终止该请求并返回一个错误响应给客户端。这样可以防止请求在后端服务长时间等待,从而避免请求积压,同时提高系统的稳定性和可用性。
超时控制的意义如下:
- 防止长时间等待: 通过设置合理的请求超时时间,避免了客户端请求在后端服务长时间等待导致的响应延迟,从而提高了用户体验。
- 快速失败机制: 当后端服务无法及时响应请求时,超时控制会快速返回错误响应,而不是让请求无限期地等待,从而避免资源浪费。
- 故障隔离: 如果某个服务出现故障或变得不可用,超时控制可以快速终止对该服务的请求,避免故障扩散到其他服务。
在 Istio 中,超时控制是通过配置请求超时策略来实现的。你可以为每个服务定义超时时间,也可以为整个服务部署或命名空间设置默认的超时时间。这样,Istio 会根据配置中的超时时间来对请求进行限制,保证请求在规定时间内得到响应。
通过例子来理解
nginx 服务设置了超时时间为3秒,如果超出这个时间就不在等待,返回超时错误
httpd 服务设置了响应时间延迟5秒,任何请求都需要等待5秒后才能返回
client 通过访问 nginx 服务去反向代理 httpd 服务,由于 httpd 服务需要5秒后才能返回,但nginx 服务只等待3秒,所以客户端会提示超时错误。
1.2.3 重试
istio 重试机制就是如果调用服务失败,Envoy 代理尝试连接服务的最大次数。而默认情况下,Envoy 代理在失败后并不会尝试重新连接服务。
举个例子:
客户端调用 nginx,nginx 将请求转发给 tomcat。tomcat 通过故障注入而中止对外服务,nginx 设置如果访问 tomcat 失败则会重试 3 次。
2.Istio架构
istio服务网格从逻辑上分为数据平面和控制平面。
1、数据平面由一组以Sidecar方式部署的智能代理容器组成。这些代理承载并控制微服务之间的所有网络通信,管理入口和出口流量,类似于一线员工。 Sidecar 一般和业务容器运行在一个pod里,来劫持业务应用容器的流量,并接受控制面组件的控制,同时会向控制面输出日志、跟踪及监控数据。
2、控制平面负责管理和配置代理来路由流量。
istio1.5+中使用了一个全新的部署模式,重建了控制平面,将原有的多个组件整合为一个单体结构istiod,这个组件是控制平面的核心,管理Istio的所有功能,主要包括Pilot、Mixer、Citadel等服务组件。
istiod是新版本中最大的变化,以一个单体组件替代了原有的架构,降低了复杂度和维护难度,但原有的多组件并不是被完全移除,而是在重构后以模块的形式整合在一起组成了istiod。
问题1:为什么代理会叫sidecar proxy?
看了上图就容易懂了,sidecar和proxy相生相伴,就像摩托车(motor)与旁边的车厢(sidecar)。未来,sidecar和proxy就指微服务进程解耦成两个进程之后,提供基础能力的那个代理进程。
3.istio组件详解
3.1 Pilot
Pilot 是 Istio 控制平面的组件,在istio系统中,Pilot 完成以下任务:
它从服务注册中心(如Kubernetes的etcd或Consul)获取服务和实例的信息,并为Envoy生成配置,Envoy 根据 Pilot 发过来的配置里的内容,完成具体流量的转发。
Pilot可以被认为是团队的领袖。它负责监督和指导队伍中的每个Envoy。Pilot知道整个团队中每个服务的位置,以及它们应该如何相互协作。当有新队员加入或者队员的位置变化时,Pilot会负责通知每个队员,确保大家都知道最新的情况,不会出现迷路或者错过重要信息,会把要做的事形成文件下发到每个envoy队员里
3.2 Envoy
Envoy是Istio中的代理,我们如果开启了istio功能,会在pod里自动注入Envoy代理容器,
它负责处理服务之间的所有网络通信,拦截并转发所有的HTTP、TCP和gRPC流量。
Envoy提供强大的流量控制和管理功能,如路由、重试、超时和故障注入等。
Istio中Envoy与Pod什么关系?
Envoy和主容器同属于一个Pod,共享网络和命名空间,Envoy代理进出Pod 的流量,并将流量按照外部请求的规则作用于主容器中。
Envoy可以看作是服务之间的守护者。它像一个中间人一样,坐在每个服务旁边(就像每个队员身边都有一个保镖一样)。它负责处理服务之间的所有信息传递,确保信息传送得又快又准确。如果有请求从一个服务发出,Envoy会帮它找到正确的目标服务并将请求送达过去。它还能处理各种不同类型的请求,就像精通各种语言的翻译一样。
3.3 Citadel
1、Citadel负责Istio中的身份和凭据管理,提供安全性相关的功能。
2、它用于为服务生成和分发TLS证书,以实现服务之间的安全通信。
Citadel可以被视为团队中的保密专员。它负责确保团队成员之间的通信是安全的,别人无法窃听或者假冒。Citadel会为每个队员提供一个保密的通信渠道,确保他们之间的交流是私密的,就像用密码和密钥加密信息一样。
3.4 Galley
- Galley是Istio的配置管理组件,负责验证、转换和分发配置给其他Istio组件。
- 它监听Kubernetes的配置更改,例如Service、Deployment等,然后根据规则和策略生成Istio所需的配置,并将其提供给Pilot和其他组件。
Galley可以被看作是团队中的文件管理员。它负责管理团队中所有的文件和信息,确保每个队员都能得到正确的信息和文件。当有新的文件产生或者文件发生变化时,Galley会及时通知团队中的每个成员,确保大家都使用的是最新的文件,不会出现信息不同步的问题。
3.5 Ingressgateway
istio-ingressgateway是Istio服务网格中的一个特殊网关,它作为整个网格的入口,接收外部请求,并将它们引导到内部的服务。可以将它比作一个大门保安,负责接收外部人员的访问请求,然后根据配置的规则将请求分发给网格内部的服务。
简单来说,当有外部的请求访问Istio服务网格时,它们会先被送到istio-ingressgateway。这个网关会检查请求,并根据一些规则判断该请求应该交给哪个服务来处理。然后,它将请求转发给网格内部的相应服务,从而实现外部请求与内部服务的连接。
3.5 egressgateway
istio-egressgateway是Istio服务网格中的另一个特殊网关,它负责处理网格内部服务对外部服务的访问请求。可以将它看作是一个网格内部的出口,负责将内部服务需要访问的外部服务请求发送到外部。
以将istio-egressgateway比作一个秘书,它会代表网格内部的服务,帮助它们联系外部的服务。当网格内部的服务需要访问外部服务时,它们会将请求交给istio-egressgateway,然后由这个网关将请求发送给外部服务。
扩展、k8s1.23及1.23以下版本安装istio微服务
4.1 准备安装Istio是要的压缩包
官网下载地址:
https://github.com/istio/istio/
官方访问相对较慢,我在课件提供了压缩包,大家最好用我的压缩包,这样做实验才不会出问题
1、把压缩包上传到k8s的控制节点xianchaomaster1。手动解压:
[root@xianchaomaster1 ~]# tar zxvf istio-1.13.1.tar.gz
2、切换到istio包所在目录下。tar zxvf istio-1.13.1.tar.gz解压的软件包包名是istio-1.13.1,则:
cd istio-1.13.1
安装目录包含如下内容:
2)samples/目录下,有示例应用程序
3)bin/目录下,包含istioctl的客户端文件。istioctl工具用于手动注入Envoy sidecar代理。
3、将istioctl客户端路径增加到path环境变量中,macOS 或 Linux 系统的增加方式如下:
export PATH=$PWD/bin:$PATH
4、把istioctl这个可执行文件拷贝到/usr/bin/目录
cd /root/istio-1.13.1/bin/
cp -ar istioctl /usr/bin/
4.2 安装istio
1.下载镜像:
安装istio需要的镜像默认从官网拉取,但是官网的镜像我们拉取会有问题,可以从课件下载镜像,然后上传到自己k8s集群的各个节点,通过docker load -i手动解压镜像:
docker load -i examples-bookinfo-details.tar.gz
docker load -i examples-bookinfo-reviews-v1.tar.gz
docker load -i examples-bookinfo-productpage.tar.gz
docker load -i examples-bookinfo-reviews-v2.tar.gz
docker load -i examples-bookinfo-ratings.tar.gz
docker load -i examples-bookinfo-reviews-v3.tar.gz
docker load -i pilot.tar.gz
docker load -i proxyv2.tar.gz
docker load -i httpbin.tar.gz
2.安装
在k8s的控制节点xianchaomaster1操作
istioctl install --set profile=demo -y
看到如下,说明istio初始化完成:
Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details.
- Applying manifest for component Base...
✔ Finished applying manifest for component Base.
- Applying manifest for component Pilot...
✔ Finished applying manifest for component Pilot.
Waiting for resources to become ready...
Waiting for resources to become ready...
- Applying manifest for component EgressGateways...
- Applying manifest for component IngressGateways...
- Applying manifest for component AddonComponents...
✔ Finished applying manifest for component EgressGateways.
✔ Finished applying manifest for component IngressGateways.
✔ Finished applying manifest for component AddonComponents.
✔ Installation complete
3.验证istio是否部署成功
kubectl get pods -n istio-system
显示如下,说明部署成功
istio-egressgateway-d84f95b69-5gtdc 1/1 Running 0 15h
istio-ingressgateway-75f6d79f48-fhxjj 1/1 Running 0 15h
istiod-c9f6864c4-nrm82 1/1 Running 0 15h
4、k8s1.24及1.24以上版本安装istio最新版微服务
4.1 准备安装Istio是要的压缩包
官网下载地址:
https://github.com/istio/istio/
官方访问相对较慢,我在课件提供了压缩包,大家最好用我的压缩包,这样做实验才不会出问题
具体下载方式如下:
访问:https://github.com/istio/istio/tags
1、把压缩包上传到k8s的控制节点xianchaomaster1。手动解压:
[root@xianchaomaster1 ~]# tar zxvf istio-1.18.2-linux-amd64.tar.gz
2、切换到istio包所在目录下。istio-1.18.2-linux-amd64.tar.gz解压的软件包包名是istio-1.18.2,进到解压目录下:
cd istio-1.18.2
安装目录包含如下内容:
2)samples/目录下,有示例应用程序
3)bin/目录下,包含istioctl的客户端文件。istioctl工具用于手动注入Envoy sidecar代理。
3、把istioctl这个可执行文件拷贝到/bin/目录
cp /root/istio-1.18.2/bin/istioctl /bin/
4.2 安装istio
1.下载镜像:
安装istio需要的镜像默认从官网拉取,但是官网的镜像我们拉取会有问题,可以从课件下载离线镜像文件,然后上传到自己k8s集群的工作节点,通过ctr -n=k8s.io images import istio1.18.tar.gz手动解压镜像即可
[root@xianchaonode1 ~]# ctr -n=k8s.io images import istio1.18.tar.gz
2.安装
在k8s的控制节点xianchaomaster1操作
istioctl install --set profile=demo -y
看到如下,说明istio初始化完成:
Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details.
- Applying manifest for component Base...
✔ Finished applying manifest for component Base.
- Applying manifest for component Pilot...
✔ Finished applying manifest for component Pilot.
Waiting for resources to become ready...
Waiting for resources to become ready...
- Applying manifest for component EgressGateways...
- Applying manifest for component IngressGateways...
- Applying manifest for component AddonComponents...
✔ Finished applying manifest for component EgressGateways.
✔ Finished applying manifest for component IngressGateways.
✔ Finished applying manifest for component AddonComponents.
✔ Installation complete
3.验证istio是否部署成功
kubectl get pods -n istio-system
显示如下,说明部署成功
istio-egressgateway-d84f95b69-5gtdc 1/1 Running 0 15h
istio-ingressgateway-75f6d79f48-fhxjj 1/1 Running 0 15h
istiod-c9f6864c4-nrm82 1/1 Running 0 15h
4.3 卸载istio
istioctl manifest generate --set profile=demo | kubectl delete -f -
[root@xianchaomaster1 istio-1.18.2]# istioctl x uninstall --purge
备注:
使用 istioctl install --set profile=demo 安装 Istio 时,会根据指定的 profile 来选择使用的 Istio 配置文件。profile 参数是一个预定义的配置选项,用于快速设置 Istio 的安装配置。每个 profile 都对应一个特定的 YAML 配置文件,其中包含了一组预定义的配置选项。
在 Istio 的安装过程中,profile 参数可以指定为以下一些值:
- demo:适用于生产环境,包含istiod、ingressgateway、egressgateway
- default:这是一个最小配置,仅包含最基本的组件,如istiod和ingressgateway
- minimal:这个配置相对更加精简,只包含了必需的组件,适用于资源受限或轻量级的环境。只会安装istiod。
在执行 istioctl install 命令时,如果指定了 --set profile=demo,那么 istioctl 会根据 demo 配置文件中定义的选项,安装 Istio,并将预定义的配置应用于集群。实际上,istioctl install 本质上是根据选择的 profile 来加载对应的 YAML 配置文件,并将配置部署到 Kubernetes 集群中。
如果你想查看 demo 配置文件的内容,可以通过以下命令查找 Istio 的安装目录并找到对应的文件:
istioctl profile dump demo
这将打印出 demo 配置的完整内容,包括各个组件的配置选项。你也可以在 Istio 官方文档中找到各种预定义的 profile 配置选项的详细信息。
5、在k8s集群部署在线书店,启动istio功能
5.1 在线书店功能介绍
在线书店-bookinfo
该应用由四个单独的微服务构成,这个应用模仿在线书店的一个分类,显示一本书的信息,页面上会显示一本书的描述,书籍的细节(ISBN、页数等),以及关于这本书的一些评论。
Bookinfo应用分为四个单独的微服务
1)productpage这个微服务会调用details和reviews两个微服务,用来生成页面;
2)details这个微服务中包含了书籍的信息;
3)reviews这个微服务中包含了书籍相关的评论,它还会调用ratings微服务;
4)ratings这个微服务中包含了由书籍评价组成的评级信息。
reviews微服务有3个版本
1)v1版本不会调用ratings服务;
2)v2版本会调用ratings服务,并使用1到5个黑色星形图标来显示评分信息;
3)v3版本会调用ratings服务,并使用1到5个红色星形图标来显示评分信息。
下图展示了这个应用的端到端架构
Bookinfo应用中的几个微服务是由不同的语言编写的。这些服务对istio并无依赖,但是构成了一个有代表性的服务网格的例子:它由多个服务、多个语言构成,并且reviews服务具有多个版本。
5.2 部署应用
要在Istio中运行这一应用,无需对应用自身做出任何改变。 只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar 注入到每个服务之中。 最终的部署结果将如下图所示:
所有的微服务都和Envoy sidecar集成在一起,被集成服务所有的出入流量都被envoy sidecar 所劫持,这样就为外部控制准备了所需的 Hook,然后就可以利用Istio控制平面为应用提供服务路由、遥测数据收集以及策略实施等功能。
5.3 启动应用服务
1.istio默认自动注入 sidecar,需要为default命名空间打上标签istio-injection=enabled
[root@xianchaomaster1# kubectl label namespace default istio-injection=enabled
2.使用kubectl部署应用
[root@xianchaonode1 ~]# ctr -n=k8ss.io images import bookinfo1.17.tar.gz
[root@xianchaomaster1]# cd istio-1.18.2
[root@xianchaomaster1]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
3.确认所有的服务和 Pod 都已经正确的定义和启动:
kubectl get services
显示如下
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
details ClusterIP 10.109.124.202 <none> 9080/TCP
productpage ClusterIP 10.102.89.129 <none> 9080/TCP
ratings ClusterIP 10.101.97.75 <none> 9080/TCP
reviews ClusterIP 10.100.105.33 <none> 9080/TCP
kubectl get pods
显示如下
NAME READY STATUS RESTARTS AGE
details-v1-78d78fbddf-qssjb 2/2 Running 0 73m
productpage-v1-85b9bf9cd7-r699f 2/2 Running 0 73m
ratings-v1-6c9dbf6b45-77kv7 2/2 Running 0 73m
reviews-v1-564b97f875-2jtxq 2/2 Running 0 73m
reviews-v2-568c7c9d8f-f5css 2/2 Running 0 73m
reviews-v3-67b4988599-fxfzx 2/2 Running 0 73m
tomcat-deploy-59664bcb6f-5z4nn 1/1 Running 0 22h
tomcat-deploy-59664bcb6f-cgjbn 1/1 Running 0 22h
tomcat-deploy-59664bcb6f-n4tqq 1/1 Running 0 22h
4、创建网关和虚拟服务
[root@xianchaomaster1 ~]# cd istio-1.18.2 && kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
查看网关和虚拟服务是否创建成功:
[root@xianchaomaster1 istio-1.18.2]# kubectl get gateway
NAME AGE
bookinfo-gateway 27s
[root@xianchaomaster1 istio-1.18.2]# kubectl get virtualservice
NAME GATEWAYS HOSTS AGE
bookinfo ["bookinfo-gateway"] ["*"] 32s
5,通过istio提供的入口网关访问pod
[root@xianchaomaster1 istio-1.18.2]# kubectl get svc -n istio-system
显示如下:
istio-ingressgateway是service资源,关联的pod是istio-system名称空间叫做istio-ingressgateway-7b84b459d6-bppj5的pod,如下:
[root@xianchaomaster1 istio-1.18.2]# kubectl get pods -n istio-system -owide
NAME READY STATUS RESTARTS AGE IP
istio-egressgateway-6cf4f6489d-nbd5k 1/1 Running 0 29m 10.244.121.3
istio-ingressgateway-7b84b459d6-bppj5 1/1 Running 0 29m 10.244.121.4
istiod-8498fbd896-k9d7p 1/1 Running 0 30m 10.244.121.2
查看istio-ingressgateway这个service的详细信息:
[root@xianchaomaster1 istio-1.18.2]# kubectl describe svc istio-ingressgateway -n istio-system
显示如下内容:
Name: istio-ingressgateway Namespace: istio-system Labels: app=istio-ingressgateway install.operator.istio.io/owning-resource=unknown install.operator.istio.io/owning-resource-namespace=istio-system istio=ingressgateway istio.io/rev=default operator.istio.io/component=IngressGateways operator.istio.io/managed=Reconcile operator.istio.io/version=1.18.2 release=istio Annotations: <none> Selector: app=istio-ingressgateway,istio=ingressgateway Type: LoadBalancer IP Family Policy: SingleStack IP Families: IPv4 IP: 10.97.58.57 IPs: 10.97.58.57 Port: status-port 15021/TCP TargetPort: 15021/TCP NodePort: status-port 30949/TCP Endpoints: 10.244.121.4:15021 Port: http2 80/TCP TargetPort: 8080/TCP NodePort: http2 30463/TCP Endpoints: 10.244.121.4:8080 Port: https 443/TCP TargetPort: 8443/TCP NodePort: https 32597/TCP Endpoints: 10.244.121.4:8443 Port: tcp 31400/TCP TargetPort: 31400/TCP NodePort: tcp 30867/TCP Endpoints: 10.244.121.4:31400 Port: tls 15443/TCP TargetPort: 15443/TCP NodePort: tls 32242/TCP Endpoints: 10.244.121.4:15443 Session Affinity: None External Traffic Policy: Cluster Events: <none> |
查看ipvs规则,可以看到istio-ingressgateway和它所关联到的pod ip的对应规则:
[root@xianchaomaster1 istio-1.18.2]# ipvsadm -Ln
如下:
TCP 192.168.40.180:30463 rr
-> 10.244.121.4:8080 Masq 1 0 0
所以访问k8s控制节点的ip:30463,可以把请求代理istio-ingressgateway-7b84b459d6-bppj5这个pod。还可以用浏览器打开网址192.168.40.180:30463/productpage来浏览应用的 Web 页面。如果刷新几次应用的页面,就会看到 productpage 页面中会随机展示 reviews 服务的不同版本的效果(红色、黑色的星形或者没有显示)。
5.4理解Istio的各组件的功能及相互之间的协作方式
1. 自动注入:Kubernetes在创建Pod时调用Sidecar代理服务,自动将Sidecar代理容器(也叫做envoy容器)注入到Pod中。
2. 流量拦截:通过设置iptables规则,Envoy拦截业务容器的入口和出口流量,应用程序感知不到Sidecar代理容器的存在。上图中,流出frontend服务的流量会被 frontend服务侧的 sidecar拦截,而当流量到达forecast容器时,Inbound流量被forecast 服务侧的sidecar拦截。
3. 服务发现:服务发起方的 Envoy 调用控制面组件 Pilot 的服务发现接口获取目标服务的实例列表。上图中,frontend 服务侧的 Envoy 通过 Pilot 的服务发现接口得到forecast服务各个实例的地址。
4. 负载均衡:服务发起方的Envoy根据配置的负载均衡策略选择服务实例,并连接对应的实例地址。上图中,数据面的各个Envoy从Pilot中获取forecast服务的负载均衡配置,并执行负载均衡动作。
5. 流量治理:Envoy 从 Pilot 中获取配置的流量规则,在拦截到 Inbound 流量和Outbound 流量时执行治理逻辑。上图中, frontend 服务侧的 Envoy 从 Pilot 中获取流量治理规则,并根据该流量治理规则将不同特征的流量分发到forecast服务的v1或v2版本。
6. 访问安全:在服务间访问时通过双方的Envoy进行双向认证和通道加密,并基于服务的身份进行授权管理。上图中,Pilot下发安全相关配置,在frontend服务和forecast服务的Envoy上自动加载证书和密钥来实现双向认证,其中的证书和密钥由另一个管理面组件 Citadel维护。
7. 服务监测:在服务间通信时,通信双方的Envoy都会连接管理面组件Mixer上报访问数据,并通过Mixer将数据转发给对应的监控后端。上图中,frontend服务对forecast服务的访问监控指标、日志和调用链都可以通过这种方式收集到对应的监控后端。
8. 策略执行:在进行服务访问时,通过Mixer连接后端服务来控制服务间的访问,判断对访问是放行还是拒绝。上图中,Mixer 后端可以对接一个限流服务对从frontend服务到forecast服务的访问进行速率控制等操作。
9. 外部访问:在网格的入口处有一个Envoy扮演入口网关的角 色。上图中,外部服务通过Gateway访问入口服务 frontend,对 frontend服务的负载均衡和一些流量治理策略都在这个Gateway上执行。
6、通过Istio实现灰度发布
6.1 什么是灰度发布?
灰度发布也叫金丝雀部署 ,是指通过控制流量的比例,实现新老版本的逐步更替。
比如对于服务A 有 version1、 version2 两个版本 , 当前两个版本同时部署, 访问version1比例90% ,访问version2比例10% ,看运行效果,如果效果好逐步调整流量占比 80~20 ,70~30 ·····10~90 ,0,100 ,最终version1版本下线。
灰度发布的特点:
1)新老板共存
2)可以实时根据反馈动态调整占比
3)理论上不存在服务完全宕机的情况。
4)适合于服务的平滑升级与动态更新。
6.2 使用istio进行金丝雀发布
下面实验需要的镜像包在课件,把canary-v2.tar.gz和canary-v1.tar.gz上传到k8s工作节点,手动解压:
[root@xianchaonode1 ~]# ctr -n=k8s.io images import canary-v1.tar.gz
[root@xianchaonode1 ~]# ctr -n=k8s.io images import canary-v2.tar.gz
创建金丝雀服务
[root@xianchaomaster1 ~]# mkdir istio-test
[root@xianchaomaster1 ~]# cd istio-test/
vim deployment-v1.yaml
内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv1
labels:
app: v1
spec:
replicas: 1
selector:
matchLabels:
app: v1
apply: canary
template:
metadata:
labels:
app: v1
apply: canary
spec:
containers:
- name: nginx
image: xianchao/canary:v1
ports:
- containerPort: 80
[root@xianchaomaster1 istio-test]# kubectl apply -f deployment-v1.yaml
vim deployment-v2.yaml
#内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv2
labels:
app: v2
spec:
replicas: 1
selector:
matchLabels:
app: v2
apply: canary
template:
metadata:
labels:
app: v2
apply: canary
spec:
containers:
- name: nginx
image: xianchao/canary:v2
ports:
- containerPort: 80
[root@xianchaomaster1 istio-test]# kubectl apply -f deployment-v2.yaml
创建service
cat service.yaml文件,内容如下:
apiVersion: v1
kind: Service
metadata:
name: canary
labels:
apply: canary
spec:
selector:
apply: canary
ports:
- protocol: TCP
port: 80
targetPort: 80
更新service.yaml文件
kubectl apply -f service.yaml
创建gateway
cat gateway.yaml文件,内容如下:
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: canary-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
更新gateway.yaml
kubectl apply -f gateway.yaml
创建virtualservice
cat virtual.yaml,内容如下:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: canary
spec:
hosts:
- "*"
gateways:
- canary-gateway
http:
- route:
- destination:
host: canary.default.svc.cluster.local
subset: v1
weight: 90
- destination:
host: canary.default.svc.cluster.local
subset: v2
weight: 10
kubectl apply -f virtual.yaml
vim destination.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: canary
spec:
host: canary.default.svc.cluster.local
subsets:
- name: v1
labels:
app: v1
- name: v2
labels:
app: v2
kubectl apply -f destination.yaml
(5)获取Ingress_port:验证金丝雀发布效果:
for i in `seq 1 100`; do curl 192.168.40.180:30463;done > 1.txt
打开1.txt可以看到结果有90次出现v1,10次出现canary-v2,符合我们预先设计的流量走向。
7、istio核心功能演示
7.1 熔断
官网:
Istio / 熔断
熔断的目的是在出现故障或异常情况时,对服务进行自动的限流和隔离,以保护整个系统的稳定性和可用性。
测试熔断:
1、在k8s集群创建后端服务
[root@xianchaomaster1 ~]# cd istio-1.18.2
[root@xianchaomaster1 istio-1.18.2]# cat samples/httpbin/httpbin.yaml
# Copyright Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##################################################################################################
# httpbin service
##################################################################################################
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
serviceAccountName: httpbin
containers:
- image: docker.io/kong/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
#把httpbin.tar.gz上传到xianchaonode1节点,手动解压:
[root@xianchaonode1 ~]# ctr -n=k8s.io images import httpbin
[root@xianchaomaster1 istio-1.18.2]# kubectl apply -f samples/httpbin/httpbin.yaml
#该httpbin应用程序充当后端服务。
2、配置熔断
#创建一个目标规则,在调用httpbin服务时应用断路器设置:
[root@xianchaomaster1 istio-1.18.2]# vim destination-1.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutiveGatewayErrors: 1
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 100
[root@xianchaomaster1 istio-1.18.2]# kubectl apply -f destination-1.yaml
destinationrule.networking.istio.io/httpbin created
- apiVersion: 指定使用的 Istio Networking API 的版本,这里使用的是 networking.istio.io/v1beta1。
- kind: 指定资源的类型,这里是 DestinationRule,用于定义目标规则。
- metadata: 元数据部分,包含资源的名称和其他附加信息。
- name: 资源的名称,这里是 httpbin。
- spec: 规则的规范部分,定义了目标规则的详细配置。
- host: 指定目标规则应用于的主机,这里是 httpbin。
- trafficPolicy: 流量策略部分,用于定义流量控制和故障恢复的策略。
- tcp部分配置用于限制TCP连接的数量:
- maxConnections: 指定每个目标服务的最大连接数限制为1。这意味着对于每个目标服务,最多只能有1个并发连接。
- http部分配置用于限制HTTP连接的数量和请求:
- http1MaxPendingRequests: 指定每个连接的最大挂起请求数为1。这表示每个连接最多只能有1个挂起的请求,超过这个数量的请求将被阻塞。
- maxRequestsPerConnection: 指定每个连接的最大请求数为1。这意味着每个连接最多只能处理1个请求,处理完请求后连接将被关闭。
- outlierDetection部分配置用于检测目标服务的异常情况:
- consecutiveGatewayErrors: 指定连续发生网关错误的次数为1。当目标服务连续出现1次网关错误时,将被视为异常情况。
- interval: 指定异常检测的时间间隔为1秒。在每个1秒的时间间隔内,将检测目标服务是否出现异常情况。
该配置文件定义了一个名为 httpbin 的目标规则,针对该规则的流量策略包括限制每个目标服务的最大连接数为 1,每个连接的最大挂起请求数为 1,每个连接的最大请求数为 1。此外,该配置还包括异常检测,当连续发生网关错误达到 1 次时,将被视为异常,并且异常检测的时间间隔为 1 秒。
3、添加客户端访问httpbin服务
创建一个客户端以将流量发送给httpbin服务。该客户端是一个简单的负载测试客户端,Fortio可以控制连接数,并发数和HTTP调用延迟。使用此客户端来“跳闸”在DestinationRule中设置的断路器策略。
#通过执行下面的命令部署fortio客户端:
#把fortio.tar.gz上传到xianchaonode1节点,手动解压:
[root@xianchaonode1 ~]# ctr -n=k8s.io images import fortio.tar.gz
vim samples/httpbin/sample-client/fortio-deploy.yaml
修改镜像拉取策略:变成IfNotPresent
[root@xianchaomaster1 istio-1.18.2]# kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml
#通过kubectl执行下面的命令,使用fortio客户端工具调用httpbin:
[root@xianchaomaster1 istio-1.18.2]# kubectl get pods
NAME READY STATUS RESTARTS AGE
appv1-77b5cbd5cc-bmch2 2/2 Running 0 28m
appv2-f78cb577-n7rhc 2/2 Running 0 28m
details-v1-847c7999fb-htd2z 2/2 Running 0 28m
fortio-deploy-576dbdfbc4-z28m7 2/2 Running 0 3m32s
httpbin-74fb669cc6-hqtzl 2/2 Running 0 15m
productpage-v1-5f7cf79d5d-6d4lx 2/2 Running 0 28m
ratings-v1-7c46bc6f4d-sfqnz 2/2 Running 0 28m
reviews-v1-549967c688-pr8gh 2/2 Running 0 28m
reviews-v2-cf9c5bfcd-tn5z5 2/2 Running 0 28m
reviews-v3-556dbb4456-dxt4r 2/2 Running 0 28m
[root@xianchaomaster1 istio-1.18.2]# kubectl exec fortio-deploy-576dbdfbc4-z28m7 -c fortio -- /usr/bin/fortio curl http://httpbin:8000/get
#显示如下:
HTTP/1.1 200 OK
server: envoy
date: Mon, 03 May 2021 02:28:06 GMT
content-type: application/json
content-length: 622
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 2
{
"args": {},
"headers": {
"Content-Length": "0",
"Host": "httpbin:8000",
"User-Agent": "fortio.org/fortio-1.11.3",
"X-B3-Parentspanid": "4631e62a6cd0b167",
"X-B3-Sampled": "1",
"X-B3-Spanid": "6d20afff1671aa89",
"X-B3-Traceid": "6f4ddb61363d04d54631e62a6cd0b167",
"X-Envoy-Attempt-Count": "1",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=498edf0dcb7f6e74f40735869a9912eca62d61fb21dbc190943c1c19dbf01c18;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default"
},
"origin": "127.0.0.1",
"url": "http://httpbin:8000/get"
}
4、触发断路器
通过发送20个请求(-n 20)和使用两个并发连接(-c 2)来调用服务。使用了Fortio工具进行测试,命令如下:
[root@xianchaomaster1 istio-1.18.2]# kubectl exec -it fortio-deploy-576dbdfbc4-z28m7 -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get
- -c 2: 指定并发连接数为 2。这表示在测试期间,将会模拟 2 个并发请求。
- -qps 0: 指定每秒请求数为 0。这表示在测试期间,将以最大速率发送请求,即不限制每秒请求数。
- -n 20: 指定总请求数为 20。这表示在测试期间,将发送总共 20 个请求
#显示如下:
02:31:00 I logger.go:127> Log level is now 3 Warning (was 2 Info)
Fortio 1.11.3 running at 0 queries per second, 6->6 procs, for 20 calls: http://httpbin:8000/get
Starting at max qps with 2 thread(s) [gomax 6] for exactly 20 calls (10 per thread + 0)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
Ended after 69.506935ms : 20 calls. qps=287.74
Aggregated Function Time : count 20 avg 0.0054352091 +/- 0.01077 min 0.000474314 max 0.04968864 sum 0.108704183
# range, mid point, percentile, count
>= 0.000474314 <= 0.001 , 0.000737157 , 35.00, 7
> 0.001 <= 0.002 , 0.0015 , 50.00, 3
> 0.002 <= 0.003 , 0.0025 , 65.00, 3
> 0.004 <= 0.005 , 0.0045 , 75.00, 2
> 0.005 <= 0.006 , 0.0055 , 85.00, 2
> 0.007 <= 0.008 , 0.0075 , 90.00, 1
> 0.016 <= 0.018 , 0.017 , 95.00, 1
> 0.045 <= 0.0496886 , 0.0473443 , 100.00, 1
# target 50% 0.002
# target 75% 0.005
# target 90% 0.008
# target 99% 0.0487509
# target 99.9% 0.0495949
Sockets used: 16 (for perfect keepalive, would be 2)
Jitter: false
Code 200 : 4 (20.0 %)
Code 503 : 16 (80.0 %)
#只有20%成功了,其余的都断开了
Response Header Sizes : count 20 avg 46 +/- 92 min 0 max 230 sum 920
Response Body/Total Sizes : count 20 avg 292.8 +/- 279.6 min 153 max 852 sum 5856
All done 20 calls (plus 0 warmup) 5.435 ms avg, 287.7 qps
从结果可以看出,只有20%的请求成功(Code 200),其余的请求都返回了503错误(Service Unavailable)。每个连接只能处理1个请求,并且最大连接数限制为1。因此,在并发数为2的情况下,第一个并发请求可以成功发送并得到响应,而第二个并发请求会被阻塞,因为只有一个连接可用。随着并发请求的增加,大部分请求都无法成功发送,导致返回了 HTTP 状态码 503。
假设k8s集群有100个节点,每个节点是100vCPU、100g内存,基于deployment部署了3个pod,运行的服务是web服务,三个pod跑在不同的节点上,每个pod最多占用6g内存6vcpu,每个pod最多的请求数是100万,三个pod前端有个四层代理,通过istio熔断机制作用在三个pod前端的四层代理上,那熔断参数值如何设置?
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutiveGatewayErrors: 1
interval: 1s
假设你的应用是一个 Web 服务,每个 Pod 最多支持 100 万并发请求数,并且你的 Kubernetes 集群中每个节点有 100 个 vCPU 和 100GB 内存。
- maxConnections:
- 假设每个 Pod 最多支持 6 个 vCPU,你可以设置 maxConnections 为 80(稍微小于节点的 CPU 核心数,考虑到其他系统进程的资源使用)。
- http1MaxPendingRequests:
- 假设你的应用在正常负载情况下,每秒请求数在 1000 到 5000 之间,你可以设置 http1MaxPendingRequests 为 500,以确保连接不会积压过多的请求。
- maxRequestsPerConnection:
- 假设你的应用的响应时间在 10 毫秒左右,你可以设置 maxRequestsPerConnection 为 100,这样每个连接可以处理 100 个请求后再关闭。
请注意,以上数值仅供参考,实际设置需要根据你的应用特性和性能测试结果来确定。压力测试是一个迭代的过程,你可能需要多次测试和优化,找到最适合你应用的参数设置。
同时,还需要考虑 Istio 熔断参数的设置。你可以根据之前提到的测试结果和分析,根据实际情况设置 consecutiveGatewayErrors 和 interval 等参数,以实现对代理层的熔断保护。
最终的参数设置是一个动态平衡的过程,需要结合多方面因素综合考虑。建议在测试环境中进行实际的压力测试和性能评估,以找到最优的参数配置,确保你的应用在高负载下能够稳定运行。
- maxConnections:TCP 连接数的最大值。它限制了单个 Pod 上的 TCP 连接数量。这个值需要根据你的 Web 服务的并发量和每个请求的连接数来确定。
- http1MaxPendingRequests:HTTP1 的最大挂起请求数。当超过这个数值时,新的请求将被拒绝,直到有请求处理完成。这个值也要根据你的 Web 服务的并发量和 HTTP1 的特性来确定。
- maxRequestsPerConnection:每个连接的最大请求数。当超过这个数值时,连接将被关闭,新的请求将使用新的连接。这个值可以用于限制长时间保持的连接。
- outlierDetection:异常检测参数。这个参数用于检测异常的流量,并触发熔断机制。以下是 outlierDetection 参数的两个属性:
- consecutiveGatewayErrors:连续网关错误数。当连续出现这么多次网关错误时,熔断将会触发。
- interval:检测的时间间隔。在这个时间间隔内进行异常检测。
针对具体的数值,取决于你的应用实际情况和性能测试的结果。一般来说,你需要进行压力测试和性能评估,观察系统在不同负载下的表现,然后逐步调整熔断参数,找到适合你应用的最佳数值。
进行压力测试和性能评估是确保你的应用在不同负载下能够正常运行的关键步骤。这些测试有助于发现系统的瓶颈、性能问题和资源需求,以便做出相应的优化和调整。下面是进行压力测试和性能评估的一般步骤:
- 确定测试目标和场景:
- 确定你要测试的具体目标,例如检查服务的响应时间、并发连接数、吞吐量等。
- 设计不同负载场景,包括正常负载和峰值负载,以及可能的异常情况。
- 配置测试环境:
- 创建与生产环境尽可能相似的测试环境。这包括硬件、网络、操作系统、Kubernetes集群等。
- 选择合适的工具:
- 选择适合你的应用和测试需求的性能测试工具。一些常见的工具包括Apache JMeter、Vegeta、wrk、Siege等。
- 设置测试参数:
- 针对不同的测试场景,设置合理的压力测试参数,包括请求频率、并发用户数、连接数等。
- 执行压力测试:
- 运行压力测试工具,模拟不同负载场景,收集性能数据。
- 监控系统指标:
- 在测试过程中,监控系统的各项指标,包括CPU利用率、内存使用、网络流量、响应时间等。
- 分析结果:
- 根据测试结果,分析系统在不同负载下的表现。发现瓶颈、性能问题和资源瓶颈。
- 优化和调整:
- 根据分析结果,进行优化和调整。可能需要调整Kubernetes资源配额、调整服务配置、进行代码优化等。
- 重复测试:
- 如果进行了优化和调整,需要再次进行压力测试,以验证改进效果。
- 容灾测试(可选):
- 在一定负载下,模拟节点故障或服务失效等情况,验证集群的容错能力和自愈能力。
- 综合评估:
- 结合所有测试结果,综合评估系统的性能和稳定性,确保满足预期的负载和性能要求。
- 在进行压力测试时,确保测试环境和生产环境隔离,以免对生产系统造成影响。
- 选择适当的负载测试场景,覆盖典型的使用情况和预期的峰值负载。
- 记录测试结果和分析过程,方便后续回溯和对比。
- 压力测试应该在非高峰期进行,以免影响正常用户的体验。
7.2 超时
在生产环境中经常会碰到由于调用方等待下游的响应过长,堆积大量的请求阻塞了自身服务,造成雪崩的情况,通过通过超时处理来避免由于无限期等待造成的故障,进而增强服务的可用性,Istio 使用虚拟服务来优雅实现超时处理。
下面例子模拟客户端调用 nginx,nginx 将请求转发给 tomcat。nginx 服务设置了超时时间为2秒,如果超出这个时间就不在等待,返回超时错误。tomcat服务设置了响应时间延迟10秒,任何请求都需要等待10秒后才能返回。client 通过访问 nginx 服务去反向代理 tomcat服务,由于 tomcat服务需要10秒后才能返回,但nginx 服务只等待2秒,所以客户端会提示超时错误。
#把busybox.tar.gz、 nginx.tar.gz、 tomcat-app.tar.gz上传到xianchaonode1节点,手动解压:
[root@xianchaonode1 ~]# ctr -n=k8s.io images import nginx.tar.gz
[root@xianchaonode1 ~]# ctr -n=k8s.io images import tomcat-app.tar.gz
[root@xianchaomaster1 ~]# mkdir /root/timeout
[root@xianchaomaster1 ~]# cd /root/timeout/
[root@xianchaomaster1 timeout]# cat nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
server: nginx
app: web
spec:
replicas: 1
selector:
matchLabels:
server: nginx
app: web
template:
metadata:
name: nginx
labels:
server: nginx
app: web
spec:
containers:
- name: nginx
image: nginx:1.14-alpine
imagePullPolicy: IfNotPresent
[root@xianchaomaster1 timeout]# kubectl apply -f nginx-deployment.yaml
vim tomcat-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat
labels:
server: tomcat
app: web
spec:
replicas: 1
selector:
matchLabels:
server: tomcat
app: web
template:
metadata:
name: tomcat
labels:
server: tomcat
app: web
spec:
containers:
- name: tomcat
image: docker.io/kubeguide/tomcat-app:v1
imagePullPolicy: IfNotPresent
kubectl apply -f tomcat-deployment.yaml
[root@xianchaomaster1 timeout]# cat nginx-tomcat-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
server: nginx
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc
spec:
selector:
server: tomcat
ports:
- name: http
port: 8080
targetPort: 8080
protocol: TCP
[root@xianchaomaster1 timeout]# cat virtual-tomcat.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: nginx-vs
spec:
hosts:
- nginx-svc
http:
- route:
- destination:
host: nginx-svc
timeout: 2s
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: tomcat-vs
spec:
hosts:
- tomcat-svc
http:
- fault:
delay:
percentage:
value: 100
fixedDelay: 10s
route:
- destination:
host: tomcat-svc
kubectl apply -f virtual-tomcat.yaml
#virtual-tomcat.yaml资源清单重点知识讲解
第一:故障注入:
http:
- fault:
delay:
percentage:
value: 100
fixedDelay: 10s
该设置说明每次调用 tomcat-svc 的 k8s service,都会延迟10s才会调用。
第二:调用超时:
hosts:
- nginx-svc
http:
- route:
- destination:
host: nginx-svc
timeout: 2s
该设置说明调用 nginx-svc 的 k8s service,请求超时时间是 2s。
#设置超时时间
[root@xianchaomaster1 timeout]# kubectl exec -it nginx-tomcat-7dd6f74846-48g9f -- sh
/ # vi /etc/nginx/conf.d/default.conf
proxy_pass http://tomcat-svc:8080;
proxy_http_version 1.1;
编辑完后,再执行如下语句验证配置和让配置生效:
/ # nginx -t
/ # nginx -s reload
这样,整个样例配置和部署都完成了。
#验证超时
登录client,执行如下语句:
[root@xianchaomaster1 timeout]# kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh
/ # time wget -q -O - http://nginx-svc
wget: server returned error: HTTP/1.1 408 Request Timeout
Command exited with non-zero status 1
real 0m 2.02s
user 0m 0.00s
sys 0m 0.00s
/ # while true; do wget -q -O - http://nginx-svc; done
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 408 Request Timeout
每隔2秒,由于 nginx 服务的超时时间到了而 tomcat未有响应,则提示返回超时错误。
验证故障注入效果,执行如下语句:
/ # time wget -q -O - http://tomcat-svc:8080
real 0m 10.02s
user 0m 0.00s
sys 0m 0.01s
执行之后10s才会有结果
7.3 故障注入和重试
Istio 重试机制就是如果调用服务失败,Envoy 代理尝试连接服务的最大次数。而默认情况下,Envoy 代理在失败后并不会尝试重新连接服务,除非我们启动 Istio 重试机制。
下面例子模拟客户端调用 nginx,nginx 将请求转发给 tomcat。tomcat 通过故障注入而中止对外服务,nginx 设置如果访问 tomcat 失败则会重试 3 次。
[root@xianchaomaster1]# cd /root/timeout/
[root@xianchaomaster1 timeout]#kubectl delete -f virtual-tomcat.yaml
[root@xianchaomaster1 timeout]# cat virtual-attempt.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: nginx-vs
spec:
hosts:
- nginx-svc
http:
- route:
- destination:
host: nginx-svc
retries:
attempts: 3
perTryTimeout: 2s
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: tomcat-vs
spec:
hosts:
- tomcat-svc
http:
- fault:
abort:
percentage:
value: 100
httpStatus: 503
route:
- destination:
host: tomcat-svc
[root@xianchaomaster1 timeout]# kubectl apply -f virtual-attempt.yaml
虚拟服务资源清单解读:
第一:故障注入。该虚拟服务的作用对象就是 tomcat-svc。使用此故障注入后,在网格中该 tomcat 就是不可用的。
abort:
percentage:
value: 100
httpStatus: 503
abort是模拟tomcat服务始终不可用,该设置说明每次调用 tomcat-svc 的 k8s service,100%都会返回错误状态码503。
第二:调用超时:
hosts:
- nginx-svc
http:
- route:
- destination:
host: nginx-svc
reties:
attempts: 3
perTryTimeout: 2s
该设置说明调用 nginx-svc 的 k8s service,在初始调用失败后最多重试 3 次来连接到服务子集,每个重试都有 2 秒的超时。
#验证重试是否生效
[root@xianchaomaster1 timeout]# kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh
/ # wget -q -O - http://nginx-svc
[root@xianchaomaster1 timeout]# kubectl logs -f nginx-tomcat-7dd6f74846-rdqqf -c istio-proxy
#执行结果如下:
由上图可知,重试设置生效。
备注:关闭istio功能,创建pod不让自动注入代理容器:
[root@xianchaomaster1]# kubectl label ns default istio-injection-