前提条件
本文假设您的 ACK 集群已经创建完成。
开启 MSE 微服务治理
- 点击 开通MSE微服务治理专业版 以使用微服务治理能力。
- 访问容器服务控制台,打开应用目录,搜索
,选择对应集群,点击创建。ack-mse-pilot
- 如果您使用了ASK/ECI,请首先 给 ECI 授权访问 MSE 的权限 。

- 安装
,安装步骤请参考之前的说明ack-kubernetes-cronhpa-controller
-
ack-ingress-nginx
- 访问 MSE 控制台,在K8s集群列表中选择相应集群,点击管理,选择
命名空间,点击开启服务治理能力。default
开启 AHAS 应用防护
- 点击开通 AHAS 应用防护 以使用应用流控能力,请注意,需要开通 AHAS 流量防护专业版
-
ack-ahas-sentinel-pilot
部署 Demo 应用程序
将下面的文件保存到 mse-demo.yaml 中,并执行
kubectl apply -f mse-demo.yaml
以部署应用,这里我们将要部署 zuul,A, B, C 三个应用,其中 A、B 两个应用分别部署一个基线版本和一个灰度版本,B应用的基线版本关闭了无损下线能力,灰度版本开启了无损下线能力。C应用有一个
spring-cloud-c-warmup
应用,开启了服务预热能力,其中预热时长为2分钟。
# 入口 zuul 应用
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-zuul
spec:
replicas: 1
selector:
matchLabels:
app: spring-cloud-zuul
template:
metadata:
annotations:
msePilotCreateAppName: spring-cloud-zuul
alibabacloud.com/burst-resource: eci
labels:
app: spring-cloud-zuul
spec:
containers:
- env:
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk/jre
- name: LANG
value: C.UTF-8
image: registry-vpc.cn-beijing.aliyuncs.com/wangtao-mse/spring-cloud-zuul:1.0.1
imagePullPolicy: Always
name: spring-cloud-zuul
ports:
- containerPort: 20000
# A 应用 base 版本,开启按照机器纬度全链路透传
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: spring-cloud-a
name: spring-cloud-a
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-a
template:
metadata:
annotations:
msePilotCreateAppName: spring-cloud-a
ahasPilotAutoEnable: "on"
ahasAppName: spring-cloud-a
armsPilotAutoEnable: "on"
armsPilotCreateAppName: spring-cloud-a
alibabacloud.com/burst-resource: eci
k8s.aliyun.com/eci-use-specs: 4-8Gi
labels:
app: spring-cloud-a
spec:
containers:
- env:
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk/jre
- name: profiler.micro.service.tag.trace.enable
value: "true"
image: registry-vpc.cn-beijing.aliyuncs.com/wangtao-mse/spring-cloud-a:0.1-SNAPSHOT
imagePullPolicy: Always
name: spring-cloud-a
ports:
- containerPort: 20001
protocol: TCP
resources:
requests:
cpu: '4'
memory: 8Gi
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 10
periodSeconds: 30
# A 应用 gray 版本,开启按照机器纬度全链路透传
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: spring-cloud-a-gray
name: spring-cloud-a-gray
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-a-gray
strategy:
template:
metadata:
annotations:
alicloud.service.tag: gray
msePilotCreateAppName: spring-cloud-a
alibabacloud.com/burst-resource: eci
k8s.aliyun.com/eci-use-specs: 4-8Gi
labels:
app: spring-cloud-a-gray
spec:
containers:
- env:
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk/jre
- name: profiler.micro.service.tag.trace.enable
value: "true"
image: registry-vpc.cn-beijing.aliyuncs.com/wangtao-mse/spring-cloud-a:0.1-SNAPSHOT
imagePullPolicy: Always
name: spring-cloud-a-gray
ports:
- containerPort: 20001
protocol: TCP
resources:
requests:
cpu: '4'
memory: 8Gi
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 10
periodSeconds: 30
# B 应用 base 版本,关闭无损下线能力
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: spring-cloud-b
name: spring-cloud-b
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-b
strategy:
template:
metadata:
annotations:
msePilotCreateAppName: spring-cloud-b
alibabacloud.com/burst-resource: eci
k8s.aliyun.com/eci-use-specs: 4-8Gi
labels:
app: spring-cloud-b
spec:
containers:
- env:
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk/jre
- name: micro.service.shutdown.server.enable
value: "false"
- name: profiler.micro.service.http.server.enable
value: "false"
- name: profiler.micro.service.warmup.enable
value: "true"
image: registry-vpc.cn-beijing.aliyuncs.com/wangtao-mse/spring-cloud-b:0.1-SNAPSHOT
imagePullPolicy: Always
name: spring-cloud-b
ports:
- containerPort: 8080
protocol: TCP
resources:
requests:
cpu: '4'
memory: 8Gi
livenessProbe:
tcpSocket:
port: 20002
initialDelaySeconds: 10
periodSeconds: 30
# B 应用 gray 版本,默认开启无损下线功能
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: spring-cloud-b-gray
name: spring-cloud-b-gray
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-b-gray
template:
metadata:
annotations:
alicloud.service.tag: gray
msePilotCreateAppName: spring-cloud-b
alibabacloud.com/burst-resource: eci
k8s.aliyun.com/eci-use-specs: 4-8Gi
labels:
app: spring-cloud-b-gray
spec:
containers:
- env:
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk/jre
- name: profiler.micro.service.warmup.enable
value: "true"
image: registry-vpc.cn-beijing.aliyuncs.com/wangtao-mse/spring-cloud-b:0.1-SNAPSHOT
imagePullPolicy: Always
name: spring-cloud-b-gray
ports:
- containerPort: 8080
protocol: TCP
resources:
requests:
cpu: '4'
memory: 8Gi
livenessProbe:
tcpSocket:
port: 20002
initialDelaySeconds: 10
periodSeconds: 30
lifecycle:
preStop:
exec:
command:
- /bin/sh
- '-c'
- >-
wget http://127.0.0.1:54199/offline 2>/tmp/null;sleep
30;exit 0
# C 应用 base 版本
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: spring-cloud-c
name: spring-cloud-c
spec:
replicas: 2
selector:
matchLabels:
app: spring-cloud-c
template:
metadata:
annotations:
msePilotCreateAppName: spring-cloud-c
alibabacloud.com/burst-resource: eci
k8s.aliyun.com/eci-use-specs: 4-8Gi
labels:
app: spring-cloud-c
spec:
containers:
- env:
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk/jre
image: registry-vpc.cn-beijing.aliyuncs.com/wangtao-mse/spring-cloud-c:0.1-SNAPSHOT
imagePullPolicy: Always
name: spring-cloud-c
ports:
- containerPort: 8080
protocol: TCP
resources:
requests:
cpu: '4'
memory: 8Gi
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 10
periodSeconds: 30
# C 应用 warmup 版本
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: spring-cloud-c-warmup
name: spring-cloud-c-warmup
spec:
replicas: 1
selector:
matchLabels:
app: spring-cloud-c-warmup
template:
metadata:
annotations:
msePilotCreateAppName: spring-cloud-c-warmup
alibabacloud.com/burst-resource: eci
k8s.aliyun.com/eci-use-specs: 4-8Gi
labels:
app: spring-cloud-c-warmup
spec:
containers:
- env:
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk/jre
- name: profiler.micro.service.warmup.enable
value: "true"
- name: profiler.micro.service.warmup.time
value: "120"
image: registry-vpc.cn-beijing.aliyuncs.com/wangtao-mse/spring-cloud-c:0.1-SNAPSHOT
imagePullPolicy: IfNotPresent
name: spring-cloud-c-warmup
ports:
- containerPort: 8080
protocol: TCP
resources:
requests:
cpu: '4'
memory: 8Gi
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 10
periodSeconds: 30
lifecycle:
preStop:
exec:
command:
- /bin/sh
- '-c'
- >-
wget http://127.0.0.1:54199/offline 2>/tmp/null;sleep
30;exit 0
# Nacos Server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nacos-server
name: nacos-server
spec:
replicas: 1
selector:
matchLabels:
app: nacos-server
template:
metadata:
labels:
app: nacos-server
spec:
containers:
- env:
- name: MODE
value: standalone
image: registry-vpc.cn-beijing.aliyuncs.com/wangtao-mse/nacos-server:latest
imagePullPolicy: Always
name: nacos-server
resources:
requests:
cpu: 250m
memory: 512Mi
dnsPolicy: ClusterFirst
restartPolicy: Always
# Nacos Server Service 配置
---
apiVersion: v1
kind: Service
metadata:
name: nacos-server
spec:
ports:
- port: 8848
protocol: TCP
targetPort: 8848
selector:
app: nacos-server
type: ClusterIP
#HPA 配置
---
apiVersion: autoscaling.alibabacloud.com/v1beta1
kind: CronHorizontalPodAutoscaler
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: spring-cloud-b
spec:
scaleTargetRef:
apiVersion: apps/v1beta2
kind: Deployment
name: spring-cloud-b
jobs:
- name: "scale-down"
schedule: "0 */4 * * * *"
targetSize: 2
- name: "scale-up"
schedule: "2 */4 * * * *"
targetSize: 4
---
apiVersion: autoscaling.alibabacloud.com/v1beta1
kind: CronHorizontalPodAutoscaler
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: spring-cloud-b-gray
spec:
scaleTargetRef:
apiVersion: apps/v1beta2
kind: Deployment
name: spring-cloud-b-gray
jobs:
- name: "scale-down"
schedule: "0 */5 * * * *"
targetSize: 2
- name: "scale-up"
schedule: "3 */5 * * * *"
targetSize: 4
---
apiVersion: autoscaling.alibabacloud.com/v1beta1
kind: CronHorizontalPodAutoscaler
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: spring-cloud-c-warmup
spec:
scaleTargetRef:
apiVersion: apps/v1beta2
kind: Deployment
name: spring-cloud-c-warmup
jobs:
- name: "scale-down"
schedule: "0 */4 * * * *"
targetSize: 0
- name: "scale-up"
schedule: "1 */4 * * * *"
targetSize: 1
# zuul 网关开启 SLB 暴露展示页面
---
apiVersion: v1
kind: Service
metadata:
name: zuul-slb
spec:
ports:
- port: 80
protocol: TCP
targetPort: 20000
selector:
app: spring-cloud-zuul
type: ClusterIP
# 为 zuul 网关开启 Ingress
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: zuul
spec:
rules:
- http:
paths:
- backend:
serviceName: zuul-slb
servicePort: 80
path: /
流量压力来源
在
spring-cloud-zuul
应用中,每个 pod 具备并发为 100 qps 的访问本地 zuul 端口的
127.0.0.1:20000:/A/a
的http请求流量,另外有10 qps 会访问
127.0.0.1:20000:/A/a
并且带上
x-mse-tag=gray
这个header,当前 zuul 的 pod 数为1,所以
spring-cloud-a
应用的平均qps为 110。压力可以通过 环境变量
demo.qps
来调节压力大小,默认为100
流量架构图如下:
结果验证
MSE 场景一:对经过机器的流量进行自动染色,实现全链路灰度
我们在 MSE 控制台对
spring-cloud-a
应用配置如下流量比例规则,由于我们对 spring-cloud-a 应用增加了
profiler.micro.service.tag.trace.enable=true
的开关,spring-cloud-a 应用会对经过他的流量进行染色透传,从而实现全链路灰度。
spring-cloud-a
中,灰度分组的流量是10,基线分组的流量是100.
spring-cloud-b 中,灰度分组的流量是也是10,基线分组的流量是100.
找到 容器服务对外暴露的 Ingress 的端点。
在命令行中输入以下命令,发现正常的流量走到基线的机器上
curl http://$IP/A/a
A[172.16.2.16] -> B[172.16.2.20] -> C[172.16.2.21]
在命令行中输入一下命令,带上特殊的 header ,发现灰度的流量走到灰度的机器上,并且会向后透传经过 A 和 B 的灰度机器,最后回到 C的基线版本中。
curl -H"x-mse-tag:gray" http://$IP/A/a
Agray[172.16.2.23] -> Bgray[172.16.2.18] -> C[172.16.2.21]
MSE 场景二:服务预热
我们在
spring-cloud-c-warmup
应用开启了定时HPA模拟应用启动的过程,同时对spring-cloud-c-warmup 应用开启了默认2分钟时长的预热功能
profiler.micro.service.warmup.time=120
可以直接在spring-cloud-c-warmup应用直观地看到效果
从上图可以看出来流量缓慢增大,直观地服务预热看到服务预热的效果。
MSE 场景三:无损下线
由于我们对
spring-cloud-b
跟
spring-cloud-b-gray
应用均开启了定时HPA,模拟每4分钟进行一次定时的扩缩容。
我们可以直接从
spring-cloud-a
应用的监控看出来,未开启无损下线功能的监控存在错误。而 gray的流量因为默认开启了无损下线功能,流量默认无损。
可以看到gray的流量在pod扩缩容的过程中无流量损失,未打标的流量由于关闭了无损下线功能,在pod扩缩容的过程中流量出现了损失,如上图所示未打标的流量有 122 的请求错误。
通过 AHAS 实现限流降级
打开
AHAS 控制台,找到
spring-cloud-a
应用,选择接口详情,找到
/a
接口,点击 + 好号新增流控规则
基于阿里云微服务引擎 MSE 的全链路灰度实践
选择流控规则,输入单机 QPS 限流阈值 10,点击下一步,最后点击新增。
点击新增添加流控规则
等待约 10s 左右,观察 接口的 QPS 情况,发现通过 QPS 从 100 下降到 20,拒绝 QPS 从 0 上升到 80,因为
spring-cloud-a
有两台机器,因此总的通过 QPS 为 20.
接下来,将该限流规则关闭
观察 QPS , 发现 通过 QPS 回到 100,拒绝 QPS 降低为 0。