逃脱只会部署集群系列 —— Istio实现微服务流量治理bookinfo案例

目录

一、实例介绍

1、创建bookinfo实例:

2、实例架构 

3、访问

二、istio微服务流量接管

1、ingress-gateway访问productpage

2、权重路由

3、访问路径路由

4、路径重写

5、匹配优先级

6、DestinationRule 转发策略

7、根据header头配置路由策略

8、流量镜像

9、熔断

10、故障注入与超时机制

2、状态码

11、Prometheus监控指标展示

         1、安装集成组件

2、可视化界面访问


一、实例介绍

1、创建bookinfo实例:

$ kubectl create namespace bookinfo
$ kubectl -n bookinfo create -f samples/bookinfo/platform/kube/bookinfo.yaml 
$ kubectl -n bookinfo get po 
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

2、实例架构 

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

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

  • productpage. 这个微服务会调用 detailsreviews 两个微服务,用来生成页面。

  • details. 这个微服务中包含了书籍的信息。

  • reviews. 这个微服务中包含了书籍相关的评论。它还会调用 ratings 微服务。

  • ratings. 这个微服务中包含了由书籍评价组成的评级信息。

reviews 微服务有 3 个版本:

  • v1 版本不会调用 ratings 服务。

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

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

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

3、访问

使用ingress访问productpage服务:

ingress-productpage.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: productpage
  namespace: bookinfo
spec:
  rules:
  - host: productpage.bookinfo.com
    http:
      paths:
      - backend:
          serviceName: productpage
          servicePort: 9080
        path: /
status:
  loadBalancer: {}

二、istio微服务流量接管

1、ingress-gateway访问productpage

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

注入sidecar容器

如何注入sidecar容器

使用istioctl kube-inject

$ kubectl -n bookinfo apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml)

为命名空间打label

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

注入bookinfo

$ kubectl -n bookinfo apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml) 

流量路由

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

ingress-gateway访问productpage

productpage-gateway.yaml

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:
    - productpage.bookinfo.com
productpage-virtualservice.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: gateway-front-tomcat
  namespace: bookinfo
spec:
  gateways:
  - productpage-gateway
  hosts:
  - productpage.bookinfo.com
  http:
  - route:
    - destination:
        host: productpage
        port:
          number: 9080

配置nginx,使用域名80端口访问。

upstream bookinfo-productpage {
  server 192.168.0.121:32437;
}
server {
    listen       80;
    listen  [::]:80;
    server_name  productpage.bookinfo.com;
​
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_pass http://bookinfo-productpage;
    }
}



$ nginx -s reload

此时,win本地hosts配置nginx域名解析可以正常访问,说明流量已经成功进入服务网格

2、权重路由

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

# 设置一条路由规则,要求访问reviews服务的流量全部转到v3的后端
$ cat virtual-service-reviews-v3.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  namespace: bookinfo
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v3
# 定义流量访问的目的地,v1对应review服务里面label为version=v1的pod
$ cat destination-rule-reviews.yaml
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
[root@k8s-master bookinfo]# kubectl get po -n bookinfo  --show-labels | grep  review
reviews-v1-d49966d6b-vn5tx        2/2     Running   2          15h   app=reviews,istio.io/rev=,pod-template-hash=d49966d6b,security.istio.io/tlsMode=istio,version=v1
reviews-v2-644f5c9ddb-pjmnh       2/2     Running   2          15h   app=reviews,istio.io/rev=,pod-template-hash=644f5c9ddb,security.istio.io/tlsMode=istio,version=v2
reviews-v3-d56b49bc8-brp5k        2/2     Running   2          15h   app=reviews,istio.io/rev=,pod-template-hash=d56b49bc8,security.istio.io/tlsMode=istio,version=v3
$ kubectl apply -f virtual-service-reviews-v3.yaml
​
# 访问productpage测试,此时发现页面一直停在v3版本不会变化,需求实现。

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

90% -> reivews-v1
10% -> reviews-v2
0%  -> reviews-v3
# 同样的方式,刚才已经定义过v1、v2、v3的去向了,现在只需要增加v1和v2路由规则即可
$ cat virtual-service-reviews-90-10.yaml
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

$ kubectl apply -f virtual-service-reviews-90-10.yaml

此时,再次访问,v3就不会出现了

3、访问路径路由

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

实现效果如下: 

# 定义允许外部流量进入网格,直接编辑已有gateway
 - hosts:
    - productpage.bookinfo.com
    - bookinfo.com

# 添加路由配置,通过网关productpage-gateway访问bookinfo.com的域名,匹配以下规则,此时只到服务发现层面,如果需要针对具体服务配置路由分配策略需要添加subset。 

$ kubectl -n bookinfo edit gw productpage-gateway
​
$ cat bookinfo-routing-with-uri-path.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
  namespace: bookinfo
spec:
  gateways:
  - productpage-gateway
  hosts:
    - bookinfo.com
  http:
  - name: productpage-route
    match:
    - uri:
        prefix: /productpage
    route:
    - 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

nginx中新增bookinfo.com配置:

upstream bookinfo {
  server 192.168.0.121:32437;
}
server {
    listen       80;
    listen  [::]:80;
    server_name  bookinfo.com;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_pass http://bookinfo;
    }
}

本地hosts添加bookinfo.com域名解析 

访问:

http://bookinfo.com/productpage

http://bookinfo.com/ratings/1

http://bookinfo.com/reviews/1

实际的访问对应为:

bookinfo.com/productpage  -> productpage:8090/productpage
bookinfo.com/ratings  ->  ratings:9080/ratings
bookinfo.com/reviews  ->  reviews:9080/reviews

实际访问productpage页面,由于需要引用css、js等静态资源,因此需要补充对/static路径的转发:

...
  http:
  - name: productpage-route
    match:
    - uri:
        prefix: /productpage
    - uri:
        prefix: /static
    route:
    - destination:
        host: productpage
...

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

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

4、路径重写

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

bookinfo.com/rate  -> ratings:8090/ratings
...
  - name: ratings-route
    match:
    - uri:
        prefix: /haha
    rewrite:
      uri: "/ratings"
    route:
    - destination:
        host: ratings
...

5、匹配优先级

需求:我们可以根据URL访问不同的后端,但是我们不可能考虑到所有的url后缀,此时点击登录发现/login的匹配也没有添加,后续有可能有别的,因此可以在规则列表最后添加一个规则,作为默认的转发规则。

$ kubectl -n bookinfo edit vs bookinfo
...
  - name: default-route
    route:
    - destination:
        host: productpage

6、DestinationRule 转发策略

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

  • Random:将请求转发到一个随机的实例上

  • Weighted:按照指定的百分比将请求转发到实例上

  • Least requests:将请求转发到具有最少请求数目的实例上

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

7、根据header头配置路由策略

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

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

$ cat virtual-service-reviews-header.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  namespace: bookinfo
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: testuser
    route:
    - destination:
        host: reviews
        subset: v3
  - route:
    - destination:
        host: reviews
        subset: v2
$ kubectl apply -f virtual-service-reviews-header.yaml
​
# 刷新观察http://bookinfo.com/productpage

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

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

8、流量镜像

背景:

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

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

实践

# 准备httpbin v1
$ cat httpbin-v1.yaml
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"]
        
# 准备httpbin v2
$ cat httpbin-v2.yaml
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"]
        
$ istioctl kube-inject -f httpbin-v2.yaml | kubectl create -f -     
$ 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": "*/*",
    "Content-Length": "0",
    "Host": "10.244.0.88",
    "User-Agent": "curl/7.29.0",
    "X-B3-Sampled": "1",
    "X-B3-Spanid": "777c7af4458c5b81",
    "X-B3-Traceid": "6b98ea81618deb4f777c7af4458c5b81"
  }
}

# Service文件
$ cat httpbin-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: bookinfo
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin

$ kubectl apply -f httpbin-svc.yaml


# 创建gateway和virtualservice,由于都是使用http请求,因此,直接
# 使用bookinfo.com/httpbin访问,因此直接修改bookinfo这个virtualservice即可
$ kubectl -n bookinfo get vs
NAME                   GATEWAYS                HOSTS               
bookinfo               [bookinfo-gateway]      [bookinfo.com]       
gateway-front-tomcat   [productpage-gateway]   [productpage.bookinfo.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
...

$ cat httpbin-destinationRule.yaml
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
$ kubectl apply -f httpbin-destinationRule.yaml

# 访问http://bookinfo.com/httpbin/headers,查看日志
# 此时发起请求,查看httpbin-v1的日志有刷,v2没反应,因为上面vs规则只匹配了v1,现在我们希望在访问v1的同时,流量也转发v2一份
[root@k8s-master bookinfo]# kubectl -n bookinfo logs -f httpbin-v1-66c7d456fb-hhqjv -c httpbin
[2022-01-17 09:04:00 +0000] [1] [INFO] Starting gunicorn 19.9.0
[2022-01-17 09:04:00 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1)
[2022-01-17 09:04:00 +0000] [1] [INFO] Using worker: sync
[2022-01-17 09:04:00 +0000] [9] [INFO] Booting worker with pid: 9
127.0.0.6 - - [17/Jan/2022:09:05:48 +0000] "GET /headers HTTP/1.1" 200 257 "-" "curl/7.29.0"
127.0.0.1 - - [17/Jan/2022:09:11:57 +0000] "GET //headers HTTP/1.1" 200 1133 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36"
127.0.0.1 - - [17/Jan/2022:09:13:07 +0000] "GET //headers HTTP/1.1" 200 1168 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36"


[root@k8s-master ~]# k logs -f httpbin-v2-69b898fddc-zv2vj -c httpbin
kubectl -n bookinfo logs -f httpbin-v2-69b898fddc-zv2vj -c httpbin
[2022-01-17 09:04:15 +0000] [1] [INFO] Starting gunicorn 19.9.0
[2022-01-17 09:04:15 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1)
[2022-01-17 09:04:15 +0000] [1] [INFO] Using worker: sync
[2022-01-17 09:04:15 +0000] [9] [INFO] Booting worker with pid: 9

# 为httpbin-v1添加mirror设置,mirror点为httpbin-v2,mirror_percent表示转发100%的流量
$ 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后台日期同步刷新,说明接收到流量镜像。 

9、熔断

介绍

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

准备环境

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

  • 创建httpbin服务

  • 创建测试客户端

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

    deployment yaml 内容如下:
    
    # httpbin-client-deploy.yaml
    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"]

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

    $ kubectl apply -f <(istioctl kube-inject -f httpbin-client-deploy.yaml)

验证

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

$ 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:

$ 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 服务设置熔断策略:

$ 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的配置片段:

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

10、故障注入与超时机制

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

        为什么要有故障注入,为了提高程序兼容性,测试存在大量404、502时,系统运行是否正常。不能因为有部分失败请求就系统挂了。

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

  • abort:非必配项,中断故障,配置一个 Abort 类型的对象。用来注入请求异常类故障。简单的说,就是用来模拟上游服务对请求返回指定异常码时,当前的服务是否具备处理能力。

  • delay:非必配项,延迟故障,配置一个 Delay 类型的对象。用来注入延时类故障。通俗一点讲,就是人为模拟上游服务的响应时间,测试在高延迟的情况下,当前的服务是否具备容错容灾的能力。

1、延迟与超时

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

productpage --> reviews v2 --> ratings
               \
                -> details

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

# 请求ratings这个hosts时,注入2s的延迟
$ cat virtualservice-ratings-2s-delay.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
  namespace: bookinfo
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percentage:
          value: 100
        fixedDelay: 2s
    route:
    - destination:
        host: ratings
$ kubectl apply -f virtualservice-ratings-2s-delay.yaml
# 再次访问http://bookinfo.com/productpage,可以明显感觉2s的延迟,network可以看到

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

$ istioctl pc r ratings-v1-556cfbd589-89ml4.bookinfo --name 9080 -ojson

此时的调用为:

productpage --> reviews v2 -(延迟2秒)-> ratings
               \
                -> details

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

$ kubectl -n bookinfo edit vs reviews
...
  http:
  - match:
    - headers:
        end-user:
          exact: testuser
    route:
    - destination:
        host: reviews
        subset: v2
    timeout: 1s
  - route:
    - destination:
        host: reviews
        subset: v3
...
此使的调用关系为:
productpage -(0.5秒超时)-> reviews v2 -(延迟2秒)-> ratings
               \
                -> details

此时,我们相当于设置review请求rating服务时注入2s的延迟,然后testuser用户注入1s的超时,如果使用testuser用户,因为超时会报错,如果使用非testuser用户,则会出现只延迟,不会失败的情况。

删除延迟:

$ kubectl -n bookinfo delete vs ratings

2、状态码

# 注入请求details服务时有50%返回500错误码的几率
$ cat virtualservice-details-aborted.yaml
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
$ 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
[2020-11-09T09:00:16.020Z] "GET /details/0 HTTP/1.1" 500 FI "-" "-" 0 18 0 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36" "f0387bb6-a445-922c-89ab-689dfbf548f8" "details:9080" "-" - - 10.111.67.169:9080 10.244.0.52:56552 - -

11、Prometheus监控指标展示

1、安装集成组件

https://istio.io/latest/docs/ops/integrations

Grafana(图标展示)

$ kubectl apply -f samples/addons/grafana.yaml
Jaeger(分布式追踪)

$ kubectl apply -f samples/addons/jaeger.yaml
Kiali(针对istio可视化组件)

# 完善扩展组件地址:
grafana url: "http://grafana.istio.com"
tracing url: "http://jaeger.istio.com"
$ kubectl apply -f samples/addons/kiali.yaml
Prometheus(监控)

$ kubectl apply -f samples/addons/prometheus.yaml

创建kiali报错:
unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1"

解决:
需要创建“CustomResourceDefinition”
cd istio-1.8.2/samples/addons/;vim kiali-crd.yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: monitoringdashboards.monitoring.kiali.io
spec:
  group: monitoring.kiali.io
  names:
    kind: MonitoringDashboard
    listKind: MonitoringDashboardList
    plural: monitoringdashboards
    singular: monitoringdashboard
  scope: Namespaced
  versions:
  - name: v1alpha1
    served: true
    storage: true

kubectl apply -f kiali-crd.yaml

参照:https://blog.csdn.net/qq_41674452/article/details/113345163

2、可视化界面访问

$ cat prometheus-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: prometheus
  namespace: istio-system
spec:
  rules:
  - host: prometheus.istio.com
    http:
      paths:
      - backend:
          serviceName: prometheus
          servicePort: 9090
        path: /
status:
  loadBalancer: {}
$ kubectl apply -f prometheus-ingress.yaml
[root@k8s-master warning]# kubectl get po -n istio-system -owide
NAME                                    READY   STATUS    RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES
grafana-75b5cddb4d-m6rph                1/1     Running   0          25m     10.244.1.216   k8s-node2   <none>           <none>
istio-egressgateway-66f8f6d69c-6mdkj    1/1     Running   3          46h     10.244.1.210   k8s-node2   <none>           <none>
istio-ingressgateway-758d8b79bd-xvxt8   1/1     Running   3          46h     10.244.1.212   k8s-node2   <none>           <none>
istiod-7556f7fddf-kjhpr                 1/1     Running   3          46h     10.244.1.209   k8s-node2   <none>           <none>
jaeger-5795c4cf99-w5lzg                 1/1     Running   0          25m     10.244.1.217   k8s-node2   <none>           <none>
kiali-6c49c7d566-n5hpr                  1/1     Running   0          8m44s   10.244.1.219   k8s-node2   <none>           <none>
prometheus-9d5676d95-67hvb              2/2     Running   0          25m     10.244.1.218   k8s-node2   <none>           <none>

配置nginx服务机器的hosts域名解析;查看默认添加的targets列表,默认已经集成好的:

其中最核心的是kubernetes-pods 的监控,服务网格内的每个服务都作为一个target被监控,而且服务流量指标直接由sidecar容器来提供指标。

$ kubectl -n bookinfo get po -owide
$ curl 10.244.0.53:15020/stats/prometheus

对于这些监控指标采集的数据,可以在grafana中查看到。

$ cat grafana-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: grafana
  namespace: istio-system
spec:
  rules:
  - host: grafana.istio.com
    http:
      paths:
      - backend:
          serviceName: grafana
          servicePort: 3000
        path: /
status:
  loadBalancer: {}
​
​
$ for i in $(seq 1 10000); do curl -s -o /dev/null "http://bookinfo.com/productpage"; done

访问界面后,可以查看到Istio Mesh Dashboard等相关的dashboard,因为在grafana的资源文件中, 中以 ConfigMap 的形式挂载了 Istio各个组件的仪表盘 JSON 配置文件:

$ kubectl -n istio-system get cm istio-services-grafana-dashboards
NAME                                DATA   AGE
istio-services-grafana-dashboards   3      7d1h

jaeger

$ cat jaeger-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: jaeger
  namespace: istio-system
spec:
  rules:
  - host: jaeger.istio.com
    http:
      paths:
      - backend:
          serviceName: tracing
          servicePort: 80
        path: /
status:
  loadBalancer: {}
  
$ kubectl apply -f jaeger-ingress.yaml

kiali

kiali 是一个 可观测性分析服务

$ cat kiali-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kiali
  namespace: istio-system
spec:
  rules:
  - host: kiali.istio.com
    http:
      paths:
      - backend:
          serviceName: kiali
          servicePort: 20001
        path: /
status:
  loadBalancer: {}
$ kubectl apply -f kiali-ingress.yaml

集成了Prometheus、grafana、tracing、log、

猜你喜欢

转载自blog.csdn.net/weixin_39855998/article/details/122530564