代码继续接着前面的文章【云原生】整合K8s + SpringCloudK8s + gRpc + RocketMQ + Istio + Envoy,本篇文章我们测试下请求路由功能。
生产中我们上了个新接口或者新功能,一般会经过 内灰 -> 外灰5% -> 外灰10% ...... 外灰100%的过程,这篇文章我们就来模拟下。为了方便测试,我修改yaml文件,同一个应用部署多个版本,每个版本代表着一个新的功能。
service-provider-deploy-version.yaml
apiVersion: v1
kind: Namespace
metadata:
name: service-k8s-demo
labels:
name: service-k8s-demo
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: service-k8s-demo
namespace: service-k8s-demo
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: service-k8s-demo
name: service-k8s-demo
rules:
- apiGroups:
- ""
resources:
- services
- configmaps
- endpoints
- nodes
- pods
- secrets
- namespaces
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: service-k8s-demo
namespace: service-k8s-demo
subjects:
- kind: ServiceAccount
name: service-k8s-demo
namespace: service-k8s-demo
roleRef:
kind: ClusterRole
name: service-k8s-demo
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-provider-v1
namespace: service-k8s-demo
labels:
app: service-provider
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: service-provider
version: v1
template:
metadata:
name: service-provider
labels:
app: service-provider
version: v1
spec:
containers:
- name: service-provider
image: service-provider:1.0
imagePullPolicy: IfNotPresent
env:
- name: SPRING_PROFILES_ACTIVE
value: "dev"
ports:
- name: http
protocol: TCP
containerPort: 30000
- name: grpc
protocol: TCP
containerPort: 9090
serviceAccountName: service-k8s-demo
restartPolicy: Always
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-provider-v2
namespace: service-k8s-demo
labels:
app: service-provider
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: service-provider
version: v2
template:
metadata:
name: service-provider
labels:
app: service-provider
version: v2
spec:
containers:
- name: service-provider
image: service-provider:1.0
imagePullPolicy: IfNotPresent
env:
- name: SPRING_PROFILES_ACTIVE
value: "dev"
ports:
- name: http
protocol: TCP
containerPort: 30000
- name: grpc
protocol: TCP
containerPort: 9090
serviceAccountName: service-k8s-demo
restartPolicy: Always
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-provider-v3
namespace: service-k8s-demo
labels:
app: service-provider
version: v3
spec:
replicas: 1
selector:
matchLabels:
app: service-provider
version: v3
template:
metadata:
name: service-provider
labels:
app: service-provider
version: v3
spec:
containers:
- name: service-provider
image: service-provider:1.0
imagePullPolicy: IfNotPresent
env:
- name: SPRING_PROFILES_ACTIVE
value: "dev"
ports:
- name: http
protocol: TCP
containerPort: 30000
- name: grpc
protocol: TCP
containerPort: 9090
serviceAccountName: service-k8s-demo
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: service-provider
namespace: service-k8s-demo
spec:
selector:
app: service-provider
ports:
- port: 80
targetPort: 30000
name: http
- port: 9090
targetPort: 9090
name: grpc
type: NodePort
dashboard里的展示
destination-rule-all.yaml
为每个应用定义版本
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: service-provider-rule-all
namespace: service-k8s-demo
spec:
host: service-provider
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
---
service-gateway.yaml
内灰
一般使用userId来做,把内部员工的userId收集起来,先让他们来体验。但是我没有测试成功,而且内灰用户有很多,match的规则支持exact、prefix和regex这三种,所以有很多内灰用户的话,该怎么配呢?有大佬知道可以告诉下小弟我哦。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: service-k8s-demo-gateway
namespace: service-k8s-demo
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 31400
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: service-k8s-demo-virtual-service
namespace: service-k8s-demo
spec:
hosts:
- "maple.example.com"
gateways:
- service-k8s-demo-gateway
http:
- match:
- uri:
prefix: /consumer
route:
- destination:
host: service-consumer
port:
number: 80
- match:
- headers:
user-id:
exact: "123456"
- uri:
prefix: /provider
route:
- destination:
host: service-provider
subset: v1
- route:
- destination:
host: service-provider
port:
number: 80
subset: v3
切流
v1给50%流量,v2给30%,v3给20%,这里是测试成功的。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: service-k8s-demo-gateway
namespace: service-k8s-demo
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 31400
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: service-k8s-demo-virtual-service
namespace: service-k8s-demo
spec:
hosts:
- "maple.example.com"
gateways:
- service-k8s-demo-gateway
http:
- match:
- uri:
prefix: /consumer
route:
- destination:
host: service-consumer
port:
number: 80
- match:
- uri:
prefix: /provider
route:
- destination:
host: service-provider
subset: v1
port:
number: 80
weight: 50
- destination:
host: service-provider
subset: v2
port:
number: 80
weight: 30
- destination:
host: service-provider
subset: v3
port:
number: 80
weight: 20
也可以针对某个接口配置,下面我就为 /provider/grpc/queryMember 这个接口配置路由到v3版本上,但是这里需要注意一下,要把最细分的 exact: /provider/grpc/queryMember 放在另一个规则prefix: /provider的前面,不然它按照顺序执行,就会被 prefix: /provider 直接拦截掉了。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: service-k8s-demo-gateway
namespace: service-k8s-demo
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 31400
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: service-k8s-demo-virtual-service
namespace: service-k8s-demo
spec:
hosts:
- "maple.example.com"
gateways:
- service-k8s-demo-gateway
http:
- match:
- uri:
prefix: /consumer
route:
- destination:
host: service-consumer
port:
number: 80
- match:
- uri:
exact: /provider/grpc/queryMember
route:
- destination:
host: service-provider
subset: v3
port:
number: 80
- match:
- uri:
prefix: /provider
route:
- destination:
host: service-provider
subset: v1
port:
number: 80
weight: 50
- destination:
host: service-provider
subset: v2
port:
number: 80
weight: 30
- destination:
host: service-provider
subset: v3
port:
number: 80
weight: 20
完全切流
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: service-k8s-demo-gateway
namespace: service-k8s-demo
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 31400
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: service-k8s-demo-virtual-service
namespace: service-k8s-demo
spec:
hosts:
- "maple.example.com"
gateways:
- service-k8s-demo-gateway
http:
- match:
- uri:
prefix: /consumer
route:
- destination:
host: service-consumer
port:
number: 80
- match:
- uri:
prefix: /provider
route:
- destination:
host: service-provider
port:
number: 80
subset: v3
测试
发了5次请求,结果发现只有v3打印了日志,测试成功
超时配置
service-consumer的代码里硬编码等待2s
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: service-k8s-demo-gateway
namespace: service-k8s-demo
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 31400
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: service-k8s-demo-virtual-service
namespace: service-k8s-demo
spec:
hosts:
- "maple.example.com"
gateways:
- service-k8s-demo-gateway
http:
- match:
- uri:
prefix: /consumer
route:
- destination:
host: service-consumer
port:
number: 80
subset: v1
- match:
- uri:
exact: /provider/grpc/queryMember
route:
- destination:
host: service-provider
subset: v3
port:
number: 80
timeout: 0.5s #测试超时
- match:
- uri:
prefix: /provider
route:
- destination:
host: service-provider
subset: v1
port:
number: 80
weight: 50 #测试切流
- destination:
host: service-provider
subset: v2
port:
number: 80
weight: 30
- destination:
host: service-provider
subset: v3
port:
number: 80
weight: 20