istio-1.0.6 流量管理 熔断

环境:

  • istio版本:istio-1.0.6
  • apiVersion: networking.istio.io/v1alpha3
  • kubernetes版本: v1.13.3

前提条件

部署示例应用

部署httpbin:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-v1
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
      annotations:
        sidecar.istio.io/inject: "true"
    spec:
      containers:
      - image: docker.io/citizenstig/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
  selector:
    app: httpbin

注意:
上面的pod用annotations的方式自动注入了sidecar(istio-proxy)容器,如果不想自动注入可以使用一下方法:

kubectl apply -f <(istioctl kube-inject -f httpbin-deployment.yaml)

断路器

官方的教程

1.创建一个目标规则,针对httpbin服务设置断路器:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - httpbin.default.svc.cluster.local
  http:
  - route:
    - destination:
        host: httpbin.default.svc.cluster.local
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      version: v1
    trafficPolicy:
      connectionPool:
        tcp:
          maxConnections: 1
        http:
          http1MaxPendingRequests: 1
          maxRequestsPerConnection: 1
      outlierDetection:
        consecutiveErrors: 1
        interval: 1s
        baseEjectionTime: 3m
        maxEjectionPercent: 100
  - name: v2
    labels:
      version: v1

virtualservice的内容就是选择目标规则子规则为v1的内容。

destination规则对v1子规则设置了断路器,v2版本没有设置断路器。

v1版本的熔断配置:
spec.trafficPolicy.connectionPool.tcp.maxConnections:最大连接数是1
spec.trafficPolicy.connectionPool.http. http1MaxPendingRequests:http最大请求等待数,默认1024
spec.trafficPolicy.connectionPool.http.maxRequestsPerConnection:每个连接到后端的最大请求数。 将此参数设置为1将禁用保持活动状态。
spec.trafficPolicy.outlierDetection.baseEjectionTime:Minimum ejection duration. A host will remain ejected for a period equal to the product of minimum ejection duration and the number of times the host has been ejected. This technique allows the system to automatically increase the ejection period for unhealthy upstream servers. format: 1h/1m/1s/1ms. MUST BE >=1ms. Default is 30s.
spec.trafficPolicy.outlierDetection.maxEjectionPercent:可以被提出负载均衡池的上有主机的百分比,默认10%。

详细的字段说明请参考官方说明

应用规则:

kubectl apply -f service-rule.yaml

2.检查目标规则,确定已经正确创建:

istioctl get destinationrule httpbin -o yaml

输出结果:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"name":"httpbin","namespace":"default"},"spec":{"host":"httpbin.default.svc.cluster.local","subsets":[{"labels":{"version":"v1"},"name":"v1","trafficPolicy":{"connectionPool":{"http":{"http1MaxPendingRequests":1,"maxRequestsPerConnection":1},"tcp":{"maxConnections":1}},"outlierDetection":{"baseEjectionTime":"3m","consecutiveErrors":1,"interval":"1s","maxEjectionPercent":100}}},{"labels":{"version":"v1"},"name":"v2"}]}}
  creationTimestamp: null
  name: httpbin
  namespace: default
  resourceVersion: "3643883"
spec:
  host: httpbin.default.svc.cluster.local
  subsets:
  - labels:
      version: v1
    name: v1
    trafficPolicy:
      connectionPool:
        http:
          http1MaxPendingRequests: 1
          maxRequestsPerConnection: 1
        tcp:
          maxConnections: 1
      outlierDetection:
        baseEjectionTime: 180.000s
        consecutiveErrors: 1
        interval: 1.000s
        maxEjectionPercent: 100
  - labels:
      version: v1
    name: v2

部署客户端

现在我们已经设置了调用httpbin服务的规则,接下来创建一个客户端,用来向后端服务发送请求,观察是否出发熔断策略。这里要使用一个简单的负载测试客户端,名字叫fortio。这个客户端可以控制连接数、并发数以及发送HTTP请求的延迟。这里我们会把客户端进行Sidecar的注入,一次保证istio对网络交互的控制:

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: fortio-deploy
spec:
  replicas: 1
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true"
      labels:
        app: fortio
    spec:
      containers:
      - name: fortio
        #image: fortio/fortio:latest_release
        image: istio/fortio:latest_release
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
          name: http-fortio
        - containerPort: 8079
          name: grpc-ping

手动注入sidecar,可以通过下面方式:

kubectl apply -f <(istioctl kube-inject -f fortio.yaml)

接下来可以登入客户端pod并使用Ofrtio工具调用httpbin。-curl参数表示只调用一次:

FORTIO_POD=$(kubectl get pod | grep fortio | awk '{ print $1 }')
kubectl exec -it $FORTIO_POD  -c fortio /usr/local/bin/fortio -- load -curl  http://httpbin:8000/get

HTTP/1.1 200 OK
server: envoy
date: Tue, 12 Mar 2019 08:35:48 GMT
content-type: application/json
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 365
x-envoy-upstream-service-time: 17

{
  "args": {},
  "headers": {
    "Content-Length": "0",
    "Host": "httpbin:8000",
    "User-Agent": "istio/fortio-1.0.1",
    "X-B3-Sampled": "0",
    "X-B3-Spanid": "85e1c4d59ca02731",
    "X-B3-Traceid": "85e1c4d59ca02731",
    "X-Request-Id": "f9e6ee91-64f7-45c4-a5d9-2385e6bbbf9a"
  },
  "origin": "127.0.0.1",
  "url": "http://httpbin:8000/get"
}

调用成功,接下来做一些改变。

触发熔断机制

在上面的熔断设置中指定了maxConnections: 1以及http1MaxPendingRequests: 1。这意味着如果超过了一个连接同时发起请求,Istio就会熔断,阻止后续的请求或连接。接下来尝试一下两个并发(-c 2),发送20请求(-n 20):

# kubectl exec -it $FORTIO_POD  -c fortio /usr/local/bin/fortio -- load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get

08:42:08 I logger.go:97> Log level is now 3 Warning (was 2 Info)
Fortio 1.0.1 running at 0 queries per second, 1->1 procs, for 20 calls: http://httpbin:8000/get
Starting at max qps with 2 thread(s) [gomax 1] for exactly 20 calls (10 per thread + 0)
08:42:08 W http_client.go:604> Parsed non ok code 503 (HTTP/1.1 503)
Ended after 38.338193ms : 20 calls. qps=521.67
Aggregated Function Time : count 20 avg 0.0037474649 +/- 0.0009945 min 0.001801204 max 0.006098462 sum 0.074949299
# range, mid point, percentile, count
>= 0.0018012 <= 0.002 , 0.0019006 , 5.00, 1
> 0.003 <= 0.004 , 0.0035 , 70.00, 13
> 0.004 <= 0.005 , 0.0045 , 85.00, 3
> 0.005 <= 0.006 , 0.0055 , 95.00, 2
> 0.006 <= 0.00609846 , 0.00604923 , 100.00, 1
# target 50% 0.00369231
# target 75% 0.00433333
# target 90% 0.0055
# target 99% 0.00607877
# target 99.9% 0.00609649
Sockets used: 3 (for perfect keepalive, would be 2)
Code 200 : 19 (95.0 %)
Code 503 : 1 (5.0 %)
Response Header Sizes : count 20 avg 218.5 +/- 50.13 min 0 max 230 sum 4370
Response Body/Total Sizes : count 20 avg 576.1 +/- 82.38 min 217 max 595 sum 11522
All done 20 calls (plus 0 warmup) 3.747 ms avg, 521.7 qps

这里可以看到,几乎所有请求都通过了。

Code 200 : 19 (95.0 %)
Code 503 : 1 (5.0 %)

istio-proxy 允许一些余地。接下来吧并发连接数量提到3:

# kubectl exec -it $FORTIO_POD  -c fortio /usr/local/bin/fortio -- load -c 3 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get
08:44:16 I logger.go:97> Log level is now 3 Warning (was 2 Info)
Fortio 1.0.1 running at 0 queries per second, 1->1 procs, for 20 calls: http://httpbin:8000/get
Starting at max qps with 3 thread(s) [gomax 1] for exactly 20 calls (6 per thread + 2)
08:44:16 W http_client.go:604> Parsed non ok code 503 (HTTP/1.1 503)
08:44:16 W http_client.go:604> Parsed non ok code 503 (HTTP/1.1 503)
08:44:16 W http_client.go:604> Parsed non ok code 503 (HTTP/1.1 503)
08:44:16 W http_client.go:604> Parsed non ok code 503 (HTTP/1.1 503)
08:44:16 W http_client.go:604> Parsed non ok code 503 (HTTP/1.1 503)
08:44:16 W http_client.go:604> Parsed non ok code 503 (HTTP/1.1 503)
08:44:16 W http_client.go:604> Parsed non ok code 503 (HTTP/1.1 503)
Ended after 30.193184ms : 20 calls. qps=662.4
Aggregated Function Time : count 20 avg 0.0029523684 +/- 0.002059 min 0.000273708 max 0.007145017 sum 0.059047367
# range, mid point, percentile, count
>= 0.000273708 <= 0.001 , 0.000636854 , 25.00, 5
> 0.001 <= 0.002 , 0.0015 , 35.00, 2
> 0.002 <= 0.003 , 0.0025 , 40.00, 1
> 0.003 <= 0.004 , 0.0035 , 75.00, 7
> 0.004 <= 0.005 , 0.0045 , 80.00, 1
> 0.005 <= 0.006 , 0.0055 , 85.00, 1
> 0.006 <= 0.007 , 0.0065 , 95.00, 2
> 0.007 <= 0.00714502 , 0.00707251 , 100.00, 1
# target 50% 0.00328571
# target 75% 0.004
# target 90% 0.0065
# target 99% 0.00711601
# target 99.9% 0.00714212
Sockets used: 9 (for perfect keepalive, would be 3)
Code 200 : 13 (65.0 %)
Code 503 : 7 (35.0 %)
Response Header Sizes : count 20 avg 149.5 +/- 109.7 min 0 max 230 sum 2990
Response Body/Total Sizes : count 20 avg 462.7 +/- 180.3 min 217 max 595 sum 9254
All done 20 calls (plus 0 warmup) 2.952 ms avg, 662.4 qps

这时会观察到,熔断行为按照之前的设计生效了:

Code 200 : 13 (65.0 %)
Code 503 : 7 (35.0 %)

只有65%的请求获得通过,剩余的请求被断路器拦截了,我们可以查询istio-proxy的状态,获取更多信息:

# kubectl exec -it $FORTIO_POD  -c istio-proxy  -- sh -c 'curl localhost:15000/stats' | grep httpbin | grep pending
cluster.outbound|8000|v1|httpbin.default.svc.cluster.local.upstream_rq_pending_active: 0
cluster.outbound|8000|v1|httpbin.default.svc.cluster.local.upstream_rq_pending_failure_eject: 0
cluster.outbound|8000|v1|httpbin.default.svc.cluster.local.upstream_rq_pending_overflow: 8
cluster.outbound|8000|v1|httpbin.default.svc.cluster.local.upstream_rq_pending_total: 32

upstream_rq_pending_overflow的值是8,说明8次调用被标记为熔断。

切换到v2版本

修改httpbin的VirtualService配置如下:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - httpbin.default.svc.cluster.local
  http:
  - route:
    - destination:
        host: httpbin.default.svc.cluster.local
        subset: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      version: v1
    trafficPolicy:
      connectionPool:
        tcp:
          maxConnections: 1
        http:
          http1MaxPendingRequests: 1
          maxRequestsPerConnection: 1
      outlierDetection:
        consecutiveErrors: 1
        interval: 1s
        baseEjectionTime: 3m
        maxEjectionPercent: 100
  - name: v2
    labels:
      version: v1

应用配置

kubectl apply -f httpbin-rule.yaml

重复上面部署完客户端后,使用fortio操作测试,不会出现熔断。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352