跳转至

虚拟机跨集群迁移

本功能暂未做 UI 界面能力,请参考以下操作步骤。

使用场景

  • 当原集群发生故障或性能下降导致该集群上的虚拟机无法访问时,将虚拟机迁移到其他的集群上。
  • 需要对集群进行计划内的维护或升级时,将虚拟机迁移到其他的集群上。
  • 当特定应用的性能需求变化,需要调整资源分配时,迁移虚拟机到其他的集群上以匹配更合适的资源配置。

前提条件

实现虚拟机跨集群迁移之前,需要满足以下前提条件:

  • 集群网络互通:确保原有集群与目标迁移集群之间的网络是互通的
  • 相同存储类型:目标迁移集群需支持与原有集群相同的存储类型(例如,如果导出集群使用 rook-ceph-block 类型的 StorageClass,则导入集群也必须支持此类型)。
  • 在原有集群的 KubeVirt 中开启 VMExport Feature Gate。

开启 VMExport Feature Gate

激活 VMExport Feature Gate,在原有集群内执行如下命令, 可参考如何激活特性门控

kubectl edit kubevirt kubevirt -n virtnest-system

这条命令将修改 featureGates,增加 VMExport

apiVersion: kubevirt.io/v1
kind: KubeVirt
metadata:
  name: kubevirt
  namespace: virtnest-system
spec:
  configuration:
    developerConfiguration:
      featureGates:
        - DataVolumes
        - LiveMigration
        - VMExport

配置原有集群的 Ingress

安装 LB 类型的 ingress-controller。

virtnest-system 命名空间下创建 tls secret:

export KEY_FILE=key.pem
export CERT_FILE=cert.ca
export HOST=upgrade-test.com
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=${HOST}/O=${HOST}" -addext "subjectAltName = DNS:${HOST}"

export CERT_NAME=nginx-tls
kubectl -n virtnest-system create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert ${CERT_FILE}

virtnest-system 命名空间下创建 Ingress,配置 Ingress 以指向 virt-exportproxy Service:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-vm-export
  namespace: virtnest-system
spec:
  tls:
    - hosts:
        - upgrade-test.com
      secretName: nginx-tls
  rules:
    - host: upgrade-test.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: virt-exportproxy
                port:
                  number: 8443
  ingressClassName: nginx

配置目标集群的 CoreDNS ConfigMap

kubectl edit cm coredns -n kube-system

找到 Corefile 配置部分,并添加 hosts 配置。这里假设 Ingress 的 LB 配置为 192.168.1.10

Corefile: |
  .:53 {
      errors
      health
      ready
      kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
      }
      hosts {
          192.168.1.10 upgrade-test.com
          fallthrough
      }
      prometheus :9153
      forward . /etc/resolv.conf
      cache 30
      loop
      reload
      loadbalance
  }

迁移步骤

  1. 创建 VirtualMachineExport CR

    apiVersion: v1
    kind: Secret
    metadata:
      name: example-token # 导出虚拟机所用 token
      namespace: default # 虚拟机所在命名空间
    stringData:
      token: 1234567890ab # 导出时所用的 token
    
    ---
    apiVersion: export.kubevirt.io/v1alpha1
    kind: VirtualMachineExport
    metadata:
      name: example-export # 导出名称, 可自行修改
      namespace: default # 虚拟机所在命名空间
    spec:
      tokenSecretRef: example-token # 和上面创建的 token 名称保持一致
      source:
        apiGroup: "kubevirt.io"
        kind: VirtualMachine
        name: testvm # 虚拟机名称
    
    apiVersion: v1
    kind: Secret
    metadata:
      name: example-token # 导出虚拟机所用 token
      namespace: default # 虚拟机所在命名空间
    stringData:
      token: 1234567890ab # 导出时所用的 token
    
    ---
    apiVersion: export.kubevirt.io/v1alpha1
    kind: VirtualMachineExport
    metadata:
      name: export-snapshot # 导出名称, 可自行修改
      namespace: default # 虚拟机所在命名空间
    spec:
      tokenSecretRef: export-token # 和上面创建的token名称保持一致
      source:
        apiGroup: "snapshot.kubevirt.io"
        kind: VirtualMachineSnapshot
        name: export-snap-202407191524 # 对应的虚拟机快照名称
    
  2. 检查 VirtualMachineExport 是否准备就绪:

    # 这里的 example-export 需要替换为创建的 VirtualMachineExport 名称
    kubectl get VirtualMachineExport example-export -n default
    
    NAME             SOURCEKIND       SOURCENAME   PHASE
    example-export   VirtualMachine   testvm       Ready
    
  3. 当 VirtualMachineExport 准备就绪后,导出虚拟机 YAML。

    使用以下命令导出虚拟机的 YAML:

    # 自行将 example-export替换为创建的 VirtualMachineExport 名称
    # 自行通过 -n 指定命名空间
    virtctl vmexport download example-export --manifest --include-secret --output=manifest.yaml
    

    使用以下命令导出虚拟机 YAML:

    # 自行替换 example-export 替换为创建的 VirtualMachineExport 名称 和命名空间
    manifesturl=$(kubectl get VirtualMachineExport example-export -n default -o=jsonpath='{.status.links.internal.manifests[0].url}')
    secreturl=$(kubectl get VirtualMachineExport example-export -n default -o=jsonpath='{.status.links.internal.manifests[1].url}')
    # 自行替换 secert 名称和命名空间
    token=$(kubectl get secret example-token -n default -o=jsonpath='{.data.token}' | base64 -d)
    
    curl -H "Accept: application/yaml" -H "x-kubevirt-export-token: $token"  --insecure  $secreturl > manifest.yaml
    curl -H "Accept: application/yaml" -H "x-kubevirt-export-token: $token"  --insecure  $manifesturl >> manifest.yaml
    
  4. 导入虚拟机

    将导出的 manifest.yaml 复制到目标迁移集群并执行以下命令(如果命名空间不存在则需要提前创建):

    kubectl apply -f manifest.yaml
    

    创建成功后,重启虚拟机,虚拟机成功运行后,在原有集群内删除原虚拟机(虚拟机未启动成功时,请勿删除原虚拟机)。

评论