使用ASM网格拓扑观测多集群的流量控制与容灾场景

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
可观测监控 Prometheus 版,每月50GB免费额度
应用型负载均衡 ALB,每月750个小时 15LCU
简介: 作为业内首个全托管Istio兼容的阿里云服务网格产品ASM,一开始从架构上就保持了与社区、业界趋势的一致性,控制平面的组件托管在阿里云侧,与数据面侧的用户集群独立。ASM产品是基于社区Istio定制实现的,在托管的控制面侧提供了用于支撑精细化的流量管理和安全管理的组件能力。通过托管模式,解耦了Istio组件与所管理的K8s集群的生命周期管理,使得架构更加灵活,提升了系统的可伸缩性。从2022年4月

作为业内首个全托管Istio兼容的阿里云服务网格产品ASM,一开始从架构上就保持了与社区、业界趋势的一致性,控制平面的组件托管在阿里云侧,与数据面侧的用户集群独立。ASM产品是基于社区Istio定制实现的,在托管的控制面侧提供了用于支撑精细化的流量管理和安全管理的组件能力。通过托管模式,解耦了Istio组件与所管理的K8s集群的生命周期管理,使得架构更加灵活,提升了系统的可伸缩性。从2022年4月1日起,阿里云服务网格ASM正式推出商业化版本, 提供了更丰富的能力、更大的规模支持及更完善的技术保障,更好地满足客户的不同需求场景,详情可进入阿里云官方网站 - 搜索服务网格ASM。

网格拓扑是一个服务网格可观测性工具,提供查看相关服务拓扑的可视化界面。阿里云服务网格ASM从1.7.5.25版本开始支持内置网格拓扑。

在默认情况下,网格拓扑服务部署在客户的数据面集群之中,并查询与客户数据面集群关联的Prometheus实例,这样可以显著降低客户操作集成服务网格、网格拓扑与Prometheus的操作成本。在这种模式下,每个客户集群都拥有自己的网格拓扑服务实例、并分别显示各自集群中的服务拓扑可视化情况。

如果客户的ASM实例管理了多个集群,且集群之间互相有流量访问,那么在一个网格拓扑服务中同时观测多个集群中的流量拓扑情况显然是不错的主意。那么可不可以做到这个效果呢?

通过配置ASM网格拓扑来对接阿里云ARMS Prometheus的聚合实例,我们就可以做到让ASM网格拓扑同时查询并展示多个集群的流量拓扑情况。让我们看看怎么做吧!

配置ASM网格拓扑连接阿里云Prometheus全局聚合实例

我们可以配置ASM网格拓扑来对接阿里云ARMS Prometheus的聚合实例,这样就可以同时查询聚合实例中提供的多个集群服务的指标信息,进而形成跨集群的网格拓扑。

前提条件

  1. 我们需要一个服务网格ASM实例,来管理多个ACK集群: 创建ASM实例
  2. 我们需要至少两个ACK集群,来实现ASM多集群管理的能力。需要注意的是,多集群场景下集群之间需要满足一定的网络条件: 多集群网络规划
  3. 由于我们通过连接阿里云ARMS Prometheus全局聚合实例来实现多集群的全局网格拓扑,因此我们的每个集群都需要接入阿里云ARMS Prometheus监控: 阿里云Prometheus监控

步骤一:将ACK集群加入ASM实例并打开监控指标

  1. 我们首先要将所有的ACK集群加入ASM实例,可以参考 在多集群管理模式下部署应用示例 来完成。
  2. 所有集群加入ASM实例后,我们需要打开ASM的监控指标能力,来启用Sidecar代理上报监控指标。
  1. 登录 ASM控制台 ,在左侧导航栏,选择 服务网格 > 网格管理
  2. 网格管理 页面,单击目标实例名称,然后在左侧导航栏,选择 可观测管理中心 > 监控指标
  3. 点选 集成自建Prometheus实现监控, 确认已按照对应文档完成相关参数配置 ,然后点击开 启监控指标生成与采集

如果勾选使用ARMS Prometheus采集监控指标并开启监控指标能力,ASM会默认为每个集群关联的ARMS Prometheus开启与服务网格的集成,同时将集群关联的ARMS Prometheus HTTP API 地址作为默认的Prometheus连接地址。

由于我们这里想要通过Prometheus全局聚合实例来查询多集群全局网格拓扑,因此这里我们选择集成自建Prometheus实现监控这个自由度更高的选项, 然后手动为ARMS Prometheus开启服务网格的集成。

  1. 我们需要为每个集群的ARMS Prometheus实例打开服务网格ASM的集成,这里可以参考 阿里云服务网格(ASM)组件接入

做完以上步骤,每个集群关联的ARMS Prometheus实例应该就可以读到本集群内Sidecar代理上报的指标了。接下来我们需要用一个全局聚合实例来将这些指标聚合起来。

步骤二:创建一个阿里云Prometheus全局聚合实例

我们可以参考这篇文档来为本地域下的多个集群Prometheus实例创建一个聚合实例:Prometheus实例 for GlobalView

  • 访问Endpoint 需要选择一个和ACK集群相同的地域,因为我们需要让集群中的ASM网格拓扑服务通过内网端点访问这个全局聚合实例。
  • 选择要聚合的实例 这一栏选中所有加入ASM的ACK集群所关联的Prometheus实例,这样网格拓扑就可以读取所有集群中Sidecar代理上报的指标了。

这一步做完之后,我们已经有了一个可以查看ASM中所有集群的全局大盘的Prometheus聚合实例,接下来我们只需要配置一下让ASM网格拓扑对接这个实例就可以了。

步骤三:开启ASM网格拓扑,对接Prometheus全局聚合实例

  1. 我们需要首先记录一下我们刚刚创建的Prometheus全局聚合实例的HTTP API地址。这可以在这个实例的设置页面中找到:

  1. 登录 ASM控制台 ,在左侧导航栏,选择 服务网格 > 网格管理
  2. 网格管理 页面,单击目标实例名称,然后在左侧导航栏,选择 可观测管理中心 > 网格拓扑 在启用ASM网格拓扑区域,输入我们上面拿到的Prometheus全局聚合实例的HTTP API内网地址,然后单击开始启用
  3. 选择一种方式来访问和登录我们的网格拓扑服务,这里可以参考 通过ASM控制台开启网格拓扑的可观测性 中的步骤二和步骤三来完成。

如果一切顺利的话,到这里我们就已经可以在任意一个ASM网格拓扑服务中观测到全局的网格拓扑图了。随意部署一个多集群场景下的应用到我们的多集群中,我们将可以看到流量在多集群中的流动情况。

一点小建议,可以调整一下ASM网格拓扑的显示信息:

  • 打开流量分布、流量请求速率和流量动画:将为拓扑图中的边提供更多有效的信息
  • 关闭命名空间分框:可以凸显集群分框,更明确地区分出不同集群中的服务及集群间的流量
  • 可以考虑关闭服务节点,并将拓扑图视角改为工作负载视角,以减少拓扑图中的冗余信息

最终效果:我们将可以看到一张多集群架构下的全局流量拓扑图,其中每个灰色的分框代表一个集群,我们可以清楚地看到流量在多集群的不同工作负载之间流动

实战:利用服务网格ASM实现多可用区的多集群容灾,并使用ASM网格拓扑观测流量变化

提到多集群的使用场景,容灾和故障转移无疑是其中重要的一部分。比如,我们可以set up以下的一个场景:

我们在两个可用区分别创建一个集群,并在其中部署相同的应用和服务,一个做主、一个做备。网关可以自由指定向两个集群中的服务发送流量的比例(比如,主机群发送80%流量、备集群发送20%流量)。

当所有服务处于正常状态时,服务间的流量访问遵循“同可用区优先”的原则,此时两个集群内的服务都只会访问本集群内的工作负载。

如果集群中的某个服务出现了故障,此时依赖故障服务的工作负载可以将请求发往另一个集群中的相同服务,来实现容灾的逻辑。

一、使用服务网格ASM实现多可用区多集群容灾

我们首先需要创建两个位于同vpc不同可用区的集群,并配置好两个集群之间的互访连通性,然后将两个集群加入ASM,布置好应用部署环境。我们可以参考在多集群管理模式下部署应用示例来完成环境的设置。

拥有一个加入两个集群的ASM实例后,我们就可以开始部署示例应用了。我们这里使用一个经典的bookinfo来作为应用的例子。bookinfo是一个经典的多语言微服务应用,由最前端的productpage服务提供前端页面,productpage服务则依赖details和reviews服务。

我们在服务网格中创建一个叫demo的全局命名空间,并给这个命名空间打开Sidecar注入,然后创建一个名称为默认的ingressgateway的ASM入口网关做访问入口,打开80端口。

接着在集群1中部署以下应用:

##################################################################################################
# Details service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: details
  namespace: demo
  labels:
    app: details
    service: details
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-details
  namespace: demo
  labels:
    account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: details-cluster1
  namespace: demo
  labels:
    app: details
    cluster: cluster1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: details
      cluster: cluster1
  template:
    metadata:
      labels:
        app: details
        cluster: cluster1
    spec:
      serviceAccountName: bookinfo-details
      containers:
      - name: details
        image: docker.io/istio/examples-bookinfo-details-v1:1.16.4
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
        securityContext:
          runAsUser: 1000
---
##################################################################################################
# Reviews service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: reviews
  namespace: demo
  labels:
    app: reviews
    service: reviews
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-reviews
  namespace: demo
  labels:
    account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-cluster1
  namespace: demo
  labels:
    app: reviews
    cluster: cluster1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      cluster: cluster1
  template:
    metadata:
      labels:
        app: reviews
        cluster: cluster1
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v1:1.16.4
        imagePullPolicy: IfNotPresent
        env:
        - name: LOG_DIR
          value: "/tmp/logs"
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: wlp-output
          mountPath: /opt/ibm/wlp/output
        securityContext:
          runAsUser: 1000
      volumes:
      - name: wlp-output
        emptyDir: {}
      - name: tmp
        emptyDir: {}
---
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: productpage
  namespace: demo
  labels:
    app: productpage
    service: productpage
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-productpage
  namespace: demo
  labels:
    account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: productpage-cluster1
  namespace: demo
  labels:
    app: productpage
    cluster: cluster1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: productpage
      cluster: cluster1
  template:
    metadata:
      labels:
        app: productpage
        cluster: cluster1
    spec:
      serviceAccountName: bookinfo-productpage
      containers:
      - name: productpage
        image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.4
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        securityContext:
          runAsUser: 1000
      volumes:
      - name: tmp
        emptyDir: {}

在多集群场景下,这个例子为工作负载的名称和标签加入了一个cluster1的标识,以识别不同集群中的工作负载。

在集群2中同理,只是将上例中工作负载名称和标签中的cluster1和cluster2。

然后用kubectl连接ASM实例,部署以下规则:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: bookinfo-gateway
  namespace: demo
spec:
  selector:
    istio: ingressgateway
  servers:
    - hosts:
        - '*'
      port:
        name: http
        number: 80
        protocol: HTTP
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: productpage-destination
  namespace: demo
spec:
  host: productpage.demo.svc.cluster.local
  subsets:
    - labels:
        cluster: ack
      name: ack
    - labels:
        cluster: distro
      name: distro
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: bookinfo
  namespace: demo
spec:
  gateways:
    - bookinfo-gateway
  hosts:
    - '*'
  http:
    - match:
        - uri:
            exact: /productpage
        - uri:
            prefix: /static
        - uri:
            exact: /login
        - uri:
            exact: /logout
        - uri:
            prefix: /api/v1/products
      route:
        - destination:
            host: productpage
            port:
              number: 9080
            subset: ack
          weight: 80
        - destination:
            host: productpage
            port:
              number: 9080
            subset: distro
          weight: 20
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: details-failover
  namespace: demo
spec:
  host: details.demo.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        maxRequestsPerConnection: 1
    loadBalancer:
      localityLbSetting:
        enabled: true
      simple: ROUND_ROBIN
    outlierDetection:
      baseEjectionTime: 1m
      consecutive5xxErrors: 1
      interval: 1s
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: ratings-failover
  namespace: demo
spec:
  host: ratings.demo.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        maxRequestsPerConnection: 1
    loadBalancer:
      localityLbSetting:
        enabled: true
      simple: ROUND_ROBIN
    outlierDetection:
      baseEjectionTime: 1m
      consecutive5xxErrors: 1
      interval: 1s
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews-failover
  namespace: demo
spec:
  host: reviews.demo.svc.cluster.local
  trafficPolicy:
    connectionPool:
      http:
        maxRequestsPerConnection: 1
    loadBalancer:
      localityLbSetting:
        enabled: true
      simple: ROUND_ROBIN
    outlierDetection:
      baseEjectionTime: 1m
      consecutive5xxErrors: 1
      interval: 1s

这里的重点是我们为每个服务都制定了一个localityLbSetting的负载均衡设定,以提供同可用区优先的路由策略。

访问http://{ASM网关ip地址}/productpage,已经可以看到bookinfo应用可以正常访问了。

二、使用ASM网格拓扑观测流量变化

使用文章开头提到的方法,我们就将能够在ASM网格拓扑中观察到两个集群下的流量拓扑情况,可以看到两个集群中部署了完全相同的应用,其中约有80%的流量打向集群1,20%的流量打向集群2 。

接下来模拟reviews服务故障的场景,我们可以直接将reviews服务在集群1中的工作负载缩容到0,随后将在ASM网格拓扑中观察到流量的走向发生了变化,集群1中的productpage服务开始将流量打向集群2中的reviews服务。

此时继续访问bookinfo应用的地址,我们可以发现服务没有中断,reviews服务的提供者被fail over到集群2中的工作负载上。

相关文章
|
3月前
|
Prometheus Kubernetes 监控
打造无缝灾备新境界:运用服务网格ASM,将集群外服务无缝融入集群内服务,铸就高可用性坚盾!
【8月更文挑战第2天】随着微服务架构的应用,服务的高可用性变得至关重要。服务网格如阿里巴巴的ASM提供流量管理、服务发现等功能,支撑高可靠服务系统。本文介绍如何利用ASM实现集群外服务作为集群内服务的灾备方案,确保服务连续性。先决条件包括已部署ASM的Kubernetes集群环境及内外部的关键服务副本。通过定义服务条目、配置虚拟服务和目的地规则,可实现自动或手动故障转移。借助ASM的流量管理能力,确保服务高可用性和业务连续性。
52 10
|
3月前
|
Perl
如何利用服务网格ASM使用集群外服务做集群内服务的灾备
本文档指导您如何配置阿里云服务网格(ASM)以实现在多集群环境下,服务间的优先访问及故障转移策略。
115 2
|
5月前
|
Cloud Native 容器 Kubernetes
基于阿里云服务网格流量泳道的全链路流量管理(三):无侵入式的宽松模式泳道
本文简要讨论了使用流量泳道来实现全链路流量灰度管理的场景与方案,并回顾了阿里云服务网格 ASM 提供的严格与宽松两种模式的流量泳道、以及这两种模式各自的优势与挑战。接下来介绍了一种基于 OpenTelemetry 社区提出的 baggage 透传能力实现的无侵入式的宽松模式泳道,这种类型的流量泳道同时具有对业务代码侵入性低、同时保持宽松模式的灵活特性的特点。同时,我们还介绍了新的基于权重的流量引流策略,这种策略可以基于统一的流量匹配规则,将匹配到的流量以设定好的比例分发到不同的流量泳道。
73530 16
基于阿里云服务网格流量泳道的全链路流量管理(三):无侵入式的宽松模式泳道
|
4月前
|
人工智能 自然语言处理 安全
使用阿里云服务网格高效管理LLM流量:(一)流量路由
ASM支持通过LLMProvider和LLMRoute资源管理大型语言模型流量。LLMProvider负责注册LLM服务,LLMRoute负责设定流量规则,应用可灵活切换模型,满足不同场景需求。
|
4月前
|
Cloud Native 测试技术 开发者
阿里云服务网格ASM多集群实践(二):高效按需的应用多环境部署与全链路灰度发布
介绍服务网格ASM提出的一种多集群部署下的多环境部署与全链路灰度发布解决方案。
|
存储 Prometheus 运维
基于 ASM 简化可观测管理、提升业务洞察力
基于 ASM 简化可观测管理、提升业务洞察力
|
6月前
|
负载均衡 安全 网络协议
如何通过计算巢在ACK集群上使用Istio服务网格
本文主要介绍怎么通过计算巢部署Isito服务网格,并介绍了使用示例。
|
Kubernetes API 容器
基于阿里云服务网格流量泳道的全链路流量管理(二):宽松模式流量泳道
基于阿里云服务网格流量泳道的全链路流量管理(二):宽松模式流量泳道
10972 15
|
监控 安全 大数据
阿里服务的ASM、MSE和ARMS都有其各自的应用场景
阿里服务的ASM、MSE和ARMS都有其各自的应用场景
433 39
|
Kubernetes Cloud Native 安全
基于阿里云服务网格流量泳道的全链路流量管理(一)严格模式流量泳道
灰度发布是一种常见的对新版本应用服务的发布手段,其特点在于能够将流量在服务的稳定版本和灰度版本之间时刻切换,以帮助我们用更加可靠的方式实现服务的升级。
29960 17
下一篇
无影云桌面