故障注入HTTPFaultInjection用于在将HTTP请求转发到路由中指定的目标时,指定要注入的一个或多个故障。故障规范是虚拟服务规则的一部分,包括从下游服务终止HTTP请求、延迟请求的代理等。
故障注入是混沌工程中经常用的一种手段。Istio可以支持2种故障注入方式(参见图6-6)。

图6-6 故障注入原理
·时延故障:故障百分比,延时;Delay配置用来在请求的转发路径上注入延迟。
·中断故障:故障百分比,Http状态码;提前终止请求,并返回预定义的错误码。
故障注入字段参见表6-10。
表6-10 故障注入

其中,中断故障用于使用预先指定的错误代码过早终止请求,参见表6-11。
表6-11 中断故障的字段

时延故障用于将延迟注入请求转发路径,参见表6-12。
表6-12 时延故障的字段

例如,针对“rating”服务版本“v1”的每1000个请求中的1个返回HTTP 400错误代码,以及每1000个请求中有1个会引入5秒延迟,代码如下:
http:
- route:
- destination:
host: ratings.prod.svc.cluster.local
subset: v1
fault:
abort:
percentage:
value: 0.001
httpStatus: 400
delay:
percentage:
value: 0.001
fixedDelay: 5s
示例
下载本书所使用的示例代码之后,切换到目录traffic-policy/faultinjection下可以查看所有相关的代码文件。
启动httpbin服务示例应用,这个应用将会作为本任务的后端服务。切换到下载文件的根目录之后,运行以下命令:
kubectl create namespace faultinjection kubectl label namespace faultinjection istio-injection=enabled kubectl apply -n faultinjection -f faultinjection/app.yaml kubectl apply -n faultinjection -f faultinjection/sleep.yaml
上述命令执行成功之后,会在命名空间sidecar下创建相应的服务,如下是创建的pod列表:
kubectl get pod -n faultinjection NAME READY STATUS RESTARTS AGE httpbin-v1-5f698657b5-kcf5f 2/2 Running 0 70s httpbin-v2-5668fdcd4c-xm8sc 2/2 Running 0 70s sleep-57f9d6fd6b-bx2zx 2/2 Running 0 9m
然后,确认Sleep_POD运行正常并执行以下命令,登录到sleep容器中:
SLEEP_POD=$(kubectl get pod -n faultinjection | grep sleep | awk '{ print $1 }')
kubectl exec -it -n faultinjection $SLEEP_POD -c sleep sh
执行如下脚本,可以看到返回结果是轮询式的负载分布:
root@sleep-6576c7f89d-9l9rz:/# for i in `seq 100`; do curl http://httpbin:5678/
ip; echo ''; sleep 1; done;
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
{"ipAddress":"172.24.0.121","hostname":"httpbin-v2-5668fdcd4c-xm8sc"}
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
{"ipAddress":"172.24.0.121","hostname":"httpbin-v2-5668fdcd4c-xm8sc"}
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
{"ipAddress":"172.24.0.121","hostname":"httpbin-v2-5668fdcd4c-xm8sc"}
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
....
然后,我们开始注入一个中断故障,使用预先指定的错误代码提前终止请求,定义如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin
http:
- fault:
abort:
httpStatus: 555
percentage:
value: 50.00
route:
- destination:
host: httpbin
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
subsets:
- name: v1
labels:
version: v1
将上述yaml内容保存为fault-injection-abort.yaml文件,或者切换到下载文件的根目录,并执行如下kubectl命令:
kubectl apply -n faultinjection -f faultinjection/fault-injection-abort.yaml
执行上述命令之后,针对httpbin服务的Istio资源定义虚拟服务和目标规则就被创建了,再次执行如下脚本,可以看到返回结果:
root@sleep-6576c7f89d-9l9rz:/# for i in `seq 100`; do curl http://httpbin:5678/
ip; echo ''; sleep 1; done;
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
fault filter abort
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
fault filter abort
fault filter abort
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
fault filter abort
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
fault filter abort
{"ipAddress":"172.24.0.120","hostname":"httpbin-v1-5f698657b5-kcf5f"}
fault filter abort
fault filter abort
....
除了中断故障之外,还可以定义延迟故障,用于将延迟注入请求转发路径,如下代码定义了一个将50%的请求延迟5s的Istio资源定义:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin
http:
- fault:
delay:
fixedDelay: 5s
percentage:
value: 50.00
route:
- destination:
host: httpbin
subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
subsets:
- name: v1
labels:
version: v1
针对httpbin服务的Istio资源定义虚拟服务和目标规则被创建之后,再次执行如下脚本,可以看到如下返回结果:
root@sleep-6576c7f89d-9l9rz:/# for i in `seq 100`; do curl -o /dev/null -s -w '%{time_total}' http://httpbin:5678/ip; echo ''; sleep 1; done;
5.008761
5.008193
5.009997
5.008574
0.013484
0.013513
0.013509
0.013444
5.008755
0.014443
0.013484
0.013502
5.012042
0.013530
5.008253
5.008147
可以看到,将近一半的请求被延迟了5s的时间。最后注意一点,时延故障和中断故障是可以并存的,即使两者同时指定,时延和中断故障也是相互独立的。