将 VM 连接到网络有两个步骤,首先需要在 spec.networks 声明网络,然后在 spec.domain.devices.interfaces 中添加网卡并指定使用的网络。
在 spec.networks 中声明的网络称为后端(Backend),在 spec.domain.devices.interfaces 中声明的网卡称为前端(Frontend)。
Backend 后端网络配置在 spec.networks,网络必须名称唯一。 每个网络都需要声明类型:
类型
描述
pod
默认 Kubernetes 网络
multus
由 Multus 提供的辅助网络
Frontend 网卡配置在 spec.domain.devices.interfaces ,里面定义的属性将在 VM 中可以看到。 每个网卡都需要声明类型:
类型
描述
bridge
使用 Linux Bridge 连接
slirp
使用 QEMU 用户网络模式连接
sriov
透传 SR-IOV PCI 设备通过 vfio
masquerade
使用 iptables 规则连接以对流量进行 NAT
访问 VM 中的服务 VM 中的提供的服务通常需要暴露给集群中其它的工作负载访问或被集群外部进行访问。
集群内部访问 使用 fedora-vm1.yaml 部署 VM,VM 使用的 PV 已经事先通过 CDI 导入了 Fedora 镜像:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: labels: kubevirt.io/os: linux name: fedora-vm1 spec: running: true template: metadata: labels: kubevirt.io/domain: fedora-vm1 spec: nodeSelector: kubernetes.io/hostname: worker01.example.com domain: cpu: cores: 1 devices: disks: - disk: bus: virtio name: disk0 - cdrom: bus: sata readonly: true name: cloudinitdisk machine: type: q35 resources: requests: memory: 512M volumes: - name: disk0 persistentVolumeClaim: claimName: fedora - cloudInitNoCloud: userData: | #cloud-config hostname: fedora-vm1 ssh_pwauth: True disable_root: false ssh_authorized_keys: - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqjnw9Xnt4buBYlfuCnZNknm0oKDgVtdzhVTnH/S7Aa0P30D89RrlSSuIcKz0p+6ss3c9sT66R/J4dNUxHuyzYJucRLfmdyEEuVR8mlJ8LLTVR8NOK7r3Ao/mx0cIVJ/YS2y7U8T0uO6YoyoKklvGhlqZHli3fsv4JAVbrCXl05/gdqnQu3u+ang97hDtHg7oSiI3e0Wjm40hwPc+agtaSgypWgmPvdvPNB2YGlmm/QGppTzg0ao0NQduGrTzzYEI54SUx1MFBsM70ykN13IOw2J30fHnnLxlFCCoOwgxy4G9soV/e0vvn7dpqIPsr+Nc+sAuweChclKhUcmBVYa6Pr5mX2y3ZeulE+Nzok165mfF9q5TMC5XziInALDOBVtHIw0St1fgrbnnZPEBiMP6i3q814//TvA0m9xotgq8OrhUbNp2ezjpqyMa+31yPP3gmAVMqji2vIaQB3tluGsH2h/djh0I52YHhDO1S5bDs2OCHCrN2WGuA9qr8NT78ISs= vagrant@master01.example.com name: cloudinitdisk
在上述资源定义中,没有定义任何关于网络和网卡的信息。 创建虚拟机后,可以看到默认使用的网络信息:
默认使用的桥接到 Pod 网络,所以在 VM 中的 IP 与 Pod 的 IP 是一致的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [vagrant@master01 ~]$ kubectl get vmi/fedora-vm1 -n vm-net -o wide NAME AGE PHASE IP NODENAME READY LIVE-MIGRATABLE PAUSED fedora-vm1 10m Running 10.42.95.178 worker01.example.com True False [vagrant@master01 ~]$ [vagrant@master01 ~]$ virtctl ssh fedora@fedora-vm1.vm-net Last login: Thu May 9 13:28:11 2024 from 10.42.45.219 [fedora@fedora-vm1 ~]$ ip a s eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc fq_codel state UP group default qlen 1000 link /ether 9e:46:39:51:10:bc brd ff:ff:ff:ff:ff:ff altname enp1s0 inet 10.42.95.178/32 scope global dynamic noprefixroute eth0 valid_lft 86313127sec preferred_lft 86313127sec inet6 fe80::6bf8:8366:c521:5857/64 scope link noprefixroute valid_lft forever preferred_lft forever
在 VM 中部署了 Web 服务,可以直接通过 Pod 的 IP 进行访问:
1 2 [vagrant@master01 ~]$ curl 10.42.95.178 KubeVirt: hi from fedora-vm1.
但使用 Bridge 模式会带来一个问题:
1 Message: cannot migrate VMI which does not use masquerade, bridge with kubevirt.io/allow-pod-bridge-network-live-migration VM annotation or a migratable plugin to connect to the pod network
原因是 Pod 的 IP 是不固定的,当发生迁移的时候,会创建新的 VM,此时 IP 将发生变化,导致 VM 中的网络也随着变化,如果要支持迁移,需要将网络类型修改为 masquerade 类型。
修改为 masquerade :
需要更改 vm 资源,修改后,还需将 vmi 删除,重新根据 vm 创建 vmi :
1 2 3 4 [vagrant@master01 ~]$ kubectl edit vm/fedora-vm1 -n vm-net virtualmachine.kubevirt.io/fedora-vm1 edited [vagrant@master01 ~]$ kubectl delete vmi fedora-vm1 -n vm-net virtualmachineinstance.kubevirt.io "fedora-vm1" deleted
然后可以看到在 VM 中 eth0 网卡的网络是一个内部网络:
1 2 3 4 5 6 7 8 9 10 11 12 13 [vagrant@master01 ~]$ kubectl get vmi/fedora-vm1 -o wide -n vm-net NAME AGE PHASE IP NODENAME READY LIVE-MIGRATABLE PAUSED fedora-vm1 106m Running 10.42.95.189 worker01.example.com True True [vagrant@master01 ~]$ virtctl ssh fedora@fedora-vm1.vm-net Last login: Fri May 10 02:03:56 2024 from 10.42.45.232 [fedora@fedora-vm1 ~]$ ip a s eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc fq_codel state UP group default qlen 1000 link /ether 36:e6:18:9a:fb:04 brd ff:ff:ff:ff:ff:ff altname enp1s0 inet 10.0.2.2/24 brd 10.0.2.255 scope global dynamic noprefixroute eth0 valid_lft 86307426sec preferred_lft 86307426sec inet6 fe80::2224:443b:537b:8b64/64 scope link noprefixroute valid_lft forever preferred_lft forever
此时访问 Pod 的 IP,依旧可以访问到 VM 中的服务:
1 2 [vagrant@master01 ~]$ curl 10.42.95.189 KubeVirt: hi from fedora-vm1.
Pod IP 不固定,需要使用 Service 资源使用固定的 IP 和集群内部的名称解析来访问 VM 中的服务。 创建 Service:
1 2 3 4 5 6 7 8 9 10 11 apiVersion: v1 kind: Service metadata: name: fedoravm1-svc namespace: vm-net spec: ports: - port: 80 targetPort: 80 selector: kubevirt.io/domain: fedora-vm1
应用并检查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 [vagrant@master01 ~]$ kubectl apply -f fedora-vm1-svc.yaml service/fedoravm1-svc created [vagrant@master01 ~]$ kubectl describe svc fedoravm1-svc Error from server (NotFound): services "fedoravm1-svc" not found [vagrant@master01 ~]$ kubectl describe svc fedoravm1-svc -n vm-net Name: fedoravm1-svc Namespace: vm-net Labels: <none> Annotations: <none> Selector: kubevirt.io/domain=fedora-vm1 Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.43.5.191 IPs: 10.43.5.191 Port: <unset > 80/TCP TargetPort: 80/TCP Endpoints: 10.42.95.189:80 Session Affinity: None Events: <none> [vagrant@master01 ~]$ cat fedora-vm1-svc.yaml apiVersion: v1 kind: Service metadata: name: fedoravm1-svc namespace: vm-net spec: ports: - port: 80 targetPort: 80 selector: kubevirt.io/domain: fedora-vm1 [vagrant@master01 ~]$ curl 10.43.5.191 KubeVirt: hi from fedora-vm1.
集群外部访问 对外提供 VM 的访问可以通过 Service NodePort 这是最简单的方式,还可以通过 Multus 辅助网络,如果是 HTTP 协议的服务,还可以使用 Ingress 资源。
使用 Service NodePort 修改 Service:
1 2 3 4 5 6 7 8 9 10 11 12 apiVersion: v1 kind: Service metadata: name: fedoravm1-svc namespace: vm-net spec: ports: - port: 80 targetPort: 80 selector: kubevirt.io/domain: fedora-vm1 type: NodePort
应用并检查:
1 2 3 4 5 6 7 8 9 [vagrant@master01 ~]$ kubectl apply -f fedora-vm1-svc.yaml service/fedoravm1-svc configured [vagrant@master01 ~]$ kubectl get svc/fedoravm1-svc -n vm-net NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE fedoravm1-svc NodePort 10.43.5.191 <none> 80:30491/TCP 7m33s [vagrant@master01 ~]$ curl localhost:30491 KubeVirt: hi from fedora-vm1.
使用 Ingress 因为 vm 中提供的是 Web 服务,所以可以使用 Ingress,如果是非 HTTP/HTTPS 协议的服务则不行。
webserver ingress 资源定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: webserver namespace: vm-net spec: defaultBackend: service: name: fedoravm1-svc port: number: 80 rules: - host: webserver.example.com http: paths: - backend: service: name: fedoravm1-svc port: number: 80 path: / pathType: Prefix
创建 ingress 资源并验证:
1 2 3 4 5 6 7 [vagrant@master01 ~]$ kubectl apply -f ingress-webserver.yaml ingress.networking.k8s.io/webserver created [vagrant@master01 ~]$ kubectl get ingress -n vm-net NAME CLASS HOSTS ADDRESS PORTS AGE webserver <none> webserver.example.com 192.168.121.109,192.168.121.110,192.168.121.27 80 6s [vagrant@master01 ~]$ curl webserver.example.com KubeVirt: hi from fedora-vm1
评论· · · · · ·