虚拟化管理软件libvirt

1. 相关命令

1、安装:

yum install libvirt libvirt-daemon-kvm qemu-kvm
rpm -q virt-manager    # 查看是否安装virt-manager
yum install virt-manager

2、启动libvirtd服务

systemctl status libvirtd
systemctl start libvirtd     # 设置立即启动,仅本次会话有效
systemctl enable libvirtd    # 设置开启自启动

2. 概述

内核管理着三个重要的资源:计算、网络和存储。计算指CPU和内存,网络指网络设备,存储指硬盘等。

2.1 qemu,KVM,Virsh

qemu,其中的emu实际上是emulator,模拟器。所以单纯使用qemu是采用的完全虚拟化的模式。qemu实际上是作为GuestOS和真正的CPU、硬件之间的“中间商”,所有的指令都要从qemu中间过一手。

image

kvm: Kernel-based Virtual Machine,基于内核的虚拟机。kvm是Linux内核的一部分,提供了对硬件虚拟化的支持。通过kvm,Linux内核可以作为一个虚拟机管理程序(hypervisor),允许在一台物理机器上运行多个隔离的虚拟机。
在kvm中创建虚拟机硬盘时,qcow2格式为动态分配,raw格式为固定大小。

由于完全虚拟化是非常慢的,因此使用硬件辅助虚拟化技术Intel-VT,AMD-V。使用后CPU将开启相应的标志位。此时通过kvm,GuestOS的CPU指令不需要再经过qemu转译,可以直接运行。因此,kvm需要在物理机的内核中设置相应的模块,来设置当前CPU是GuestOS在用还是HostOS在用。

接着,qemu将kvm整合进来,通过ioctl调用/dev/kvm接口,将有关CPU指令的部分交由内核模块来做,即qemu-kvm(qemu-system-XXX)。这样CPU的性能问题就得到了解决。但是由于qemu还会模拟其他的硬件,如Network和Disk等,因此qemu采用半虚拟化直通的方式,让GuestOS加载特殊的驱动来做这件事。

例如网络需要加载virtio_net,存储需要加载virtio_blk,GuestOS需要安装这些半虚拟化驱动,GuestOS知道自己是虚拟机,所以数据直接发送给半虚拟化设备,经过特殊处理,例如排队,缓存,批量处理等性能优化方式,最终发送给真正的硬件,一定程度上提高了性能。

直接用qemu或qemu-kvm的较少,大多数通过virsh启动。virsh属于libvirt工具,分服务端和客户端。libvirtd是一个daemon进程,是服务端,可以被本地的virsh调用,也可以被远程的virsh调用,virsh相当于客户端。

整个关系如下:

image

总的来说,qemu、kvm和virsh的关系如下:

  • kvm是Linux内核的一部分,主要负责CPU和内存的虚拟化。

  • qemu是一个开源的硬件虚拟化软件,可以独立运行,也可以和kvm结合来帮助处理I/O虚拟化和设备虚拟化等任务。

  • virsh是基于libvirt的命令行工具,用于管理不同的虚拟化技术,包括kvm/qemu在内。

2.2 libvirt

libvirt是对KVM虚拟机进行管理的工具和应用程序接口,一些常用的虚拟机管理工具(如virsh、virt-install、virt-manager等)和云计算框架平台(如OpenStack、ZStack、OpenNebula、Eucalyptus等)都在底层使用libvirt的应用程序接口。

在libvirt中涉及几个重要概念:

  • Node:物理机器,上面运行着多个虚拟客户机。

  • Hypervisor:也称虚拟机监控器VMM,如kvm、VMware、Hyper-V等,是虚拟化中的一个底层软件层,它可以虚拟化一个节点让其运行多个虚拟客户机。

  • Domain:Hypervisor上运行的一个客户机操作系统实例,域(Domain)和实例(Instance)、客户机操作系统(GuestOS)、虚拟机(Virtual Machine)均为同一个概念。

image

3. libvirt API使用

libvirt源码地址:https://gitlab.com/libvirt/libvirt.git

一个简单的示例:通过调用libvirt的API来查询一些关于某个域的信息。

/**
 * Get domain information via libvirt C API.
 * Tested with libvirt-devel-2.0.0 on a RHEL 7.3 host system.
 */
#include <libvirt/libvirt.h>
#include <stdio.h>
 
int getDomainInfo(int id) {
  virConnectPtr conn = NULL; /* the hypervisor connection */
  virDomainPtr dom = NULL;   /* the domain being checked */
  virDomainInfo info;        /* the information being fetched */
  /* NULL means connect to local QEMU/KVM hypervisor */
  conn = virConnectOpenReadOnly(NULL);
  if (conn == NULL) {
    fprintf(stderr, "Failed to connect to hypervisor\n");
    return 1;
  }
  /* Find the domain by its ID */
  dom = virDomainLookupByID(conn, id);
  if (dom == NULL) {
    fprintf(stderr, "Failed to find Domain %d\n", id);
    virConnectClose(conn);
    return 1;
  }
  /* Get virDomainInfo structure of the domain */
  if (virDomainGetInfo(dom, &info) < 0) {
    fprintf(stderr, "Failed to get information for Domain %d\n", id);
    virDomainFree(dom);
    virConnectClose(conn);
    return 1;
  }
  /* Print some info of the domain */
  printf("Domain ID: %d\n", id);
  printf(" vCPUs: %d\n", info.nrVirtCpu);
  printf(" maxMem: %d KB\n", info.maxMem);
  printf(" memory: %d KB\n", info.memory);
  if (dom != NULL)
    virDomainFree(dom);
  if (conn != NULL)
    virConnectClose(conn);
  return 0;
}
int main(int argc, char **argv) {
  int dom_id = 1;
  printf("-----Get domain info by ID via libvirt C API -----\n");
  getDomainInfo(dom_id);
  return 0;
}

编译:

gcc libvirt-demo.c -o libvirt-demo -lvirt

运行:

$ sudo ./libvirt-demo 
-----Get domain info by ID via libvirt C API -----
Domain ID: 1
 vCPUs: 2
 maxMem: 4194304 KB
 memory: 4194304 KB
posted @ 2025-08-01 14:29  midorii  阅读(90)  评论(0)    收藏  举报