文档

云盘类型有状态应用的跨可用区迁移

更新时间:

storage-operator组件提供了云盘类型有状态应用跨可用区迁移和多地域打散的功能,实现了跨可用区迁移的自动化。迁移过程出现异常时,storage-operator组件可以通过预检查和回滚机制在原可用区恢复应用,保证业务的可用性。本文介绍如何实现云盘类型的有状态应用跨可用区迁移。

适用场景

  • 当遇到规划变更、应用规模扩大从而需要在多可用区部署,或当前可用区资源不足时,您都需要将已部署的有状态应用迁移至其他的可用区。

  • NAS、OSS存储底层支持跨可用区、多挂载使用。但云盘本身无多可用区漂移的能力,无法复用存储声明和存储卷,此时,需要将云盘的有状态应用迁移至新的可用区。

实现原理及迁移流程

云盘实现应用的跨可用区迁移,依赖云盘快照功能,并且支持设定新建的快照保留时间。关于云盘快照的更多信息,请参见快照介绍。关于快照计费请参见快照计费

storage-operator组件提供的云盘类型有状态应用迁移流程如下。

  1. 相关预检查,例如,待迁移应用运行是否正常、是否有需要迁移的云盘等。若检查失败,则不会进行迁移。

  2. 将云盘类型有状态应用缩容至0副本,此时应用处于暂停状态。

  3. 为待迁移的有状态应用挂载的云盘制作快照,快照支持跨可用区。

  4. 确认快照可用后,使用快照在目标可用区制作新云盘,新云盘与原云盘的数据一致。

  5. 重建同名的存储声明及其对应的新存储卷,绑定新云盘。

  6. 云盘类型有状态应用副本恢复至原副本数量,并自动关联重建的存储声明,实际挂载新云盘。

    重要

    预检查完成并开始迁移后,每个步骤均对应了不同的失败回滚策略。为确保回滚后的应用能挂载原云盘,避免数据丢失,请确认迁移后的有状态应用运行正常后,再删除云盘。

  7. (可选)确认有状态应用运行正常后,删除原存储卷和相应的云盘。关于云盘计费,请参见块存储计费

注意事项

  • 待迁移的有状态应用使用的所有存储均为ESSD云盘。

    为了提升快照制作时间,本功能在迁移时选用极速快照,具体操作请参见快照极速可用能力。目前极速快照仅支持ESSD云盘,若您的应用使用非ESSD类型云盘,可通过以下方式处理。

  • 目标可用区支持ESSD云盘,且集群中已有在目标可用区支持ESSD云盘的节点可供调度。

  • 能业务接受中断。对于多副本的有状态应用,为保证数据的一致性,在迁移前会缩容至0副本,云盘迁移完成后再一次性恢复至原副本数,而非滚动迁移。

重要

有状态应用的跨可用区迁移过程中会产生业务的中断,中断时长与副本数量、容器启动速度、所使用云盘容量等因素相关。

前提条件

  • 已创建Kubernetes集群,Kubernetes版本为v1.20及以上,且存储插件选择为CSI。具体操作,请参见已创建Kubernetes托管版集群

  • 若您的集群为ACK专有版集群,则需要为集群WorkerRole配置如下权限。具体操作,请参见创建自定义权限策略

    展开查看ACK专有版集群WorkerRole权限策略内容

    {
        "Version": "1",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "ecs:CreateSnapshot",
                    "ecs:DescribeSnapshot",
                    "ecs:DeleteSnapshot",
                    "ecs:ModifyDiskSpec",
                    "ecs:DescribeTaskAttribute"
                ],
                "Resource": "*"
            }
        ]
    }
    说明

    ACK Pro版集群无需配置权限。

  • storage-operator组件版本不低于v1.26.2-1de13b6-aliyun。关于升级storage-operator组件的操作,请参见管理组件

使用方式

  1. 执行以下命令,修改集群中ConfigMap的配置。

    kubectl patch configmap/storage-operator \
      -n kube-system \
      --type merge \
      -p '{"data":{"storage-controller":"{\"imageRep\":\"acs/storage-controller\",\"imageTag\":\"\",\"install\":\"true\",\"template\":\"/acs/templates/storage-controller/install.yaml\",\"type\":\"deployment\"}"}}'
  2. 执行以下命令,在集群中创建有状态应用迁移任务。

    cat <<EOF | kubectl apply -f -
    apiVersion: storage.alibabacloud.com/v1beta1
    kind: ContainerStorageOperator
    metadata:
      name: default
    spec:
      operationType: APPMIGRATE
      operationParams:
        stsName: web
        stsNamespace: default
        stsType: kube
        targetZone: cn-beijing-h,cn-beijing-j
        checkWaitingMinutes: "1"
        healthDurationMinutes: "1"
        snapshotRetentionDays: "2"
        retainSourcePV: "true"
    EOF

    参数

    是否必选

    说明

    operationType

    必选

    取值为APPMIGRATE,表明当前的操作是有状态应用迁移。

    stsName

    必选

    有状态应用名称,当前仅支持填写单个有状态应用。

    说明

    部署多个有状态应用的迁移任务时,组件将以部署时间顺序依次迁移。

    stsNamespace

    必选

    有状态应用所在命名空间。

    targetZone

    必选

    迁移的目标可用区列表。当存在多个目标可用区时,可用区之间用英文半角逗号(,)隔开。例如cn-beijing-h,cn-beijing-j

    • 当应用挂载的某个云盘已在列表中时,应用将不进行迁移。

    • 当目标可用区大于1时,剩余云盘将按列表中可用区的排列顺序依次迁移至各个目标可用区。

    stsType

    可选

    指定的有状态应用的类型,默认为kube。取值:

    • kube:原生StatefulSet。

    • kruise:OpenKruise组件提供的Advanced StatefulSet。

    checkWaitingMinutes

    可选

    有状态应用在迁移后的可用区启动时,其状态检查的轮询间隔时间,单位为分钟。

    默认为"1",即每分钟检查一次,直至可用副本数与预期一致,或多次检查失败重试后回滚,回迁至原可用区。

    重要

    对于副本数较多、镜像拉取时间长、业务本身启动耗时较长的应用,需要适当增加轮询间隔时间,避免重试次数过多后应用回滚。

    healthDurationMinutes

    可选

    二次检查的间隔时间,单位为分钟。二次检查即当有状态应用迁移完成,可用副本数与预期一致后,等待指定时间进行二次检查,以增强数据敏感业务的迁移可靠性。

    默认为"0",即不进行二次检查。

    snapshotRetentionDays

    可选

    迁移过程中,新建极速快照的保留时间,单位为天。取值:

    • "1":默认值,保留一天。

    • "-1":将永久保留极速快照。

    retainSourcePV

    可选

    是否保留原云盘及其在集群中对应的存储卷资源。取值:

    • "false":默认值,不保留。

    • "true":保留,您可以登录ECS管理控制台找到原云盘实例,且集群内对应的存储卷资源也不会被删除,存储卷处于Released状态。

使用示例

测试集群为cn-beijing的ACK集群Pro版,包含可用区来自cn-beijing-i, cn-beijing-j, cn-beijing-k的节点node-zone-i, node-zone-j, node-zone-k。

示例1:云盘跨可用区迁移

步骤一:创建使用ESSD云盘的有状态应用

  1. 执行以下命令,在集群中部署有状态应用Nginx。

    展开查看部署有状态应用Nginx的文件

    cat << EOF | kubectl apply -f -
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      selector:
        matchLabels:
          app: nginx
      serviceName: "nginx"
      replicas: 2
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx:1.14.2
              ports:
                - containerPort: 80
                  name: web
              volumeMounts:
                - name: www
                  mountPath: /usr/share/nginx/html
      volumeClaimTemplates:
        - metadata:
            name: www
            labels:
              app: nginx
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "alicloud-disk-essd"
            resources:
              requests:
                storage: 20Gi
    EOF
    
  2. 执行以下命令,确认应用的两个副本的部署情况。

    kubectl get pod -owide | grep web-

    预期输出:

    NAME                        READY    STATUS   RESTARTS    AGE     IP                ZONE                  NOMINATED NODE   READINESS GATES
    web-0                        1/1     Running   0          44s     172.29.XX.XX    node-zone-i           <none>           <none>
    web-1                        1/1     Running   0          3s      172.29.XX.XX    node-zone-j           <none>           <none>

    预期输出表明,应用的两个副本分别部署在cn-beijing-i, cn-beijing-j两个可用区的节点上。实际部署的结果由调度器决定。

步骤二:创建有状态应用迁移任务

  1. 执行以下命令,在集群中创建有状态应用迁移任务。

    以下迁移任务中,将有状态应用的两个副本全部迁移至cn-beijing-k可用区。迁移前,已确认该节点有足够的资源,且可用区和机型均支持ESSD云盘。

    cat <<EOF | kubectl apply -f -
    apiVersion: storage.alibabacloud.com/v1beta1
    kind: ContainerStorageOperator
    metadata:
      name: migrate-to-k
    spec:
      operationType: APPMIGRATE
      operationParams:
        stsName: web
        stsNamespace: default
        stsType: kube
        targetZone: cn-beijing-k      # 迁移至cn-beijing-k可用区。
        healthDurationMinutes: "1"    # 迁移完成后隔1分钟确认应用运行正常。
        snapshotRetentionDays: "-1"   # 新建的快照长期保留,直至在控制台删除。
        retainSourcePV: "true"        # 保留原可用区的云盘和对应PV。
    EOF
  2. 执行以下命令,查询迁移任务的状态。

    kubectl describe cso migrate-to-k | grep Status

    预期输出:

      Status:  SUCCESS

    预期输出为SUCCESS,表明迁移任务状态正常。如果预期输出为FAILED,表明迁移任务创建失败,关于失败问题排查,请参见(可选)任务失败时原因排查

  3. 执行以下命令,查询迁移后应用的两个副本的部署情况。

    kubectl get pod -owide | grep web-

    预期输出:

    NAME                        READY    STATUS    RESTARTS   AGE     IP                  ZONE                 NOMINATED NODE    READINESS GATES
    web-0                        1/1     Running   0          25m     172.29.XX.XX     node-zone-k           <none>           <none>
    web-1                        1/1     Running   0          25m     172.29.XX.XX     node-zone-k           <none>           <none>

    预期输出表明,应用的副本均已迁移至可用区cn-beijing-k的节点上。

  4. 登录ECS管理控制台

    确认如下信息:

    • 新建的极速快照为长期保留。

    • 新建的云盘在cn-beijing-k可用区。

    • 原cn-beijing-i和cn-beijing-j的云盘配置未被删除,因为迁移任务中retainSourcePV的配置为true

(可选)任务失败时原因排查

若在步骤二中查询到的迁移任务状态为FAILED,可通过以下步骤查询失败原因,根据原因调整后重试。

  1. 执行以下命令,确认应用已经成功回滚。

    kubectl get pod -owide | grep web-

    预期输出:

    NAME                        READY    STATUS    RESTARTS   AGE     IP                  ZONE                 NOMINATED NODE    READINESS GATES
    web-0                        1/1     Running   0          12m     172.29.XX.XX   node-zone-i           <none>           <none>
    web-1                        1/1     Running   0          12m     172.29.XX.XX    node-zone-j           <none>           <none>
  2. 执行以下指令,查询迁移任务失败的原因。

    kubectl describe cso migrate-to-k | grep Message -A 1

    预期输出:

      Message:
        Consume: no pvc mounted in statefulset or no pvc need to migrated web

    预期输出表明,失败的原因是由于找不到待迁移的存储声明,可能为应用并未挂载存储、应用已挂载在目标可用区,无法获取存储声明信息等,请根据实际情况修改后重试。

示例2:云盘多可用区打散

例如,示例一中的有状态应用的两个副本当前都部署在cn-beijing-k可用区中,即运行在节点node-beijing-k上。为提高应用的可用性,现需要将副本打散到cn-beijing-i及cn-beijing-j双可用区中。您可以通过以下操作实现云盘的多可用区打散。

  1. 执行以下命令,在集群中创建有状态应用迁移任务。

    cat <<EOF | kubectl apply -f -
    apiVersion: storage.alibabacloud.com/v1beta1
    kind: ContainerStorageOperator
    metadata:
      name: migrate-to-i-and-j
    spec:
      operationType: APPMIGRATE
      operationParams:
        stsName: web
        stsNamespace: default
        stsType: kube
        targetZone: cn-beijing-i,cn-beijing-j   # 迁移至cn-beijing-i和cn-beijing-j可用区。
        healthDurationMinutes: "1"              # 迁移完成后隔1分钟确认应用运行正常。
        snapshotRetentionDays: "-1"             # 新建的快照长期保留,直至在控制台删除。
        retainSourcePV: "true"                  # 保留原可用区的云盘和对应PV。
    EOF
  2. 执行以下命令,查询迁移任务的状态。

    kubectl describe cso migrate-to-i-and-j | grep Status

    预期输出:

      Status:  SUCCESS
  3. 执行以下命令,查询迁移后应用两个副本的部署情况。

    kubectl get pod -owide | grep web-

    预期输出:

    NAME                        READY    STATUS    RESTARTS   AGE     IP                  ZONE                NOMINATED NODE   READINESS GATES
    web-0                        1/1     Running   0          12m     172.29.XX.XX    node-zone-i           <none>           <none>
    web-1                        1/1     Running   0          12m     172.29.XX.XX    node-zone-j           <none>           <none>

    预期输出表明,应用的两个副本已被打散至可用区cn-beijing-i和cn-beijing-j的节点上。

  4. 登录ECS管理控制台

    确认如下信息:

    • 新建的极速快照为长期保留。

    • 新建的云盘在cn-beijing-i、cn-beijing-j可用区。

    • 原cn-beijing-k的云盘配置未被删除,因为迁移任务中retainSourcePV的配置为true