当您需要优化网络拓扑、扩容应用服务器或调整业务流量时,可以通过ASM的流量管理中心实现TCP应用流量的平滑迁移,确保关键业务的连续性和服务的高可用性。以Istio官方Task TCP-Traffic-Shifting为例,本文介绍如何在一个TCP服务的两个版本之间进行流量灰度切换。该Task中的Echo服务有两个版本,v1版本响应时会在接收到的消息前添加前缀“one”,v2版本会添加“two”,您可以观察流量转移的效果,并对分流策略进行微调,以满足具体的业务需求和性能目标。
前提条件
已开通以下服务:
已创建ACK集群。具体操作,请参见创建Kubernetes专有版集群和创建Kubernetes托管版集群。
已将ACK集群添加到ASM实例。具体操作,请参见创建ASM实例和添加集群到ASM实例。
步骤一:部署示例应用
部署TCP- Echo应用的2个版本。
登录容器服务管理控制台,在左侧导航栏选择集群。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择 。
在无状态页面上方,选择目标命名空间,然后单击右上角的使用YAML创建资源。
设置示例模板为自定义,将下面的YAML粘贴到模板文本框,然后单击创建。
在无状态页面,可以看到新创建的两个版本的TCP-Echo应用。
创建一个服务,并将其对外暴露。
登录容器服务管理控制台,在左侧导航栏选择集群。
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择 。
在服务页面上方,选择目标命名空间,然后单击右上角的创建。
在创建服务对话框,配置服务的相关信息,然后单击确定。
配置项
说明
服务名称
配置为tcp-echo。
服务类型
选择服务类型,即服务访问的方式。支持虚拟集群IP、节点端口和负载均衡。
说明当服务类型选择虚拟集群IP时,才能设置实例间发现服务(Headless Service)。您可以使用无头Service与其他服务发现机制进行接口,不与Kubernetes的实现捆绑在一起。
服务关联
配置名称为app,值为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配置传统型负载均衡CLB。标签
为服务添加一个标签,标识该服务。
创建成功后,在服务页面,可以看到新创建的tcp-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控制台,在左侧导航栏,选择 。
在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
在入口网关页面,单击创建,进行相关配置,然后单击创建。
部分配置项说明如下。关于配置项的更多说明,请参见创建入口网关。
配置项
说明
部署集群
选择要部署入口网关的集群。
负载均衡CLB类型
本文选择公网访问。
选择负载均衡
使用已有负载均衡:从已有负载均衡列表中选择。
新建负载均衡CLB:单击新建负载均衡CLB,从下拉列表中选择所需的负载均衡规格。
说明建议您为每个Kubernetes服务分配一个CLB。如果多个Kubernetes服务复用同一个CLB,存在以下风险和限制:
使用已有的CLB会强制覆盖已有监听,可能会导致您的应用不可访问。
Kubernetes通过Service创建的CLB不能复用,只能复用您手动在控制台(或调用OpenAPI)创建的CLB。
复用同一个CLB的多个Service不能有相同的前端监听端口,否则会造成端口冲突。
复用CLB时,监听的名字以及虚拟服务器组的名字被Kubernetes作为唯一标识符。请勿修改监听和虚拟服务器组的名字。
不支持跨集群复用CLB。
端口映射
单击添加端口,配置名称为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%。