TCM服务网格同城双活设计方案

175 阅读4分钟

TCM服务网格能力概述

架构概述

上篇文章,讲述了接入层高可用架构设计,这篇文章我们聊聊TCM(服务网格)TCM(服务网格)是腾讯云提供的微服务流量治理云产品,100% 兼容支持 Istio API,TCM与腾讯云基础设施原生集成,提供全托管服务化的支撑能力,轻松保障和管理网格生命周期。

简易架构如下图:

腾讯云托管网格主要是增强了Control plane,默认与腾讯云基础设施集成,如CLB(负载均衡)、APM(应用性能监控)、TMP(Prometheus)、CLS(日志服务)、TKE(容器服务)等,用户无需配置即可用原生方式使用服务网格。

托管网格的跨区可用性

托管网格的控制面,部署在对所有云用户不可见的TKE集群。

TKE集群内node来自多可用区,同时通过反亲和性配置,保证同一个用户的控制面进程在不同的可用区,从而实现了部署层面的高可用。

同时,基于TKE集群本身的健康检查机制等,保证了进程的高可用

TCM详细资料参考:cloud.tencent.com/document/pr…

架构设计方案

同城双活需求分析

使用了TCM服务网格产品,只需要考虑数据面的高可用建设,即业务程序的同城双活。

这种架构模式下,有两个技术点需要解决:

1、  接入层的流量负载均衡

2、  逻辑层的set部署,即可用区内流量闭环

设计方案

适合上面同城双活的集群部署模式,如下图一、图二所示。

图一代表一个服务网格 + 一个TKE集群的部署模式,TKE集群的Node节点分布在两个可用区

图二代表一个服务网格 + 两个TKE集群的部署模式,一个TKE的node节点分布在上海四区,另一个TKE的node节点分布在上海五区。

图一 图二

建设要求一个服务网格+一个TKE集群一个服务网格+两个TKE集群
部署模式承载双活业务的node节点在两个可用区内平均分布保证在一个可用区内pod>=2副本保证在一个TKE集群内>=2副本
反亲和性配置避免同区、同node的反亲和性配置(preferred模式)配置避免同node的反亲和性配置(preferred模式)
就近接入能力网格默认能力网格默认能力
failover能力需配置outlierDetection需配置outlierDetection

原理分析

就近接入能力

istio本身会参考Region/Zone/Sub-zone这个三元组来决定就近调度。

Region来源:对应云的地域,从k8s node节点label中获取,key是 topology.kubernetes.io/region

Zone来源:对应云的可用区,从k8s node节点label中获取,key是topology.kubernetes.io/zone

Sub-zone来源:istio自定义的,用来定义比可用区更细的调度单元,需用户按需给node节点打label topology.istio.io/subzone

计算就近的顺序是Region、Zone、Sub-zone。

比如一个服务网格+一个TKE集群场景,流量进入四区的istio-gateway后,只会调用四区的Service A,依此类推。

默认情况下,该能力是关闭的,即流量进入四区的istio-gateway后,会在四区、五区的Service A轮询,如需使用,需开启异常检测能力,即配置outlierDetection流量管理功能,参考配置如下:

spec:
  host: stock
  trafficPolicy:
    outlierDetection:
      consecutiveErrors: 5
      interval: 10000ms
      baseEjectionTime: 30000ms
      maxEjectionPercent: 10
      minHealthPercent: 50

failover能力

就近接入能力开启后,那就面临一个问题,如果就近区域的服务全部不可用,如何failover呢?

实际是通过envoy endpoints中的priority参数来控制,不设置默认是0。

在大于两个单元的场景,failover的顺序是按0>1>2的顺序来转移。

细节参考文档:Locality Weighted Load Balancing — envoy tag-v1.23.0 documentation

相关配置分析

调用链路

如果流量是从四区的istio gateway进入,那么访问product时,链路会是istio gateway --> frontend --> product,且都在四区,反之亦然。

配置情况

下面是一个服务网格+一个TKE集群场景下ingress-gateway的endpoint配置,172.16.0.38 locality为zone: "200005"

- addedViaApi: true
  hostStatuses:
  - address:
      socketAddress:
        address: 172.16.1.124
        portValue: 80
    healthStatus:
      edsHealthStatus: HEALTHY
    locality:
      region: sh
      zone: "200004"
    weight: 1
  - address:
      socketAddress:
        address: 172.16.0.38
        portValue: 80
    healthStatus:
      edsHealthStatus: HEALTHY
    locality:
      region: sh
      zone: "200005"
    weight: 1
  name: outbound|80||istio-ingressgateway.istio-system.svc.cluster.local
  observabilityName: outbound|80||istio-ingressgateway.istio-system.svc.cluster.local

frontend的endpoint配置,172.16.0.37 locality为zone: "200005"

- addedViaApi: true
  hostStatuses:
  - address:
      socketAddress:
        address: 172.16.0.37
        portValue: 80
    healthStatus:
      edsHealthStatus: HEALTHY
    locality:
      region: sh
      zone: "200005"
    weight: 1
  - address:
      socketAddress:
        address: 172.16.1.120
        portValue: 80
    healthStatus:
      edsHealthStatus: HEALTHY
    locality:
      region: sh
      zone: "200004"
    priority: 1
    weight: 1
  name: outbound|80||frontend.base.svc.cluster.local
  observabilityName: outbound|80||frontend.base.svc.cluster.local

pronduct的endpoint配置,172.16.0.36 locality为zone: "200005"

- addedViaApi: true
  hostStatuses:
  - address:
      socketAddress:
        address: 172.16.0.36
        portValue: 7000
    locality:
      region: sh
      zone: "200005"
    weight: 1
  - address:
      socketAddress:
        address: 172.16.1.119
        portValue: 7000
    locality:
      region: sh
      zone: "200004"
    priority: 1
    weight: 1
  name: outbound|7000||product.base.svc.cluster.local
  observabilityName: outbound|7000||product.base.svc.cluster.local

结果验证

从调用链来看,确实实现了就近接入,且与上面配置一致:

从前端界面来看,相关请求都到了五区。