Kubernetes Kubevirt | 从零到一:在K8s集群中构建并管理你的首个虚拟机
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 部署与连接虚拟机应用配置并启动VMkubectl apply -f vm-container.yml virtctl start centos-vm安装virtctl客户端就像kubectl之于K8sexport VERSIONv0.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一样管理VM5.1 虚拟机生命周期管理停止和启动VM比开关灯还简单virtctl stop centos-vm # 关机 virtctl start centos-vm # 开机 virtctl restart centos-vm # 重启查看所有虚拟机状态kubectl get vmi5.2 暴露虚拟机服务把VM的SSH端口暴露为NodePortvirtctl expose vm centos-vm --namecentos-ssh --port22 --typeNodePort kubectl get svc centos-ssh这样就能通过节点IP和分配端口访问SSH了。5.3 虚拟机迁移实战Kubevirt支持热迁移对于维护节点特别有用virtctl migrate centos-vm --namespacedefault迁移过程中服务不会中断我在金融项目里用这个特性实现了零停机升级。6. 避坑指南那些年我踩过的雷网络问题默认的pod网络可能不满足需求建议安装Multus CNI实现多网卡支持存储性能生产环境一定要用块存储hostpath只适合测试资源分配VM的内存必须连续分配建议预留足够内存避免碎片镜像安全qcow2镜像可能携带恶意脚本务必从可信源获取有次半夜被报警吵醒发现VM全部卡死。查了半天原来是宿主机的KSM内存合并导致内存泄漏。现在我的部署清单里总会加上这个配置spec: template: spec: domain: resources: overcommitGuestOverhead: true limits: memory: 3Gi