前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Istio边界流量-Ingress Gateway拓展用法

Istio边界流量-Ingress Gateway拓展用法

作者头像
王先森sec
发布2023-04-24 17:40:40
6420
发布2023-04-24 17:40:40
举报
文章被收录于专栏:王先森

实例架构

该应用由四个单独的微服务构成。 这个应用模仿在线书店的一个分类,显示一本书的信息。 页面上会显示一本书的描述,书籍的细节(ISBN、页数等),以及关于这本书的一些评论。

Bookinfo 应用分为四个单独的微服务:

  • productpage. 这个微服务会调用 detailsreviews 两个微服务,用来生成页面。
  • details. 这个微服务中包含了书籍的信息。
  • reviews. 这个微服务中包含了书籍相关的评论。它还会调用 ratings 微服务。
  • ratings. 这个微服务中包含了由书籍评价组成的评级信息。

reviews 微服务有 3 个版本:

  • v1 版本不会调用 ratings 服务。
  • v2 版本会调用 ratings 服务,并使用 1 到 5 个黑色星形图标来显示评分信息。
  • v3 版本会调用 ratings 服务,并使用 1 到 5 个红色星形图标来显示评分信息。

Bookinfo 是一个异构应用,几个微服务是由不同的语言编写的。这些服务对 Istio 并无依赖,但是构成了一个有代表性的服务网格的例子:它由多个服务、多个语言构成,并且 reviews 服务具有多个版本。

创建实例

代码语言:javascript
复制
$ kubectl create namespace bookinfo
# istio 源码包中携带此实例
$ kubectl -n bookinfo create -f /opt/istio/samples/bookinfo/platform/kube/bookinfo.yaml 
$ kubectl -n bookinfo get pods 
NAME                                  READY   STATUS    RESTARTS   AGE
details-v1-5974b67c8-wclnd            1/1     Running   0          34s
productpage-v1-64794f5db4-jsdbg       1/1     Running   0          33s
ratings-v1-c6cdf8d98-jrfrn            1/1     Running   0          33s
reviews-v1-7f6558b974-kq6kj           1/1     Running   0          33s
reviews-v2-6cb6ccd848-qdg2k           1/1     Running   0          34s
reviews-v3-cc56b578-kppcx             1/1     Running   0          34s

使用ingress访问productpage服务:

代码语言:javascript
复制
cat > ingress-productpage.yaml <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: productpage
  namespace: bookinfo
spec:
  rules:
  - host: bookinfo.od.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: 
            name: productpage
            port:
              number: 9080
EOF

如何实现更细粒度的流量管控?

注入sidecar容器

如何注入sidecar容器

使用istioctl kube-inject

代码语言:javascript
复制
$ kubectl -n bookinfo apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml)

为命名空间打label

代码语言:javascript
复制
# 给命名空间打标签,这样部署在该命名空间的服务会自动注入sidecar容器
$ kubectl label namespace dafault istio-injection=enabled

注入bookinfo

代码语言:javascript
复制
$ kubectl -n bookinfo apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml) 

服务流量治理

作用:实现ingress解决不了的按照比例分配流量

配置访问productpage

  • Gateway
  • Service
代码语言:javascript
复制
cat > productpage-gateway.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: productpage-gateway
  namespace: bookinfo
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - bookinfo.istio.com
EOF
代码语言:javascript
复制
cat > productpage-virtualservice.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-bookinfo
  namespace: bookinfo
spec:
  gateways:
  - productpage-gateway
  hosts: 
  - bookinfo.istio.com
  http:
  - route:
    - destination:
        host: productpage
        port:
          number: 9080
EOF

权重路由

需求一:只想访问reviews-v3,所有流量都调度到v3也就是红心上面。其他不调度

  • DestinationRule
  • VirtualService
代码语言:javascript
复制
$ cat > destination-rule-reviews.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
  namespace: bookinfo
spec:
  host: reviews
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
EOF
代码语言:javascript
复制
$ cat > virtual-service-reviews-v3.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  namespace: bookinfo
spec:
  hosts:
    - reviews
  http: 
  - route:
    - destination:
        host: reviews
        subset: v3
EOF

应用资源配置清单

代码语言:javascript
复制
kubectl apply -f  destination-rule-reviews.yaml
kubectl apply -f virtual-service-reviews-v3.yaml

# 访问productpage测试,此时发现页面一直停在v3版本不会变化,需求实现。

需求二:实现如下流量分配:

reivews-v1 导入90%流量 reviews-v2 导入10%流量 reviews-v3 不导入流量

代码语言:javascript
复制
# 同样的方式,刚才已经定义过v1、v2、v3的去向了,现在只需要增加v1和v2路由规则即可
$ cat > virtual-service-reviews-90-10.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  namespace: bookinfo
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 90
    - destination:
        host: reviews
        subset: v2
      weight: 10
EOF

$ kubectl apply -f virtual-service-reviews-90-10.yaml
# 此时,再次访问,v3就不会出现了

访问路径路由

需求:意思是根据不同路径访问不同页面

实现效果如下:

代码语言:javascript
复制
# 修改外部流量进入网格后的规则

$ cat > virtualservice-bookinfo-with-uri-path.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-bookinfo
  namespace: bookinfo
spec:
  gateways:
  - productpage-gateway
  hosts:  # 列出VirtualService的hosts,可以是IP、DNS名称、FQDN或*
  - book.istio.com
  http: # 指定符合规则的流量到那些Destination,支持HTTP/1.1、HTTP2,及gRPC等协议
  - name: productpage-route
    match: # 指定具体的匹配规则
    - uri:
        prefix: /productpage
    - uri:
        prefix: /static
    route:
    - destination: # 满足条件会把流量打入具体的Destination
        host: productpage
  - name: reviews-route
    match:
    - uri:
        prefix: /reviews
    route:
    - destination:
        host: reviews
  - name: ratings-route
    match:
    - uri:
        prefix: /ratings
    route:
    - destination:
        host: ratings
  - route:
    - destination:
        host: productpage
        port:
          number: 9080
EOF

访问:

代码语言:javascript
复制
$ curl http://book.istio.com/ratings/1        
{"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}
$ curl http://book.istio.com/reviews/1
{"id": "1","podname": "reviews-v3-6dc9897554-8g9v2","clustername": "null","reviews": [{  "reviewer": "Reviewer1",  "text": "An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!", "rating": {"stars": 5, "color": "red"}},{  "reviewer": "Reviewer2",  "text": "Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare.", "rating": {"stars": 4, "color": "red"}}]}

实际的访问对应为:

book.istio.com/productpage -> productpage:8090/productpage book.istio.com/ratings -> ratings:9080/ratings book.istio.com/reviews -> reviews:9080/reviews

我们可以发现virtualservice的配置中有并未指定service的port端口,转发同样可以生效?

注意,若service中只有一个端口,则不用显式指定端口号,会自动转发到该端口中

路径重写

如果想实现rewrite的功能,隐藏真实url路径名称,很简单:

book.istio.com/rate -> ratings:8090/ratings

代码语言:javascript
复制
...
  - name: ratings-route
    match:
    - uri:
        prefix: /rate
    rewrite:   # 如果match中存在多个uri是不能使用reweite的
      uri: "/ratings"
    route:
    - destination:
        host: ratings
...


# 验证
$ curl http://book.istio.com/rate/1                             
{"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}

DestinationRule 转发策略

默认会使用轮询策略,此外也支持如下负载均衡模型,可以在 DestinationRule 中使用这些模型,将请求分发到特定的服务或服务子集。

Name

Description

UNSPECIFIED

No load balancing algorithm has been specified by the user. Istio will select an appropriate default.

RANDOM

The random load balancer selects a random healthy host. The random load balancer generally performs better than round robin if no health checking policy is configured.

PASSTHROUGH

This option will forward the connection to the original IP address requested by the caller without doing any form of load balancing. This option must be used with care. It is meant for advanced use cases. Refer to Original Destination load balancer in Envoy for further details.

ROUND_ROBIN

A basic round robin load balancing policy. This is generally unsafe for many scenarios (e.g. when enpoint weighting is used) as it can overburden endpoints. In general, prefer to use LEAST_REQUEST as a drop-in replacement for ROUND_ROBIN.

LEAST_REQUEST

The least request load balancer spreads load across endpoints, favoring endpoints with the least outstanding requests. This is generally safer and outperforms ROUND_ROBIN in nearly all cases. Prefer to use LEAST_REQUEST as a drop-in replacement for ROUND_ROBIN.

LEAST_CONN

Deprecated. Use LEAST_REQUEST instead.

代码语言:javascript
复制
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-destination-rule
spec:
  host: my-svc
  trafficPolicy:     #默认的负载均衡策略模型为随机
    loadBalancer:
      simple: RANDOM # 随机的策略
  subsets:
  - name: v1  #subset1,将流量转发到具有标签 version:v1 的 deployment 对应的服务上
    labels:
      version: v1
  - name: v2  #subset2,将流量转发到具有标签 version:v2 的 deployment 对应的服务上,指定负载均衡为轮询
    labels:
      version: v2
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN # 轮询策略
  - name: v3   #subset3,将流量转发到具有标签 version:v3 的 deployment 对应的服务上
    labels:
      version: v3

https://preliminary.istio.io/latest/zh/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-SimpleLB

使用https

方式一:把证书绑定在外部的nginx中, nginx 443端口监听外网域名并转发请求到Istio Ingress网关IP+http端口 ,如果使用公有云lb的话(如slb,clb),可以在lb层绑定证书

方式二:在istio侧使用证书

https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/

根据header头路由策略

该项目默认登录时会将用户名写入head的请求头,这个一般在代码中实现,我们可以根据这个特性,利用istop获取请求的head头信息。

需求:v2为正式版本,v3为测试版本,内测用户wangxiansen登录时访问v3界面,其他用户或者未登录访问v2界面。

代码语言:javascript
复制
$ cat > virtual-service-reviews-header.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  namespace: bookinfo
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: wangxiansen
    route:
    - destination:
        host: reviews
        subset: v3
  - route:
    - destination:
        host: reviews
        subset: v2
EOF

$ kubectl apply -f virtual-service-reviews-header.yaml

# https://github.com/nocalhost/bookinfo-productpage/blob/main/productpage.py
# 刷新观察http://book.istio.com.com/productpage

更多支持的匹配类型可以在此处查看。

https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPMatchRequest

故障注入

故障注入与超时机制

在一个微服务架构的系统中,为了让系统达到较高的健壮性要求,通常需要对系统做定向错误测试。比如电商中的订单系统、支付系统等若出现故障那将是非常严重的生产事故,因此必须在系统设计前期就需要考虑多样性的异常故障并对每一种异常设计完善的恢复策略或优雅的回退策略,尽全力规避类似事故的发生,使得当系统发生故障时依然可以正常运作。而在这个过程中,服务故障模拟一直以来是一个非常繁杂的工作。

istio提供了无侵入式的故障注入机制,让开发测试人员在不用调整服务程序的前提下,通过配置即可完成对服务的异常模拟。目前,包含两类:

  • abort:非必配项,配置一个 Abort 类型的对象。用来注入请求异常类故障。简单的说,就是用来模拟上游服务对请求返回指定异常码时,当前的服务是否具备处理能力。
  • delay:非必配项,配置一个 Delay 类型的对象。用来注入延时类故障。通俗一点讲,就是人为模拟上游服务的响应时间,测试在高延迟的情况下,当前的服务是否具备容错容灾的能力。

延迟与超时

目前针对wangxiansen登录用户,访问服务的示意为:

代码语言:javascript
复制
productpage --> reviews v2 --> ratings
               \
                -> details

可以通过如下方式,为ratings服务注入2秒的延迟:

代码语言:javascript
复制
$ cat > virtualservice-ratings-2s-delay.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
  namespace: bookinfo
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percentage:
          value: 100
        fixedDelay: 2s
    match:
    - headers:
        end-user:
          exact: wangxiansen
    route:
    - destination:
        host: ratings
  - route:
    - destination:
        host: ratings
EOF

$ kubectl apply -f virtualservice-ratings-2s-delay.yaml
# 再次访问http://book.istio.com/productpage,用wangxiansen用户登录可以明显感觉2s的延迟

可以查看对应的envoy的配置:

代码语言:javascript
复制
$ istioctl pc r ratings-v1-5967f59c58-9lmc5.bookinfo --name 9080 -ojson

此时的调用为:

代码语言:javascript
复制
productpage --> reviews v2 -(延迟2秒)-> ratings
               \
                -> details

此时,为reviews服务添加请求超时时间:

代码语言:javascript
复制
$ kubectl -n bookinfo edit vs reviews
...
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: wangxiansen
    route:
    - destination:
        host: reviews
        subset: v3
  - route:
    - destination:
        host: reviews
        subset: v2
    timeout: 0.5s
...

此使的调用关系为:

代码语言:javascript
复制
productpage -(0.5秒超时)-> reviews v2 -(延迟2秒)-> ratings
               \
                -> details

此时,如果使用wangxiansen用户,则会出现只延迟,不会失败的情况。

删除延迟:

代码语言:javascript
复制
$ kubectl -n bookinfo delete vs ratings

状态码

代码语言:javascript
复制
$ cat > virtualservice-details-aborted.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: details
  namespace: bookinfo
spec:
  hosts:
  - details
  http:
  - fault:
      abort:
        percentage:
          value: 50
        httpStatus: 500
    route:
    - destination:
        host: details
EOF
$ kubectl apply -f virtualservice-details-aborted.yaml

# 再次刷新查看details的状态,查看productpage的日志
$ kubectl -n bookinfo logs -f $(kubectl -n bookinfo get po -l app=productpage -ojsonpath='{.items[0].metadata.name}') -c istio-proxy
[2023-03-01T04:40:17.274Z] "GET /details/0 HTTP/1.1" 500 FI fault_filter_abort - "-" 0 18 0 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36" "3791d5f0-9b41-9cc6-9ade-fe351ae6107e" "details:9080" "-" outbound|9080||details.bookinfo.svc.cluster.local - 192.168.137.113:9080 172.7.100.4:59160 - -

流量镜像

介绍

很多情况下,当我们对服务做了重构,或者我们对项目做了重大优化时,怎么样保证服务是健壮的呢?在传统的服务里,我们只能通过大量的测试,模拟在各种情况下服务的响应情况。虽然也有手工测试、自动化测试、压力测试等一系列手段去检测它,但是测试本身就是一个样本化的行为,即使测试人员再完善它的测试样例,无法全面的表现出线上服务的一个真实流量形态 。

流量镜像的设计,让这类问题得到了最大限度的解决。流量镜像讲究的不再是使用少量样本去评估一个服务的健壮性,而是在不影响线上坏境的前提下将线上流量持续的镜像到我们的预发布坏境中去,让重构后的服务在上线之前就结结实实地接受一波真实流量的冲击与考验,让所有的风险全部暴露在上线前夕,通过不断的暴露问题,解决问题让服务在上线前夕就拥有跟线上服务一样的健壮性。由于测试坏境使用的是真实流量,所以不管从流量的多样性,真实性,还是复杂性上都将能够得以展现,同时预发布服务也将表现出其最真实的处理能力和对异常的处理能力。

实践

  • httpbin V1
  • httpbin V2
  • Service
  • DestinationRule
  • Virtualservice
代码语言:javascript
复制
# 准备httpbin v1
$ cat > httpbin-v1.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-v1
  namespace: bookinfo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
EOF

$ istioctl kube-inject -f httpbin-v1.yaml | kubectl create -f -
$ curl $(kubectl -n bookinfo get po  -l version=v1,app=httpbin -ojsonpath='{.items[0].status.podIP}')/headers
{
  "headers": {
    "Accept": "*/*", 
    "Host": "172.7.100.3", 
    "User-Agent": "curl/7.29.0", 
    "X-B3-Sampled": "1", 
    "X-B3-Spanid": "e1ab3a80b34475ac", 
    "X-B3-Traceid": "41308935982594d1e1ab3a80b34475ac"
  }
}
代码语言:javascript
复制
# 准备httpbin v2
$ cat > httpbin-v2.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-v2
  namespace: bookinfo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v2
  template:
    metadata:
      labels:
        app: httpbin
        version: v2
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        command: ["gunicorn", "--access-logfile", "-", "-b", "0.0.0.0:80", "httpbin:app"]
EOF

$ istioctl kube-inject -f httpbin-v2.yaml | kubectl create -f -
代码语言:javascript
复制
# Service文件
$ cat > httpbin-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: bookinfo
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
EOF

$ kubectl apply -f httpbin-svc.yaml
代码语言:javascript
复制
$ cat > httpbin-destinationRule.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
  namespace: bookinfo
spec:
  host: httpbin
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
EOF

$ kubectl apply -f httpbin-destinationRule.yaml
代码语言:javascript
复制
# 使用www.bookinfo.com/httpbin访问,因此直接修改bookinfo这个virtualservice即可
$ kubectl -n bookinfo get vs
NAME                   GATEWAYS                HOSTS               
bookinfo               [bookinfo-gateway]      [bookinfo.com]       
gateway-front-tomcat   [productpage-gateway]   [bookinfo.luffy.com]
reviews                                        [reviews]     
$ kubectl -n bookinfo edit vs bookinfo
#添加httpbin的规则
...
  - match:
    - uri:
        prefix: /httpbin
    name: httpbin-route
    rewrite:
      uri: /
    route:
    - destination:
        host: httpbin
        subset: v1
...
# 访问http://www.bookinfo.com/httpbin/headers,查看日志

此时发起请求,查看httpbin-v1的日志有刷,v2没反应,因为上面vs规则只匹配了v1,现在我们希望在访问v1的同时,流量也转发v2一份

流量镜像配置
代码语言:javascript
复制
# 为httpbin-v1添加mirror设置,mirror点为httpbin-v2
$ kubectl -n bookinfo edit vs bookinfo
...
  - match:
    - uri:
        prefix: /httpbin
    name: httpbin-route
    rewrite:
      uri: /
    route:
    - destination:
        host: httpbin
        subset: v1
    mirror:
      host: httpbin
      subset: v2
    mirror_percent: 100
...

此时访问页面即v1服务,v2后台日期同步刷新,说明接收到流量镜像。

重试与熔断

重试

在网络环境不稳定的情况下,会出现暂时的网络不可达现象,这时需要重试机制,通过多次尝试来获取正确的返回信息。 istio 可以通过简单的配置来实现重试功能,让开发人员无需关注重试部分的代码实现,专心实现业务代码。

准备实践

浏览器访问http://www.bookinfo.com/httpbin/status/502

代码语言:javascript
复制
# 此时查看httpbin-v1的日志,显示一条状态码为502的日志
$ kubectl -n bookinfo logs -f httpbin-v1-5967569c54-sp874 -c istio-proxy
[2023-03-01T05:16:41.929Z] "GET /httpbin/status/502 HTTP/1.1" 502 - via_upstream - "-" 0 0 1 1 "10.1.1.1,172.7.100.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36" "fa5bee29-d86b-9022-87b5-d635dfd6c005" "book.istio.com" "172.7.100.7:80" inbound|80|| 127.0.0.6:40871 172.7.100.7:80 172.7.100.1:0 outbound_.8000_.v1_.httpbin.bookinfo.svc.cluster.local default

我们为httpbin服务设置重试机制,这里设置如果服务在 2 秒内没有返回正确的返回值,就进行重试,重试的条件为返回码为5xx,重试 3 次。

代码语言:javascript
复制
$ kubectl -n bookinfo edit vs bookinfo
...
  - match:
    - uri:
        prefix: /httpbin
    mirror:
      host: httpbin
      subset: v2
    mirror_percent: 100
    name: httpbin-route
    retries:
      attempts: 3
      perTryTimeout: 2s
      retryOn: 5xx
    rewrite:
      uri: /
    route:
    - destination:
        host: httpbin
        subset: v1
...

# 再次查看httpbin-v1的日志,显示四条状态码为502的日志

熔断

熔断(Circuit Breaker),原是指当电流超过规定值时断开电路,进行短路保护或严重过载保护的机制 。对于微服务系统而言,熔断尤为重要,它可以使系统在遭遇某些模块故障时,通过服务降级等方式来提高系统核心功能的可用性,得以应对来自故障、潜在峰值或其他未知网络因素的影响。

准备环境

Istio 是通过 Envoy Proxy 来实现熔断机制的,Envoy 强制在网络层面配置熔断策略,这样就不必为每个应用程序单独配置或重新编程。下面就通过一个示例来演示如何为 Istio 网格中的服务配置熔断的连接数、请求数和异常检测。istio的熔断本质是一种限流

创建测试客户端

我们已经为 httpbin 服务设置了熔断策略,接下来创建一个 Java 客户端,用来向后端服务发送请求,观察是否会触发熔断策略。这个客户端可以控制连接数量、并发数、待处理请求队列,使用这一客户端,能够有效的触发前面在目标规则中设置的熔断策略。该客户端的

代码语言:javascript
复制
deployment yaml 内容如下:
 
# cat > httpbin-client-deploy.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-client-v1
  namespace: bookinfo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin-client-v1
      version: v1
  template:
    metadata:
      labels:
        app: httpbin-client-v1
        version: v1
    spec:
      containers:
      - image: ceposta/http-envoy-client-standalone:latest
        imagePullPolicy: IfNotPresent
        name: httpbin-client
        command: ["/bin/sleep","infinity"]
EOF

这里我们会把给客户端也进行 Sidecar 的注入,以此保证 Istio 对网络交互的控制:

代码语言:javascript
复制
$ kubectl apply -f <(istioctl kube-inject -f httpbin-client-deploy.yaml)
验证

先尝试通过单线程(NUM_THREADS=1)创建一个连接,并进行 5 次调用(默认值:NUM_CALLS_PER_CLIENT=5):

代码语言:javascript
复制
$ CLIENT_POD=$(kubectl get pod -n bookinfo | grep httpbin-client | awk '{ print $1 }')
$ kubectl -n bookinfo exec -it $CLIENT_POD -c httpbin-client -- sh -c 'export URL_UNDER_TEST=http://httpbin:8000/get export NUM_THREADS=1 && java -jar http-client.jar'

下面尝试把线程数提高到 2:

代码语言:javascript
复制
$ kubectl -n bookinfo exec -it $CLIENT_POD -c httpbin-client -- sh -c 'export URL_UNDER_TEST=http://httpbin:8000/get export NUM_THREADS=2 && java -jar http-client.jar'

创建DestinationRule, 针对 httpbin 服务设置熔断策略:

代码语言:javascript
复制
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
  namespace: bookinfo
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
EOF
  • maxConnections : 限制对后端服务发起的 HTTP/1.1 连接数,如果超过了这个限制,就会开启熔断。
  • maxPendingRequests : 限制待处理请求列表的长度, 如果超过了这个限制,就会开启熔断。
  • maxRequestsPerConnection : 在任何给定时间内限制对后端服务发起的 HTTP/2 请求数,如果超过了这个限制,就会开启熔断。

可以查看设置的熔断策略在envoy的配置片段:

代码语言:javascript
复制
$ istioctl pc cluster httpbin-client-v1-56b86fb85c-vg5pp.bookinfo --fqdn httpbin.bookinfo.svc.cluster.local -ojson
...
        "connectTimeout": "10s",
        "maxRequestsPerConnection": 1,
        "circuitBreakers": {
            "thresholds": [
                {
                    "maxConnections": 1,
                    "maxPendingRequests": 1,
                    "maxRequests": 4294967295,
                    "maxRetries": 4294967295
                }
            ]
        },
...

istio的熔断策略本质上是一种代理层面的补救措施,不会侵入代码层,若要想真正实现异常规避,最好的方式还是通过代码实现重试或者异常处理比较有效

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实例架构
    • 创建实例
      • 注入sidecar容器
        • 如何注入sidecar容器
        • 注入bookinfo
    • 服务流量治理
      • 配置访问productpage
        • 权重路由
          • 访问路径路由
            • 路径重写
              • DestinationRule 转发策略
                • 使用https
                  • 根据header头路由策略
                    • 故障注入
                      • 故障注入与超时机制
                      • 延迟与超时
                      • 状态码
                    • 流量镜像
                      • 介绍
                      • 实践
                    • 重试与熔断
                      • 重试
                      • 熔断
                  相关产品与服务
                  服务网格
                  服务网格(Tencent Cloud Mesh, TCM),一致、可靠、透明的云原生应用通信网络管控基础平台。全面兼容 Istio,集成腾讯云基础设施,提供全托管服务化的支撑能力保障网格生命周期管理。IaaS 组网与监控组件开箱即用,跨集群、异构应用一致发现管理加速云原生迁移。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档