第十四部分 Istio TCP 流量转移

简述

本文介绍如何优雅的将微服务中的 TCP 流量从一个版本迁移到另一个版本。例如将 TCP 流量从旧版本迁移到一个新版本。在 Istio 中可以通过定义一组规则,将 TCP 流量在不同服务之间进行分配。此示例首先把 100% 的 TCP 流量发送到 tcp-echo:v1;下一步就是使用 Istio 的路由分配能力,把 20% 的流量分配到 tcp-echo:v2 服务之中。

前提

  • 正确安装Istio
  • 了解流量管理相关概念

应用基于权重的 TCP 路由

部署 tcp-echo 微服务的 v1 版本手工 Sidecar 注入,使用如下命令:

kubectl apply -f <(istioctl kube-inject -f samples/tcp-echo/tcp-echo-services.yaml)

YAML内容具体如下:

apiVersion: v1
kind: Service
metadata:
  name: tcp-echo
  labels:
    app: tcp-echo
spec:
  ports:
  - name: tcp
    port: 9000
  selector:
    app: tcp-echo
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tcp-echo-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: tcp-echo
        version: v1
    spec:
      containers:
      - name: tcp-echo
        image: istio/tcp-echo-server:1.1
        imagePullPolicy: IfNotPresent
        args: [ "9000", "one" ]
        ports:
        - containerPort: 9000
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tcp-echo-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: tcp-echo
        version: v2
    spec:
      containers:
      - name: tcp-echo
        image: istio/tcp-echo-server:1.1
        imagePullPolicy: IfNotPresent
        args: [ "9000", "two" ]
        ports:
        - containerPort: 9000

把所有目标是 tcp-echo 微服务的 TCP 流量路由到 v1 版本:

kubectl apply -f samples/tcp-echo/tcp-echo-all-v1.yaml

具体的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:
    - "*"
---
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
---
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

确认 tcp-echo 服务已经启动并开始运行。

获取 $INGRESS_PORT 的值,用它保存 Ingress 的外部 IP 地址:

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')

向 tcp-echo 微服务发送一些 TCP 流量:

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 前缀,这代表所有访问 tcp-echo 服务的流量都被路由到了 v1 版本。

用下面的命令把 20% 的流量从 tcp-echo:v1 转移到 tcp-echo:v2:

kubectl apply -f samples/tcp-echo/tcp-echo-20-v2.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

需要一定时间完成新规则的传播和生效。

确认该规则已经完成替换:

kubectl get virtualservice tcp-echo -o yaml

向 tcp-echo 微服务发送更多 TCP 流量:

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

现在应该会看到,输出内容中有 20% 的时间戳前缀为 two,这意味着 80% 的流量被路由到 tcp-echo:v1,其余 20% 流量被路由到了 v2。

理解原理

这个任务里,用 Istio 的权重路由功能,把一部分访问 tcp-echo 服务的 TCP 流量被从旧版本迁移到了新版本。容器编排平台中的版本迁移使用的是对特定组别的实例进行伸缩来完成对流量的控制的,两种迁移方式显然大相径庭。在 Istio 中可以对两个版本的 tcp-echo 服务进行独立的扩缩容,伸缩过程中不会对流量的分配结果造成影响。

 

你可能感兴趣的:(istio,IstioTCP流量转移)