Glance 深度解析:OpenStack 镜像服务原理与实践 定位与职责 Glance 是 OpenStack 的镜像服务 ,负责虚拟机镜像的存储、检索和分发:
上传、下载、删除虚拟机镜像
管理镜像元数据(格式、架构、最小内存等)
支持多种存储后端(本地文件系统、Swift、Ceph、S3)
镜像共享(跨 Project 共享)
镜像签名验证(安全性)
架构总览 1 2 3 4 5 6 7 8 9 10 glance-api(唯一进程) │ ├── Registry Layer(元数据管理)→ MySQL │ └── Store Layer(镜像数据存储) ├── filesystem store → /var/lib/glance/images/ ├── rbd store → Ceph RBD Pool ├── swift store → Swift 对象存储 ├── s3 store → AWS S3 / MinIO └── http store → 外部 HTTP URL
从 Ocata 版本起,glance-registry 进程被废弃,功能合并到 glance-api。
镜像格式
格式
说明
适用场景
qcow2
QEMU Copy-On-Write v2,支持快照、压缩、加密
KVM 虚拟化首选
raw
裸格式,无额外开销,性能最好
配合 Ceph 使用
vmdk
VMware 格式
VMware 迁移
vhd
Hyper-V 格式
Windows 虚拟化
iso
光盘镜像
系统安装盘
aki/ari/ami
Amazon 镜像格式
AWS 兼容
格式
说明
bare
无容器,直接是磁盘镜像(最常用)
ovf
Open Virtualization Format
ova
OVF 的打包格式
镜像上传流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class ImagesController : def upload (self, req, image_id, data, size ): self .gateway.upload_image_data( req.context, image, data, backend=backend )def store_add_to_backend (image_id, data, size, store, ... ): (uri, size, checksum, loc) = store.add(image_id, data, size)
上传到 Ceph RBD 1 2 3 4 5 6 7 8 9 10 11 12 13 class Store (driver.Store): def add (self, image_id, image_file, image_size, ... ): with self .get_connection() as conn: rbd_image = rbd.Image(conn.ioctx, image_id) bytes_written = 0 for chunk in image_file: rbd_image.write(chunk, bytes_written) bytes_written += len (chunk) return (self ._get_uri(image_id), bytes_written, checksum, {})
镜像属性(Properties) 镜像属性是 Glance 的重要特性,Nova 调度和创建 VM 时会读取这些属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 openstack image create ubuntu-22.04 \ --file ubuntu-22.04-server-cloudimg-amd64.img \ --disk-format qcow2 \ --container-format bare \ --property hw_disk_bus=virtio \ --property hw_vif_model=virtio \ --property hw_scsi_model=virtio-scsi \ --property os_type=linux \ --property os_distro=ubuntu \ --property os_version=22.04 \ --property hw_qemu_guest_agent=yes \ --min-disk 20 \ --min-ram 1024
Nova 读取镜像属性的关键场景
属性
作用
hw_disk_bus
磁盘总线类型(virtio/ide/scsi)
hw_vif_model
网卡型号(virtio/e1000/rtl8139)
hw_numa_nodes
NUMA 节点数,影响调度
hw_cpu_policy
CPU 绑定策略(dedicated/shared)
hw_machine_type
QEMU 机器类型(pc/q35)
img_config_drive
是否需要 config drive
os_require_quiesce
快照前是否需要 quiesce(需要 QEMU Guest Agent)
镜像缓存机制 Nova compute 节点会缓存 Glance 镜像,避免每次创建 VM 都下载:
1 2 3 4 /var /lib/nova/instances/_base/ ├── <image -id> ← 原始镜像缓存 ├── <image -id>_10G ← resize 后的缓存 └── <image -id>.sha256 ← 校验文件
1 2 3 4 5 6 7 8 9 10 11 class Qcow2 (Image ): def create_image (self, fetch_func, filename, size, ... ): if not os.path.exists(self .path): fetch_func(target=filename) utils.execute('qemu-img' , 'create' , '-f' , 'qcow2' , '-b' , filename, self .path)
这就是为什么同一镜像创建第二个 VM 比第一个快很多——第一次需要下载,后续直接 COW。
镜像共享与可见性 1 2 3 4 5 6 7 8 9 10 11 12 openstack image add project <image-id> <project-id> openstack image set --shared <image-id> openstack image set --accept <image-id>
镜像签名验证 从 Mitaka 版本起,Glance 支持镜像签名,防止镜像被篡改:
1 2 3 4 5 6 7 8 9 10 11 12 13 openssl genrsa -out private.pem 2048 openssl rsa -in private.pem -pubout -out public.pem openssl dgst -sha256 -sign private.pem ubuntu.img | base64 > signature.b64 openstack image create ubuntu-signed \ --property img_signature=$(cat signature.b64) \ --property img_signature_hash_method=SHA-256 \ --property img_signature_key_type=RSA-PSS \ --property img_signature_certificate_uuid=<cert-uuid>
多存储后端(Glance Store) 1 2 3 4 5 6 7 8 9 10 [glance_store] stores = rbd,httpdefault_store = rbd[glance_store] rbd_store_pool = imagesrbd_store_user = glancerbd_store_ceph_conf = /etc/ceph/ceph.confrbd_store_chunk_size = 8
源码关键路径 1 2 3 4 5 6 7 8 9 10 11 glance/ ├── api/ │ └── v2/ │ ├── images.py │ └── image_data.py ├── common/ │ └── store_utils.py ├── db/ │ └── sqlalchemy/ │ └── models.py └── location.py
生产运维要点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 openstack image show <image-id> | grep locations qemu-img convert -f qcow2 -O raw ubuntu.qcow2 ubuntu.raw qemu-img check ubuntu.qcow2 qemu-img convert -c -f qcow2 -O qcow2 ubuntu.qcow2 ubuntu-compressed.qcow2 nova-manage image clean_compute_nodes