全部产品
Search
文档中心

服务网格 ASM:通过ASM多主控制面架构实现多集群容灾

更新时间:Dec 10, 2024

服务网格 ASM(Service Mesh)支持多主控制面架构,即由多个服务网格实例共同管理多个Kubernetes集群的架构模式。多主控制面架构相比单个ASM实例添加多个Kubernetes集群,在配置隔离、配置下发延迟等方面有明显优势,更适用于搭建业务对等部署的多集群容灾方案。本文将介绍如何基于两个ACK集群搭建包含两个ASM实例的多主控制面架构。

背景信息

多主控制面架构是一种使用服务网格管理多个Kubernetes集群的架构模式。在这种架构中,多个服务网格实例分别管理各自的Kubernetes集群的数据面组件,并为集群中的网格代理分发配置。同时,这些实例依靠共享的信任根证书,实现跨集群的服务发现和通信。

image

相比直接在一个ASM实例中添加多个集群,多主控制面架构有着以下优势:

  • 拥有更好的配置推送延迟表现:多个集群通常跨地域、可用区或VPC部署。在这种情况下,使用多个ASM实例分别连接到就近的Kubernetes集群中的网格代理拥有更好的配置推送性能表现。

  • 配置和环境隔离性更好:多个集群分别由多个ASM实例管理。每个ASM实例可以部署不同的控制面资源,从而实现对配置和版本的灰度或隔离。同时,在升级ASM实例时可以多个控制面分批进行升级,从而更好地确保线上环境的可用性。

  • 稳定性表现更佳:遇到可用区、地域不可用或网络问题等极端情况时,一个控制面连接所有集群的方式,可能会出现集群因为无法连接到控制面而无法同步配置或启动的问题;而在多主控制面架构下,正常地域或可用区中的网格代理仍可正常连接到控制面,不影响服务网格配置的下发与网格代理的正常启动。

构建多主控制面架构,需要创建复用相同网格根证书的多个ASM实例。网格根证书是控制面为网格代理签发身份验证所用证书时使用的根证书。通过复用相同的根证书,连接到每个ASM实例的网格代理之间可以实现相互信任以及使用mTLS协议相互访问。

前提条件

已创建两个Kubernetes集群,分别命名为cluster-1和cluster-2,都设置为开启使用EIP暴露API Server。具体操作,请参见创建ACK托管集群

步骤一:创建两个复用根证书的ASM实例,并各添加一个集群

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页单击创建新网格,具体创建时使用的关键配置项见下表。

    配置项

    示例值

    网格名称

    mesh-1。

    地域

    选择和cluster-1集群相同的地域。

    Istio版本

    选择v1.22.6.71-g7d67a80b-aliyun或以上版本。

    Kubernetes集群

    选择cluster-1,选择后,专有网络、交换机配置项将会自动填充。

    具体操作以及其他配置项的说明,请参见创建ASM实例。创建后,稍等2-3分钟直至mesh-1实例的状态转变为运行中

  3. 再次在网格管理页单击创建新网格,具体创建时使用的关键配置项见下表。

    配置项

    示例值

    网格名称

    mesh-2。

    地域

    选择和cluster-2集群相同的地域。

    Istio版本

    选择v1.22.6.71-g7d67a80b-aliyun或以上版本。

    Kubernetes集群

    选择cluster-2,选择后,专有网络、交换机配置项将会自动填充。

    网格根证书

    单击展开高级选项,选中复用已有ASM实例根证书,在下方下拉框中选择mesh-1。

    具体操作以及其他配置项的说明与mesh-1相同。创建后,稍等2-3分钟直至mesh-2实例的状态转变为运行中

步骤二:以仅服务发现模式将集群添加到ASM实例

步骤一执行后,mesh-1实例将会添加并管理cluster-1集群,mesh-2实例将会添加并管理cluster-2集群。此外,两个ASM实例还需要以仅服务发现模式添加对方所管理的集群,以发现对方集群中的服务以及服务端点。

  1. 在mesh-1实例中以仅服务发现模式添加cluster-2集群。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

    2. 网格管理页面,单击目标实例名称mesh-1,然后在左侧导航栏,选择集群与工作负载管理 > Kubernetes集群,然后单击添加

    3. 添加Kubernetes集群页面,找到cluster-2集群,然后单击集群操作列中的添加(仅服务发现)。在弹出的对话框中单击确定。添加集群后,在网格实例 > 基本信息页面,可以看到ASM实例的状态变为更新中。数秒之后(时长与添加的集群数量有关),单击页面右上方的image,ASM实例的状态会变为运行中。在Kubernetes集群页面,可以看到已添加集群的信息。

      image

  2. 在mesh-2实例中以仅服务发现模式添加cluster-1集群。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

    2. 网格管理页面,单击目标实例名称mesh-2,然后在左侧导航栏,选择集群与工作负载管理 > Kubernetes集群,然后单击添加

    3. 添加Kubernetes集群页面,找到cluster-1集群,然后单击集群操作列中的添加(仅服务发现)。在弹出的对话框中单击确定。添加集群后,在网格实例 > 基本信息页面,可以看到ASM实例的状态变为更新中。数秒之后(时长与添加的集群数量有关),单击页面右上方的image,ASM实例的状态会变为运行中。在Kubernetes集群页面,可以看到已添加集群的信息。

      image

重要

当以仅服务发现模式添加Kubernetes集群时,ASM实例仅会对该集群内的服务以及服务端点进行服务发现,但不会向该集群下发任何数据面组件。同时,针对ASM实例所做的任何配置修改无法作用于以仅服务发现模式添加的Kubernetes集群。

仅服务发现模式仅适用于构建多主控制面架构的场景。如果您希望ASM实例直接管理您的Kubernetes集群,请直接将集群添加到ASM实例。具体操作,请参见添加集群到ASM实例

步骤三(可选):在两个ASM实例中进行多集群网络配置

如果cluster-1、cluster-2两个Kubernetes集群分别位于不同的网络(即两个集群存在跨VPC、跨地域等情况),且集群间网络没有通过CEN打通,则需要在两个ASM实例中进行多集群网络配置,并为cluster-1、cluster-2分别部署跨集群网格代理,以保证集群间的相互访问可达。关于跨集群网格代理的更多信息,请参见使用ASM跨集群网格代理实现多集群跨网络互通

  1. 在mesh-1实例中配置cluster-1和cluster-2集群的网络配置。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

    2. 网格管理页面,单击目标实例mesh-1名称,然后在左侧导航栏,选择集群与工作负载管理 > Kubernetes集群

    3. 单击多集群网络配置按钮,按照以下方式配置多集群网络。

      1. 为cluster-1集群指定所属逻辑网络为network1,并为cluster-1集群启用跨集群网格代理访问。

      2. 为cluster-2集群指定所属逻辑网络为network2。

    image

  1. 在mesh-2实例中配置cluster-1和cluster-2集群的网络配置。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

    2. 网格管理页面,单击目标实例mesh-2名称,然后在左侧导航栏,选择集群与工作负载管理 > Kubernetes集群

    3. 单击多集群网络配置按钮,按照以下方式配置多集群网络。

      1. 为cluster-1集群指定所属逻辑网络为network1。

      2. 为cluster-2集群指定所属逻辑网络为network2,并为cluster-2集群启用跨集群网格代理访问。

    image

步骤四:在两个ASM实例中部署示例应用

如下图所示,本节将在cluster-1部署sleep服务和helloworld服务的v1版本,cluster-2部署helloworld服务的v2版本。两个集群中的服务可以通过ASM跨集群网络代理实现相互访问。

image
  1. 在mesh-1实例和mesh-2实例中为default命名空间开启自动注入。具体操作,参考管理全局命名空间

  2. 使用以下内容,创建sleep应用和helloworld应用的v1版本。

    展开查看YAML内容

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: registry.cn-hangzhou.aliyuncs.com/acs/curl:8.1.2
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: helloworld
      labels:
        app: helloworld
    spec:
      ports:
      - port: 5000
        name: http
      selector:
        app: helloworld
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: helloworld
      labels:
        account: helloworld
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloworld-v1
      labels: 
        apps: helloworld
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: helloworld
          version: v1
      template:
        metadata:
          labels:
            app: helloworld
            version: v1
        spec:
          serviceAccount: helloworld
          serviceAccountName: helloworld
          containers:
          - name: helloworld
            image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-helloworld-v1:1.0
            imagePullPolicy: IfNotPresent 
            ports:
            - containerPort: 5000
  3. 在cluster-1中部署此YAML。具体操作,请参见通过编排模板创建Linux应用

  4. 使用以下内容,创建helloworld应用的v2版本。

    展开查看YAML内容

    apiVersion: v1
    kind: Service
    metadata:
      name: helloworld
      labels:
        app: helloworld
    spec:
      ports:
      - port: 5000
        name: http
      selector:
        app: helloworld
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: helloworld
      labels:
        account: helloworld
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloworld-v2
      labels: 
        apps: helloworld
        version: v2
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: helloworld
          version: v2
      template:
        metadata:
          labels:
            app: helloworld
            version: v2
        spec:
          serviceAccount: helloworld
          serviceAccountName: helloworld
          containers:
          - name: helloworld
            image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-helloworld-v2:1.0
            imagePullPolicy: IfNotPresent 
            ports:
            - containerPort: 5000
  5. 在cluster-2中部署此YAML。具体操作,请参见通过编排模板创建Linux应用

步骤五:验证多主控制面架构下部署的应用互相访问

  1. 使用cluster-1集群的kubeconfig,执行以下命令。

     kubectl exec -it deploy/sleep -- sh -c 'for i in $(seq 1 10); do curl helloworld:5000/hello; done;'

    预期输出:

    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx

    可以看到helloworld的版本在v1和v2之间来回切换。

  2. 执行以下命令,将cluster-1集群中的sleep应用的Pod副本数量改为0。

    kubectl scale deploy sleep --replicas=0
  3. 使用以下内容创建单独的sleep应用。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: registry.cn-hangzhou.aliyuncs.com/acs/curl:8.1.2
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
  4. 在cluster-2集群中部署以上内容。具体操作,请参见通过编排模板创建Linux应用

  5. 使用cluster-2集群的kubeconfig再次执行以下命令。

     kubectl exec -it deploy/sleep -- sh -c 'for i in $(seq 1 10); do curl helloworld:5000/hello; done;'

    预期输出:

    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v1, instance: helloworld-v1-7b888xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx
    Hello version: v2, instance: helloworld-v2-7b949xxxxx-xxxxx

    可以看到helloworld的版本仍然在v1和v2之间来回切换。