服务网格ASM的流量管理功能可以实现应用的流量迁移。本文介绍如何通过ASM实现TCP应用流量的迁移。
背景信息
本文以Istio官方Task TCP-Traffic-Shifting为例来讲述如何实现在一个TCP服务的两个版本之间进行流量灰度切换。该Task中的服务是一个简单地Echo服务,在v1版本中,该服务在收到的数据在前面加上“one”并返回;在v2版本中,该服务在收到的数据前面加上“two”并返回。
步骤一:部署示例应用
- 部署TCP- Echo应用的2个版本。
- 登录容器服务管理控制台,在左侧导航栏中选择集群。
- 在集群列表页面中,单击目标集群名称,然后在左侧导航栏中,选择。
- 在无状态页面上方,选择目标命名空间,然后单击右上角的使用YAML创建资源。
- 设置示例模板为自定义,将下面的YAML粘贴到模板文本框,然后单击创建。
apiVersion: apps/v1
kind: Deployment
metadata:
name: tcp-echo-v1
spec:
replicas: 1
selector:
matchLabels:
app: tcp-echo
version: v1
template:
metadata:
labels:
app: tcp-echo
version: v1
spec:
containers:
- name: tcp-echo
image: docker.io/istio/tcp-echo-server:1.1
imagePullPolicy: IfNotPresent
args: [ "9000", "one" ]
ports:
- containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tcp-echo-v2
spec:
replicas: 1
selector:
matchLabels:
app: tcp-echo
version: v2
template:
metadata:
labels:
app: tcp-echo
version: v2
spec:
containers:
- name: tcp-echo
image: docker.io/istio/tcp-echo-server:1.1
imagePullPolicy: IfNotPresent
args: [ "9000", "two" ]
ports:
- containerPort: 9000
在
无状态页面,可以看到新创建的两个版本的TCP-Echo应用。
- 创建一个服务,并将其对外暴露。
- 登录容器服务管理控制台,在左侧导航栏中选择集群。
- 在集群列表页面中,单击目标集群名称,然后在左侧导航栏中,选择。
- 在服务页面上方,选择目标命名空间,然后单击右上角的创建。
- 在创建服务对话框,配置服务的相关信息,然后单击创建。
配置项 |
说明 |
名称 |
本文配置为tcp-echo。 |
类型 |
选择服务类型,即服务访问的方式。支持虚拟集群IP、节点端口和负载均衡。
说明 当服务类型选择
虚拟集群IP时,才能设置
实例间发现服务(Headless Service)。您可以使用无头Service与其他服务发现机制进行接口,不与Kubernetes的实现捆绑在一起。
|
关联 |
本文选择tcp-echo-v1。
说明 将从关联的Deployment中提取
app 这个标签作为Service的Selector,这决定了Kubernetes service将流量转发到哪个Deployment。由于tcp-echo-v1和tcp-echo-v2两个Deployment拥有相同的标签,即
app:tcp-echo ,因此可以关联任一Deployment。
|
外部流量策略 |
支持Local或Cluster。
说明 当您的服务类型为
节点端口或
负载均衡时,才能设置
外部流量策略。
|
端口映射 |
本文配置名称为tcp,服务端口和容器端口为9000,协议为TCP。 |
注解 |
为该服务添加一个注解(annotation ),配置负载均衡的参数。例如,设置service.beta.kubernetes.io/alicloud-loadbalancer-bandwidth:20 表示将该服务的带宽峰值设置为20 Mbit/s,控制服务的流量。关于参数的说明,请参见通过Annotation配置负载均衡。 |
标签 |
为服务添加一个标签,标识该服务。 |
创建成功后,在
服务(Service)页面,可以看到新创建的
type-echo服务。
步骤二:设置路由规则
通过设置服务网格的Istio网关、虚拟服务和目标规则,将流量全部指向tcp-echo服务的v1版本。
- 登录ASM控制台,在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 创建服务网关。
- 在网格详情页面左侧导航栏,选择,然后在右侧页面,单击使用YAML创建。
- 在创建页面,命名空间选择default,选择任意场景模板,配置以下YAML,然后单击创建。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: tcp-echo-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 31400
name: tcp
protocol: TCP
hosts:
- "*"
- 创建虚拟服务。
- 在网格详情页面左侧导航栏,选择,然后在右侧页面,单击使用YAML创建。
- 在创建页面,命名空间选择default,选择任意场景模板,配置以下YAML,然后单击创建。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: tcp-echo
spec:
hosts:
- "*"
gateways:
- tcp-echo-gateway
tcp:
- match:
- port: 31400
route:
- destination:
host: tcp-echo
port:
number: 9000
subset: v1
- 创建目标规则。
- 在网格详情页面左侧导航栏,选择,然后在右侧页面,单击使用YAML创建。
- 在创建页面,命名空间选择default,选择任意场景模板,配置以下YAML,然后单击创建。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: tcp-echo-destination
spec:
host: tcp-echo
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
步骤三:部署入口网关
在入口网关中,添加端口31400,并指向Istio网关的31400端口。
- 登录ASM控制台,在左侧导航栏,选择。
- 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择。
- 在入口网关页面,单击创建,进行相关配置,然后单击创建。
部分配置项说明如下。关于配置项的更多说明,请参见
入口网关配置项说明。
配置项 |
说明 |
部署集群 |
选择要部署入口网关的集群。 |
负载均衡类型 |
本文选择公网访问。 |
选择负载均衡 |
- 使用已有负载均衡:从已有负载均衡列表中选择。
- 新建负载均衡:单击新建负载均衡,从下拉列表中选择所需的负载均衡规格。
说明 建议您为每个Kubernetes服务分配一个SLB。如果多个Kubernetes服务复用同一个SLB,存在以下风险和限制:
- 使用已有的SLB会强制覆盖已有监听,可能会导致您的应用不可访问。
- Kubernetes通过Service创建的SLB不能复用,只能复用您手动在控制台(或调用OpenAPI)创建的SLB。
- 复用同一个SLB的多个Service不能有相同的前端监听端口,否则会造成端口冲突。
- 复用SLB时,监听的名字以及虚拟服务器组的名字被Kubernetes作为唯一标识符。请勿修改监听和虚拟服务器组的名字。
- 不支持跨集群复用SLB。
|
端口映射 |
单击添加端口,配置名称为tcp,服务端口为31400。 |
步骤四:检查部署结果
通过Kubectl确认tcp-echo服务的流量指向是否符合预期。
- 通过Kubectl客户端连接至Kubernetes集群。具体操作,请参见步骤二:选择集群凭证类型。
- 执行以下命令,获得服务的地址与端口。
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')
- 使用
telnet
指令向tcp-echo服务发起连接请求。
telnet $INGRESS_HOST $INGRESS_PORT
Trying xxx.xxx.xxx.xxx...
Connected to xxx.xxx.xxx.xxx.
Escape character is '^]'
- 输入任意字符串,按Enter发送。
返回的字符串前面带了“one”,说明tcp-echo服务已经成功部署,且流量全部指向了tcp-echo-v1版本。
步骤五:按比例将流量路由到tcp-echo-v2
此处将20%的流量指向tcp-echo-v2版本,其余80%仍然打到tcp-echo-v1。
- 修改ASM实例的虚拟服务配置。
- 在网格详情页面左侧导航栏,选择。
- 在虚拟服务页面,单击tcp-echo所在操作列中的YAML。
- 在编辑实例页面的文本框中输入以下YAML文件内容,单击确定。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: tcp-echo
spec:
hosts:
- "*"
gateways:
- tcp-echo-gateway
tcp:
- match:
- port: 31400
route:
- destination:
host: tcp-echo
port:
number: 9000
subset: v1
weight: 80
- destination:
host: tcp-echo
port:
number: 9000
subset: v2
weight: 20
- 执行以下命令,向tcp-echo服务发起10次请求。
for i in {1..10}; do \
docker run -e INGRESS_HOST=$INGRESS_HOST -e INGRESS_PORT=$INGRESS_PORT -it --rm busybox sh -c "(date; sleep 1) | nc $INGRESS_HOST $INGRESS_PORT"; \
done
one Mon Nov 12 23:38:45 UTC 2018
two Mon Nov 12 23:38:47 UTC 2018
one Mon Nov 12 23:38:50 UTC 2018
one Mon Nov 12 23:38:52 UTC 2018
one Mon Nov 12 23:38:55 UTC 2018
two Mon Nov 12 23:38:57 UTC 2018
one Mon Nov 12 23:39:00 UTC 2018
one Mon Nov 12 23:39:02 UTC 2018
one Mon Nov 12 23:39:05 UTC 2018
one Mon Nov 12 23:39:07 UTC 2018
根据以上请求的分发情况,可以看到20%的流量指向了tcp-echo-v2。
说明 您的测试结果可能不一定总是10次中有2次打到tcp-echo-v2,但从较长时间范围的总体比例来看,将接近20%。