OpenStack Stacking vs Spreading
The Nova scheduler decides which compute host runs each new instance. Two fundamental strategies govern this decision: stacking (fill hosts before moving to the next) and spreading (distribute instances evenly across all hosts). Choosing the right strategy directly impacts resource utilization, performance, and power consumption.
Stacking vs Spreading at a Glance
| Aspect | Stacking (RAM weight = -1.0) | Spreading (RAM weight = 1.0) |
|---|---|---|
| Placement pattern | Fill one host, then the next | Distribute evenly |
| CPU/RAM utilization | High per host | Even across hosts |
| Power consumption | Lower (fewer active hosts) | Higher (all hosts active) |
| Noisy neighbor risk | Higher | Lower |
| Best for | Cost optimization, dev/test | Production, SLA workloads |
| Failover blast radius | Large (many VMs on one host) | Small (few VMs per host) |
How the Nova Scheduler Works
The Nova scheduler uses a two-phase process:
- Filtering — eliminates hosts that cannot run the instance (not enough RAM, wrong AZ, affinity rules, etc.)
- Weighing — scores remaining hosts to pick the best one
The ram_weight_multiplier setting controls stacking vs spreading:
Positive value (1.0) = prefer hosts with MORE free RAM = spreading
Negative value (-1.0) = prefer hosts with LESS free RAM = stacking
Configuring Spreading (Default)
Edit /etc/nova/nova.conf on the controller:
[filter_scheduler]
available_filters = nova.scheduler.filters.all_filters
enabled_filters = AvailabilityZoneFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter,NUMATopologyFilter
[DEFAULT]
scheduler_weight_classes = nova.scheduler.weights.ram.RAMWeigher
[filter_scheduler]
ram_weight_multiplier = 1.0
With ram_weight_multiplier = 1.0, the scheduler prefers the host with the most free RAM, distributing instances evenly.
Configuring Stacking
[filter_scheduler]
ram_weight_multiplier = -1.0
With a negative value, the scheduler prefers the host with the least free RAM (but still enough to fit the instance), packing hosts tightly.
Adding CPU and Disk Weighers
For more nuanced scheduling, combine multiple weighers:
[DEFAULT]
scheduler_weight_classes = nova.scheduler.weights.ram.RAMWeigher,nova.scheduler.weights.cpu.CPUWeigher,nova.scheduler.weights.disk.DiskWeigher
[filter_scheduler]
ram_weight_multiplier = 1.0
cpu_weight_multiplier = 1.0
disk_weight_multiplier = 1.0
All positive values = spreading across RAM, CPU, and disk simultaneously.
Overcommit Ratios
Overcommit ratios interact with stacking/spreading by defining how much more than physical capacity you allow:
[DEFAULT]
cpu_allocation_ratio = 4.0 # 4:1 vCPU to physical CPU
ram_allocation_ratio = 1.5 # 1.5:1 virtual to physical RAM
disk_allocation_ratio = 1.0 # no disk overcommit
| Ratio | Stacking Effect | Spreading Effect |
|---|---|---|
| High CPU (16:1) | Extreme density, high contention | Even spread, moderate contention |
| Low CPU (1:1) | No overcommit, fewer VMs per host | Even spread, guaranteed resources |
| High RAM (2.0) | Many VMs per host, swap risk | Even spread, some swap risk |
| Low RAM (1.0) | Physical RAM guaranteed | Even spread, no swap |
Real-World Strategies
Dev/Test Cloud (Stacking + High Overcommit)
[filter_scheduler]
ram_weight_multiplier = -1.0
[DEFAULT]
cpu_allocation_ratio = 16.0
ram_allocation_ratio = 2.0
Maximizes density. Acceptable for non-production workloads.
Production Cloud (Spreading + Low Overcommit)
[filter_scheduler]
ram_weight_multiplier = 1.0
[DEFAULT]
cpu_allocation_ratio = 2.0
ram_allocation_ratio = 1.0
Ensures consistent performance and limits blast radius.
Mixed Strategy with Host Aggregates
Use host aggregates to apply different strategies to different host groups:
# Create aggregates
openstack aggregate create --zone dev-zone dev-aggregate
openstack aggregate create --zone prod-zone prod-aggregate
# Add hosts
openstack aggregate add host dev-aggregate compute-dev-01
openstack aggregate add host prod-aggregate compute-prod-01
openstack aggregate add host prod-aggregate compute-prod-02
# Set metadata
openstack aggregate set --property cpu_allocation_ratio=16.0 dev-aggregate
openstack aggregate set --property cpu_allocation_ratio=2.0 prod-aggregate
Monitoring Placement
Verify where instances land:
openstack server list --long -c Name -c Host -c Status
openstack hypervisor stats show
openstack hypervisor list --long
Check per-host resource usage:
openstack hypervisor show compute-01 -c vcpus_used -c memory_mb_used -c running_vms
Troubleshooting
| Issue | Fix |
|---|---|
| All VMs on one host | You are stacking; set ram_weight_multiplier = 1.0 to spread |
No valid host found |
All hosts filtered out; check RAM, CPU, and disk availability |
| Uneven placement | Enable all weighers and verify multiplier signs |
| Overcommit causing OOM | Reduce ram_allocation_ratio or increase host RAM |
Summary
Stacking maximizes per-host density and reduces power costs; spreading minimizes noisy-neighbor effects and failure blast radius. Most production clouds use spreading with moderate overcommit ratios, while dev/test environments benefit from stacking.