如果需要将IDC集群或第三方公共云的服务迁移至阿里云ACK,可以利用ACK One的多集群服务,在不修改代码、CoreDNS Config及Pod的DNSConfig的情况下实现无缝迁移。本文将通过模拟迁移场景介绍服务迁移的具体步骤。
背景信息
在Kubernetes集群间迁移应用是一个常见的需求,通常涉及跨云搬迁、平台重大升级或资源规划调整等情况。当需要进行跨集群迁移时,理想情况下应确保迁移过程平滑且不影响业务运行,同时将风险降至最低。在ACK上,实现跨Kubernetes集群应用迁移的主要方案有以下两种:
搬迁旧集群完整环境到新集群。
基于ACK One多集群Service,实现跨集群服务双向互通,分批迁移。
搬迁旧集群完整环境到新集群方案适合应用数量之间依赖极少的场景,而在应用数量庞大(几百上千个应用),相互之间依赖关系复杂且无法理清的情况下,会存在以下不足:
应用数量庞大,全面验证所需的工作量极为庞大,迁移周期过长,通常无法接受。
一次性迁移的风险不可控,依赖关系复杂,不能通过分批迁移应用来降低风险。
如果不同应用分属不同团队,迁移计划和速度不一致,也可能会导致迁移过程中停机。
基于ACK One MultiClusterService的迁移方案
基于ACK One MultiClusterService实现的跨集群应用迁移方案,主要是基于ACK One多集群Service的MultiClusterService提供的跨集群服务互访能力,进而分批迁移应用,无需关注应用间的依赖关系,直至所有应用迁移成功。该迁移方案可实现大批量应用跨集群无缝迁移,具有以下优势:
风险最小化:借助ACK One多集群服务功能,无需关注应用间的依赖关系,支持分批迁移,减少迁移风险,风险控制方便,并且可以快速回滚。
无损迁移:该方案不会拦截业务流量,不会造成流量异常,也无需担心业务外的性能影响。
ACK One MultiClusterService简述
在舰队中创建MultiClusterService,并且在Consumer Cluster中创建同名Service,即可实现Consumer Cluster使用原生Service Name跨集群访问到Provider Cluster上的该Service。 架构如下图所示:
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>
name
和namespace
保持和要处理的Service一致。一个集群可以同时是Consumer Cluster和Provider Cluster。
providerClusters
:指要提供该Service被其他集群访问的集群列表。consumerClusters
:指要访问该Service的集群列表。
关于ACK One MultiClusterService详细信息及使用方式,请参见使用原生Service域名跨集群服务访问。
跨集群应用迁移方案
在迁移过程中,由于应用和服务众多且服务间依赖关系复杂,整个过程可能需要较长时间。因此,在迁移期间,需要确保Old Cluster和New Cluster之间能够通过服务域名进行双向跨集群访问。这样可以逐步分批迁移服务,最终将所有服务迁移到New Cluster。待所有服务迁移完成后,将外部流量切换到New Cluster,从而完成整个迁移过程。迁移方案如下所示。
将Old Cluster中所有Service资源都部署到New Cluster中,并为所有Service在舰队中创建MultiClusterService(每个Service对应一个同名的MultiClusterService)。
从Old Cluster中选择一批要迁移的服务,如图中的
Service2
,将其Deployment部署到New Cluster中。此时
Service1
会有部分流量路由到New Cluster的Service2
后端,验证无误后,将Old Cluster中的Service2
的副本数缩容为0,以便将所有到Service2
的流量路由到New Cluster中的Service2
后端。若验证有误,则将New Cluster的Deployment副本缩容为0,修复后再扩容副本数。
重复执行2和3,继续迁移下一批服务,直至所有服务迁移完成。
最后迁移Front Service后将流量完全切换到New Cluster。
前提条件
已开启舰队管理功能。
舰队的Fleet实例已添加2个关联集群(Old Cluster & New Cluster)。具体操作,请参见管理关联集群。
关联集群的版本不低于1.22。
关联集群(Old Cluster & New Cluster)的Pod CIDR已相互可通。具体操作,请参见多集群服务概述。
获取服务Old Cluster和New Cluster的KubeConfig,并通过kubectl连接集群。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。
步骤一:在Old Cluster中部署Service和Deployment
使用Old Cluster的KubeConfig,通过以下示例内容,创建
web-demo-svc-old.yaml
。执行以下命令,在Old Cluster中部署三个服务的Service和Deployment资源。
kubectl apply -f web-demo-svc-old.yaml
使用以下内容,创建
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"]
执行以下命令,部署Client Pod用于访问链路。
kubectl apply -f client-pod.yaml
使用舰队KubeConfig,执行以下命令获取Server URL。
kubectl get secret -n argocd cluster-<Old-Clsuter-ID> -ojsonpath='{.data.server}' |base64 -d
部署三个服务的Service和Deployment资源。
登录ACK One控制台,在左侧导航栏选择 。
在多集群应用页面左上角,单击舰队名称后的
按钮,在下拉列表中选择目标舰队。
单击
进入创建多集群应用 - GitOps页面。在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
部署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
使用New Cluster的KubeConfig,通过以下示例内容,创建
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
执行以下命令,部署
service1
、service2
、service3
三个服务的Service资源。kubectl apply -f web-demo-svc-new.yaml
使用舰队KubeConfig,执行以下命令获取Server URL。
kubectl get secret -n argocd cluster-<New-Clsuter-ID> -ojsonpath='{.data.server}' |base64 -d
登录ACK One控制台,在左侧导航栏选择 。
在多集群应用页面左上角,单击舰队名称后的
按钮,在下拉列表中选择目标舰队。
单击
进入创建多集群应用 - GitOps页面。在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
使用以下命令在舰队创建Service的Namespace。
kubectl create ns mcs-demo
使用舰队的KubeConfig,通过以下示例内容,创建
multiclusterservice.yaml
。请将
<Your-New-Cluster-ID>
和<Your-Old-Cluster-ID>
替换为您关联的集群ID。MultiClusterService的
name
和namespace
需与要提供跨集群访问的服务保持一致。
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>
执行以下命令,在舰队中创建所有服务的MultiClusterService。
kubectl apply -f multiclusterservice.yaml
步骤四:在New Cluster中部署要迁移Service的Deployment
完成上述步骤后,目前的调用链仍为service1(oldcluster) --> service2(oldcluster) --> service3(oldcluster)
。本步骤将模拟迁移随机选择的Service2
,部署其Deployment到New Cluster,Pod Running后将会有流量路由到New Cluster的Service2
后端。
使用New Cluster的KubeConfig,通过以下示例内容,创建
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
执行以下命令,在New Cluster中创建
Service2
后端应用。kubectl apply -f web-demo-new.yaml
创建成功后,在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 Cluster的Deployment副本缩容为0,修复后再扩容副本数。
重复执行该步骤,直至所有服务迁移完成。迁移完成后,将所有外部流量重定向至新集群的Front Service,以完成整个迁移过程。
- 本页导读 (1)
- 背景信息
- 基于ACK One MultiClusterService的迁移方案
- 跨集群应用迁移方案
- 前提条件
- 步骤一:在Old Cluster中部署Service和Deployment
- 步骤二:在New Cluster中部署Old Cluster中全量Service
- 步骤三:在舰队中创建所有服务的MultiClusterService
- 步骤四:在New Cluster中部署要迁移Service的Deployment