本小节主要讲解针对连接、请求、和异常点检测如何配置断路器。
断路是创建弹性微服务应用程序的重要模式。断路允许您编写应用程序来限制故障、延迟峰值和网络特性的其他不良影响的影响。
1. 准备工作
- 假如开启了自动sidecar的注入,部署
httpbin
服务。
$ kubectl apply -f samples/httpbin/httpbin.yaml
- 否则,就必须在部署http-bin应用前手工的注入sidecar.
$ kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml)
2. 配置断路器
- 当调用
httpbin
服务时,创建destination rules
去应用断路器
[warning] 如果您安装/配置了Istio,并且启用了相互TLS身份验证,那么在应用之前,您必须在DestinationRule中添加一个TLS流量策略模式:ISTIO_MUTUAL。否则请求将产生503个错误。
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutiveErrors: 1
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 100
EOF
- 校验创建的目的规则是否正确
$ kubectl get destinationrule httpbin -o yaml
3. 添加一个客户端
创建一个向httpbin服务发送流量的客户机。客户机是一个简单的负载测试客户机,名为fortio。Fortio允许您控制发出HTTP调用的连接数、并发性和延迟。您将使用此客户端“测试”您在DestinationRule中设置的断路器策略。
- 向客户机注入Istio sidecar代理,以便网络交互由Istio控制。
- 开启自动注册sidecar执行如下
$ kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml
- 如果没有开启自动注册sidecar,执行如下
$ kubectl apply -f <(istioctl kube-inject -f samples/httpbin/sample-client/fortio-deploy.yaml)
- 登陆进客户端Pod,使用fortio工具去调用httpbin,传送-curl去表明你想要调用一次。
$ FORTIO_POD=$(kubectl get pods -lapp=fortio -o 'jsonpath={.items[0].metadata.name}')
$ kubectl exec -it "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -curl http://httpbin:8000/get
HTTP/1.1 200 OK
server: envoy
date: Fri, 10 Apr 2020 03:19:57 GMT
content-type: application/json
content-length: 586
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 134
{
"args": {},
"headers": {
"Content-Length": "0",
"Host": "httpbin:8000",
"User-Agent": "fortio.org/fortio-1.3.1",
"X-B3-Parentspanid": "85a9d5e068b0a40a",
"X-B3-Sampled": "1",
"X-B3-Spanid": "f0a5e5e2d2df027d",
"X-B3-Traceid": "96a730935071ea8d85a9d5e068b0a40a",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=8458355f1e914accb3c7a6345699026f394c44f766776b4f592a96c6bcee0e41;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default"
},
"origin": "127.0.0.1",
"url": "http://httpbin:8000/get"
}
可以看到请求是成功的,现在终止一些东西。
4. 使用断路器
在目的的规则中,指定了maxConnections: 1
和http1MaxPendingRequests: 1
,这表明假如你执行超过一个连接和并发请求超过一个的话,那么应该看到一些错误,这是因为istio-proxy为进一步的请求和连接打开断路。
- 调用服务使用两个并发连接(-c 2)和发送20个请求(-n 20):
$ kubectl exec -it "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get
03:24:54 I logger.go:97> Log level is now 3 Warning (was 2 Info)
Fortio 1.3.1 running at 0 queries per second, 4->4 procs, for 20 calls: http://httpbin:8000/get
Starting at max qps with 2 thread(s) [gomax 4] for exactly 20 calls (10 per thread + 0)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
03:24:54 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
Ended after 190.411754ms : 20 calls. qps=105.04
Aggregated Function Time : count 20 avg 0.017717231 +/- 0.01876 min 0.000951346 max 0.061150454 sum 0.354344623
# range, mid point, percentile, count
>= 0.000951346 <= 0.001 , 0.000975673 , 5.00, 1
> 0.001 <= 0.002 , 0.0015 , 30.00, 5
> 0.005 <= 0.006 , 0.0055 , 35.00, 1
> 0.009 <= 0.01 , 0.0095 , 40.00, 1
> 0.011 <= 0.012 , 0.0115 , 45.00, 1
> 0.012 <= 0.014 , 0.013 , 55.00, 2
> 0.014 <= 0.016 , 0.015 , 65.00, 2
> 0.016 <= 0.018 , 0.017 , 70.00, 1
> 0.018 <= 0.02 , 0.019 , 75.00, 1
> 0.02 <= 0.025 , 0.0225 , 80.00, 1
> 0.025 <= 0.03 , 0.0275 , 85.00, 1
> 0.05 <= 0.06 , 0.055 , 95.00, 2
> 0.06 <= 0.0611505 , 0.0605752 , 100.00, 1
# target 50% 0.013
# target 75% 0.02
# target 90% 0.055
# target 99% 0.0609204
# target 99.9% 0.0611274
Sockets used: 10 (for perfect keepalive, would be 2)
Code 200 : 11 (55.0 %)
Code 503 : 9 (45.0 %)
Response Header Sizes : count 20 avg 126.9 +/- 114.8 min 0 max 231 sum 2538
Response Body/Total Sizes : count 20 avg 557.65 +/- 286.4 min 241 max 817 sum 11153
All done 20 calls (plus 0 warmup) 17.717 ms avg, 105.0 qps
有意思的是大部分请求都通过了. 看来istio-proxy看来做了些均衡。
Code 200 : 11 (55.0 %)
Code 503 : 9 (45.0 %)
- 现在把并发连接调整为3:
$ kubectl exec -it "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://httpbin:8000/get
07:13:36 I logger.go:97> Log level is now 3 Warning (was 2 Info)
Fortio 1.3.1 running at 0 queries per second, 4->4 procs, for 30 calls: http://httpbin:8000/get
Starting at max qps with 3 thread(s) [gomax 4] for exactly 30 calls (10 per thread + 0)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
07:13:36 W http_client.go:679> Parsed non ok code 503 (HTTP/1.1 503)
Ended after 86.401572ms : 30 calls. qps=347.22
Aggregated Function Time : count 30 avg 0.0082447178 +/- 0.006973 min 0.000991901 max 0.021700013 sum 0.247341535
# range, mid point, percentile, count
>= 0.000991901 <= 0.001 , 0.00099595 , 6.67, 2
> 0.001 <= 0.002 , 0.0015 , 13.33, 2
> 0.002 <= 0.003 , 0.0025 , 33.33, 6
> 0.003 <= 0.004 , 0.0035 , 46.67, 4
> 0.004 <= 0.005 , 0.0045 , 53.33, 2
> 0.005 <= 0.006 , 0.0055 , 56.67, 1
> 0.007 <= 0.008 , 0.0075 , 60.00, 1
> 0.01 <= 0.011 , 0.0105 , 66.67, 2
> 0.012 <= 0.014 , 0.013 , 76.67, 3
> 0.014 <= 0.016 , 0.015 , 83.33, 2
> 0.016 <= 0.018 , 0.017 , 86.67, 1
> 0.02 <= 0.0217 , 0.02085 , 100.00, 4
# target 50% 0.0045
# target 75% 0.0136667
# target 90% 0.020425
# target 99% 0.0215725
# target 99.9% 0.0216873
Sockets used: 20 (for perfect keepalive, would be 3)
Code 200 : 12 (40.0 %)
Code 503 : 18 (60.0 %)
Response Header Sizes : count 30 avg 92.233333 +/- 113 min 0 max 231 sum 2767
Response Body/Total Sizes : count 30 avg 471.23333 +/- 282 min 241 max 817 sum 14137
All done 30 calls (plus 0 warmup) 8.245 ms avg, 347.2 qps
- 查询 istio-proxy的统计信息:
[root@c72082 istio-1.5.1]# kubectl exec "$FORTIO_POD" -c istio-proxy -- pilot-agent request GET stats | grep httpbin | grep pending
cluster.outbound|8000||httpbin.default.svc.cluster.local.circuit_breakers.default.rq_pending_open: 0
cluster.outbound|8000||httpbin.default.svc.cluster.local.circuit_breakers.high.rq_pending_open: 0
cluster.outbound|8000||httpbin.default.svc.cluster.local.upstream_rq_pending_active: 0
cluster.outbound|8000||httpbin.default.svc.cluster.local.upstream_rq_pending_failure_eject: 0
cluster.outbound|8000||httpbin.default.svc.cluster.local.upstream_rq_pending_overflow: 23
cluster.outbound|8000||httpbin.default.svc.cluster.local.upstream_rq_pending_total: 28
你可以看到upstream_rq_pending_overflow
的值为23,意味着到目前为止已经被标记为断路。
5. 清除本次实验
$ kubectl delete destinationrule httpbin
$ kubectl delete deploy httpbin fortio-deploy
$ kubectl delete svc httpbin fortio
```