Istio 熔断
Fortio 部署
1、介绍
Fortio 是 Istio 的负载测试工具,它提供了 web 控制台和命令行控制台的操作方式。因为后期我们在 Istio 断路器介绍中会使用到 Fortio,因此这节需要对 Fortio 进行安装和简单地操作。
2、安装
这里使用rpm装
1 | curl -L https://github.com/fortio/fortio/releases/download/v1.3.1/fortio-1.3.1-1.x86_64.rpm -o fortio-1.3.1-1.x86_64.rpm |
3、命令行
1 | fortio load -c 5 -n 20 -qps 0 http://www.baidu.com |
4、Web控制台
·· web 控制台方式就是提供给习惯使用 web 界面操作的同学一个途径来使用 Fortio。因为是基于 web 方式,所以就需要首先启动一个 web server,这样客户端浏览器才可以访问到 web server 提供的操作界面进行负载压测。默认情况 fortio server 会启动 8080 端口,如下图所示:
1 | nohup fortio server & |
打开浏览器,输入 http://192.168.10.11:8080/fortio,访问 Fortio server:
直接点击“start”按钮,将会看到压测效果:
Istio网络弹性之超时
1、网络弹性介绍
网络弹性也称为运维弹性,是指网络在遇到灾难事件时快速恢复和继续运行的能力。灾难事件的范畴很广泛,比如长时间停电、网络设备故障、恶意入侵等
2、Istio 超时实例
需要结合 Istio 故障注入模拟被调用方响应请求慢的场景,该实例的架构图如下:
架构说明如下,本实例就是模拟客户端调用 nginx,nginx 将请求转发给 tomcat 的常见功能。tomcat 响应请求设置为 10s(通过故障注入实现,相当于 sleep 10s 逻辑),nginx 设置 client 的请求超时时间为 2s。因为 nginx 需要在 2s 内返回给 client,而 nginx 请求 tomcat 却需要 10s,因此模拟 client 调用 nginx 超时的情景。
2.1 部署客户端
1 | apiVersion: apps/v1 |
2.2 部署nginx和tomcat实例
1 | apiVersion: v1 |
2.3 Istio 虚拟服务资源
1 | apiVersion: networking.istio.io/v1alpha3 |
2.4 部署以上示例,并进行istio注入
1 | istioctl kube-inject -f test-client.yaml | kubectl apply -f - |
3、配置nginx转发tomcat
1 | kubectl exec -it nginx-579d7f7ff-9pspn /bin/sh |
修改内容如下
4、客户端验证
1 | kubectl exec -it client-8496866cdf-vkmcw /bin/sh |
为了实验效果,设置长了时间,和设置的nginx 2s和tomcat 10s是吻合的,除去操作时间
Istio 流量转移
1、虚拟服务(Virtual Service)
虚拟服务(Virtual Service)以及目标规则(Destination Rule)是 Istio 流量路由的两大基石。虚拟服务可以将流量路由到 Istio 服务网格中的服务。每个虚拟服务由一组路由规则组成,这些路由规则按顺序进行评估。
如果没有 Istio virtual service,仅仅使用 k8s service 的话,那么只能实现最基本的流量负载均衡转发,但是就不能实现类似按百分比来分配流量等更加复杂、丰富、细粒度的流量控制了。
备注:虚拟服务相当于 K8s 服务的 sidecar,在原本 K8s 服务的功能之上,提供了更加丰富的路由控制。
2、虚拟服务示例
以下介绍使用 “虚拟服务(virtual service)+目标规则(destination rule)” 实现一个流量分流的例子。本示例共需要四种资源,k8s 和 istio 各两种:
k8s 资源介绍如下:
1 | 1、两个deployment,一个nginx,一个tomcat |
istio资源介绍如下:
1 | 1、一个destination rule #设置目标规则定义 |
3、部署k8s资源
1 | apiVersion: apps/v1 |
自此,k8s 层面的资源文件准备完毕,现在通过访问 service,可以发现自动实现了RoundBin的负载均衡策略,即分配到 tomcat 和 nginx 的流量各为 50%。
4、部署istio资源
Istio 资源共有两类,分别为虚拟服务(Virtual Service)和目的地规则(Destination Rule)。虚拟服务作用在 k8s 服务之上,并加强了原 k8s 服务的功能:
- 指定目的地(tomcat 或 nginx)
- 重新分配流量(即不再是 50% / 50%,而是 75% / 25%)
4.1 目的地规则文件
1 | apiVersion: networking.istio.io/v1alpha3 |
上面的目的地资源文件作用在 web-svc 这个 k8s 服务上,通过 labels 字段指定不同的 pod,然后通过 name 字段提供给下面的 virtual service,起到关联到具体 pod 的作用。
4.2 虚拟服务文件
1 | apiVersion: networking.istio.io/v1alpha3 |
4.3 istio注入
执行如下命令进行 Istio 注入:
1 | istioctl kube-inject -f test-deploy.yaml |kubectl apply -f - |
然后exec进入nginx-deploy的pod中修改配置文件监听端口为8080
1 | vi /etc/nginx/conf.d/default.conf |
修改完保存退出,并重新加载nginx配置:
1 | nginx -s reload |
备注:如果不想每次注入,就给ns注入sidecar
1 | kubectl label namespaces test istio-injection=enabled |
4.4 通过客户端访问测试
1 | kubectl run --namespace=test busybox --rm -ti --image busybox /bin/sh |
会发现出现页面的比例和设置的权重是一致的。
emmmm…不想麻烦就直接在nginx的pod中去测试,这样能看到welcome nginx的页面,在其他pod中访问nginx页面503,没研究出来为啥看不到nginx欢迎界面!
5、destination rule介绍
destination rules 是 Istio 流量路由的关键功能,它不能独自使用,必须跟 Virtual Service 共同发挥作用。当 destination rules 跟 virtual service 共同使用的时候,virtual service 决定将流量路由到逻辑地址,而 destination rules 则决定流量路由到物理地址。
virtual service 跟 destination rules 路由关系就像变量到内存的地址映射一样,destination 代表内存实际地址,而 virtual service 作用就像程序的指针。
destination rules 通常用在微服务的版本分组上(例如可以通过 version 标签将微服务进行分组)。通过 destination rules 的分组规则可以实现将流量路由到服务的不同版本中,进而实现类似灰度、金丝雀、蓝绿等版本分流的策略。
destination rules 不仅可以决定把流量路由到何处,还可以制定如何路由流量(比如是轮询路由流量,还是随机路由流量等等)
6、路由策略
默认情况下,Istio 使用轮询的负载均衡路由策略(round-robin),也就是说服务所有实例按顺序接收请求。当然 Istio 也支持如下的模型,这些模型都可以通过在 destination rule 中进行指定:
- Random:请求被随机分配给服务的实例
- Weighted:请求基于权重被分配给服务的实例
- Least requests:请求被分配给服务最少被访问的实例
Istio 故障注入
1、介绍
Istio 故障注入与其他在网络层引入错误(例如延迟数据包或者直接杀死 Pod)的机制不同,Istio 允许在应用程序层注入故障。这使得可以注入更多相关的故障,比如 HTTP 错误代码等。
Istio 可以注入两种类型的故障,而这两种故障都是使用虚拟服务来配置的:
1 | 延迟:模拟增加网络延迟或上游服务过载。 |
2、使用系统配置
1)注入HTTP延迟故障
1 | kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml |
经过上面的配置,下面是请求的流程:
productpage
→reviews:v2
→ratings
(针对jason
用户)productpage
→reviews:v1
(其他用户)
为了测试微服务应用程序 Bookinfo 的弹性,将为用户 jason
在 reviews:v2
和 ratings
服务之间注入一个 7 秒的延迟。
1 | kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml |
2)测试延迟配置
通过浏览器打开Bookinfo应用
使用用户Jason登录到/prodectpage页面,会发现大约7秒钟加载完成并没有错误,但Reviews部分显示了错误消息
查看页面的相应时间大约6s
3)造成原理
按照预期,引入的 7 秒延迟不会影响到 reviews
服务,因为 reviews
和 ratings
服务间的超时被硬编码为 10 秒。 但是,在 productpage
和 reviews
服务之间也有一个 3 秒的硬编码的超时,再加 1 次重试,一共 6 秒。 结果,productpage
对 reviews
的调用在 6 秒后提前超时并抛出错误了。Istio 的故障注入规则可以帮助您识别此类异常,而不会影响最终用户。
4)修复错误
- 增加
productpage
与reviews
服务之间的超时或降低reviews
与ratings
的超时 - 终止并重启修复后的微服务
- 确认
/productpage
页面正常响应且没有任何错误
将所有流量转移到 reviews:v3
, 您可以尝试修改延迟规则为任何低于 2.5 秒的数值,例如 2 秒,然后确认端到端的流程没有任何错误。
5)注入HTTP abort故障
将给 ratings
微服务为测试用户 jason
引入一个 HTTP abort。在这种情况下,希望页面能够立即加载,同时显示 Ratings service is currently unavailable
这样的消息。为用户 jason
创建一个发送 HTTP abort 的故障注入规则:
1 | kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-abort.yaml |
6)测试终止配置
- 用浏览器打开
Bookinfo
应用。 - 使用用户
jason
登陆到/productpage
页面。如果规则成功传播到所有的 pod,能立即看到页面加载并看到Ratings service is currently unavailable
消息。 - 如果您注销用户
jason
或在匿名窗口(或其他浏览器)中打开 Bookinfo 应用程序, 将看到/productpage
为除jason
以外的其他用户调用了reviews:v1
(完全不调用ratings
)。 因此,您不会看到任何错误消息。
3、自定义配置
1. 故障延迟
1.1 客户端资源
1 | apiVersion: apps/v1 |
部署并使用istio注入,最终得到以下
1.2 服务端资源
1 | apiVersion: v1 |
1.3 虚拟服务
1 | apiVersion: networking.istio.io/v1alpha3 |
2. 验证故障注入
进入客户端容器中,访问nginx服务
1 | kubectl exec -it client-8496866cdf-vkmcw /bin/sh |
可以看出时间延迟在十多秒,加上操作时间,和上面设置的时间是吻合的。
3. 故障中止
修改虚拟服务文件
1 | apiVersion: networking.istio.io/v1alpha3 |
4. 再次进入客户端验证
1 | kubectl exec -it client-8496866cdf-vkmcw /bin/sh |
Istio Gateway 设置路由
1、命名空间注入sidecar
1 | kubectl label namespaces test istio-injection=enabled |
2、使用默认文件
2.1 安装
说明:istio有默认文件,也可自己写,默认的安装与查看如下
1 | kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml |
将 Istio 配置为路由到 Bookinfo 微服务的 v1
版本,最重要的是 reviews
服务的版本 1。
2.2 测试
通过再次刷新 Bookinfo 应用程序的 /productpage
轻松测试新配置,无论刷新多少次,页面的评论部分都不会显示评级星标。这是因为将 Istio 配置为 将评论服务的所有流量路由到版本 reviews:v1
,而此版本的服务不访问星级评分服务。
2.3 基于用户身份路由
来自名为 Jason 的用户的所有流量将被路由到服务 reviews:v2
,Istio 对用户身份没有任何特殊的内置机制。productpage
服务在所有到 reviews
服务的 HTTP 请求中都增加了一个自定义的 end-user
请求头,从而达到了本例子的效果。
1 | kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml |
在 Bookinfo 应用程序的
/productpage
上,以用户jason
身份登录。刷新浏览器,看到星级评分显示在每个评论旁边以其他用户身份登录(选择您想要的任何名称)。刷新浏览器。现在星星消失了。这是因为除了 Jason 之外,所有用户的流量都被路由到
reviews:v1
。
成功配置 Istio 以根据用户身份路由流量。
2.4 理解原理
使用 Istio 将 100% 的请求流量都路由到了 Bookinfo 服务的 v1 版本。 然后设置了一条路由规则,它根据 productpage
服务发起的请求中的 end-user
自定义请求头内容,选择性地将特定的流量路由到了 reviews
服务的 v2
版本。
3、自定义相关资源
3.1 配置Deployment和Service
1 | apiVersion: v1 |
创建deployment和service
3.2 gateway
首先,需要为服务网格启用HTTP/HTTPS流量。 为此,我们需要创建一个Gateway。 Gateway描述了在网络边缘运行的负载均衡器,用于接收传入或传出的HTTP / TCP连接。
让我们创建一个test-gateway.yaml文件:
1 | apiVersion: networking.istio.io/v1alpha3 |
创建Gateway
已经为集群启用了HTTP流量。 需要将之前创建的Kubernetes服务映射到Gateway。将使用VirtualService执行此操作。
3.3 VirtualService
VirtualService实际上将Kubernetes服务连接到Istio网关。它还可以执行更多操作,例如定义一组流量路由规则,以便在主机被寻址时应用
创建一个test-virtualservice.yaml文件:
1 | apiVersion: networking.istio.io/v1alpha3 |
创建VirtualService,请注意,VirtualService与特定网关绑定,并定义引用Kubernetes服务的主机。
测试app v1版本
现在可以开始测试应用了,首先需要拿到Istio Ingress Gateway的外部端口。
1 | kubectl get svc istio-ingressgateway -n istio-system |
![image-20200330111235863](istio Gateway 设置路由.assets/image-20200330111235863.png)
3.4 DestinationRule
在某些时候,希望将应用更新为新版本。 也许想分割两个版本之间的流量。 您需要创建一个DestinationRule来定义那些版本,在Istio中称为子集。
首先,更新test.yaml文件,用v2版本的容器来定义v2的部署(Deployment)
1 | apiVersion: v1 |
创建一个新的部署(Deployment),如果刷新浏览器,你可以看到VirtualService 在v1 和v2 版本之间切换:
如果您想将服务仅限于v2该怎么办? 可以通过在VirtualService中指定子集来完成,但需要首先在DestinationRules中定义这些子集。 DestinationRule本质上将标签映射到Istio子集。
创建一个test-destinationrule.yaml文件:
1 | apiVersion: networking.istio.io/v1alpha3 |
创建DestinnationRule,可以在VirtualService指向v2子集:
1 | apiVersion: networking.istio.io/v1alpha3 |
更新VirtualService,现在再刷新浏览器,你应该只会看到v2版本的内容了
部署istio Bookinfo应用
1、bookinfo 架构介绍
bookinfo 是 istio 的学习样例,通过 bookinfo 你可以对 istio 提供的路由、遥测等功能有更加深入的理解。下图是 bookinfo 在没有嵌入 istio 前的物理架构图:
bookinfo 是一个在线书店应用,该应用由 4 个微服务组成,分别为 Product page、Reviews、Details 和 Ratings。为了表现 istio 的无侵入性,这 4 个微服务分别由 python、java、ruby 和 node 开发。下面分别说明如下:
1 | Product page:聚合服务,内容由 Reviews 和 Details 内容聚合而成 |
下图是 bookinfo 嵌入 istio 后的物理架构图:
该架构图演示了嵌入 istio 后 bookinfo 的每个微服务都会新增一个 Envoy,这个 Envoy 就是所谓的 sidecar,它会接管跟它配对的微服务的所有网络进、出口流量。其实 Envoy(sidecar)的作用就像你的手机,它正在逐渐把你变成哑巴、聋子和植物人,它承接了你所有的信息入口和出口,某些别有用心的人和组织通过对手机进行监控、遥测、路由等控制,起到控制你的思维、舆论导向、审美爱好等目的。
2、bookinfo 配置与部署
2.1 配置istio自动注入
因为 bookinfo 会启动多个 pod,每次手动注入 sidecar 会特别繁琐,因此我们使用批注入的方式
1 | kubectl label namespace default istio-injection=enabled |
2.2 部署bookinfo 应用
1 | kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml |
执行如下命令查看 bookinfo 的 service 列表:
1 | kubectl get svc -n test |
执行如下命令查看 bookinfo 的 pod 列表:
1 | kubectl get pod -n test |
2.3 验证 bookinfo 部署情况
在服务列表中寻找 productpage 服务,然后使用 curl 命令验证服务是否发布成功。
1 | kubectl get svc |
3、设置 bookinfo 网关
此时,BookInfo 应用已经部署,但还不能被外界访问。 要开放访问,你需要创建 Istio 入站网关(Ingress Gateway), 它会在网格边缘把一个路径映射到路由。
1 | kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml #定义 bookinfo 入口网关 |
4、 访问 bookinfo 应用
1 | kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}' # 获取 INGRESS_HOST |
根据此 host 和 port,打开浏览器进行访问,多刷新几次页面,你会发现 bookinfo 应用使用到的多个 reviews 版本,有时书评的输出包含星级评分,有时则不包含。 这是因为没有明确的默认服务版本路由,Istio 将以循环方式请求路由到所有可用版本。如下所示:
1 | http://192.168.10.200:31862/productpage #ip加端口会报404 |
5、卸载 bookinfo 应用
1 | /root/istio-1.10.0-rc.1/samples/bookinfo/platform/kube/cleanup.sh |
执行如下命令验证你是否成功卸载:
1 | kubectl get virtualservices.networking.istio.io |
Istio注入sidecar
1、注入
为了充分利用 Istio 的所有特性,网格中的 pod 必须运行一个 Istio sidecar 代理。
向 pod 中注入 Istio sidecar 的两种方法:使用 istioctl
手动注入或启用 pod 所属命名空间的 Istio sidecar 注入器自动注入。
手动注入直接修改配置,如 deployment,并将代理配置注入其中。
当 pod 所属命名空间启用自动注入后,自动注入器会使用准入控制器在创建 Pod 时自动注入代理配置。
通过应用 istio-sidecar-injector
ConfigMap 中定义的模版进行注入。
2、手动注入sidecar
上一节实现了istio的安装,所有的pod都是running状态,但不知其作用,现在先创建一个deployment
1 | apiVersion: apps/v1 |
为了方便视图,创建一个新的名称空间
1 | kubectl create namespace test |
执行如下语句:
1 | istioctl kube-inject -f nginx.yml | kubectl apply -n test -f - |
稍等会儿就能看到原来一个pod变成了两个,如果你有类似 rancher 这样的 web 控制台,可以看得更仔细些,如
下图所示。
从上图可知。此时 nginx pod 内部一共有 3 个容器,一个初始化容器 istio-init 已经运行成功并结束了,一个就是
nginx 本尊,另外一个就是本文的主角 istio-proxy 了,它就是 sidecar,作用是负责跟外部打交到用的。
3、命名空间注入sidecar
当你在一个命名空间中设置了 istio-injection=enabled
标签,且 injection webhook 被启用后,任何新的 pod 都有将在创建时自动添加 sidecar。
现在删除掉刚才创建的 nginx:
1 | kubectl delete deploy nginx -n test |
执行如下命令在命名空间内实现自动注入 sidecar:
1 | kubectl label namespaces test istio-injection=enabled |
再次创建nginx的deploy文件
1 | kubectl apply -f nginx.yml -n test |
稍等会儿就能看到已经自动注入了
安装Istio
1、环境介绍
2、运行以下命令来自动下载并解压缩最新版本:
1 | curl -L https://istio.io/downloadIstio | sh - |
说明:由于k8s集群是1.21.0版本,这里使用的是istio最新测试版本
3、安装目录包含:
samples/
目录下的示例应用程序bin/
目录下的istioctl
客户端二进制文件
4、设置环境变量
1 | cd cd istio-1.10.0-rc.1/ |
5、安装demo
配置文件
- default: 根据默认的安装选项启用组件 (建议用于生产部署)。
- demo: 这一配置具有适度的资源需求,旨在展示 Istio 的功能。它适合运行 Bookinfo 应用程序和相关任务。
- minimal: 使用 Istio 的流量管理功能所需的最少组件集。
- sds: 和 default 配置类似,但是启用了 Istio 的 SDS (secret discovery service) 功能。 这个配置文件默认启用了附带的认证功能 (Strict Mutual TLS)。
1 | istioctl install --set profile=demo -y |
备注:这里有的镜像可能拉不下来,需要自己想办法,等待时间可能有点长
6、通过确保已部署以下Kubernetes服务来验证安装
1 | kubectl get pod -n istio-system |
说明:由于自建集群没有lb,所以会ingressgateway会处于pending状态,改成NodePort即可
7、卸载会删除RBAC权限,istio-system
名称空间以及它下面的层次结构中的所有资源
1 | istioctl manifest generate --set profile=demo | kubectl delete -f - |