1. 初识Kubevirt:当Kubernetes遇上虚拟机
第一次听说Kubevirt时,我正被一个棘手问题困扰:团队需要在Kubernetes集群里同时运行容器和传统虚拟机。当时K8s只能管理容器,而虚拟机还得靠OpenStack单独维护,运维成本直接翻倍。直到发现Kubevirt这个神器,才明白原来鱼和熊掌可以兼得。
简单来说,Kubevirt是Kubernetes的虚拟机管理插件,它让K8s具备了创建、调度和管理KVM虚拟机的超能力。最妙的是,虚拟机实际运行在Pod里,复用K8s的网络和存储体系。这意味着你可以用熟悉的kubectl命令操作虚拟机,就像操作普通Pod一样自然。
去年我们给某银行做云原生改造时就用了这招。他们的老旧系统必须跑在虚拟机里,而新开发的应用都是容器化部署。通过Kubevirt,我们只用一套K8s集群就统一管理了所有工作负载,运维团队再也不用在两个平台间来回切换了。
2. 环境准备:搭建你的Kubevirt实验场
2.1 硬件检查与依赖安装
在开始前,先确认你的节点支持硬件虚拟化。执行这个命令会告诉你答案:
virt-host-validate qemu如果看到"PASS"字样就放心了,如果显示"FAIL"也别慌,可以通过软件模拟(后面会讲)。
以CentOS为例,安装基础依赖就像煮方便面一样简单:
yum install -y qemu-kvm libvirt virt-install bridge-utilsUbuntu用户换成apt命令即可。这里有个小坑:有些云主机的内核默认没加载kvm模块,需要手动执行modprobe kvm_intel或modprobe kvm_amd。
2.2 部署Kubevirt全家桶
官方提供了傻瓜式安装方案,直接复制粘贴就能用:
# 安装Kubevirt核心组件 export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- '-rc' | head -1 | awk -F': ' '{print $2}' | sed 's/,//' | xargs) kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml # 安装CDI(容器化数据导入工具) export CDI_VERSION=$(curl -s https://github.com/kubevirt/containerized-data-importer/releases/latest | grep -o "v[0-9]\.[0-9]*\.[0-9]*") kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$CDI_VERSION/cdi-operator.yaml kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$CDI_VERSION/cdi-cr.yaml等上几分钟,用这个命令检查是否部署成功:
kubectl get pods -n kubevirt应该能看到virt-api、virt-controller等组件都在Running状态。
3. 制作你的第一个虚拟机镜像
3.1 下载基础镜像
我习惯从CentOS官方源获取qcow2格式镜像:
wget https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1805.qcow2这个镜像已经预装了cloud-init,特别适合云环境使用。如果想用Ubuntu,可以去cloud-images.ubuntu.com找对应版本。
3.2 定制化镜像
直接使用原始镜像就像住毛坯房,得先装修。创建Dockerfile来打包镜像:
FROM kubevirt/registry-disk-v1alpha COPY CentOS-7-x86_64-GenericCloud-1805.qcow2 /disk/centos.img构建并推送到镜像仓库:
docker build -t your-registry/centos:1805 . docker push your-registry/centos:1805重要提示:生产环境一定要设置镜像仓库的认证!我见过有人把测试镜像传到公开仓库导致安全事件。
4. 启动你的处女座虚拟机
4.1 编写虚拟机YAML
创建vm-container.yml文件:
apiVersion: kubevirt.io/v1 kind: VirtualMachine metadata: name: centos-vm spec: running: false template: metadata: labels: kubevirt.io/domain: centos-vm spec: domain: cpu: cores: 2 resources: requests: memory: 2Gi devices: disks: - name: containerdisk disk: bus: virtio - name: cloudinitdisk disk: bus: virtio volumes: - name: containerdisk containerDisk: image: your-registry/centos:1805 - name: cloudinitdisk cloudInitNoCloud: userData: | password: centos chpasswd: { expire: False }这个配置做了三件事:
- 分配2核CPU和2GB内存
- 挂载我们制作的系统镜像
- 通过cloud-init设置默认密码
4.2 部署与连接虚拟机
应用配置并启动VM:
kubectl apply -f vm-container.yml virtctl start centos-vm安装virtctl客户端(就像kubectl之于K8s):
export VERSION=v0.41.0 wget https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-linux-amd64 mv virtctl-${VERSION}-linux-amd64 /usr/local/bin/virtctl chmod +x /usr/local/bin/virtctl连接虚拟机控制台:
virtctl console centos-vm按ctrl+]可以退出控制台。第一次登录记得用刚设置的密码。
5. 高级玩法:像管理Pod一样管理VM
5.1 虚拟机生命周期管理
停止和启动VM比开关灯还简单:
virtctl stop centos-vm # 关机 virtctl start centos-vm # 开机 virtctl restart centos-vm # 重启查看所有虚拟机状态:
kubectl get vmi5.2 暴露虚拟机服务
把VM的SSH端口暴露为NodePort:
virtctl expose vm centos-vm --name=centos-ssh --port=22 --type=NodePort kubectl get svc centos-ssh这样就能通过节点IP和分配端口访问SSH了。
5.3 虚拟机迁移实战
Kubevirt支持热迁移,对于维护节点特别有用:
virtctl migrate centos-vm --namespace=default迁移过程中服务不会中断,我在金融项目里用这个特性实现了零停机升级。
6. 避坑指南:那些年我踩过的雷
- 网络问题:默认的pod网络可能不满足需求,建议安装Multus CNI实现多网卡支持
- 存储性能:生产环境一定要用块存储,hostpath只适合测试
- 资源分配:VM的内存必须连续分配,建议预留足够内存避免碎片
- 镜像安全:qcow2镜像可能携带恶意脚本,务必从可信源获取
有次半夜被报警吵醒,发现VM全部卡死。查了半天原来是宿主机的KSM(内存合并)导致内存泄漏。现在我的部署清单里总会加上这个配置:
spec: template: spec: domain: resources: overcommitGuestOverhead: true limits: memory: "3Gi"