kubevirt是什么
- 一个开源项目,CNCF sandbox
- 将虚拟机(VM)运行引入了 k8s 集群中,使得用户可以在 k8s 中同时管理容器和虚拟机工作负载
- 帮助企业和开发者通过 k8s 统一管理虚拟机和容器,方便地运行和迁移传统的虚拟机工作负载到云原生环境中
特点
- 虚拟机和容器共存:KubeVirt 将虚拟机作为 Kubernetes CRD 来进行管理,从而允许在 Kubernetes 集群内同时调度和运行虚拟机和容器
- Kubernetes 原生支持:KubeVirt 完全整合到 Kubernetes 生态系统中。通过 Kubernetes API,用户可以像管理容器一样管理虚拟机(VM),包括启动、停止、扩展、迁移等操作
- 支持传统和现代应用:通过 KubeVirt,可以将遗留系统或传统应用程序从虚拟化平台迁移到 Kubernetes,方便地与现代云原生应用程序一起运行,助力企业数字化转型。
- 无缝的网络和存储集成:KubeVirt 使用 Kubernetes 的网络和存储资源,这意味着虚拟机可以使用 Kubernetes 的网络插件(如 Calico、Flannel 等)和持久存储卷(如 NFS、Ceph 等)
- 虚拟机的动态调度和负载均衡:KubeVirt 支持虚拟机的动态调度和负载均衡功能,可以根据集群状态自动调度虚拟机到合适的节点
- Live Migration(在线迁移):KubeVirt 支持虚拟机的在线迁移功能,即在不中断服务的情况下将虚拟机从一个节点迁移到另一个节点
- 支持多种操作系统:KubeVirt 支持运行多种操作系统,包括 Linux 和 Windows。这使得它在多种业务场景下都能胜任
kubevirt架构

kubevirt以CRD的形式将VM管理接口接入到kubernetes中,通过一个pod去使用libvirtd管理VM的方式,实现pod与VM的一一对应,做到如同容器一般去管理虚拟机,并且做到与容器一样的资源管理、调度规划
- VirtualMachine(VM):这是 KubeVirt 中的核心资源类型。每个 VirtualMachine 对象定义了虚拟机的配置,比如 CPU、内存、磁盘、网络等信息
- VirtualMachineInstance(VMI):当你启动一个虚拟机时,会创建一个 VMI 对象,表示该虚拟机的运行实例。这个对象包含虚拟机的运行时状态信息
- **virt-api:**其是所有虚拟化操作的入口,包括常规的CRD更新验证、console、vm 的start和stop操作
- virt-controller:其是 KubeVirt 的控制器,负责监视和管理 VirtualMachine 和 VirtualMachineInstance 的生命周期,比如启动、停止、重启和迁移等操作
- virt-handler:其会以deamonset的形式部署在每一个node上,负责监控node上的每个虚拟机实例状态变化
- virt-launcher:这是一个短生命周期的 Pod,每个 VMI 都会有一个对应的 virt-launcher Pod,负责在节点上启动和管理实际的虚拟机进程
root@master01:/home/ubuntu/yst/cdi-manage-vm-disk-image# k exec -it virt-launcher-vm1-7kxt5 -- pstree -U
virt-launcher-m─┬─qemu-kvm───5*[{qemu-kvm}]
├─virt-launcher─┬─virtlogd
│ ├─virtqemud───18*[{virtqemud}]
│ └─15*[{virt-launcher}]
└─7*[{virt-launcher-m}]
- virt-launcher-m: 这是一个管理虚拟机的进程,负责启动和管理虚拟机实例。它是 Kubernetes 中 KubeVirt 的一部分,KubeVirt 用于在 Kubernetes 环境中运行虚拟机。
- qemu-kvm: 是虚拟机的实际运行进程,负责运行用户自定义的镜像操作系统,模拟虚拟的硬件环境,包括CPU、内存、磁盘和网络情况
- 子进程: 在进程树中,可以看到许多子进程:
- 5*[{qemu-kvm}]: 这是 qemu-kvm 的工作线程,表明有 5 个线程在处理虚拟机的请求。
- virtlogd: 这是一个用于管理虚拟机日志的守护进程,负责收集和存储虚拟机的日志信息。
- virtqemud: 这是一个用于管理 QEMU 实例的守护进程,也可能有多个线程(18*[{virtqemud}] 表示有 18 个线程)。
4.进程树的结构: 每一层的缩进表示进程之间的父子关系。例如,virt-launcher 是 virt-launcher-m 的子进程,而 qemu-kvm 是 virt-launcher-m 的子进程。
deploy kubevirt & install virtctl
构建基础镜像
首先,选择基础镜像,这里我们选择 ubuntu22.04LST
curl -L -o jammy-server-cloudimg-amd64.img https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
安装需要的包
sudo apt update
sudo apt install qemu-utils qemu-kvm qemu-system cloud-image-utils genisoimage
设置登陆密码
# 1.这里的 cloudconfig 创建了一个密码为 root,其用户名默认为ubuntu
cat >user-data <<EOF
#cloud-config
password: root
chpasswd: { expire: False }
ssh_pwauth: True
EOF
#2.创建一个空的 meta-data
cat >meta-data<<EOF
EOF
将创建的 user-data转化为qemu可以使用的img格式的文件
cloud-localds user-data.img user-data
默认的系统盘只有2G,后续安装可能会爆磁盘空间不足的错误,可以提前扩容(正好凑够20G,按需扩容)
sudo qemu-img resize ./jammy-server-cloudimg-amd64.img +18G
启动虚拟机
sudo qemu-system-x86_64 -smp 4 -m 16384m -nographic -drive file=jammy-server-cloudimg-amd64.img,format=qcow2 -drive file=user-data.img,format=raw -device virtio-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2333-:22
配置root密码、开启自启动DHCP
# 注意下面操作的内容是永久生效的
# 1. 允许root登陆
sudo sed -i 's/\#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
# 2. 设置root密码,其中root用户的密码我设置为root
sudo passwd root
# 3.修改网卡自动dhcp
sudo apt-get install isc-dhcp-client
sudo vi /etc/rc.local
添加一下内容
#!/bin/bash
dhclient -v
# 4.授权
sudo chmod 755 /etc/rc.local
下载docker并设置自启动
# 添加docker官方 GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# 添加repo到 Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
#安装docker及其组件
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
#验证
sudo docker version
sudo docker run hello-world
#将docker设置为自启动
sudo systemctl enable docker
#验证是否成功
sudo systemctl is-enabled docker
最终
此时的img就是一个包含我们自己安装的img了,可以按需,利用此基础镜像img进行扩展
可以将此img镜像打包为docker镜像进行保存
#将 img 文件转换为 qcow2 格式
sudo qemu-img convert -p -c -O qcow2 jammy-server-cloudimg-amd64.img jammy-server-cloudimg-amd64.qcow2
#编写Dockerfile
sudo vi Dockerfile
#添加一下内容
FROM scratch
COPY --chown=107:107 jammy-server-cloudimg-amd64.qcow2 /disk/
#构建镜像,注意上下文
sudo docker build -t kubevirt-image/ubuntu22.04lts:with-docker
构建VM
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: ubuntu
labels:
vmName: ubuntu
sshtest: "true"
spec:
dataVolumeTemplates:
- metadata:
name: sys-dv
spec:
storage:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: openebs-lvmpv
source:
registry:
url: docker://....
running: true
template:
metadata:
labels:
vmName: ubuntu
sshtest: "true"
spec:
domain:
cpu:
cores: 4
devices:
disks:
- name: datavolumevolume
disk:
bus: virtio
- name: cloudinitdisk
disk:
bus: virtio
interfaces:
- name: default
masquerade: {}
resources:
requests:
memory: 8Gi
networks:
- name: default
pod: {}
volumes:
- name: datavolumevolume
persistentVolumeClaim:
claimName: sys-dv
- name: cloudinitdisk
cloudInitNoCloud:
userData: |
#cloud-config
hostname: vm1
ssh_pwauth: True
disable_root: false
ssh_authorized_keys:
- ssh-rsa ....
chpasswd:
list: |
ubuntu:ubuntu
expire: False
运行
virtctl console vmname