入门Istio架构原理及实战

官网:https://istio.io/v1.11/zh/docs/concepts/what-is-istio/

istio架构

入门Istio架构原理及实战_第1张图片

实际上Istio 就是 Service Mesh 架构的一种实现,服务之间的通信(比如这里的 Service A 访问 Service B)会通过代理(默认是 Envoy)来进行。

而且中间的网络协议支持 HTTP/1.1,HTTP/2,gRPC 或者 TCP,可以说覆盖了主流的通信协议。代理这一层,称之为数据平面。

控制平面做了进一步的细分,分成了 Pilot、Citadel 和 Galley,它们的各自功能如下:

Pilot:为 Envoy 提供了服务发现,流量管理和智能路由(AB 测试、金丝雀发布等),以及错误处理(超时、重试、熔断)功能。

Citadel:为服务之间提供认证和证书管理,可以让服务自动升级成 TLS 协议。

Galley:Galley 是 Istio 的配置验证、提取、处理和分发组件。它负责将其余的 Istio 组件与从底层平台(例如 Kubernetes)获取用户配置的细节隔离开来。

数据平面会和控制平面通信,一方面可以获取需要的服务之间的信息,另一方面也可以汇报服务调用的 Metrics 数据。

为什么使用 Istio?

通过负载均衡、服务间的身份验证、监控等方法,Istio 可以轻松地创建一个已经部署了服务的网络,而服务的代码只需很少更改甚至无需更改。通过在整个环境中部署一个特殊的 sidecar 代理为服务添加 Istio 的支持,而代理会拦截微服务之间的所有网络通信,然后使用其控制平面的功能来配置和管理 Istio,这包括:

  • 为 HTTP、gRPC、WebSocket 和 TCP 流量自动负载均衡。
  • 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制。
  • 可插拔的策略层和配置 API,支持访问控制、速率限制和配额。
  • 集群内(包括集群的入口和出口)所有流量的自动化度量、日志记录和追踪。
  • 在具有强大的基于身份验证和授权的集群中实现安全的服务间通信。

Istio 为可扩展性而设计,可以满足不同的部署需求。

流量管理

Istio 简单的规则配置和流量路由允许您控制服务之间的流量和 API 调用过程。Istio 简化了服务级属性(如熔断器、超时和重试)的配置,并且让它轻而易举的执行重要的任务(如 A/B 测试、金丝雀发布和按流量百分比划分的分阶段发布)。
有了更好的对流量的可视性和开箱即用的故障恢复特性,您就可以在问题产生之前捕获它们,无论面对什么情况都可以使调用更可靠,网络更健壮。

Istio 版本支持状态

版本 目前支持 发行日期 停止维护 支持的 Kubernetes 版本 未测试,可能支持的 Kubernetes 版本
master 否,仅限开发 - - - -
1.15 2022 年 8 月 31 日 ~ 2023 年 3 月(预期) 1.22, 1.23, 1.24, 1.25 1.16, 1.17, 1.18, 1.19, 1.20, 1.21
1.14 2022 年 5 月 24 日 ~ 2023 年 1 月(预期) 1.21, 1.22, 1.23, 1.24 1.16, 1.17, 1.18, 1.19, 1.20
1.13 2022 年 2 月 11 日 ~ 2022 年 10 月(预期) 1.20, 1.21, 1.22, 1.23 1.16, 1.17, 1.18, 1.19
1.12 2021 年 11 月 18 日 2022 年 7 月 12 日 1.19, 1.20, 1.21, 1.22 1.16, 1.17, 1.18
1.11 2021 年 8 月 12 日 2022 年 3 月 25 日 1.18, 1.19, 1.20, 1.21, 1.22 1.16, 1.17
1.10 2021 年 5 月 18 日 2022 年 1 月 7 日 1.18, 1.19, 1.20, 1.21 1.16, 1.17, 1.22
1.9 2021 年 2 月 9 日 2021 年 10 月 8 日 1.17, 1.18, 1.19, 1.20 1.15, 1.16
1.8 2020 年 11 月 10 日 2021 年 5 月 12 日 1.16, 1.17, 1.18, 1.19 1.15
1.7 2020 年 8 月 21 日 2021 年 2 月 25 日 1.16, 1.17, 1.18 1.15
1.6 及更早 - - - -

1.下载

curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.11.7 TARGET_ARCH=x86_64 sh -


#转到 Istio 包目录。例如,如果包是 istio-1.11.7:
cd istio-1.11.7

#将 istioctl 客户端添加到路径
export PATH=$PWD/bin:$PATH


2.安装istio

istioctl install --set profile=demo -y

给命名空间添加标签,指示 Istio 在部署应用的时候,自动注入 Envoy 边车代理:

kubectl label namespace default istio-injection=enabled

#卸载istio

istioctl manifest generate --set profile=demo | kubectl delete -f -

3.部署示例应用

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

Bookinfo 应用分为四个单独的微服务:
productpage. 这个微服务会调用 details 和 reviews 两个微服务,用来生成页面。
details. 这个微服务中包含了书籍的信息。
reviews. 这个微服务中包含了书籍相关的评论。它还会调用 ratings 微服务。
ratings. 这个微服务中包含了由书籍评价组成的评级信息。

reviews 微服务有 3 个版本:
v1 版本不会调用 ratings 服务。
v2 版本会调用 ratings 服务,并使用 1 到 5 个黑色星形图标来显示评分信息。
v3 版本会调用 ratings 服务,并使用 1 到 5 个红色星形图标来显示评分信息。
下图展示了这个应用的端到端架构。
入门Istio架构原理及实战_第2张图片

部署 Bookinfo 示例应用:

bookinfo.yaml

##################################################################################################
# Details service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: details
  labels:
    app: details
    service: details
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-details
  labels:
    account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: details-v1
  labels:
    app: details
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: details
      version: v1
  template:
    metadata:
      labels:
        app: details
        version: v1
    spec:
      serviceAccountName: bookinfo-details
      containers:
      - name: details
        image: docker.io/istio/examples-bookinfo-details-v1:1.16.2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
        securityContext:
          runAsUser: 1000
---
##################################################################################################
# Ratings service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: ratings
  labels:
    app: ratings
    service: ratings
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: ratings
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-ratings
  labels:
    account: ratings
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ratings-v1
  labels:
    app: ratings
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ratings
      version: v1
  template:
    metadata:
      labels:
        app: ratings
        version: v1
    spec:
      serviceAccountName: bookinfo-ratings
      containers:
      - name: ratings
        image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
        securityContext:
          runAsUser: 1000
---
##################################################################################################
# Reviews service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: reviews
  labels:
    app: reviews
    service: reviews
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-reviews
  labels:
    account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v1
  labels:
    app: reviews
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v1
  template:
    metadata:
      labels:
        app: reviews
        version: v1
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v1:1.16.2
        imagePullPolicy: IfNotPresent
        env:
        - name: LOG_DIR
          value: "/tmp/logs"
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: wlp-output
          mountPath: /opt/ibm/wlp/output
        securityContext:
          runAsUser: 1000
      volumes:
      - name: wlp-output
        emptyDir: {}
      - name: tmp
        emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v2
  labels:
    app: reviews
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v2
  template:
    metadata:
      labels:
        app: reviews
        version: v2
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v2:1.16.2
        imagePullPolicy: IfNotPresent
        env:
        - name: LOG_DIR
          value: "/tmp/logs"
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: wlp-output
          mountPath: /opt/ibm/wlp/output
        securityContext:
          runAsUser: 1000
      volumes:
      - name: wlp-output
        emptyDir: {}
      - name: tmp
        emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v3
  labels:
    app: reviews
    version: v3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v3
  template:
    metadata:
      labels:
        app: reviews
        version: v3
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v3:1.16.2
        imagePullPolicy: IfNotPresent
        env:
        - name: LOG_DIR
          value: "/tmp/logs"
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: wlp-output
          mountPath: /opt/ibm/wlp/output
        securityContext:
          runAsUser: 1000
      volumes:
      - name: wlp-output
        emptyDir: {}
      - name: tmp
        emptyDir: {}
---
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: productpage
  labels:
    app: productpage
    service: productpage
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-productpage
  labels:
    account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: productpage-v1
  labels:
    app: productpage
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: productpage
      version: v1
  template:
    metadata:
      labels:
        app: productpage
        version: v1
    spec:
      serviceAccountName: bookinfo-productpage
      containers:
      - name: productpage
        image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        securityContext:
          runAsUser: 1000
      volumes:
      - name: tmp
        emptyDir: {}
---

部署bookinfo

kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

kubectl get po


#测试页面
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o ".*"


4.对外开放应用程序

此时,BookInfo 应用已经部署,但还不能被外界访问。 要开放访问,您需要创建 Istio 入站网关(Ingress Gateway), 它会在网格边缘把一个路径映射到路由。

  1. 把应用关联到 Istio 网关:

如果集群运行在一个不支持外部负载均衡器的环境中(例如:minikube),istio-ingressgateway 的 EXTERNAL-IP 将显示为 状态。请使用服务的 NodePort 或 端口转发来访问网关。

kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

kubectl get svc -n istio-system

#服务的 NodePort
kubectl -n istio-system edit svc istio-ingressgateway

kubectl get svc -n istio-system

确保配置文件没有问题:

istioctl analyze

确定入站 IP 和端口

按照下面说明:如果您的环境中没有外部负载均衡器,那就选择一个节点端口来代替。
设置入站的端口


export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')

#ceph1主机Ip
export INGRESS_HOST=ceph1

export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

echo "$GATEWAY_URL"

echo "http://$GATEWAY_URL/productpage"

验证外部访问

用浏览器查看 Bookinfo 应用的产品页面,验证 Bookinfo 已经实现了外部访问。

  1. 运行下面命令,获取 Bookinfo 应用的外部访问地址。
kubectl get svc istio-ingressgateway -n istio-system


curl ceph1:31479/productpage



for i in `seq 1 100`; do curl -s -o /dev/null http://ceph1:31479/productpage; done


把上面命令的输出地址复制粘贴到浏览器并访问,确认 Bookinfo 应用的产品页面是否可以打开

5.查看仪表板

Istio 和几个遥测应用做了集成。 遥测能帮您了解服务网格的结构、展示网络的拓扑结构、分析网格的健康状态。
使用下面说明部署 Kiali 仪表板、 以及 Prometheus、 Grafana、 还有 Jaeger。

  1. 安装 Kiali 和其他插件,等待部署完成。
kubectl apply -f samples/addons

kubectl rollout status deployment/kiali -n istio-system


2.修改Kiali外部访问NodePort

kubectl -n istio-system get svc

kubectl -n istio-system edit svc kiali

#type: NodePort


kubectl -n istio-system get svc |grep kiali

#访问 Kiali 仪表板  
http://ceph1:32514

在左侧的导航菜单,选择 Graph ,然后在 Namespace 下拉列表中,选择 default
要查看追踪数据,必须向服务发送请求。请求的数量取决于 Istio 的采样率。 采样率在安装 Istio 时设置,默认采样速率为 1%。在第一个跟踪可见之前,您需要发送至少 100 个请求。 使用以下命令向 productpage 服务发送 100 个请求:

测试url

for i in `seq 1 100`; do curl -s -o /dev/null http://ceph1:31479/productpage; done

Kiali设置
入门Istio架构原理及实战_第3张图片

6.测试istio

1、应用默认目标规则

给各个服务创建DestinationRule
在使用 Istio 控制 Bookinfo 版本路由之前,您需要在目标规则中定义好可用的版本,命名为 subsets 。

#设置
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

#查询
kubectl get destinationrules -o yaml

至此,Istio 完成了全部的接管,第一个示例部署完成。

2、请求路由

按照版本路由

目前reviews有三个版本,在浏览器中访问 Bookinfo 应用程序的 /productpage 并刷新几次。我们发现有时书评的输出包含星级评分,有时则不包含。 这是因为没有明确的默认服务版本路由。

现在我们要做就是让istio接管路由,比如将所有流量都路由到每个微服务的v1版本,Istio实现起来是非常简单的,只需要添加虚拟服务(VirtualService)即可。

3、示例:将所有流量都路由到各个微服务的v1版本

#virtual-service-all-v1.yaml是官方提供的示例文件

kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

其内容如下:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: productpage
spec:
  hosts:
  - productpage
  http:
  - route:
    - destination:
        host: productpage
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1  #在这里指定了所有的http请求都通过v1完成,而v1在默认的规则中有定义
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - route:
    - destination:
        host: ratings
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: details
spec:
  hosts:
  - details
  http:
  - route:
    - destination:
        host: details
        subset: v1
---

经过测试,发现reviews不再切换样式。

4、 按照不同用户身份路由

  接下来,您将更改路由配置,以便将来自特定用户的所有流量路由到特定服务版本。在这,来自名为 Jason 的用户的所有流量将被路由到服务 reviews:v2。
  请注意,Istio 对用户身份没有任何特殊的内置机制。事实上,productpage 服务在所有到 reviews 服务的 HTTP 请求中都增加了一个自定义的 end-user 请求头,从而达到了本例子的效果。

请记住,reviews:v2 是包含星级评分功能的版本。

  1. 运行以下命令以启用基于用户的路由:
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml

2.确认规则已创建

kubectl get virtualservice reviews -o yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
  ...
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1

3.在 Bookinfo 应用程序的 /productpage 上,以用户 jason 身份登录。
刷新浏览器。你看到了什么?星级评分显示在每个评论旁边。

4.以其他用户身份登录(选择您想要的任何名称)。
刷新浏览器。现在星星消失了。这是因为除了 Jason 之外,所有用户的流量都被路由到 reviews:v1。

您已成功配置 Istio 以根据用户身份路由流量。

5、 流量转移-灰度发布

还可以将reviews的部分流量转移到v3版本,基于此可以实现灰度发布、A/B测试等:

#将所有流量都路由到每个服务的v1版本
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

#将reviews服务 50%的流量转移到v3
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml

内容如下:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 50
    - destination:
        host: reviews
        subset: v3
      weight: 50

刷新浏览器中的 /productpage 页面,大约有 50% 的几率会看到页面中出带 红色 星级的评价内容。这是因为 v3 版本的 reviews 访问了带星级评级的 ratings 服务,但 v1 版本却没有。

如果认为 reviews:v3 微服务已经稳定,可以通过应用此 virtual service 规则将 100% 的流量路由到 reviews:v3:

#将reviews服务的全部流量都切换到v3版本

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-v3.yaml

这样,所有的请求都转向到了v3了。
如果需要删除所有服务的虚拟网络,可以执行:

kubectl delete -f samples/bookinfo/networking/virtual-service-all-v1.yaml

virtual-service-all-v1.yaml配置文件中配置了所有服务的路由信息,如果删除了则所有的路由信息都删了

6、超时

http 请求的超时可以用路由规则的 timeout 字段来指定。 默认情况下,超时是禁用的

这里我们来实验 reviews 服务的请求超时,将请求路由到 reviews 服务的 v2 版本,它会去调用 ratings 服务,我们首先在 ratings 服务上人为的引入2s的延迟(故障注入),再对 reviews 服务配置超时timeout
1、在/samples/bookinfo/networking 目录下创建配置文件

#创建配置文件
cat > samples/bookinfo/networking/virtual-service-reviews-v2-timeout.yaml <apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percent: 100
        fixedDelay: 2s
    route:
    - destination:
        host: ratings
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2
    #timeout: 0.5s
EOF

在ratings服务上注入2s的延迟,

2、应用该路由配置,就在当前目录下执行即可

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-v2-timeout.yaml

3、访问该网址,这时可以看到 Bookinfo 应用运行正常(显示了评级的星型符号),但是每次刷新页面,都会有 2 秒的延迟。

4、重新编辑该文件,放开对 reviews 服务的调用增加一个半秒的请求超时(去掉timeout的注释)

5、重新应用该配置,还是执行第2步的命令,然后通过如下命令查看配置是否更新

kubectl get virtualservice -o yaml

6、再次刷新网页
这时候应该看到 1 秒钟就会返回,而不是之前的 2 秒钟,但 reviews 是不可用的(页面没有reviews的数据)

即使超时配置为半秒,响应仍需要 1 秒,是因为 productpage 服务中存在硬编码重试,因此它在返回之前调用 reviews 服务超时两次(重试)。

7、重试

描述 HTTP 请求失败时要使用的重试策略。为 例如,以下规则将最大重试次数设置为 3 时 呼叫评级:V1 服务,每次重试超时 2 秒。

#创建配置文件
cat > samples/bookinfo/networking/ratings-route-v1-request-timeout.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings-route
spec:
  hosts:
  - ratings
  http:
  - route:
    - destination:
        host: ratings
        subset: v1
    retries:
      attempts: 3
      perTryTimeout: 2s
      retryOn: gateway-error,connect-failure,refused-stream
EOF


kubectl apply -f samples/bookinfo/networking/ratings-route-v1-request-timeout.yaml

8、熔断

熔断器是 Istio 为创建具有弹性的微服务应用提供的有用的机制。在熔断器中,设置一个对服务中的单个主机调用的限制,例如并发连接的数量或对该主机调用失败的次数。一旦限制被触发,熔断器就会“跳闸”并停止连接到该主机。

使用熔断模式可以快速失败而不必让客户端尝试连接到过载或有故障的主机。
部署httpbin

httpbin是一个开源项目,使用Python+Flask编写,利用它可以测试各种HTTP请求和响应。官网:http://httpbin.org/

kubectl apply -f samples/httpbin/httpbin.yaml

该配置文件的内容为:

##################################################################################################
# httpbin service
##################################################################################################
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80

8.1 配置熔断器
创建一个目标熔断规则(DestinationRule),在调用 httpbin 服务时应用熔断设置:

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  #http请求pending状态的最大请求数
        maxRequestsPerConnection: 1  #在一定时间内限制对后端服务发起的最大请求数
    outlierDetection:  #熔断设置
      consecutiveErrors: 1  #从连接池开始拒绝连接,已经连接失败的次数,当通过HTTP访问时,返回代码是502、503或504则视为错误。
      interval: 1s  #拒绝访问扫描的时间间隔,即在interval(1s)内连续发生1个consecutiveErrors错误,则触发服务熔断,格式是1h/1m/1s/1ms,但必须大于等于1ms。即分析是否需要剔除的频率,多久分析一次,默认10秒。
      baseEjectionTime: 3m  #最短拒绝访问时长。这个时间主机将保持拒绝访问,且如果决绝访问达到一定的次数。格式:1h/1m/1s/1ms,但必须大于等于1ms。实例被剔除后,至少多久不得返回负载均衡池,默认是30秒。
      maxEjectionPercent: 100  #服务在负载均衡池中被拒绝访问(被移除)的最大百分比,负载均衡池中最多有多大比例被剔除,默认是10%。
EOF

验证目标规则是否已正确创建:

kubectl get destinationrule httpbin -o yaml

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
  ...
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
      tcp:
        maxConnections: 1
    outlierDetection:
      baseEjectionTime: 180.000s
      consecutiveErrors: 1
      interval: 1.000s
      maxEjectionPercent: 100

客户端

创建客户端程序以发送流量到 httpbin 服务。这是一个名为 Fortio 的负载测试客户的,其可以控制连接数、并发数及发送 HTTP 请求的延迟。通过 Fortio 能够有效的触发前面 在 DestinationRule 中设置的熔断策略。

kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml

kubectl get po


中间稍等一会,让客户端部署成功!!!

登入客户端 Pod 并使用 Fortio 工具调用 httpbin 服务。-curl 参数表明发送一次调用:

$ FORTIO_POD=$(kubectl get pod | grep fortio | awk '{ print $1 }')
$ kubectl exec -it $FORTIO_POD  -c fortio -- /usr/bin/fortio load -curl  http://httpbin:8000/get
HTTP/1.1 200 OK
server: envoy
date: Tue, 16 Jan 2018 23:47:00 GMT
content-type: application/json
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 445
x-envoy-upstream-service-time: 36

{
  "args": {},
  "headers": {
    "Content-Length": "0",
    "Host": "httpbin:8000",
    "User-Agent": "istio/fortio-0.6.2",
    "X-B3-Sampled": "1",
    "X-B3-Spanid": "824fbd828d809bf4",
    "X-B3-Traceid": "824fbd828d809bf4",
    "X-Ot-Span-Context": "824fbd828d809bf4;824fbd828d809bf4;0000000000000000",
    "X-Request-Id": "1ad2de20-806e-9622-949a-bd1d9735a3f4"
  },
  "origin": "127.0.0.1",
  "url": "http://httpbin:8000/get"
}

可以看到调用后端服务的请求已经成功!接下来,可以测试熔断。

触发熔断器
在 DestinationRule 配置中,定义了 maxConnections: 1 和 http1MaxPendingRequests: 1。 这些规则意味着,如果并发的连接和请求数超过一个,在 istio-proxy 进行进一步的请求和连接时,后续请求或 连接将被阻止。

发送并发数为 2 的连接(-c 2),请求 20 次(-n 20):
[root@node1 istio-1.6.5]# kubectl exec -it $FORTIO_POD  -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get
...
Code 200 : 14 (70.0 %)
Code 503 : 6 (30.0 %)
...

将并发连接数提高到 3 个:

[root@node1 istio-1.6.5]# kubectl exec -it $FORTIO_POD  -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://httpbin:8000/get
...
Code 200 : 11 (36.7 %)
Code 503 : 19 (63.3 %)
...

查询 istio-proxy 状态以了解更多熔断详情:

[root@ceph1 istio-1.11.7]# 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.remaining_pending: 1
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: 89
cluster.outbound|8000||httpbin.default.svc.cluster.local.upstream_rq_pending_total: 114

可以看到 upstream_rq_pending_overflow 值 89,这意味着,目前为止已有 89 个调用被标记为熔断

9、清理 httpbin

#清理规则:
kubectl delete destinationrule httpbin


#下线 httpbin 服务和客户端:
kubectl delete deploy httpbin fortio-deploy
kubectl delete svc httpbin

参考博客
https://blog.csdn.net/bxg_kyjgs/article/details/125599452?utm_source=miniapp_weixin

你可能感兴趣的:(k8s,istio,架构,云原生)