背景
在未启用慢启动预热能力时, 每当新目标Pod加入时,请求方都会向该Pod发送一定比例的流量, 不支持新 Pod 的渐进式流量增加。这对于需要一些预热时间来提供全部负载的服务可能是不可取的,并且可能会导致请求超时、数据丢失和用户体验恶化。
作为一个实际示例,上述问题体现在基于 JVM 的 Web 应用程序中,这些应用程序使用水平 pod 自动缩放。当服务刚启动时,它会被大量请求淹没,这会导致应用程序预热时持续超时。因此,每次扩展服务时,都会丢失数据或者会导致这部分请求的响应时间增加。预热的基本思想就是让刚启动的机器逐步接入流量。
ASM服务预热功能介绍
ASM 在1.14 版本开始支持慢启动预热能力。简单介绍:
•慢启动模式又称渐进式流量增加,有助于克服上述问题。用户可以为他们的服务配置一个时间段,这样每当一个服务实例启动时, 请求方会向该实例发送一部分请求负载,并在配置的时间段内逐步增加请求量。当慢启动窗口持续时间到达,它就会退出慢启动模式。
•在慢启动模式下,在添加新的目标服务Pod时,可以使得他们不会被大量请求压倒,这些新目标服务可以根据指定的加速期在接受其均衡策略的请求之前进行预热。
•慢启动对于依赖缓存并且需要预热期才能以最佳性能响应请求的应用程序非常有用。
对应在ASM 下,只需在服务对应的DestinationRule 下的配置trafficPolicy/loadBalancer即可,注意的是
- loadBalancer的类型限定于ROUND_ROBIN 和 LEAST_REQUEST 负载均衡器。
- warmupDurationSecs表示 Service 的预热持续时间。如果设置,则新创建的服务端点在此窗口期间从其创建时间开始保持预热模式,并且 Istio 逐渐增加该端点的流量,而不是发送成比例的流量。
示例如下:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: mocka
spec:
host: mocka
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
warmupDurationSecs: 100s
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
前提准备
- 已创建ASM实例, 服务预热功能需要使用ASM 企业版或者旗舰版,且版本为v1.14.3+ 。具体操作,请参见创建ASM实例。
- 已创建ACK集群。具体操作,请参见创建Kubernetes托管版集群。
- 添加集群到ASM实例。具体操作,请参见添加集群到ASM实例。
- 通过kubectl连接ACK集群。具体操作,请参见通过kubectl管理Kubernetes集群。
- 创建ASM 网关。具体操作,请参见添加入口网关服务
- 已部署示例应用bookinfo, 本示例中,为演示方便移除了review-v3版本。 具体操作, 请参见 部署应用到ASM实例。
Step1: 配置路由规则及确认应用运行
本示例中,为演示方便首先将review的v2和v3版本的Deployment副本数调整为0, 即在Kubernetes集群中将名为reviews-v2与reviews-v3的Deployment部署的副本数缩容为0。
同时, 确认在ASM中已经创建如下规则配置, 包括:
- 用于定义访问入口的配置
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
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
- 定义reviews服务的配置
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
在开启网格拓扑之后, 通过不断地访问入口网关地址,例如通过如下hey命令发送请求。采用hey 命令发送压测请求10s
hey 命令下载和安装参考链接: https://github.com/rakyll/hey
hey -z 10s http://${网关地址}/productpage
可以看到正常的调用拓扑如下所示, 具体参考https://help.aliyun.com/document_detail/432495.html:
Step2: 通过可观测数据查看Pod启动
在ASM控制台中, 选择对应的ASM实例,在左侧导航栏选择可观测管理下的Prometheus监控,在右侧页面中选择 网格服务级别监控, 选择对应的reviews服务。
在未开启预热功能的情况下, 在Kubernetes集群中将名为reviews-v2的Deployment部署的副本数从0扩为1,采用hey 命令发送压测请求入口网关 。注意观察Prometheus监控的仪表盘数据, 大概需要15s左右的时间reviews-v2 Pod将接收均衡的请求(具体时间会跟实际压测环境有关)。
然后在Kubernetes集群中将名为reviews-v2的Deployment部署的副本数缩容为0。等待1分钟之后, 将开启预热功能。
Step3: 启用预热功能
更新名为reviews的DestinationRule,增加warmupDurationSecs值为120s, 即定义预热持续时间为120s 。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
warmupDurationSecs: 120s
Step4: 通过可观测数据查看预热效果
类似地, 在开启了预热功能的情况下, 在Kubernetes集群中将名为reviews-v2的Deployment部署的副本数从0扩为1,采用hey 命令发送压测请求入口网关 。注意观察Prometheus监控的仪表盘数据, 大概需要45s左右的时间reviews-v2 Pod将接收均衡的请求(具体时间会跟实际压测环境有关)。
可以看到在启用预热功能的情况下, 每当一个服务实例启动时, 请求方会向该实例发送一部分请求负载,并在配置的时间段内逐步增加请求量。当慢启动窗口持续时间到达,它就会退出慢启动模式。
此外, 启用预热功能之后, 需要2分30秒左右, 流量均衡地分布到v1和v2版本。
Step5: 通过代理计数器查看预热效果
在查看服务预热效果之前, 操作以下两个步骤:
- 需要清空计数器的已有数据便于查看新增的计数值,执行如下命令:
## reviews-v1 版本对应Pod中的Sidecar代理计数器
kubectl exec reviews-v1-55b668fc65-jhxlj -c istio-proxy -- curl localhost:15000/reset_counters -X POST
执行如下命令可以查看Sidecar代理中的计数器统计成功处理了多少次, 清空之后应当为0:
kubectl exec reviews-v1-55b668fc65-jhxlj -c istio-proxy -- curl localhost:15000/stats |grep inbound |grep upstream_rq_200
可以看到类似结果输出:
cluster.inbound|8000||.upstream_rq_200: 0
- 将review的v2版本的Deployment副本数调整为0, 即在Kubernetes集群中将名为reviews-v2的Deployment部署的副本数缩容为0。
然后, 重新将在Kubernetes集群中将名为reviews-v2的Deployment部署的副本数从0扩为1,采用hey 命令发送压测请求入口网关 。并立即执行hey 命令同样发送压测请求20s:
hey -z 20s http://${网关地址}/productpage
Status code distribution:
[200] 3260 responses
这表示通过hey 命令在20s 时间内成功发送了3260 个请求
然后对比reviews-v1 和 reviews-v2 两个pod ,可以看到reviews-v2 POD实例接受到的请求只占少量比例;
执行如下命令可以查看reviews-v1 中Sidecar代理中的计数器统计成功处理了多少次:
kubectl exec reviews-v1-55b668fc65-jhxlj -c istio-proxy -- curl localhost:15000/stats |grep inbound |grep upstream_rq_200
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 20873 0 20873 0 0 19.9M 0 --:--:-- --:--:-- --:--:-- 19.9M
cluster.inbound|9080||.external.upstream_rq_200: 2927
cluster.inbound|9080||.upstream_rq_200: 2927
执行如下命令可以查看reviews-v2 中Sidecar代理中的计数器统计成功处理了多少次:
kubectl exec reviews-v2-858f99c99-j6jww -c istio-proxy -- curl localhost:15000/stats |grep inbound |grep upstream_rq_200
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 30149 0 30149 0 0 28.7M 0 --:--:-- --:--:-- --:--:-- 28.7M
cluster.inbound|9080||.external.upstream_rq_200: 333
cluster.inbound|9080||.upstream_rq_200: 333
根据上述统计数据, 可以看到在前20s 因为在120s 的慢启动窗口期内,reviews-v2 Pod处理了少量请求(10% 左右)
慢启动窗口期之后测试, 再次清空reviews-v1、reviews-v2 的计数器。执行如下命令:
## reviews-v1 版本对应Pod中的Sidecar代理计数器
kubectl exec reviews-v1-55b668fc65-jhxlj -c istio-proxy -- curl localhost:15000/reset_counters -X POST
## reviews-v2 版本对应Pod中的Sidecar代理计数器
kubectl exec reviews-v2-858f99c99-j6jww -c istio-proxy -- curl localhost:15000/reset_counters -X POST
然后同样执行hey 命令发送压测流量20s, 再次执行如下命令查看reviews-v1与reviews-v2 中的Sidecar代理中的计数器统计成功处理了多少次:
kubectl exec reviews-v1-55b668fc65-jhxlj -c istio-proxy -- curl localhost:15000/stats |grep inbound |grep upstream_rq_200
cluster.inbound|9080||.external.upstream_rq_200: 1600
cluster.inbound|9080||.upstream_rq_200: 1600
kubectl exec reviews-v2-858f99c99-j6jww -c istio-proxy -- curl localhost:15000/stats |grep inbound |grep upstream_rq_200
cluster.inbound|9080||.external.upstream_rq_200: 1600
cluster.inbound|9080||.upstream_rq_200: 1600
可以看到在慢启动窗口时间之外,reviews-v1 和 reviews-v2 接受并处理了等量的请求数。