Learn OpenStack · core/orchestration/heat
Heat Architecture
Heat Services
Heat is composed of three discrete processes that communicate over an oslo.messaging bus (typically RabbitMQ). Each service can be scaled independently.
Client (CLI / Horizon / Magnum)
│
┌──────┴──────┐
│ heat-api │ ← REST API (port 8004)
│ (WSGI) │
└──────┬──────┘
│ oslo.messaging RPC
┌──────┴──────┐
│ heat-engine │ ← Resource orchestration
│ │ (multiple workers)
└──────┬──────┘
│
┌────────────────┼──────────────────────┐
│ │ │
Nova API Neutron API Cinder API
(servers) (networks) (volumes)
heat-api
The HTTP API server. Accepts REST requests from clients, validates them against Keystone, enforces oslo.policy, and dispatches work to heat-engine over RPC. Runs as a WSGI application (Apache mod_wsgi or uWSGI).
- Exposes the Heat Orchestration API v1 on port 8004
- Handles template validation (calling the engine for full validation)
- Handles stack preview (dry-run resource resolution)
- All resource-mutating operations are dispatched asynchronously to the engine
Endpoint registration (example):
openstack service create --name heat --description "Orchestration" orchestration
openstack endpoint create --region RegionOne orchestration public http://10.0.0.10:8004/v1/%\(tenant_id\)s
openstack endpoint create --region RegionOne orchestration internal http://10.0.0.11:8004/v1/%\(tenant_id\)s
openstack endpoint create --region RegionOne orchestration admin http://10.0.0.11:8004/v1/%\(tenant_id\)s
heat-api-cfn
An optional compatibility endpoint that accepts AWS CloudFormation-compatible API requests. Translates CloudFormation API calls and templates into native Heat operations.
- Exposes the CFN-compatible API on port 8000
- Supports CloudFormation template format (JSON or YAML)
- Required if migrating AWS CloudFormation templates or using tools that emit CFN API calls
- Not required for HOT-only deployments; disabled in many modern deployments
- Uses the same
heat-enginebackend
Endpoint registration:
openstack service create --name heat-cfn --description "Orchestration CloudFormation" cloudformation
openstack endpoint create --region RegionOne cloudformation public http://10.0.0.10:8000/v1
heat-engine
The orchestration engine. Receives RPC calls from heat-api, resolves the template, builds the resource dependency graph, and drives resource operations through to completion. Handles the full stack lifecycle.
- Runs as a long-lived daemon (typically multiple workers,
num_engine_workers) - Each engine worker processes stack operations independently
- Manages the convergence traversal (see below)
- Calls OpenStack service APIs (Nova, Neutron, Cinder, Glance, etc.) directly
- Writes stack, resource, and event records to the Heat database
- Uses Keystone trusts to perform deferred operations (auto-scaling, wait conditions) as the stack owner
Summary table:
| Service | Default Port | Notes |
|---|---|---|
| heat-api | 8004 | REST API for Heat clients |
| heat-api-cfn | 8000 | AWS CloudFormation compat; optional |
| heat-engine | — (RPC only) | Multiple workers; scale horizontally |
HOT Template Format
HOT (Heat Orchestration Template) is the native Heat template format. Templates are YAML or JSON documents.
Top-Level Sections
heat_template_version: 2021-04-16 # Required. Determines available features.
description: | # Optional. Human-readable description.
Multi-tier web application stack.
parameter_groups: # Optional. UI grouping hints.
- label: Network Configuration
parameters:
- public_net
- private_net_cidr
parameters: # Input parameters (values injected at create/update).
key_name:
type: string
description: SSH key pair name
constraints:
- custom_constraint: nova.keypair
image:
type: string
default: ubuntu-24.04
constraints:
- custom_constraint: glance.image
flavor:
type: string
default: m1.small
constraints:
- custom_constraint: nova.flavor
db_password:
type: string
hidden: true # Masked in API responses
public_net:
type: string
default: public
private_net_cidr:
type: string
default: 192.168.100.0/24
conditions: # Optional. Boolean expressions for conditional resources.
enable_monitoring:
equals:
- get_param: environment
- production
resources: # Required. The resource definitions.
my_server:
type: OS::Nova::Server
properties:
...
outputs: # Optional. Values to expose after creation.
server_ip:
description: Floating IP of the web server
value: { get_attr: [floating_ip, floating_ip_address] }
Template Versions
| Version String | Release | Key Features Added |
|---|---|---|
2013-05-23 |
Icehouse | Initial HOT version |
2014-10-16 |
Juno | repeat function, conditions preview |
2015-04-30 |
Kilo | conditions, if function |
2016-04-08 |
Newton | equals, not, and, or condition functions |
2016-10-14 |
Ocata | yaql function |
2017-02-24 |
Pike | merge_list, contains |
2018-08-31 |
Rocky | digest function |
2021-04-16 |
Wallaby | Latest stable; recommended for new templates |
Always use heat_template_version: 2021-04-16 for new templates. Older versions are still parsed but may lack features.
Intrinsic Functions
| Function | Description | Example |
|---|---|---|
get_param |
Read a parameter value | {get_param: key_name} |
get_resource |
Get the reference (ID) of another resource | {get_resource: my_network} |
get_attr |
Read an attribute from a resource | {get_attr: [server, first_address]} |
get_file |
Embed a local file's contents as a string | {get_file: scripts/setup.sh} |
str_replace |
String substitution with named tokens | {str_replace: {template: "Hello $name", params: {$name: World}}} |
list_join |
Join a list into a string | {list_join: [',', [a, b, c]]} |
repeat |
Generate a list by iterating over values | {repeat: {template: ..., for_each: {%item%: [1, 2, 3]}}} |
if |
Conditional value selection | {if: [enable_monitoring, m1.medium, m1.small]} |
equals |
Equality test (for conditions) | {equals: [{get_param: env}, prod]} |
not |
Boolean negation | {not: {equals: [...]}} |
and / or |
Boolean combination | {and: [cond1, cond2]} |
digest |
Compute hash of a value | {digest: [sha256, {get_param: secret}]} |
yaql |
Evaluate a YAQL expression | {yaql: {expression: "$.data.len()", data: [1,2,3]}} |
Resource Types
Heat ships with a large library of built-in resource types. The most commonly used:
Compute
| Type | Description |
|---|---|
OS::Nova::Server |
Virtual machine instance |
OS::Nova::KeyPair |
SSH key pair |
OS::Nova::ServerGroup |
Server group (affinity/anti-affinity) |
OS::Nova::Flavor |
Custom flavor definition (admin only) |
Networking
| Type | Description |
|---|---|
OS::Neutron::Net |
Tenant network |
OS::Neutron::Subnet |
Subnet within a network |
OS::Neutron::Router |
L3 router |
OS::Neutron::RouterInterface |
Attach a subnet to a router |
OS::Neutron::FloatingIP |
Allocate a floating IP |
OS::Neutron::FloatingIPAssociation |
Assign floating IP to a port |
OS::Neutron::Port |
Neutron port with specific IP/security groups |
OS::Neutron::SecurityGroup |
Security group |
OS::Neutron::SecurityGroupRule |
Individual security group rule |
Block Storage
| Type | Description |
|---|---|
OS::Cinder::Volume |
Persistent block volume |
OS::Cinder::VolumeAttachment |
Attach a volume to a server |
OS::Cinder::EncryptedVolumeType |
Encrypted volume type |
Orchestration / Heat-specific
| Type | Description |
|---|---|
OS::Heat::Stack |
Nested stack (references another template) |
OS::Heat::ResourceGroup |
Create N copies of a resource |
OS::Heat::AutoScalingGroup |
Auto-scaling group of resources |
OS::Heat::ScalingPolicy |
Scale-out/scale-in policy for an ASG |
OS::Heat::WaitCondition |
Block until a signal is received |
OS::Heat::WaitConditionHandle |
URL endpoint for wait condition signals |
OS::Heat::SoftwareConfig |
Cloud-init or config management script definition |
OS::Heat::SoftwareDeployment |
Apply a SoftwareConfig to a server |
OS::Heat::SoftwareDeploymentGroup |
Apply a SoftwareConfig to multiple servers |
OS::Heat::StructuredConfig |
JSON-structured SoftwareConfig |
OS::Heat::StructuredDeployment |
Apply StructuredConfig to a server |
OS::Heat::RandomString |
Generate a random string (passwords, secrets) |
OS::Heat::Value |
Store and expose a computed value |
Load Balancing
| Type | Description |
|---|---|
OS::Octavia::LoadBalancer |
Octavia load balancer |
OS::Octavia::Listener |
Frontend listener |
OS::Octavia::Pool |
Backend server pool |
OS::Octavia::PoolMember |
Add a server to a pool |
OS::Octavia::HealthMonitor |
Pool health check |
List all available resource types
openstack orchestration resource type list
openstack orchestration resource type show OS::Nova::Server
Environments
An environment is a YAML file that augments a template with:
- Parameter defaults (override template defaults without modifying the template)
- Parameter values (inject values at stack create/update)
- Resource registry (map type aliases to custom templates or existing resources)
- Event sinks (route resource events to webhooks)
Environment File Structure
# prod-env.yaml
parameters:
flavor: m1.large
image: ubuntu-24.04
key_name: prod-keypair
public_net: provider-net
private_net_cidr: 10.10.0.0/24
db_password: supersecretpassword
parameter_defaults:
# Applied when a parameter is not supplied by the user or a higher-priority env
flavor: m1.small
image: ubuntu-22.04
resource_registry:
# Map a type alias to a custom nested template
MyOrg::WebServer: file:///etc/heat/templates/webserver.yaml
# Map to a provider URL
MyOrg::DBCluster: https://example.com/templates/db-cluster.yaml
# Freeze an existing resource (prevent Heat from managing it)
OS::Nova::KeyPair: OS::Heat::None
event_sinks:
- type: zaqar-queue
target_queue: heat-events
ttl: 86400
Multiple Environments
Multiple environment files are applied in order; later files override earlier ones:
openstack stack create \
-t main.yaml \
-e base-env.yaml \
-e prod-env.yaml \
-e secrets.yaml \
my-stack
Convergence Architecture
Heat's convergence engine (introduced in Newton, default since Ocata) manages stack operations using a directed acyclic graph (DAG) of resource nodes and performs operations in parallel wherever dependencies allow.
How Convergence Works
-
Template parsing: Heat parses the template and resolves all intrinsic functions to build a dependency graph where each resource is a node and
get_resource/get_attrreferences are directed edges. -
Graph traversal: Heat generates a set of resource traversal records in the database, one per resource per direction (forward for create/update, reverse for delete). Each record acts as a work item for engine workers.
-
Worker polling: Engine workers pick up traversal records. A resource is processed only when all its dependencies have completed (forward direction) or all its dependents have completed (reverse direction).
-
Parallel execution: Resources with no outstanding dependencies are processed simultaneously across multiple engine workers.
-
State machine: Each resource transitions through states:
IN_PROGRESS → COMPLETE(success) orIN_PROGRESS → FAILED(failure). The overall stack state reflects the aggregate of all resource states.
Convergence vs Legacy Engine
| Aspect | Convergence (default) | Legacy (deprecated) |
|---|---|---|
| Resource ordering | Parallel, graph-based | Sequential, depth-first |
| Update strategy | In-place with graph diff | Full re-traversal |
| Lock granularity | Per-resource | Per-stack (global lock) |
| Failed resource handling | Other independent resources continue | Stack halts on first failure |
| Database writes | Traversal records per resource | Stack-level state |
Stack Update with Convergence
During an update Heat computes the diff between the old and new template dependency graphs:
- Resources present in both templates are updated in-place (if properties changed) or left unchanged.
- Resources added to the new template are created.
- Resources removed from the new template are deleted.
- The update traversal runs forward (for new/changed resources) and reverse (for deleted resources) concurrently.
Inter-Service Integration
Keystone (Trust Delegation)
Heat uses Keystone trusts to perform deferred operations as the stack owner. When a stack is created, Heat stores a trust credential so that auto-scaling events, wait condition callbacks, and stack updates can be executed asynchronously on behalf of the original user — even after their session token has expired.
The heat service user must have the heat_stack_owner role assigned (or equivalent policy):
openstack role add --user heat --project service heat_stack_owner
Nova, Neutron, Cinder
Heat calls these services' standard REST APIs directly from heat-engine. The credentials come from the trust. Heat does not use RPC for cross-service calls; it uses HTTP clients (heatclient, novaclient, neutronclient, etc.) wrapped in a consistent retry/backoff layer.
Aodh (Alarming) — Auto-Scaling
OS::Heat::ScalingPolicy generates a signed webhook URL. An Aodh alarm is pointed at that URL. When the alarm fires, Aodh calls the URL, which triggers Heat to execute the scaling policy (add or remove instances from the OS::Heat::AutoScalingGroup).