VM 固定 IP¶
在容器场景下,容器的 IP 地址通常是动态分配的,并且会在容器重启后发生变化。但是对于 VM 用户来说,他们希望 VM 的 IP 地址是固定的,来进行后续的管理和操作。
但是大部分常见 CNI 存在下面的局限性:
- 无法将 IP 地址和 VM 生命周期绑定,VM 重启或者后 IP 发生变化。
- IP 地址和 Node 绑定,VM 迁移到新的节点后无法复用之前 IP。
- 无法支持 IP 地址配置,用户无法指定 VM 的 IP 地址。
因此通常会使用 KubeVirt 的 masquerade 网络模式,通过 iptables 将 VM 的流量转发到宿主机网卡上,从而实现 VM 的 IP 固定,但 masquerade 相比 bridge 存在以下问题:
- Pod IP 和 VM IP 不一致,管理方面存在复杂度,且重启和热迁移后 Pod IP 发生变化,外部访问来看地址依然不固定。
- masquerade使用 iptables 进行流量转发,性能相比- bridge模式要差。
- masquerade只支持三层流量转发,一些二层网络功能无法实现。
- masquerade流量通过 conntrack 记录转发状态,热迁移期间存在流量中断可能。
Kube-OVN 支持为 KubeVirt 下 bridge 和 managedTap 网络模式下的 IP 和 VM 生命周期绑定,该 IP 地址在 VM 重启,热迁移等操作后仍然保持不变。同时也支持通过添加 annotation 的方式为 VM 配置固定 IP 地址。
IP 和 VM 生命周期绑定¶
对于只希望 VM 生命周期内 IP 地址固定,但不需要指定 IP 地址的场景,用户只需按原先方式创建 VM 即可。Kube-OVN 内部的 IPAM 会自动记录 VM 生命周期,保证 VM 在重启和迁移后使用相同的 IP 地址。
下面以 bridge 网络模式为例,创建一个 VM,进行重启,热迁移等操作,并观察 IP 地址的变化。
- 创建 VM
kubectl apply -f - <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: testvm
spec:
  runStrategy: Always 
  template:
    metadata:
      labels:
        kubevirt.io/size: small
        kubevirt.io/domain: testvm
      annotations:
        kubevirt.io/allow-pod-bridge-network-live-migration: "true"
    spec:
      domain:
        devices:
          disks:
            - name: containerdisk
              disk:
                bus: virtio
            - name: cloudinitdisk
              disk:
                bus: virtio
          interfaces:
          - name: default
            bridge: {}
        resources:
          requests:
            memory: 64M
      networks:
      - name: default
        pod: {}
      volumes:
        - name: containerdisk
          containerDisk:
            image: quay.io/kubevirt/cirros-container-disk-demo
        - name: cloudinitdisk
          cloudInitNoCloud:
            userDataBase64: SGkuXG4=
EOF
- 查看 VM 状态
kubectl get vmi testvm
- 重启 VM
virtctl restart testvm
- 热迁移 VM
virtctl migrate testvm
可观察到在 bridge 模式下 VM 重启和热迁移后,IP 地址保持不变。
指定 IP 地址¶
对于需要指定 VM 的 IP 地址的场景,用户可以通过创建 VM 时添加 annotation 的方式为 VM 指定 IP 地址。其他使用方式和原生 KubeVirt 一致。
kubectl apply -f - <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: testvm
spec:
  runStrategy: Always 
  template:
    metadata:
      labels:
        kubevirt.io/size: small
        kubevirt.io/domain: testvm
      annotations:
        ovn.kubernetes.io/ip_address: 10.16.0.15
        kubevirt.io/allow-pod-bridge-network-live-migration: "true"
    spec:
      domain:
        devices:
          disks:
            - name: containerdisk
              disk:
                bus: virtio
            - name: cloudinitdisk
              disk:
                bus: virtio
          interfaces:
          - name: default
            bridge: {}
        resources:
          requests:
            memory: 64M
      networks:
      - name: default
        pod: {}
      volumes:
        - name: containerdisk
          containerDisk:
            image: quay.io/kubevirt/cirros-container-disk-demo
        - name: cloudinitdisk
          cloudInitNoCloud:
            userDataBase64: SGkuXG4=
EOF