网站快速设计,滨海县网站建设,网站建设和网袷宣传,域名怎么转移到自己名下云原生专栏大纲 文章目录 流量管理基于版本的路由配置基于 Http header 的路由配置故障注入延迟故障注入异常故障注入故障注入测试 比例分配流量请求超时熔断什么是熔断创建 httpbin 服务创建访问者服务 流量管理
Istio 是服务治理的工具#xff0c;Istio 的流量管理能力Istio 的流量管理能力能解决微服务中关于服务治理的部分问题。Istio 的流量管理模型源于和服务一起部署的 Envoy网格内 Pod 中的应用发送和接收的所有流量data plane流量都经由 Envoy而应用本身不需要对服务做任何的更改这对业务来说是非侵入式的却可以实现强大的流量管理。常见服务治理的问题 服务发现在动态的微服务环境中如何实时地发现和注册新的服务实例负载均衡如何在服务实例之间有效地分配请求流量以实现高性能和高可用性容错处理如何处理服务之间的故障例如服务实例故障、网络故障等流量管理如何控制服务间的请求流量例如请求路由、流量分割、金丝雀发布等服务监控如何实时地监控服务的性能和健康状况链路追踪如何跟踪和分析分布式系统中的请求调用链安全性如何确保服务之间的通信安全例如身份验证、授权和加密策略执行如何实施和管理服务治理的策略例如限流、熔断、访问控制等配置管理如何在服务之间统一和动态地管理配置信息服务编排如何协调服务之间的交互以实现复杂的业务流程 基于版本的路由配置
Kubenetes Service 通过标签中的 app: reviews 来绑定对应的 Pod selector:app: reviews正常情况下Kubernetes 会将客户端的请求以轮询的方式转发到 Deployment 中的 Pod。三个不同的 Reviews Deployment 都带有相同的 app: reviews 标签标记不同的版本。所以 Service 会把它们的 Pod 放到一起VirtualService 会将流量以轮询的方式分发到每个版本中。如何将流量划分到不同的版本服务中Istio 通过 DestinationRule 定义了应用的版本使用 Istio DestinationRule 设置 reviews v1/v2/v3 版本的定义如下所示
编写service_br.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: productpage
spec:host: productpagesubsets:- name: v1labels:version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: reviews
spec:host: reviewssubsets:- name: v1labels:version: v1- name: v2labels:version: v2- name: v3labels:version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: ratings
spec:host: ratingssubsets:- name: v1labels:version: v1- name: v2labels:version: v2- name: v2-mysqllabels:version: v2-mysql- name: v2-mysql-vmlabels:version: v2-mysql-vm
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: details
spec:host: detailssubsets:- name: v1labels:version: v1- name: v2labels:version: v2
---部署br
kubectl -n bookinfo apply -f service_br.yaml查看规则
# kubectl get destinationrules -o wide -n bookinfo
NAME HOST AGE
details details 13s
productpage productpage 13s
ratings ratings 13s
reviews reviews 13s为微服务 productpage、ratings、details 定义 Istio VirtualService
因为它们都只有 v1 版本所以在 VirtualService 中直接将流量转发的 v1 版本即可。编写3vs.yaml主要定义route目的地若不定义则轮询方式访问该三个微服务只有一个版本此处也可不部署vs
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: productpage
spec:hosts:- productpagehttp:- route:- destination:host: productpagesubset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: ratings
spec:hosts:- ratingshttp:- route:- destination:host: ratingssubset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: details
spec:hosts:- detailshttp:- route:- destination:host: detailssubset: v1
---部署
kubectl -n bookinfo apply -f 3vs.yamlreviews 服务流量只进入v1版本配置
reviews_v1_vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: reviews
spec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v1kubectl -n bookinfo apply -f reviews_v1_vs.yaml查看vs
# kubectl get vs -n bookinfo
NAME GATEWAYS HOSTS AGE
bookinfo [bookinfo-gateway] [*] 155m
details [details] 2m13s
productpage [productpage] 2m13s
ratings [ratings] 2m13s
reviews [reviews] 9s访问测试
http://192.168.31.21:32666/productpage此时无论怎么访问都不好出现星v1版本没星星查看kiali链路图也可看到v2、v3没有流量原理分析Istio 起作用的原理大概是这样的首先是 istio-ingressgateway 将流量转发到 bookinfo 网关中然后 productpage VirtualService 根据对应的路由规则判断是否放通流量最后转发到对应的 productpage 应用中。接着 productpage 需要访问其它服务例如 reviews发出的请求会经过 EnvoyEnvoy 根据配置的 VirtualService 规则直接将流量转发到对应的 Pod 中。
基于 Http header 的路由配置
基于 Http header 的转发是通过 HTTP 请求中的 header 值将流量转发到对应的 Pod 中。
编写reviews_v2_vs.yaml 将 header 带有 end-user: jason 的流量转发到 v2 中其它情况依然转发到 v1 版本。 apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: reviews
spec:hosts:- reviewshttp:- match:- headers:end-user:exact: jasonroute:- destination:host: reviewssubset: v2- route:- destination:host: reviewssubset: v1kubectl -n bookinfo apply -f reviews_v2_vs.yaml登录访问测试
然后在页面中的右上角点击 Sign in 进行登录账号密码都是 jason。此时登录无论怎么刷新都显示黑色星星v2版本
查看 productpage 的日志 productpage 将这个 header 头转发给 http://reviews:9080/ 然后流量经过 Envoy 时Envoy 检测到 Http header 中带有 end-user 通过规则决定将流量转发到 reviews v2。在这个过程中并不需要 Service 参与。
经过上面的配置下面是请求的流程 productpage → reviews:v2 → ratings (针对 jason 用户)productpage → reviews:v1 (其他用户)
当然我们也可以通过 URL 的方式划分流量例如 /v1/productpage 、/v2/productpage 等
故障注入
故障注入是 Istio 模拟故障的一种手段通过故障注入我们可以模拟一个服务出现故障的情况然后从实际请求中看到出现故障时整个微服务是否会乱套。通过故意在服务间通信中引入错误例如延迟、中断或错误的返回值可以测试系统在不理想的运行状况下的表现。这有助于发现潜在的问题提高系统的健壮性和可靠性。
在 Istio 的 VirtualService 中fault 配置用于注入故障以模拟和测试应用程序在出现问题时的行为。主要有两种类型的故障注入延迟delay和异常abort。
延迟故障注入
延迟故障注入用于在应答之前向请求添加指定的延迟时间。这可以测试应用程序在网络延迟或服务响应缓慢的情况下的表现。延迟故障注入配置如下
http: fault: delay: percentage: value: 50.0 fixedDelay: 5s延迟delay故障注入有两个主要属性。 percentage: 表示注入延迟的概率取值范围为 0.0 到 100.0。例如50.0 表示有 50% 的概率注入延迟。fixedDelay: 表示注入的固定延迟时间通常以秒s或毫秒ms为单位。例如5s 表示 5 秒延迟。 异常故障注入
异常故障注入用于模拟请求失败的情况例如 HTTP 错误状态码或 gRPC 状态码。这可以帮助测试应用程序在遇到故障时的恢复能力。以下是一个示例演示了如何在 VirtualService 中添加一个异常故障注入
http: fault: abort: percentage: value: 50.0 httpStatus: 503也可以将延迟故障注入 和 异常故障注入两者放在一起同时使用。虽然放在一起使用但是并不会两种情况同时发生而是通过 percentage 来配置出现的概率。异常abort故障注入有四个主要属性。 percentage: 表示注入异常的概率取值范围为 0.0 到 100.0。例如50.0 表示有 50% 的概率注入异常。httpStatus: 表示要注入的 HTTP 错误状态码。例如503 表示 HTTP 503 错误。grpcStatus: 表示要注入的 gRPC 错误状态码。例如UNAVAILABLE 表示 gRPC 服务不可用错误。http2Error: 表示要注入的 HTTP/2 错误。例如CANCEL 表示 HTTP/2 流被取消。 故障注入测试
编写ratings_vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: ratings
spec:hosts:- ratingshttp:- match:- headers:end-user:exact: jasonfault:delay:percentage:value: 100.0fixedDelay: 7sroute:- destination:host: ratingssubset: v1- route:- destination:host: ratingssubset: v1访问测试
再次访问网页因为超时发现评论区已经加载不出来了
将ratings 服务恢复正常
kubectl -n bookinfo apply -f 3vs.yaml注意kubectl -n bookinfo delete -f ratings_vs.yaml不是恢复绑定关系是metadata:name: ratings需更新。 比例分配流量
把 50% 的流量分配给 reviews:v1 和 reviews:v3
编写reviews_scale_v13_vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: reviews
spec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v1weight: 50- destination:host: reviewssubset: v3weight: 50kubectl -n bookinfo apply -f reviews_scale_v13_vs.yaml刷新浏览器中的 /productpage 页面大约有 50% 的几率会看到页面中带 红色 星级的评价内容。这是因为 reviews 的 v3 版本可以访问带星级评价但 v1 版本不能。
请求超时
在 Istio 中服务间的调用由 Istio 进行管理可以设置超时断开。 补充除了像本文一样在路由规则中进行超时设置之外还可以进行请求一级的设置只需在应用的对外请求中加入 x-envoy-upstream-rq-timeout-ms 请求头即可。在这个请求头中的超时设置单位是毫秒而不是秒。 编写reviews_timeout.yaml
为 reviews 服务设置 http 入口超时时间当其它服务 请求reviews 服务时如果 http 请求超过 0.5s那么 Istio 立即断开 http 请求。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: reviews
spec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v2timeout: 0.5skubectl -n bookinfo apply -f reviews_timeout.yaml注入延迟故障模拟超时
reviews 依赖于 ratings 服务为了模拟这种超时情况我们可以给 ratings 注入延迟故障。这样 ratings 会给所有请求都延迟 2s 才会返回响应但是 reviews 要求所有请求 reviews 的流量在 0.5s 内响应。
kubectl -n bookinfo apply -f - EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: ratings
spec:hosts:- ratingshttp:- fault:delay:percent: 100fixedDelay: 2sroute:- destination:host: ratingssubset: v1
EOF访问测试 查看productpage 日志 恢复故障
kubectl -n bookinfo apply -f - EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: reviews
spec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v1weight: 50- destination:host: reviewssubset: v3weight: 50
EOF
kubectl -n bookinfo apply -f - EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: ratings
spec:hosts:- ratingshttp:- route:- destination:host: ratingssubset: v1
EOF熔断 什么是熔断
熔断Circuit Breaking是微服务架构中的一种重要的弹性设计模式在微服务环境中不同的服务存在依赖关系当其中一个依赖的服务出现问题时可能导致请求积压从而影响到其他服务和整个系统的稳定性。比如说B 服务来了 100 个请求B 需要请求 100 次 A 服务但是 A 服务故障了那么每次失败时都会重试一次那么整体上就一共请求了 200 次。这样就会造成很大的浪费。而熔断器可以检测到这种情况当检测到 A 服务故障之后一段时间内所有对 A 的请求都会直接返回错误。熔断器模式的工作原理如下
正常状态熔断器处于关闭状态允许请求通过熔断器会监控请求的成功和失败率。故障检测当失败率达到预先定义的阈值时熔断器就会启动。熔断状态熔断器处于打开状态时将拒绝所有新的请求并返回错误响应。这可以防止故障级联和给故障服务带来更多的压力。恢复状态在一段时间后熔断器会进入半打开状态允许一部分请求通过。如果这些请求成功则熔断器将返回到关闭状态如果仍然存在失败请求则熔断器继续保持打开状态。
使用熔断器模式可以提高微服务系统的弹性和稳定性。这些工具提供了熔断器模式的实现以及其他弹性设计模式如负载均衡、重试和超时等。
创建 httpbin 服务
部署httpbin
https://github.com/istio/istio/tree/release-1.11/samples/httpbin
kubectl -n bookinfo apply -f httpbin.yaml暴露httpbin 访问测试 给httpbin 创建一个 DestinationRule 里面配置了熔断规则
httpbin_circurt.yaml
apiVersion: networking.istio.io/v1alpha3
# 目标规则用于定义访问特定服务的流量策略
kind: DestinationRule
metadata:name: httpbin
spec:# 指定了该规则适用于名为 httpbin 的主机host: httpbin# 允许为服务指定全局的流量策略这些策略包括负载均衡设置、连接池设置、异常检测等。trafficPolicy: # 定义了连接池的配置包括最大连接数限制connectionPool:tcp:maxConnections: 1 # 限制了 TCP 连接的最大数量为 1http:http1MaxPendingRequests: 1 # 限制了允许排队的最大 HTTP 请求数量为 1maxRequestsPerConnection: 1 # 限制了每个连接的最大请求数量为 1# 定义了异常检测的配置用于检测出现异常的后端服务实例并对其进行隔离。outlierDetection:consecutive5xxErrors: 1 # 定义了允许的连续 5xx 错误次数为 1interval: 1s # 定义了异常检测的时间间隔为 1 秒baseEjectionTime: 3m # 定义了基础隔离时间为 3 分钟maxEjectionPercent: 100 # 定义了最大隔离百分比为 100%表示当异常检测条件满足时可以隔离的服务实例的最大比例为 100%这个 DestinationRule 的配置限制了对名为 httpbin 的服务的流量包括连接池的最大连接数限制和 HTTP 请求的限制并配置了异常检测策略以便在出现异常时对后端服务实例进行隔禽。 kubectl -n bookinfo apply -f httpbin_circuit.yaml创建熔断时也可以设置重试次数 retries:attempts: 3perTryTimeout: 1sretryOn: 5xx创建访问者服务
部署一个服务请求 httpbin才能观察到熔断过程。Istio 官方推荐使用 fortio 。
编写fortio_deploy.yaml
apiVersion: v1
kind: Service
metadata:name: fortiolabels:app: fortioservice: fortio
spec:ports:- port: 8080name: httpselector:app: fortio
---
apiVersion: apps/v1
kind: Deployment
metadata:name: fortio-deploy
spec:replicas: 1selector:matchLabels:app: fortiotemplate:metadata:annotations:# This annotation causes Envoy to serve cluster.outbound statistics via 15000/stats# in addition to the stats normally served by Istio. The Circuit Breaking example task# gives an example of inspecting Envoy stats via proxy config.proxy.istio.io/config: |-proxyStatsMatcher:inclusionPrefixes:- cluster.outbound- cluster_manager- listener_manager- server- cluster.xds-grpclabels:app: fortiospec:containers:- name: fortioimage: fortio/fortio:latest_releaseimagePullPolicy: Alwaysports:- containerPort: 8080name: http-fortio- containerPort: 8079name: grpc-pingkubectl -n bookinfo apply -f fortio_deploy.yaml执行命令请求 httpbin
# 执行命令获取 fortio 的 Pod 名称
export FORTIO_POD$(kubectl get pods -n bookinfo -l appfortio -o jsonpath{.items[0].metadata.name})
# 让 Pod 容器执行命令
kubectl -n bookinfo exec $FORTIO_POD -c fortio -- /usr/bin/fortio curl -quiet http://httpbin:8000/get或通过可视化界面进入到 fortio 容器中执行命令请求 httpbin
/usr/bin/fortio curl -quiet http://httpbin:8000/get模拟大量请求触发熔断
kubectl -n bookinfo exec $FORTIO_POD -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get可以看到下图中返回 200 和 503 的比例 ####创建 productpage 熔断
编写productpage_circuit.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: productpage
spec:host: productpagesubsets:- name: v1labels:version: v1trafficPolicy:connectionPool:tcp:maxConnections: 1http:http1MaxPendingRequests: 1maxRequestsPerConnection: 1outlierDetection:consecutive5xxErrors: 1interval: 1sbaseEjectionTime: 3mmaxEjectionPercent: 100kubectl -n bookinfo apply -f productpage_circuit.yaml使用 fortio 测试 productpage 应用
从 istio gateway 入口进行访问
kubectl -n bookinfo exec $FORTIO_POD -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 200 -loglevel Warning http://192.168.31.21:32666/productpage访问页面
发现被熔断了
删除熔断配置
kubectl -n bookinfo apply -f - EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: productpage
spec:host: productpagesubsets:- name: v1DestinationRulelabels:version: v1
EOF再次访问页面正常
再次fortio 测试 productpage 应用
kubectl -n bookinfo exec $FORTIO_POD -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 20 -loglevel Warning http://192.168.31.21:32666/productpage请求全部成功