ITPub博客

首页 > 数据库 > 数据库开发技术 > Service Mesh从0-1教程(下)

Service Mesh从0-1教程(下)

原创 数据库开发技术 作者:步步运维步步坑 时间:2024-07-18 00:00:00 0 删除 编辑

3.2、搭建 Istio 环境

3.2.1、下载 Istio

下载 Istio,下载内容将包含:安装文件、示例和 istioctl 命令行工具


可以通过github官方代码仓库下载合适的release版本:

Istio release (https://github.com/istio/istio/releases/tag/1.22.2)再Linux 系统中,也可以通过以下命令下载最新版本的 Istio:

[root@m1 istio]# curl -L https://istio.io/downloadIstio | sh -  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100   102  100   102    0     0    275      0 --:--:-- --:--:-- --:--:--   275100  4899  100  4899    0     0   1947      0  0:00:02  0:00:02 --:--:--  4331
Downloading istio-1.22.2 from https://github.com/istio/istio/releases/download/1.22.2/istio-1.22.2-linux-amd64.tar.gz ...
Istio 1.22.2 Download Complete!
Istio has been successfully downloaded into the istio-1.22.2 folder on your system.
Next Steps:See https://istio.io/latest/docs/setup/install/ to add Istio to your Kubernetes cluster.
To configure the istioctl client tool for your workstation,add the /data/istio/istio-1.22.2/bin directory to your environment path variable with: export PATH="$PATH:/data/istio/istio-1.22.2/bin"
Begin the Istio pre-installation check by running: istioctl x precheck
Need more information? Visit https://istio.io/latest/docs/setup/install/


可用指定版本:

$ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.2 sh -

切换到 Istio 包所在目录下。例如:Istio 包名为 istio-1.22.2,则:


[root@m1 istio]# cd istio-1.22.2/[root@m1 istio-1.22.2]# lltotal 40drwxr-x---. 2 root root 4096 Jun 27 04:02 bin-rw-r--r--. 1 root root 11357 Jun 27 04:02 LICENSEdrwxr-xr-x. 4 root root 4096 Jun 27 04:02 manifests-rw-r-----. 1 root root 956 Jun 27 04:02 manifest.yaml-rw-r--r--. 1 root root 6759 Jun 27 04:02 README.mddrwxr-xr-x. 26 root root 4096 Jun 27 04:02 samplesdrwxr-xr-x. 3 root root 4096 Jun 27 04:02 tools[root@m1 istio-1.22.2]#


安装目录包含如下内容:

  • samples/ 目录下,有示例应用程序

  • bin/ 目录下,包含 istioctl 的客户端文件。istioctl 工具用于手动注入 Envoy sidecar 代理。

将 istioctl 客户端路径增加到 path 环境变量中

[root@m1 istio-1.22.2]# export PATH=$PWD/bin:$PATH[root@m1 istio-1.22.2]# echo $PATH/data/istio/istio-1.22.2/bin:/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64/bin:/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_6/bin:/data/apache-maven-3.6.1/bin:/root/bin[root@m1 istio-1.22.2]#


安装 bash 自动补全文件

[root@m1 istio-1.22.2]# source ./tools/istioctl.bash [root@m1 istio-1.22.2]#

如果 istioctl 补全文件已经正确安装,在你输入 istioctl 命令时通过按 Tab 键,它会返回一组推荐命令供你选择:

[root@m1 istio-1.22.2]# istioctl proxy-<TAB>proxy-config  (Retrieve information about proxy configuration from Envoy [kube only])proxy-status  (Retrieves the synchronization status of each Envoy in the mesh)

3.2.2、安装 Istio

请按照以下步骤在你所选的平台上使用 demo 配置文件安装 Istio。

安装 demo 配置

[root@m1 data]# istioctl manifest apply --set profile=demoThe default revision has been updated to point to this installation.This will install the Istio 1.22.2 "demo" profile (with components: Istio core, Istiod, Ingress gateways, and Egress gateways) into the cluster. Proceed? (y/N) y✔ Istio core installed                                                                                                                                         ✔ Istiod installed                                                                                                                                             ✔ Egress gateways installed                                                                                                                             ✔ Ingress gateways installed                                                                                                                             ✔ Installation completeMade this installation the default for injection and validation.[root@m1 data]#


选择要安装的组件在 istio-1.22.2/manifests/profiles 中!

为了验证是否安装成功,需要先确保以下 Kubernetes 服务正确部署,是否有正确的clusterIP


如果集群运行在一个不支持外部负载均衡器的环境中(例如:minikube),istio-ingressgateway 的 EXTERNAL-IP 将显示为 <pending> 状态。请使用服务的 NodePort 或 端口转发来访问网关。确保关联的 Kubernetes pod 已经部署,并且 STATUS 为 Running:



3.2.3、卸载 Istio

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


3.3、Bookinfo 示例

3.3.1、应用说明


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

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

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

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

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

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

reviews 微服务有 3 个版本:

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

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

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

下图展示了这个应用的端到端架构。

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

3.3.2、部署应用

要在 Istio 中运行这一应用,无需对应用自身做出任何改变。你只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar 注入到每个服务之中。最终的部署结果将如下图所示:

所有的微服务都和 Envoy sidecar 集成在一起,被集成服务所有的出入流量都被 sidecar 所劫持,这样就为外部控制准备了所需的 Hook,然后就可以利用 Istio 控制平面为应用提供服务路由、遥测数据收集以及策略实施等功能。


3.3.3、启动应用服务

进入 Istio 安装目录。

Istio 默认自动注入 Sidecar. 请为 default 命名空间打上标签 istio-injection=enabled:

[root@m1 istio-1.22.2]# kubectl label namespace default istio-injection=enablednamespace/default not labeled[root@m1 istio-1.22.2]# kubectl describe ns defaultName:         defaultLabels:       istio-injection=enabled              kubernetes.io/metadata.name=defaultAnnotations:  <none>Status:       Active
No resource quota.
No LimitRange resource.[root@m1 istio-1.22.2]#

使用 kubectl 部署应用:

[root@m1 istio-1.22.2]# lltotal 40drwxr-x---.  2 root root  4096 Jun 27 04:02 bin-rw-r--r--.  1 root root 11357 Jun 27 04:02 LICENSEdrwxr-xr-x.  4 root root  4096 Jun 27 04:02 manifests-rw-r-----.  1 root root   956 Jun 27 04:02 manifest.yaml-rw-r--r--.  1 root root  6759 Jun 27 04:02 README.mddrwxr-xr-x. 26 root root  4096 Jun 27 04:02 samplesdrwxr-xr-x.  3 root root  4096 Jun 27 04:02 tools[root@m1 istio-1.22.2]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yamlservice/details createdserviceaccount/bookinfo-details createddeployment.apps/details-v1 createdservice/ratings createdserviceaccount/bookinfo-ratings createddeployment.apps/ratings-v1 createdservice/reviews createdserviceaccount/bookinfo-reviews createddeployment.apps/reviews-v1 createddeployment.apps/reviews-v2 createddeployment.apps/reviews-v3 createdservice/productpage createdserviceaccount/bookinfo-productpage createddeployment.apps/productpage-v1 created[root@m1 istio-1.22.2]#

注意:如果你在安装过程中禁用了 Sidecar(未设置istio-injection=true) 自动注入功能而选择手动注入 Sidecar,请在部署应用之前使用 istioctl kube-inject 命令修改 bookinfo.yaml 文件。

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


上面的命令会启动全部的四个服务,其中也包括了 reviews 服务的三个版本(v1、v2 以及 v3)。

在实际部署中,微服务版本的启动过程需要持续一段时间,并不是同时完成的。

确认所有的服务和 Pod 都已经正确的定义和启动


要确认 Bookinfo 应用是否正在运行,请在某个 Pod 中用 curl 命令对应用发送请求,例如 ratings                                                                            

[root@m1 data]# kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"<title>Simple Bookstore App</title>[root@m1 data]#

3.3.4、确定 Ingress 的 IP

现在 Bookinfo 服务启动并运行中,现在需要使应用程序可以从外部访问 Kubernetes 集群,例如使用浏览器。可以用 Istio Gateway 来实现这个目标。

为应用程序定义 Ingress 网关:

[root@m1 istio-1.22.2]#  kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yamlgateway.networking.istio.io/bookinfo-gateway createdvirtualservice.networking.istio.io/bookinfo created[root@m1 istio-1.22.2]#

确认网关创建完成:

[root@m1 istio-1.22.2]# kubectl get gateway NAME               AGEbookinfo-gateway   2m56s[root@m1 istio-1.22.2]#

设置访问网关的 INGRESS_HOST 和 INGRESS_PORT 变量。确认并设置。

[root@m1 istio-1.22.2]# export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')[root@m1 istio-1.22.2]# export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')[root@m1 istio-1.22.2]# export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')[root@m1 istio-1.22.2]# echo $INGRESS_PORT   $SECURE_INGRESS_PORT $INGRESS_HOST32020 32156 172.16.20.121[root@m1 istio-1.22.2]#

设置 GATEWAY_URL:

[root@m1 istio-1.22.2]# echo $GATEWAY_URL172.16.20.121:32020[root@m1 istio-1.22.2]#

可以用浏览器打开网址 http://$GATEWAY_URL/productpage,来浏览应用的 Web 页面。如果刷新几次应用的页面,就会看到 productpage 页面中会随机展示 reviews 服务的不同版本的效果(红色、黑色的星形或者没有显示)。r出现这种情况的远呀是因为我们还没有使用 Istio 来控制版本的路由


3.3.5、应用默认目标规则

给各个服务创建 DestinationRule

在使用 Istio 控制 Bookinfo 版本路由之前,你需要在目标规则中定义好可用的版本,命名为 subsets 。

#设置[root@m1 istio-1.22.2]# kubectl apply -f samples/bookinfo/networking/destination-rule-all.yamldestinationrule.networking.istio.io/productpage createddestinationrule.networking.istio.io/reviews createddestinationrule.networking.istio.io/ratings createddestinationrule.networking.istio.io/details created[root@m1 istio-1.22.2]# #查询[root@m1 istio-1.22.2]# kubectl get destinationrules -o yamlapiVersion: v1items:- apiVersion: networking.istio.io/v1  kind: DestinationRule  metadata:   ...  spec:    host: details    subsets:    - labels:        version: v1      name: v1    - labels:        version: v2      name: v2- apiVersion: networking.istio.io/v1  kind: DestinationRule  metadata:   ...  spec:    host: productpage    subsets:    - labels:        version: v1      name: v1- apiVersion: networking.istio.io/v1  kind: DestinationRule  metadata:    ...  spec:    host: ratings    subsets:    - labels:        version: v1      name: v1    - labels:        version: v2      name: v2    - labels:        version: v2-mysql      name: v2-mysql    - labels:        version: v2-mysql-vm      name: v2-mysql-vm- apiVersion: networking.istio.io/v1  kind: DestinationRule  metadata:...  spec:    host: reviews    subsets:    - labels:        version: v1      name: v1    - labels:        version: v2      name: v2    - labels:        version: v3      name: v3kind: Listmetadata:  resourceVersion: ""[root@m1 istio-1.22.2]#


3.3.6、详细说明

以下是每个 DestinationRule 的详细说明:detailsHost: detailsSubsets:v1 (版本: v1)v2 (版本: v2)这个规则定义了名为 details 的服务,并将其流量分配到 v1 和 v2 两个版本。productpageHost: productpageSubsets:v1 (版本: v1)这个规则定义了名为 productpage 的服务,并将其流量分配到 v1 版本。ratingsHost: ratingsSubsets:v1 (版本: v1)v2 (版本: v2)v2-mysql (版本: v2-mysql)v2-mysql-vm (版本: v2-mysql-vm)这个规则定义了名为 ratings 的服务,并将其流量分配到 v1, v2, v2-mysql 和 v2-mysql-vm 四个版本。reviewsHost: reviewsSubsets:v1 (版本: v1)v2 (版本: v2)v3 (版本: v3)这个规则定义了名为 reviews 的服务,并将其流量分配到 v1, v2 和 v3 三个版本。

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

3.4、体验 Istio

3.4.1、请求路由

按照版本路由,目前的 reviews 有三个版本,但是我们在浏览器中访问 Bookinfo 应用程序的 /productpage 并刷新几次。我们发现有时书评的输出包含星级评分,有时则不包含。这是因为没有明确的默认服务版本路由。所以现在我们要做就是让 istio 接管路由,比如将所有流量都路由到每个微服务的 v1 版本,Istio 实现起来是非常简单的,只需要添加虚拟服务(VirtualService)即可。

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

#virtual-service-all-v1.yaml是官方提供的示例文件[root@m1 istio-1.22.2]# kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yamlvirtualservice.networking.istio.io/productpage createdvirtualservice.networking.istio.io/reviews createdvirtualservice.networking.istio.io/ratings createdvirtualservice.networking.istio.io/details created

其内容如下:

[root@m1 istio-1.22.2]# cat samples/bookinfo/networking/virtual-service-all-v1.yamlapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: productpagespec:  hosts:  - productpage  http:  - route:    - destination:        host: productpage        subset: v1---apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: reviewsspec:  hosts:  - reviews  http:  - route:    - destination:        host: reviews        subset: v1---apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: ratingsspec:  hosts:  - ratings  http:  - route:    - destination:        host: ratings        subset: v1---apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: detailsspec:  hosts:  - details  http:  - route:    - destination:        host: details        subset: v1---

详细解释

每个 VirtualService 的详细说明:productpageHosts: productpageHTTP:Route:Destination:Host: productpageSubset: v1这个规则定义了名为 productpage 的服务,并将所有流量路由到 v1 版本的 productpage 服务实例。reviewsHosts: reviewsHTTP:Route:Destination:Host: reviewsSubset: v1这个规则定义了名为 reviews 的服务,并将所有流量路由到 v1 版本的 reviews 服务实例。ratingsHosts: ratingsHTTP:Route:Destination:Host: ratingsSubset: v1这个规则定义了名为 ratings 的服务,并将所有流量路由到 v1 版本的 ratings 服务实例。detailsHosts: detailsHTTP:Route:Destination:Host: detailsSubset: v1这个规则定义了名为 details 的服务,并将所有流量路由到 v1 版本的 details 服务实例。

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

按照不同用户身份路由
接下来,更改路由配置,以便将来自特定用户的所有流量路由到特定服务版本。本例中,一个来自名为 Jason 的用户的所有流量将被路由到服务 reviews:v2。
请注意,Istio 对用户身份没有任何特殊的内置机制。事实上,productpage 服务在所有到 reviews 服务的 HTTP 请求中都增加了一个自定义的 end-user 请求头,从而达到了本例子的效果。
这里,reviews:v2 是包含星级评分功能的版本。
运行以下命令以启用基于用户的路由:
[root@m1 istio-1.22.2]# kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yamlvirtualservice.networking.istio.io/reviews configured[root@m1 istio-1.22.2]#
确认规则易创建
[root@m1 istio-1.22.2]# kubectl get virtualservice reviews -o yamlapiVersion: networking.istio.io/v1kind: VirtualServicemetadata:...spec:  hosts:  - reviews  http:  - match:    - headers:        end-user:          exact: jason    route:    - destination:        host: reviews        subset: v2  - route:    - destination:        host: reviews        subset: v1[root@m1 istio-1.22.2]#
在 Bookinfo 应用程序的 /productpage 上,以用户 jason (无密码)身份登录。
刷新浏览器。会看到星级评分显示在每个评论旁边。

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

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

3.4.2、流量转移

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

#将所有流量都路由到每个服务的v1版本[root@m1 istio-1.22.2]# kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yamlvirtualservice.networking.istio.io/productpage unchangedvirtualservice.networking.istio.io/reviews configuredvirtualservice.networking.istio.io/ratings unchangedvirtualservice.networking.istio.io/details unchanged[root@m1 istio-1.22.2]# [root@m1 istio-1.22.2]# kubectl get virtualservice reviews -o yamlapiVersion: networking.istio.io/v1kind: VirtualServicemetadata:...spec:  hosts:  - reviews  http:  - route:    - destination:        host: reviews        subset: v1[root@m1 istio-1.22.2]# 
#将reviews服务 50%的流量转移到v3[root@m1 istio-1.22.2]# kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yamlvirtualservice.networking.istio.io/reviews configured[root@m1 istio-1.22.2]# kubectl get virtualservice reviews -o yamlapiVersion: networking.istio.io/v1kind: VirtualServicemetadata:...spec: hosts: - reviews http: - route: - destination: # 指定流量的目的地服务和子集。 host: reviews subset: v1 # 服务的子集(需要在 DestinationRule 中定义 weight: 50 # 权重 - destination: host: reviews subset: v3 weight: 50[root@m1 istio-1.22.2]# .

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

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

#将reviews服务的全部流量都切换到v3版本[root@m1 istio-1.22.2]# kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-v3.yamlvirtualservice.networking.istio.io/reviews configured[root@m1 istio-1.22.2]# kubectl get virtualservice reviews -o yamlapiVersion: networking.istio.io/v1kind: VirtualServicemetadata:...spec:  hosts:  - reviews  http:  - route:    - destination:        host: reviews        subset: v3[root@m1 istio-1.22.2]# 

这样,所有的请求都转向到了 v3 了。

如果需要删除所有服务的虚拟网络,可以执行:

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

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

3.4.3、超时与重试

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

这里我们来实验 reviews 服务的请求超时,将请求路由到 reviews 服务的 v2 版本,它会去调用 ratings 服务,我们首先在 ratings 服务上人为的引入 2s 的延迟(故障注入),再对 reviews 服务配置超时 timeout

在 istio-1.22.2/samples/bookinfo/networking 目录下创建配置文件

#创建配置文件# vim virtual-service-reviews-v2-timeout.yaml
apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata: name: ratingsspec: hosts: - ratings http: # 定义HTTP流量的路由规则。 - fault: delay: percent: 100 # 故障注入的百分比。这里设为100%,意味着所有请求都会受到影响 fixedDelay: 2s # 固定的延迟时间。所有请求都会被延迟2秒。 route: - destination: host: ratings subset: v1---apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata: name: reviewsspec: hosts: - reviews http: - route: - destination: host: reviews subset: v2 #timeout: 0.5s   
在 ratings 服务上注入 2s 的延迟,
应用该路由配置,就在当前目录下执行即可
[root@m1 istio-1.22.2]# kubectl apply -f virtual-service-reviews-v2-timeout.yamlvirtualservice.networking.istio.io/ratings configuredvirtualservice.networking.istio.io/reviews configured[root@m1 istio-1.22.2]#
访问该网址,这时可以看到 Bookinfo 应用运行正常(显示了评级的星型符号),但是每次刷新页面,都会有 2 秒的延迟。
重新编辑该文件,放开对 reviews 服务的调用增加一个半秒的请求超时(去掉 timeout 的注释)
重新应用该配置,还是执行之前更新的命令,然后通过如下命令查看配置是否更新
[root@m1 istio-1.22.2]# kubectl get virtualservice -o yamlapiVersion: v1items:- apiVersion: networking.istio.io/v1  kind: VirtualService  metadata:   ...  spec:    gateways:    - bookinfo-gateway    hosts:    - '*'    http:    - match:      - uri:          exact: /productpage      - uri:          prefix: /static      - uri:          exact: /login      - uri:          exact: /logout      - uri:          prefix: /api/v1/products      route:      - destination:          host: productpage          port:            number: 9080- apiVersion: networking.istio.io/v1  kind: VirtualService...  spec:    hosts:    - details    http:    - route:      - destination:          host: details          subset: v1- apiVersion: networking.istio.io/v1  kind: VirtualService ...  spec:    hosts:    - productpage    http:    - route:      - destination:          host: productpage          subset: v1- apiVersion: networking.istio.io/v1  kind: VirtualService....  spec:    hosts:    - ratings    http:    - fault:        delay:          fixedDelay: 2s          percent: 100      route:      - destination:          host: ratings          subset: v1- apiVersion: networking.istio.io/v1  kind: VirtualService ...  spec:    hosts:    - reviews    http:    - route:      - destination:          host: reviews          subset: v2      timeout: 0.5skind: Listmetadata:  resourceVersion: ""

再次刷新网页
这时候应该看到 1 秒钟就会返回,而不是之前的 2 秒钟,但 reviews 是不可用的(页面没有 reviews 的数据)
即使超时配置为半秒,响应仍需要 1 秒,是因为 productpage 服务中存在硬编码重试,因此它在返回之前调用 reviews 服务超时两次(重试)。
关于重试:直接参考官方文档


3.4.4、熔断

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

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

部署 httpbin

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

[root@m1 istio-1.22.2]# kubectl apply -f samples/httpbin/httpbin.yamlserviceaccount/httpbin createdservice/httpbin createddeployment.apps/httpbin created[root@m1 istio-1.22.2]#

该配置文件的内容为:

################################################################################################### httpbin service##################################################################################################apiVersion: v1kind: ServiceAccount # SCC授权metadata:  name: httpbin  ---apiVersion: v1  # svc服务kind: Servicemetadata:  name: httpbin  labels:    app: httpbinspec:  ports:  - name: http    port: 8000    targetPort: 80  selector:    app: httpbin---apiVersion: apps/v1kind: Deployment  #  应用metadata:  name: httpbinspec:  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
配置熔断器:创建一个目标熔断规则(DestinationRule),在调用 httpbin 服务时应用熔断设置
kubectl apply -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: DestinationRulemetadata:  name: httpbinspec:  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

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

[root@m1 data]# kubectl get destinationrule httpbin -o yamlapiVersion: networking.istio.io/v1kind: DestinationRulemetadata:...spec:  host: httpbin  trafficPolicy:    connectionPool:      http:        http1MaxPendingRequests: 1        maxRequestsPerConnection: 1      tcp:        maxConnections: 1    outlierDetection:      baseEjectionTime: 3m      consecutiveErrors: 1      interval: 1s      maxEjectionPercent: 100[root@m1 data]#
创建客户端程序以发送流量到 httpbin 服务。这是一个名为 Fortio 的负载测试客户的,其可以控制连接数、并发数及发送 HTTP 请求的延迟。通过 Fortio 能够有效的触发前面 在 DestinationRule 中设置的熔断策略。
向客户端注入 Istio Sidecar 代理,以便 Istio 对其网络交互进行管理
[root@m1 istio-1.22.2]#  kubectl apply -f <(istioctl kube-inject -f samples/httpbin/sample-client/fortio-deploy.yaml)service/fortio createddeployment.apps/fortio-deploy created[root@m1 istio-1.22.2]#

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


登入客户端 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[root@m1 istio-1.22.2]#  FORTIO_POD=$(kubectl get pod | grep fortio | awk '{ print $1 }')[root@m1 istio-1.22.2]#  kubectl exec -it $FORTIO_POD  -c fortio -- /usr/bin/fortio load -curl  http://httpbin:8000/get09:33:07.101 r1 [INF] scli.go:123> Starting, command="Φορτίο", version="1.60.3 h1:adR0uf/69M5xxKaMLAautVf9FIVkEpMwuEWyMaaSnI0= go1.20.10 amd64 linux"HTTP/1.1 200 OKserver: envoydate: Mon, 15 Jul 2024 09:33:07 GMTcontent-type: application/jsoncontent-length: 425access-control-allow-origin: *access-control-allow-credentials: truex-envoy-upstream-service-time: 13
{ "args": {}, "headers": { "Host": "httpbin:8000", "User-Agent": "fortio.org/fortio-1.60.3", "X-Envoy-Attempt-Count": "1", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=92b9a6c7c4ac913de4723527e99738d1adbfad46f37056fcadeec719ba6f5216;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default" }, "origin": "127.0.0.6", "url": "http://httpbin:8000/get"}[root@m1 istio-1.22.2]# HTTP/1.1 200 OKserver: envoydate: Tue, 16 Jan 2018 23:47:00 GMTcontent-type: application/jsonaccess-control-allow-origin: *access-control-allow-credentials: truecontent-length: 445x-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@m1 istio-1.22.2]# kubectl exec -it $FORTIO_POD  -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get09:33:49.694 r1 [INF] logger.go:254> Log level is now 3 Warning (was 2 Info)Fortio 1.60.3 running at 0 queries per second, 16->16 procs, for 20 calls: http://httpbin:8000/getStarting at max qps with 2 thread(s) [gomax 16] for exactly 20 calls (10 per thread + 0)09:33:49.705 r35 [WRN] http_client.go:1104> Non ok http code, code=503, status="HTTP/1.1 503", thread=0, run=009:33:49.715 r36 [WRN] http_client.go:1104> Non ok http code, code=503, status="HTTP/1.1 503", thread=1, run=009:33:49.720 r35 [WRN] http_client.go:1104> Non ok http code, code=503, status="HTTP/1.1 503", thread=0, run=009:33:49.727 r36 [WRN] http_client.go:1104> Non ok http code, code=503, status="HTTP/1.1 503", thread=1, run=009:33:49.730 r35 [WRN] http_client.go:1104> Non ok http code, code=503, status="HTTP/1.1 503", thread=0, run=009:33:49.741 r35 [WRN] http_client.go:1104> Non ok http code, code=503, status="HTTP/1.1 503", thread=0, run=009:33:49.744 r36 [WRN] http_client.go:1104> Non ok http code, code=503, status="HTTP/1.1 503", thread=1, run=0Ended after 59.342745ms : 20 calls. qps=337.03Aggregated Function Time : count 20 avg 0.0058604489 +/- 0.004583 min 0.000356057 max 0.017002726 sum 0.117208979# range, mid point, percentile, count>= 0.000356057 <= 0.001 , 0.000678028 , 20.00, 4> 0.001 <= 0.002 , 0.0015 , 25.00, 1> 0.003 <= 0.004 , 0.0035 , 50.00, 5> 0.006 <= 0.007 , 0.0065 , 60.00, 2> 0.007 <= 0.008 , 0.0075 , 75.00, 3> 0.009 <= 0.01 , 0.0095 , 80.00, 1> 0.01 <= 0.011 , 0.0105 , 90.00, 2> 0.014 <= 0.016 , 0.015 , 95.00, 1> 0.016 <= 0.0170027 , 0.0165014 , 100.00, 1# target 50% 0.004# target 75% 0.008# target 90% 0.011# target 99% 0.0168022# target 99.9% 0.0169827Error cases : count 7 avg 0.0020124073 +/- 0.00244 min 0.000356057 max 0.007465399 sum 0.014086851# range, mid point, percentile, count>= 0.000356057 <= 0.001 , 0.000678028 , 57.14, 4> 0.001 <= 0.002 , 0.0015 , 71.43, 1> 0.003 <= 0.004 , 0.0035 , 85.71, 1> 0.007 <= 0.0074654 , 0.0072327 , 100.00, 1# target 50% 0.000892676# target 75% 0.00325# target 90% 0.00713962# target 99% 0.00743282# target 99.9% 0.00746214# Socket and IP used for each connection:[0]   5 socket used, resolved to 10.111.166.239:8000, connection timing : count 5 avg 0.0001413654 +/- 2.207e-05 min 0.000124169 max 0.000183986 sum 0.000706827[1]   4 socket used, resolved to 10.111.166.239:8000, connection timing : count 4 avg 0.00017490925 +/- 5.561e-05 min 9.554e-05 max 0.000238633 sum 0.000699637Connection time (s) : count 9 avg 0.00015627378 +/- 4.385e-05 min 9.554e-05 max 0.000238633 sum 0.001406464Sockets used: 9 (for perfect keepalive, would be 2)Uniform: false, Jitter: false, Catchup allowed: trueIP addresses distribution:10.111.166.239:8000: 9Code 200 : 13 (65.0 %)Code 503 : 7 (35.0 %)Response Header Sizes : count 20 avg 149.6 +/- 109.8 min 0 max 231 sum 2992Response Body/Total Sizes : count 20 avg 510.2 +/- 197.5 min 241 max 656 sum 10204All done 20 calls (plus 0 warmup) 5.860 ms avg, 337.0 qps[root@m1 istio-1.22.2]#
结果:
Code 200 : 13 (65.0 %)Code 503 : 7 (35.0 %)
将并发连接数提高到 3 个
[root@m1 istio-1.22.2]#  kubectl exec -it $FORTIO_POD  -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://httpbin:8000/get09:35:10.778 r1 [INF] logger.go:254> Log level is now 3 Warning (was 2 Info)...10.111.166.239:8000: 21Code 200 : 10 (33.3 %)Code 503 : 20 (66.7 %)Response Header Sizes : count 30 avg 76.666667 +/- 108.4 min 0 max 230 sum 2300Response Body/Total Sizes : count 30 avg 379 +/- 195.2 min 241 max 655 sum 11370All done 30 calls (plus 0 warmup) 2.529 ms avg, 941.8 qps[root@m1 istio-1.22.2]#
可以看到,只有 36.7% 的请求成功,其余的均被熔断器拦截
Code 200 : 10 (33.3 %)Code 503 : 20 (66.7 %)

查询 istio-proxy 状态了解更多熔断详情
[root@m1 istio-1.22.2]# kubectl exec $FORTIO_POD -c istio-proxy -- pilot-agent request GET stats | grep httpbin | grep pending

可以看到 upstream_rq_pending_overflow 值 27,这意味着,目前为止已有 27个调用被标记为熔断。
清理
清理规则$ kubectl delete destinationrule httpbin夏县httpbin应用$ kubectl delete deploy httpbin fortio-deploy$ kubectl delete svc httpbin

3.4.5、可观测性

istio 的可观测性体现在:指标度量,日志,分布式追踪,网格可视化等方面

网格可视化我们可以将 istio 网格以可视化的方式呈现,基于 Web 的图形用户界面来查看网格和 Istio 配置对象的服务图,使我们的操作更方便

在 Istio 中可以使用 Kiali 进行可视化的管理服务网格。Kiali 官网:https://www.kiali.io/

[root@m1 istio-1.22.2]# kubectl apply -f samples/addons/kiali.yaml serviceaccount/kiali createdconfigmap/kiali createdclusterrole.rbac.authorization.k8s.io/kiali createdclusterrolebinding.rbac.authorization.k8s.io/kiali createdrole.rbac.authorization.k8s.io/kiali-controlplane createdrolebinding.rbac.authorization.k8s.io/kiali-controlplane createdservice/kiali createddeployment.apps/kiali created[root@m1 istio-1.22.2]# kubectl apply -f samples/addons/prometheus.yaml serviceaccount/prometheus createdconfigmap/prometheus createdclusterrole.rbac.authorization.k8s.io/prometheus createdclusterrolebinding.rbac.authorization.k8s.io/prometheus createdservice/prometheus createddeployment.apps/prometheus created[root@m1 istio-1.22.2]# [root@m1 istio-1.22.2]# kubectl apply -f samples/addons/loki.yaml serviceaccount/loki createdconfigmap/loki createdconfigmap/loki-runtime createdservice/loki-memberlist createdservice/loki-headless createdservice/loki createdstatefulset.apps/loki created[root@m1 istio-1.22.2]# kubectl apply -f samples/addons/grafana.yaml serviceaccount/grafana createdconfigmap/grafana createdservice/grafana createddeployment.apps/grafana createdconfigmap/istio-grafana-dashboards createdconfigmap/istio-services-grafana-dashboards created[root@m1 istio-1.22.2]# kubectl apply -f samples/addons/jaeger.yaml deployment.apps/jaeger createdservice/tracing createdservice/zipkin createdservice/jaeger-collector created[root@m1 istio-1.22.2]#

打开 Kiali UI

[root@m1 istio-1.22.2]# istioctl dashboard kiali --address  172.16.20.122 http://172.16.20.122:20001/kialiFailed to open browser; open http://172.16.20.122:20001/kiali in your browser.

将流量发送到网格,有两种选择:
在浏览器中访问 http://$GATEWAY_URL/productpage
如果你在系统中安装了 watch 命令,请通过以下方式连续发送请求,时间间隔为 0.1 秒:
$ watch -n 0.1 curl -o /dev/null -s -w %{http_code} $GATEWAY_URL/productpage

图表

查看流量分配数量

请求统计数据,RPS 数据(最小 / 最大的比值)

四种类型:

  1. APP:图形类型将一个应用程序的所有版本聚合到一个图形节点

  2. Versioned App:图类型显示每个应用程序版本的节点,但是特定应用程序的所有版本都组合在一起。


  3. Workload:图类型显示了服务网格中每个工作负载的节点

  4. Service:图类型显示网格中每个服务的节点



路由加权
默认路由规则会平均分配浏览到每个可用节点,通过 kiali 可以可行可视化的调节:
第一步,查看 servers 列表:

第二步,进入 reviews 服务:

第三步,删除原有路由规则:


第四步,创建权重的规则:

默认情况:

进行调整:

保存操作。
第五步,通过 watch 执行一段时间,观察效果

可以看到,分配到 reviews 的 v1、v2、v3 的百分比发生了变化

查看工作负载

入站、出站信息

日志信息

入站指标

出站指标

Enovy代理


查看工作负载

THE

END

期待你的

分享

点赞

在看

添加博主

微信号|yfq940-



原文作者:步步运维步步坑;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-10-08

  • 博文量
    100
  • 访问量
    51734