ACK One多集群Service帮助大批量应用跨集群无缝迁移

更新时间:2025-03-13 05:10:51

如果需要将IDC集群或第三方公共云的服务迁移至阿里云ACK,可以利用ACK One的多集群服务,在不修改代码、CoreDNS ConfigPodDNSConfig的情况下实现无缝迁移。本文将通过模拟迁移场景介绍服务迁移的具体步骤。

背景信息

Kubernetes集群间迁移应用是一个常见的需求,通常涉及跨云搬迁、平台重大升级或资源规划调整等情况。当需要进行跨集群迁移时,理想情况下应确保迁移过程平滑且不影响业务运行,同时将风险降至最低。在ACK上,实现跨Kubernetes集群应用迁移的主要方案有以下两种:

  1. 搬迁旧集群完整环境到新集群。

  2. 基于ACK One多集群Service,实现跨集群服务双向互通,分批迁移。

搬迁旧集群完整环境到新集群方案适合应用数量之间依赖极少的场景,而在应用数量庞大(几百上千个应用),相互之间依赖关系复杂且无法理清的情况下,会存在以下不足:

  • 应用数量庞大,全面验证所需的工作量极为庞大,迁移周期过长,通常无法接受。

  • 一次性迁移的风险不可控,依赖关系复杂,不能通过分批迁移应用来降低风险。

  • 如果不同应用分属不同团队,迁移计划和速度不一致,也可能会导致迁移过程中停机。

基于ACK One MultiClusterService的迁移方案

基于ACK One MultiClusterService实现的跨集群应用迁移方案,主要是基于ACK One多集群ServiceMultiClusterService提供的跨集群服务互访能力,进而分批迁移应用,无需关注应用间的依赖关系,直至所有应用迁移成功。该迁移方案可实现大批量应用跨集群无缝迁移,具有以下优势:

  • 风险最小化:借助ACK One多集群服务功能,无需关注应用间的依赖关系,支持分批迁移,减少迁移风险,风险控制方便,并且可以快速回滚。

  • 无损迁移:该方案不会拦截业务流量,不会造成流量异常,也无需担心业务外的性能影响。

ACK One MultiClusterService简述

在舰队中创建MultiClusterService,并且在Consumer Cluster中创建同名Service,即可实现Consumer Cluster使用原生Service Name跨集群访问到Provider Cluster上的该Service。 架构如下图所示:

image

MultiClusterService yaml如下所示:

apiVersion: networking.one.alibabacloud.com/v1alpha1
kind: MultiClusterService
metadata:
   name: service
   namespace: demo
spec:
  consumerClusters:
    - name: <your consumer cluster id>
  providerClusters:
    - name: <your provider cluster id>
说明
  • namenamespace保持和要处理的Service一致。

  • 一个集群可以同时是Consumer ClusterProvider Cluster。

  • providerClusters:指要提供该Service被其他集群访问的集群列表。

  • consumerClusters:指要访问该Service的集群列表。

关于ACK One MultiClusterService详细信息及使用方式,请参见使用原生Service域名跨集群服务访问

跨集群应用迁移方案

在迁移过程中,由于应用和服务众多且服务间依赖关系复杂,整个过程可能需要较长时间。因此,在迁移期间,需要确保Old ClusterNew Cluster之间能够通过服务域名进行双向跨集群访问。这样可以逐步分批迁移服务,最终将所有服务迁移到New Cluster。待所有服务迁移完成后,将外部流量切换到New Cluster,从而完成整个迁移过程。迁移方案如下所示。

image
  1. Old Cluster中所有Service资源都部署到New Cluster中,并为所有Service在舰队中创建MultiClusterService(每个Service对应一个同名的MultiClusterService)。

  2. Old Cluster中选择一批要迁移的服务,如图中的Service2,将其Deployment部署到New Cluster中。

  3. 此时Service1会有部分流量路由到New ClusterService2后端,验证无误后,将Old Cluster中的Service2的副本数缩容为0,以便将所有到Service2的流量路由到New Cluster中的Service2后端。

    若验证有误,则将New ClusterDeployment副本缩容为0,修复后再扩容副本数。

  4. 重复执行23,继续迁移下一批服务,直至所有服务迁移完成。

  5. 最后迁移Front Service后将流量完全切换到New Cluster。

前提条件

步骤一:在Old Cluster中部署ServiceDeployment

连接子集群部署应用
通过GitOps为子集群分发应用
  1. 使用Old ClusterKubeConfig,通过以下示例内容,创建web-demo-svc-old.yaml

    展开查看YAML内容

    apiVersion: v1
    kind: Service
    metadata:
      name: service1
      namespace: mcs-demo
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: service1
      type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: service1
      name: svc-demo-service1
      namespace: mcs-demo
    spec:
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: service1
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: service1
        spec:
          containers:
          - env:
            - name: ENV_NAME
              value: oldcluster
            - name: MY_SERVICE_NAME
              value: service1
            - name: SERVICE_URL
              value: http://service2.mcs-demo:80/call
            - name: MY_CLUSTER
              value: oldcluster
            image: registry-cn-hongkong.ack.aliyuncs.com/acs/web-demo:v0.6.0-2
            imagePullPolicy: Always
            name: svc-demo
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: service2
      namespace: mcs-demo
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: service2
      type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: service2
      name: svc-demo-service2
      namespace: mcs-demo
    spec:
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: service2
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: service2
        spec:
          containers:
          - env:
            - name: ENV_NAME
              value: oldcluster
            - name: MY_SERVICE_NAME
              value: service2
            - name: SERVICE_URL
              value: http://service3.mcs-demo:80/svc
            - name: MY_CLUSTER
              value: oldcluster
            image: registry-cn-hongkong.ack.aliyuncs.com/acs/web-demo:v0.6.0-2
            imagePullPolicy: Always
            name: svc-demo
      
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: service3
      namespace: mcs-demo
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: service3
      type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: service3
      name: svc-demo-service3
      namespace: mcs-demo
    spec:
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: service3
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: service3
        spec:
          containers:
          - env:
            - name: ENV_NAME
              value: oldcluster
            - name: MY_SERVICE_NAME
              value: service3
            - name: SERVICE_URL
              value: http://service3.mcs-demo:80/svc
            - name: MY_CLUSTER
              value: oldcluster
            image: registry-cn-hongkong.ack.aliyuncs.com/acs/web-demo:v0.6.0-2
            imagePullPolicy: Always
            name: svc-demo
  2. 执行以下命令,在Old Cluster中部署三个服务的ServiceDeployment资源。

    kubectl apply -f web-demo-svc-old.yaml
  3. 使用以下内容,创建client-pod.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: curl-client
    spec:
      containers:
      - name: curl-client
        image: registry-cn-hangzhou.ack.aliyuncs.com/dev/curl:8.11.1
        command: ["sh", "-c", "sleep 12000"]
  4. 执行以下命令,部署Client Pod用于访问链路。

    kubectl apply -f client-pod.yaml
  1. 使用舰队KubeConfig,执行以下命令获取Server URL。

    kubectl get secret -n argocd cluster-<Old-Clsuter-ID> -ojsonpath='{.data.server}' |base64 -d
  2. 部署三个服务的ServiceDeployment资源。

    1. 登录ACK One控制台,在左侧导航栏选择舰队 > 多集群应用

    2. 多集群应用页面左上角,单击舰队名称后的Dingtalk_20231226104633.jpg按钮,在下拉列表中选择目标舰队。

    3. 单击创建多集群应用 > GitOps进入创建多集群应用 - GitOps页面。

    4. YAML创建页签,将以下示例YAML内容复制到控制台,然后单击确定部署应用。

      apiVersion: argoproj.io/v1alpha1
      kind: ApplicationSet
      metadata:
        name: svc-demo-oldcluster
        namespace: argocd
      spec:
        generators:
          - list:
              elements:
              - envSvcName: service1
                envCluster: oldcluster
                envCallSvcName: service2
                envAPI: call
              - envSvcName: service2
                envCluster: oldcluster
                envCallSvcName: service3
                envAPI: svc
              - envSvcName: service3
                envCluster: oldcluster
                envCallSvcName: service3
                envAPI: svc
        template:
          metadata:
            name: '{{envSvcName}}-{{envCluster}}-svc-demo'
          spec:
            project: default
            source:
              repoURL: https://github.com/AliyunContainerService/gitops-demo.git 
              targetRevision: main
              path: manifests/helm/svc-demo
              helm:
                parameters:
                - name: envSvcName
                  value: '{{envSvcName}}'
                - name: envCallSvcName
                  value: '{{envCallSvcName}}'
                - name: envAPI
                  value: '{{envAPI}}'
                - name: envCluster
                  value: '{{envCluster}}'
                valueFiles:
                  - values.yaml
            destination:
              server: <Your-Old-Cluster-Server-URL>   # 请替换<Your-Old-Cluster-Server-URL>为对应集群的Server URL。
              namespace: mcs-demo
            syncPolicy:
              automated: {}
              syncOptions:
                - CreateNamespace=true
  3. 部署Client Pod用于访问链路。

    多集群应用页面单击GitOps控制台,进入ArgoCD UI页面创建以下Application 。

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: curl-client-pod
      namespace: argocd
    spec:
      destination:
        namespace: customer-ns
        server: <Your-Old-Cluster-Server-URL>   # 请替换<Your-Old-Cluster-Server-URL>为对应集群的Server URL。
      project: default
      source:
        path: manifests/directory/curlclient
        repoURL: https://github.com/AliyunContainerService/gitops-demo.git
        targetRevision: HEAD
      syncPolicy:
        syncOptions:
        - CreateNamespace=true

创建成功后,在Client Pod中执行以下命令测试调用链路。

kubectl exec -it -ncustomer-ns curl-client -- sh
curl service1.mcs-demo/call

预期输出:

service1(oldcluster) --> service2(oldcluster) --> service3(oldcluster)

步骤二:在New Cluster中部署Old Cluster中全量Service

连接子集群部署应用
通过GitOps为子集群分发应用
  1. 使用New ClusterKubeConfig,通过以下示例内容,创建web-demo-svc-new.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: service1
      namespace: mcs-demo
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: service1
      type: ClusterIP
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: service2
      namespace: mcs-demo
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: service2
      type: ClusterIP
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: service3
      namespace: mcs-demo
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: service3
      type: ClusterIP
  2. 执行以下命令,部署service1service2service3三个服务的Service资源。

    kubectl apply -f web-demo-svc-new.yaml
  1. 使用舰队KubeConfig,执行以下命令获取Server URL。

    kubectl get secret -n argocd cluster-<New-Clsuter-ID> -ojsonpath='{.data.server}' |base64 -d
  2. 登录ACK One控制台,在左侧导航栏选择舰队 > 多集群应用

  3. 多集群应用页面左上角,单击舰队名称后的Dingtalk_20231226104633.jpg按钮,在下拉列表中选择目标舰队。

  4. 单击创建多集群应用 > GitOps进入创建多集群应用 - GitOps页面。

  5. YAML创建页签,将以下示例YAML内容复制到控制台,然后单击确定部署应用。

    apiVersion: argoproj.io/v1alpha1
    kind: ApplicationSet
    metadata:
      name: svc-demo-newcluster
      namespace: argocd
    spec:
      generators:
        - list:
            elements:
            - envSvcName: service1
              envCluster: newcluster
              onlyService: "true"
            - envSvcName: service2
              envCluster: newcluster
              onlyService: "true"
            - envSvcName: service3
              envCluster: newcluster
              onlyService: "true"
      template:
        metadata:
          name: '{{envSvcName}}-{{envCluster}}-svc-demo'
        spec:
          project: default
          source:
            repoURL: https://github.com/AliyunContainerService/gitops-demo.git
            targetRevision: main
            path: manifests/helm/svc-demo
            helm:
              parameters:
              - name: envSvcName
                value: '{{envSvcName}}'
              - name: onlyService
                value: '{{onlyService}}'
              valueFiles:
                - values.yaml
          destination:
            server: <Your-New-Cluster-Server-URL>   # 请替换<Your-New-Cluster-Server-URL>为对应集群的Server URL。
            namespace: mcs-demo
          syncPolicy:
            automated: {}
            syncOptions:
              - CreateNamespace=true

步骤三:在舰队中创建所有服务的MultiClusterService

  1. 使用以下命令在舰队创建ServiceNamespace。

    kubectl create ns mcs-demo
  2. 使用舰队的KubeConfig,通过以下示例内容,创建multiclusterservice.yaml

    说明
    • 请将 <Your-New-Cluster-ID><Your-Old-Cluster-ID> 替换为您关联的集群ID。

    • MultiClusterServicenamenamespace需与要提供跨集群访问的服务保持一致。

    apiVersion: networking.one.alibabacloud.com/v1alpha1
    kind: MultiClusterService
    metadata:
       name: service1
       namespace: mcs-demo
    spec:
      consumerClusters:
        - name: <Your-New-Cluster-ID>
        - name: <Your-Old-Cluster-ID>
      providerClusters:
        - name: <Your-New-Cluster-ID>
        - name: <Your-Old-Cluster-ID>
    ---
    apiVersion: networking.one.alibabacloud.com/v1alpha1
    kind: MultiClusterService
    metadata:
       name: service2
       namespace: mcs-demo
    spec:
      consumerClusters:
        - name: <Your-New-Cluster-ID>
        - name: <Your-Old-Cluster-ID>
      providerClusters:
        - name: <Your-New-Cluster-ID>
        - name: <Your-Old-Cluster-ID>
    ---
    apiVersion: networking.one.alibabacloud.com/v1alpha1
    kind: MultiClusterService
    metadata:
       name: service3
       namespace: mcs-demo
    spec:
      consumerClusters:
        - name: <Your-New-Cluster-ID>
        - name: <Your-Old-Cluster-ID>
      providerClusters:
        - name: <Your-New-Cluster-ID>
        - name: <Your-Old-Cluster-ID>
  3. 执行以下命令,在舰队中创建所有服务的MultiClusterService。

    kubectl apply -f multiclusterservice.yaml

步骤四:在New Cluster中部署要迁移ServiceDeployment

完成上述步骤后,目前的调用链仍为service1(oldcluster) --> service2(oldcluster) --> service3(oldcluster)。本步骤将模拟迁移随机选择的Service2,部署其DeploymentNew Cluster,Pod Running后将会有流量路由到New ClusterService2后端。

  1. 使用New ClusterKubeConfig,通过以下示例内容,创建web-demo-new.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: service2
      name: svc-demo-service2
      namespace: mcs-demo
    spec:
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: service2
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: service2
        spec:
          containers:
          - env:                    # 环境变量中使用newcluster,与Old Cluster中的Deployment的oldcluster链路进行区分。 
            - name: ENV_NAME
              value: newcluster                 
            - name: MY_SERVICE_NAME
              value: service2
            - name: SERVICE_URL
              value: http://service3.mcs-demo:80/svc
            - name: MY_CLUSTER
              value: newcluster
            image: registry-cn-hangzhou.ack.aliyuncs.com/dev/web-demo:v0.6.0
            imagePullPolicy: Always
            name: svc-demo
  2. 执行以下命令,在New Cluster中创建Service2后端应用。

    kubectl apply -f web-demo-new.yaml
  3. 创建成功后,在Client Pod中执行以下命令测试调用链路。

    kubectl exec -it -ncustomer-ns curl-client -- sh
    curl service1.mcs-demo/call

    预期输出:

    service1(oldcluster) --> service2(newcluster) --> service3(oldcluster)
    说明
    • 验证无误后,将Old Cluster中的Service2的副本数缩容为0,以便将所有到Service2的流量路由到New Cluster中的Service2后端。

    • 若验证有误,则将New ClusterDeployment副本缩容为0,修复后再扩容副本数。

  4. 重复执行该步骤,直至所有服务迁移完成。迁移完成后,将所有外部流量重定向至新集群的Front Service,以完成整个迁移过程。

  • 本页导读 (1)
  • 背景信息
  • 基于ACK One MultiClusterService的迁移方案
  • 跨集群应用迁移方案
  • 前提条件
  • 步骤一:在Old Cluster中部署Service和Deployment
  • 步骤二:在New Cluster中部署Old Cluster中全量Service
  • 步骤三:在舰队中创建所有服务的MultiClusterService
  • 步骤四:在New Cluster中部署要迁移Service的Deployment
AI助理

点击开启售前

在线咨询服务

你好,我是AI助理

可以解答问题、推荐解决方案等