Learn OpenStack · core/storage/block
Cinder Architecture
Service Components
Cinder is composed of four daemon processes that communicate over an oslo.messaging RPC bus (typically RabbitMQ). Each process can be scaled and placed independently.
cinder-api
The WSGI API server. Validates and authenticates requests (via keystonemiddleware), enforces policy (policy.yaml / oslo.policy), and forwards work to cinder-scheduler or cinder-volume via RPC. The API is versioned; the current stable version is v3 (microversions). API v2 was removed in the Xena release.
The API process is stateless and horizontally scalable behind a load balancer. All state lives in the database.
Key responsibilities: - Accept and validate volume/snapshot/backup/type CRUD requests - Enforce project quotas before dispatching (quota checks use the DB) - Route requests to the appropriate scheduler or volume RPC target - Return job IDs for asynchronous operations (volume creation, backup, etc.)
Configuration file: /etc/cinder/cinder.conf
WSGI entry point: cinder.wsgi.osapi_volume
cinder-scheduler
Selects which backend (cinder-volume service instance and pool) should fulfill a create_volume or retype request. It runs a configurable filter and weigher pipeline, similar to nova-scheduler.
The scheduler maintains an in-memory capability cache populated by periodic update_service_capabilities messages sent by each cinder-volume worker. This cache holds free capacity, total capacity, thin-provisioning info, driver capabilities, and backend-specific extra specs support.
Default scheduler driver: cinder.scheduler.filter_scheduler.FilterScheduler
The scheduler is stateless between requests and can be scaled horizontally. Multiple scheduler instances process requests concurrently from the same RabbitMQ queue.
cinder-volume
The data-plane orchestrator. One cinder-volume process manages one or more storage backends. It receives RPC calls from the scheduler (for creates) or from cinder-api (for operations on existing volumes) and calls the appropriate storage driver.
Each cinder-volume process registers itself in the services table with a host value of the form <hostname>@<backend_name>. For multi-backend deployments the host value includes the backend stanza name, e.g., storage01@lvm or storage01@ceph.
Key responsibilities: - Call storage driver to create/delete/extend/clone volumes and snapshots - Export volumes for attachment (iSCSI target creation, RBD map, NFS export) - Call Nova's os-initialize_connection and os-terminate_connection APIs - Manage volume migration between backends - Perform periodic capacity reporting to the scheduler
cinder-volume is the only component that requires direct network connectivity to the storage backend. It does not need to be co-located with compute nodes.
cinder-backup
Manages volume backup and restore operations. Supports multiple backup backends:
| Backend | Driver | Notes |
|---|---|---|
| Ceph (RBD) | cinder.backup.drivers.ceph.CephBackupDriver |
Efficient incremental backups via RBD diff |
| Swift | cinder.backup.drivers.swift.SwiftBackupDriver |
Default; stores backup chunks in Swift containers |
| NFS | cinder.backup.drivers.nfs.NFSBackupDriver |
Mounts NFS share, stores backup files |
| POSIX | cinder.backup.drivers.posix.PosixBackupDriver |
Local filesystem; rarely used in production |
| Google Cloud Storage | cinder.backup.drivers.google.GoogleBackupDriver |
For hybrid clouds |
Backup operations are asynchronous. cinder-backup reads from the volume (via the volume driver or via a snapshot) and writes chunked, optionally compressed and encrypted, data to the backup store.
cinder-backup can be scaled horizontally. Multiple instances share the work queue. Backup metadata is stored in the Cinder database.
Volume Lifecycle
User request cinder-api
│ │
│ POST /volumes │ validate + quota check
│ ────────────────────────────► │
│ │ cast to scheduler
│ ▼
cinder-scheduler
│ run filter/weigher pipeline
│ select backend host+pool
│ cast to cinder-volume@host
▼
cinder-volume (on chosen host)
│ call driver.create_volume()
│ update DB: status=available
▼
Storage Backend
(LVM / Ceph / etc.)
Attach flow (Nova-initiated):
nova-compute
│ os-attach (reserve) cinder-api
│ ────────────────────────────► │
│ │ RPC → cinder-volume
│ ▼
cinder-volume
│ driver.initialize_connection()
│ returns connection_info (iqn, portal, rbd pool, etc.)
▼
cinder-api → returns connection_info to nova-compute
nova-compute
│ attach device (libvirt/os-brick connects iSCSI/RBD)
│ os-attach (finalize)
│ ────────────────────────────► cinder-api → volume status: in-use
Volume Types
A volume type is a named set of extra specifications that maps user intent to backend capabilities. Every volume create request either specifies a type or uses the configured default (default_volume_type in [DEFAULT]).
Volume types contain:
- Extra specs: key-value pairs matched against driver-reported capabilities and scheduler filters. Common keys:
- volume_backend_name — direct-target a specific backend
- replication_enabled — <is> True for replicated backends
- IOPS_sec — passed to QoS specs if linked
- multiattach — <is> True to allow multi-attach volumes
- encrypted — set by encryption providers (see below)
- QoS specs: linked QoS policy (see below)
- Encryption spec: linked encryption provider (see below)
# Create a volume type
openstack volume type create ssd-replicated \
--property volume_backend_name=ceph-ssd \
--property replication_enabled='<is> True'
# Show type and its extra specs
openstack volume type show ssd-replicated
Default Volume Type
Set in cinder.conf:
[DEFAULT]
default_volume_type = standard
If no default is configured and a request omits --type, Cinder uses any type named __DEFAULT__ (created automatically during DB migration in recent releases).
QoS Specs
QoS specs define I/O limits that are enforced either front-end (by the hypervisor/libvirt) or back-end (by the storage array). They are created independently and then associated with one or more volume types.
Front-end QoS (enforced by libvirt via cgroup blkio):
| Key | Description |
|---|---|
total_bytes_sec |
Total throughput limit (bytes/sec) |
read_bytes_sec |
Read throughput limit |
write_bytes_sec |
Write throughput limit |
total_iops_sec |
Total IOPS limit |
read_iops_sec |
Read IOPS limit |
write_iops_sec |
Write IOPS limit |
total_bytes_sec_max |
Burst total throughput |
total_iops_sec_max |
Burst total IOPS |
Back-end QoS keys are driver-specific (e.g., Pure Storage uses maxIOPS, maxBWS).
openstack volume qos create high-iops \
--consumer front-end \
--property total_iops_sec=5000 \
--property total_bytes_sec=524288000
openstack volume qos associate high-iops ssd-replicated
Volume Encryption
Cinder supports per-type volume encryption using the LUKS provider backed by Barbican for key management.
When a volume of an encrypted type is created:
1. cinder-volume calls Barbican to generate a new symmetric key (AES-256 by default).
2. The key reference (Barbican secret UUID) is stored in the encryption_key_id column of the volumes table.
3. nova-compute retrieves the key from Barbican at attach time and sets up dm-crypt/LUKS on the compute node.
4. The encrypted device is presented to the instance.
# Create an encryption provider for a volume type
openstack volume encryption type create \
--provider nova.volume.encryptors.luks.LuksEncryptor \
--cipher aes-xts-plain64 \
--key-size 256 \
--control-location front-end \
encrypted-ssd
Requirements:
- Barbican must be deployed and registered in the Keystone catalog
- [keymgr] backend = barbican in cinder.conf
- Nova compute nodes need cryptsetup and dm-crypt kernel module
Integration with Nova
Nova interacts with Cinder for:
| Operation | Nova action | Cinder action |
|---|---|---|
| Boot from volume | os-createBackup or regular create |
Cinder creates volume from image (clones or copies) |
| Attach volume | os-attach (reserve → initialize_connection → attach) |
Driver exports volume, returns connector info |
| Detach volume | os-detach (begin_detach → terminate_connection → detach) |
Driver unexports volume |
| Resize instance (root volume) | os-resize triggers volume extend |
extend_volume on the root Cinder volume |
| Evacuate | Nova calls detach + attach on new host | Cinder volume stays in-use until re-attached |
| Snapshot instance | Nova calls os-createBackup |
Cinder creates a snapshot of each attached volume |
The Nova compute node uses os-brick (the OpenStack connector library) to handle the actual host-level connection: logging into iSCSI targets, mapping RBD devices, mounting NFS, etc.
Multiattach volumes (requires multiattach=True extra spec and a capable driver):
- Nova must use the libvirt shareable disk mode
- Only supported for volumes where the driver reports multiattach capability
Integration with Glance
Cinder can use Glance images as volume sources and can export volumes back to Glance:
| Flow | Description |
|---|---|
| Volume from image | openstack volume create --image <img> — Cinder downloads image from Glance, writes to new volume |
| Upload volume to image | openstack image create --volume <vol> — Cinder reads volume data, uploads to Glance |
| Glance image store (Cinder) | Glance can store images directly in a Cinder volume (via cinder store in glance-api.conf) |
For the "volume from image" path, certain drivers (Ceph, NetApp) support native cloning from Glance images stored in the same backend, bypassing full data copy.
Active-Active HA Architecture
Traditional Active-Passive
The simplest HA model: two cinder-volume nodes share a Pacemaker/Corosync cluster. One node is active; the other takes over on failure. Volume host names are stable (virtual IP or fixed hostname). No DLM required.
Limitation: failover time is 30–60 seconds; backend I/O is interrupted during that window.
Active-Active HA (2025.x)
Active-active allows multiple cinder-volume workers for the same backend to process requests simultaneously. This requires:
-
A distributed lock manager (DLM) — Tooz-backed, typically using etcd3 or ZooKeeper as the coordination backend. Prevents concurrent conflicting operations on the same volume.
-
Stable per-worker host names — Each worker registers with a UUID-based
clustername rather than hostname, so the scheduler can address the cluster rather than individual nodes. -
[coordination]section in cinder.conf:
[coordination]
backend_url = etcd3+http://etcd01:2379,etcd3+http://etcd02:2379,etcd3+http://etcd03:2379
[DEFAULT] cluster = cinder-cluster-1— All workers in the same AA group share this cluster name.
Active-active cinder-backup is also supported using the same Tooz coordination mechanism.
The scheduler routes requests to the cluster name. Individual workers compete for lock ownership before executing a driver call. If a worker dies mid-operation, another worker detects the stale lock (via TTL expiry) and can attempt recovery.
Requirements for active-active:
- All workers must use a shared-access backend (Ceph, a SAN with multipath, etc.). LVM is not suitable for active-active unless the volume group is on shared storage.
- etcd 3.x or ZooKeeper 3.6+
- oslo.concurrency and tooz Python packages
Database HA
Cinder requires a highly-available database. Recommended: MariaDB Galera Cluster (3+ nodes) fronted by ProxySQL or HAProxy. The API and scheduler processes are stateless and tolerate brief DB unavailability; in-flight driver operations may fail if the DB becomes unavailable mid-operation.
Service Registration and Health
All Cinder services register in the services table. Check service health:
openstack volume service list
Expected output for a healthy three-backend deployment:
+------------------+----------------------------+------+---------+-------+
| Binary | Host | Zone | Status | State |
+------------------+----------------------------+------+---------+-------+
| cinder-scheduler | controller01 | nova | enabled | up |
| cinder-volume | storage01@lvm | nova | enabled | up |
| cinder-volume | storage01@ceph | nova | enabled | up |
| cinder-backup | storage01 | nova | enabled | up |
+------------------+----------------------------+------+---------+-------+
A service with State: down indicates missed heartbeats. Default heartbeat interval: 10 seconds. Service is considered down after service_down_time seconds (default: 60).