OpenStack, Kayobe-Config, and StackHPC Kayobe-Config

OpenStack — technical deep dive

OpenStack is an open-source Infrastructure-as-a-Service (IaaS) platform. Technically, it is better thought of as a collection of distributed control-plane services and APIs that orchestrate compute, networking, storage, identity and images, rather than as a single hypervisor or monolithic cloud product.

A useful mental model is:

OpenStack is a distributed control plane that turns pools of compute, network and storage resources into an API-driven cloud.

The major architectural layers are:

                    OpenStack APIs
                         │
          ┌──────────────┼──────────────┐
          │              │              │
       Keystone        Nova           Neutron
       Identity       Compute         Network
          │              │              │
          └──────────────┼──────────────┘
                         │
              OpenStack Control Plane
                         │
       ┌─────────────────┼─────────────────┐
       │                 │                 │
     Glance           Cinder             Heat
     Images           Volumes          Orchestration
       │                 │
       └─────────────────┼─────────────────┘
                         │
              Infrastructure layer
                         │
        ┌────────────────┼────────────────┐
        │                │                │
     KVM/QEMU          OVN/OVS           Ceph
     Compute           Networking       Storage

1. Core OpenStack services

The most important services are:

ServiceCodenameResponsibility
KeystoneIdentityAuthentication, authorisation, tokens
NovaComputeVM lifecycle and scheduling
NeutronNetworkingNetworks, subnets, routers, ports, IPs
GlanceImageVM image catalogue/storage interface
CinderBlock StoragePersistent VM volumes
PlacementPlacementTracks resource inventory and allocation
HorizonDashboardWeb UI
HeatOrchestrationInfrastructure-as-code/orchestration
SwiftObject StorageOpenStack-native object storage
OctaviaLoad BalancerLBaaS
BarbicanKey ManagerSecrets/keys
IronicBare MetalPhysical server provisioning
ManilaShared File SystemFile shares
Telemetry servicesVariousMetrics/events/monitoring

In a modern deployment, you don’t necessarily run all of these.

A typical private cloud might use:

Keystone
Nova
Neutron
Glance
Cinder
Placement
Horizon
Octavia

with Ceph providing much of the storage infrastructure.


2. Keystone — identity

Keystone is effectively the authentication and authorisation authority for OpenStack.

A client might authenticate:

User
 │
 │ username/password/application credential
 ▼
Keystone
 │
 │ token
 ▼
OpenStack service APIs

Keystone deals with concepts such as:

Domain
 └── Project
      ├── User
      ├── Role
      └── Resource

For example:

Domain: company

Project: AI-research

Users:
    alice
    bob

Roles:
    member
    admin

A user doesn’t simply get “access to OpenStack”.

They receive a token representing an authenticated identity and its authorised scope.

For example:

POST /v3/auth/tokens

The resulting token can then be used against Nova, Neutron, Glance, Cinder, etc.


3. Nova — the compute service

OpenStack Nova is responsible for VM lifecycle.

It does things like:

create VM
delete VM
reboot VM
resize VM
migrate VM
attach volume
allocate resources

But Nova doesn’t directly perform all of these operations itself.

Its architecture is distributed.

A simplified version:

                 nova-api
                    │
                    ▼
              nova-conductor
                    │
                    ▼
              nova-scheduler
                    │
                    ▼
             Placement API
                    │
             ┌──────┴──────┐
             │             │
        Compute node 1  Compute node 2
             │             │
         nova-compute   nova-compute
             │             │
          libvirt       libvirt
             │             │
           QEMU/KVM     QEMU/KVM

nova-api

Provides the REST API.

For example:

POST /servers

essentially means:

Create me a VM with these properties.


4. Nova scheduler

The scheduler determines where the VM should run.

Suppose you have:

compute01
    128 CPUs
    512 GB RAM

compute02
    256 CPUs
    1 TB RAM

gpu01
    128 CPUs
    512 GB RAM
    8 × NVIDIA GPUs

A VM request might be:

flavor:
    vCPU: 32
    RAM: 128 GB

extra_specs:
    accelerator: GPU

Nova scheduler queries Placement.

Placement knows resource inventories and allocations.

It can therefore determine:

compute01 → unsuitable
compute02 → unsuitable
gpu01     → suitable

Then Nova sends the build request to gpu01.


5. Placement

Placement is particularly important in modern OpenStack architecture.

It tracks:

Resource Providers
    │
    ├── VCPU
    ├── MEMORY_MB
    ├── DISK_GB
    ├── PCI devices
    └── custom resources

For example:

Resource Provider: gpu01

VCPU:
    inventory = 128

MEMORY_MB:
    inventory = 524288

CUSTOM_NVIDIA_GPU:
    inventory = 8

This is much more sophisticated than simply asking:

“Which server has enough RAM?”

OpenStack can model resource traits, inventories and allocations.

This becomes extremely important for AI/HPC infrastructure.


6. Nova Compute

Once the scheduler has selected a host:

nova-compute
      │
      ▼
libvirt
      │
      ▼
QEMU
      │
      ▼
KVM
      │
      ▼
CPU
RAM
NIC
Disk

The VM is ultimately a QEMU process using KVM acceleration.

For example:

/usr/bin/qemu-system-x86_64

with resources such as:

-vcpu
-m 32768
-drive ...
-netdev ...

Nova abstracts this away from the user.


7. Neutron — networking

OpenStack Neutron is one of the more technically complex parts of OpenStack.

It provides abstractions such as:

Network
Subnet
Port
Router
Security Group
Floating IP

For example:

                  Internet
                      │
                 External Net
                      │
                Floating IP
                      │
                 Neutron Router
                      │
              ┌───────┴───────┐
              │               │
          Private Net      Private Net
              │
        ┌─────┴─────┐
        │           │
       VM1         VM2

A VM may have:

eth0
10.10.1.20

while the outside world sees:

203.0.113.50

Neutron performs the networking necessary to connect those two worlds.


8. Neutron architecture

Traditionally:

neutron-server
      │
      ├── ML2
      │
      ├── DHCP agent
      │
      ├── L3 agent
      │
      └── metadata agent

The ML2 (Modular Layer 2) plugin provides an abstraction layer between Neutron and the actual network implementation.

Common mechanisms include:

Open vSwitch
Linux bridge
OVN

Modern OpenStack deployments increasingly use:

ML2/OVN

where OVN — Open Virtual Network provides the virtual networking control plane.


9. OVN

With OVN, the architecture becomes approximately:

Neutron
   │
   ▼
ML2/OVN
   │
   ▼
OVN Northbound DB
   │
   ▼
OVN Southbound DB
   │
   ▼
OVN controllers
   │
   ▼
Open vSwitch
   │
   ▼
Linux networking

OVN then programs the dataplane.

This distinction is important:

Control plane

Neutron
OVN
Databases
APIs
Schedulers

Data plane

Open vSwitch
Linux kernel
VXLAN/Geneve
Physical NICs

OpenStack’s control plane can therefore be relatively slow while the actual packet forwarding happens at much higher speed in the dataplane.


10. Tenant networking

OpenStack commonly uses overlay networks.

For example:

VM1
10.1.0.10
 │
 ▼
OVS
 │
 │ Geneve/VXLAN
 ▼
Physical network
 │
 ▼
OVS
 │
 ▼
VM2
10.1.0.20

The physical network doesn’t necessarily need to know about every tenant subnet.

It transports the overlay.

This allows thousands of tenant networks to coexist over the same physical infrastructure.


11. Security groups

Security groups provide stateful filtering.

For example:

web-security-group

Ingress:
    TCP 22    from 10.0.0.0/8
    TCP 443   from 0.0.0.0/0

Egress:
    allow all

These rules are implemented in the networking dataplane.

Depending on the architecture, this can involve:

OVS flows
iptables
nftables
OVN ACLs

12. Glance — images

OpenStack Glance provides the image service.

A typical image:

Ubuntu 24.04
    │
    ├── qcow2
    ├── size
    ├── checksum
    ├── architecture
    └── metadata

Glance itself doesn’t necessarily need to store the actual image locally.

The architecture can be:

Glance
   │
   ▼
Ceph RBD

or:

Glance
   │
   ▼
S3 / Swift

or filesystem-backed storage.

This is particularly useful when using Ceph.


13. Cinder — block storage

OpenStack Cinder provides persistent block devices.

Conceptually:

VM
 │
 │ /dev/vdb
 ▼
Cinder volume
 │
 ▼
Storage backend

For Ceph:

VM
 │
 ▼
Cinder
 │
 ▼
RBD
 │
 ▼
Ceph
 │
 ├── OSD
 ├── OSD
 ├── OSD
 └── OSD

The VM might see:

/dev/vda
/dev/vdb

while OpenStack sees:

volume-7c2...

14. Ceph + OpenStack

This is one of the most important OpenStack architectures.

A mature private cloud can look like:

                    OpenStack
                        │
          ┌─────────────┼─────────────┐
          │             │             │
        Glance        Cinder         Nova
          │             │             │
          └─────────────┼─────────────┘
                        │
                       RBD
                        │
                   ┌────┴────┐
                   │  Ceph   │
                   └────┬────┘
                        │
             ┌──────────┼──────────┐
             │          │          │
            OSD        OSD        OSD

Ceph can provide:

RBD  → block storage
RGW  → object/S3 storage
CephFS → filesystem

This means one storage platform can underpin multiple OpenStack services.


15. VM creation — end-to-end

This is where OpenStack becomes particularly interesting.

Imagine:

openstack server create \
    --image ubuntu \
    --flavor m4.large \
    --network private \
    web01

Conceptually:

Step 1 — Authentication

Client
  │
  ▼
Keystone
  │
  ▼
Token

Step 2 — API request

Client
  │
  ▼
Nova API

Step 3 — Validate request

Nova checks:

image
flavor
project
network
quotas

Step 4 — Scheduling

Nova asks Placement:

Who can satisfy:

4 vCPU
8 GB RAM
20 GB disk
network requirements
?

Step 5 — Select compute host

compute03

Step 6 — Network preparation

Neutron/OVN creates:

port
MAC address
IP address
security rules
network attachment

Step 7 — Image

Nova obtains the image through Glance.

Possibly:

Glance → Ceph RBD

Step 8 — VM creation

On compute03:

nova-compute
     │
     ▼
libvirt
     │
     ▼
QEMU/KVM

Step 9 — Networking

The VM gets:

eth0
10.10.20.15

Step 10 — Metadata

The VM can access:

169.254.169.254

to obtain instance metadata/cloud-init information.

Step 11 — cloud-init

Cloud-init configures:

hostname
SSH keys
users
network
packages

Result:

VM running

16. The OpenStack message bus

Another critical piece is the internal messaging infrastructure.

OpenStack services communicate asynchronously.

Historically this is commonly:

RabbitMQ

For example:

nova-api
    │
    ▼
RabbitMQ
    │
    ├── nova-scheduler
    ├── nova-conductor
    └── nova-compute

This decouples services.

Instead of:

nova-api ─────────────── nova-compute

you get:

nova-api
    │
    ▼
Message broker
    │
    ▼
nova-compute

That provides resilience and scalability.


17. Databases

OpenStack services generally have their own databases/schema.

For example:

Nova DB
Neutron DB
Keystone DB
Cinder DB
Glance DB

Typically:

MariaDB / Galera

might be used in a highly available deployment.

Architecture:

             MariaDB Galera
          ┌──────┬──────┬──────┐
          │      │      │      │
        DB01   DB02   DB03

Galera provides synchronous multi-primary replication.


18. High availability

A production OpenStack control plane cannot depend on one API node.

Instead:

                    VIP
                     │
                  HAProxy
               ┌─────┴─────┐
               │           │
            ctrl01       ctrl02
               │           │
            services     services
               │           │
               └─────┬─────┘
                     │
                 ctrl03

Common components include:

HAProxy
Keepalived
MariaDB Galera
RabbitMQ
Memcached

For example:

             10.0.0.100
                 VIP
                  │
              HAProxy
          ┌───────┼───────┐
          │       │       │
        ctrl01  ctrl02  ctrl03

The VIP provides a stable endpoint.


19. Kolla-Ansible

This is particularly relevant to the OpenStack environment you’ve been working with.

Kolla-Ansible deploys OpenStack services primarily as containers and uses Ansible for orchestration.

Instead of installing:

nova
neutron
keystone
glance
...

directly onto the OS, Kolla gives you:

Docker/Podman
   │
   ├── keystone
   ├── nova-api
   ├── nova-scheduler
   ├── nova-conductor
   ├── neutron-server
   ├── glance-api
   ├── cinder-api
   ├── mariadb
   ├── rabbitmq
   └── haproxy

Ansible controls deployment/configuration.

This makes Kolla particularly useful for repeatable private-cloud deployments.


20. OpenStack vs Kubernetes

This distinction is important.

OpenStack primarily manages:

Infrastructure
     │
     ├── VM
     ├── network
     ├── storage
     └── bare metal

Kubernetes manages:

Applications
     │
     ├── Pods
     ├── Deployments
     ├── Services
     └── Containers

A very common architecture is:

              OpenStack
                  │
          ┌───────┴───────┐
          │               │
       VM compute       VM compute
          │
       Kubernetes
          │
    ┌─────┼─────┐
    │     │     │
   Pod   Pod   Pod

OpenStack provides the infrastructure.

Kubernetes consumes it.


21. OpenStack for AI/HPC

This is where OpenStack becomes particularly interesting for your current cloud-engineering context.

Imagine:

OpenStack
    │
    ├── CPU compute
    │
    ├── GPU compute
    │
    ├── high-speed network
    │
    ├── NVMe
    │
    └── Ceph

GPU resources can be exposed through:

PCI passthrough
SR-IOV
MIG
mediated devices

Nova/Placement can represent GPU resources.

For example:

CUSTOM_NVIDIA_A100 = 8

Then a workload requests:

resources:
    VCPU=16
    MEMORY_MB=131072
    CUSTOM_NVIDIA_A100=2

Placement finds a suitable host.

That’s essentially resource scheduling for infrastructure, analogous to Kubernetes scheduling but at the cloud-resource level.


22. Observability

For a serious OpenStack deployment, you need to observe multiple layers.

OpenStack

Nova
Neutron
Cinder
Glance
Keystone
Placement

Infrastructure

CPU
RAM
disk
network
GPU

Hypervisor

libvirt
QEMU
KVM

Networking

OVN
OVS
Geneve
physical NICs

Storage

Ceph
OSDs
MONs
MGRs
RBD

Messaging

RabbitMQ

Databases

MariaDB
Galera

A useful observability architecture is:

OpenStack
   │
   ├── exporters
   │
   ├── logs
   │
   └── OpenTelemetry
          │
          ▼
       Collector
          │
     ┌────┼────┐
     ▼    ▼    ▼
  Mimir  Loki Tempo
     │    │    │
     └────┼────┘
          ▼
       Grafana

That gives you:

Metrics + Logs + Traces = MELT


23. The most important conceptual distinction

If you’re learning OpenStack at Staff Cloud Engineer level, I would focus less on memorising service names and more on understanding the following chain:

             USER/API
                 │
                 ▼
             Keystone
                 │
                 ▼
              Nova API
                 │
                 ▼
             Scheduler
                 │
                 ▼
             Placement
                 │
                 ▼
          Compute selection
                 │
                 ▼
           nova-compute
                 │
              libvirt
                 │
             QEMU/KVM
                 │
                 ▼
               VM
                 │
        ┌────────┴────────┐
        ▼                 ▼
     Neutron            Cinder
        │                 │
      OVN/OVS            Ceph
        │                 │
      Network             RBD

If you can explain that architecture and troubleshoot it from API → scheduler → placement → compute → network → storage, you’re operating at a substantially deeper level than someone who merely knows how to deploy OpenStack.

For your current work, I’d prioritise these five areas

  1. Nova + Placement — understand scheduling and resource providers deeply.
  2. Neutron + OVN/OVS — understand the actual packet path from VM → physical network.
  3. Ceph integration — understand RBD, Cinder, Glance and Nova interactions.
  4. Kolla-Ansible architecture — understand how the control plane is deployed and operated.
  5. Failure analysis — be able to trace a failed VM creation across Keystone → Nova → Placement → Neutron → Glance/Cinder → libvirt.

The Kayobe Deployment Tool

StackHPC Kayobe configuration

1. What StackHPC Kayobe Config actually is

The easiest way to understand it is:

                    Git repository
                         │
                         ▼
             stackhpc-kayobe-config
                         │
        ┌────────────────┼────────────────┐
        │                │                │
        ▼                ▼                ▼
     Kayobe           Kolla-Ansible     Custom
     config             config         playbooks
        │                │                │
        └────────────────┼────────────────┘
                         ▼
                     Ansible
                         │
          ┌──────────────┼──────────────┐
          ▼              ▼              ▼
       Bare metal      OS/network    Containers
       provisioning    config        OpenStack
          │                              │
        Bifrost                       Kolla
          │                              │
          └──────────────┬───────────────┘
                         ▼
                    OpenStack cloud

StackHPC effectively builds an opinionated platform engineering layer on top of Kayobe/Kolla-Ansible.

The underlying stack is:

Bifrost
   ↓
Kayobe
   ↓
Kolla-Ansible
   ↓
OpenStack containers

with StackHPC adding configuration and automation around that stack. The repository explicitly identifies Bifrost for hardware provisioning, Kolla for container images, Kolla-Ansible for deployment, and Kayobe for host/network configuration and orchestration.


2. The most important thing: it is configuration composition

This is where StackHPC’s repository differs from a simple globals.yml.

Think of the configuration as several layers:

                         Highest specificity
                                ▲
                                │
                    Environment-specific
                                │
                    ┌───────────┴───────────┐
                    │                       │
             environment/              mixins/
                    │                       │
                    └───────────┬───────────┘
                                │
                         Site configuration
                                │
                    ┌───────────┴───────────┐
                    │                       │
                inventory/             *.yml
                    │                       │
                    └───────────┬───────────┘
                                │
                     StackHPC base config
                                │
                    ┌───────────┴───────────┐
                    │                       │
                  Kayobe               Kolla
                  defaults             defaults
                                │
                                ▼
                         Ansible variables
                                │
                                ▼
                       generated deployment

That composition model is one of the key things to understand if you’re working with StackHPC rather than plain upstream Kayobe.


3. The repository structure

The current repository’s etc/kayobe contains a surprisingly large amount of functionality. The top-level configuration includes things such as:

etc/kayobe/
│
├── ansible/
├── containers/
├── environments/
├── hooks/
├── inventory/
├── kolla/
├── trivy/
├── trust-store/
│
├── globals.yml
├── networks.yml
├── kolla.yml
├── nova.yml
├── neutron.yml
├── controllers.yml
├── compute.yml
├── storage.yml
├── ironic.yml
├── cephadm.yml
├── monitoring.yml
├── openbao.yml
├── pulp.yml
├── seed.yml
├── seed-vm.yml
├── seed-hypervisor.yml
├── overcloud.yml
├── stackhpc.yml
└── ...

The current 2026.1 tree contains dedicated configuration for Cephadm, controllers, compute, storage, networking, Neutron, Nova, monitoring, OpenBao, OFED, OpenSM, Pulp, seed infrastructure, GPUs/vGPU and several StackHPC-specific components.

This is a platform configuration repository, not simply a collection of Kolla variables.


4. globals.yml

At the top level:

etc/kayobe/globals.yml

contains global Kayobe configuration.

Interestingly, the current StackHPC file is mostly a reference/configuration surface rather than being packed with hard-coded deployment values.

It exposes things such as:

kayobe_config_path:
kayobe_environment:

base_path:
config_path:
image_cache_path:
source_checkout_path:
virtualenv_path:

kayobe_ansible_user:

os_distribution:
os_family:
os_release:

kayobe_control_host_become:

network_engine:

The current file also supports network_engine values such as:

network_engine: default

or:

network_engine: nmstate

and documents the distinction between the control-host configuration path and the remote-host state/configuration paths.

Why this matters

A common mistake is to think:

globals.yml = all of Kayobe’s configuration.

It isn’t.

It’s one layer of variables which Kayobe consumes alongside:

  • inventory
  • group vars
  • host vars
  • environment configuration
  • Kolla configuration
  • custom playbooks
  • hooks

5. networks.yml is extremely important

For an OpenStack cloud, I would consider:

networks.yml

one of the most important files to understand.

StackHPC’s current configuration explicitly models network roles such as:

admin
OOB
provisioning
internal API
external
public API
tunnel
storage
storage management
Swift storage
inspection
cleaning
Octavia

The actual variables include things like:

admin_oc_net_name:
oob_oc_net_name:
provision_oc_net_name:

internal_net_name:
external_net_names:
public_net_name:
tunnel_net_name:

storage_net_name:
storage_mgmt_net_name:

inspection_net_name:
cleaning_net_name:
octavia_net_name:

These define what a network means, rather than merely defining an interface.

StackHPC’s file explicitly distinguishes network-role mappings from the actual network definitions.


6. Network definition vs network role

This distinction is important.

You might have:

internal_net_name: internal

and then:

internal_cidr: 10.10.10.0/24
internal_gateway: 10.10.10.1
internal_vlan: 100

Conceptually:

internal_net_name
       │
       ▼
    "internal"
       │
       ├── CIDR
       ├── VLAN
       ├── allocation pool
       ├── gateway
       └── physical interfaces

StackHPC explicitly notes that global network attributes belong in networks.yml, while host/group-specific attributes such as interface names are generally configured through inventory variables.

That separation is excellent infrastructure-as-code design:

Network definition
        ≠
Host implementation

7. Inventory is another major layer

The repository contains:

etc/kayobe/inventory/
├── groups
├── hosts.example
└── group_vars/

The inventory is where you describe the physical topology.

For example:

[controllers]
controller01
controller02
controller03

[compute]

compute01 compute02 compute03

[storage]

storage01 storage02 storage03

Then groups can be composed:

[overcloud:children]
controllers
compute
storage

The current StackHPC repository explicitly separates groups, group_vars, and the hosts definition.


8. Why the inventory matters so much

Consider:

compute01

You can attach variables to it:

ansible_host: 10.0.0.21

neutron_external_interface: eno3

storage_interface: eno4

tunnel_interface: eno5

But you can also put common settings in:

inventory/group_vars/compute/

so that:

                 compute
                    │
        ┌───────────┼───────────┐
        │           │           │
    compute01   compute02   compute03
        │           │           │
        └───────────┼───────────┘
                    │
             common variables

This is standard Ansible inheritance being used as a cloud topology model.


9. Multiple environments

This is arguably one of the most sophisticated parts of the StackHPC configuration.

The repository contains:

etc/kayobe/environments/

and the current branch has environments such as:

aio
aufn-ceph
baremetal
baremetal-policy
ci-aio
ci-builder
ci-doca-builder
ci-multinode
ci-tenks

This allows the same base configuration to support multiple deployments.

For example:

                         Base
                          │
             ┌────────────┼────────────┐
             │            │            │
          ci-aio      ci-multinode   baremetal
             │            │            │
             ▼            ▼            ▼
          inventory    inventory    inventory
          networks     networks     networks
          kolla        kolla        kolla

10. Environment inheritance

Modern Kayobe supports:

.kayobe-environment

with:

dependencies:
  - baremetal

For example:

production
    │
    ├── baremetal
    │
    ├── monitoring
    │
    └── security

The dependencies are resolved into a precedence chain.

If:

environment-C
      ↓
environment-B
      ↓
environment-A

then C has the highest precedence.

Kayobe resolves the dependency graph and applies inventory/extra-vars in the corresponding order.

This is particularly powerful because StackHPC uses this mechanism for mixin environments.


11. StackHPC mixins

This is a major StackHPC-specific concept.

Instead of creating:

production/
staging/
development/

with huge amounts of duplicated configuration, you can have reusable capability modules:

baremetal
baremetal-policy
some-monitoring-feature
some-security-feature
...

Then:

my-production
      │
      ├── baremetal
      ├── monitoring
      └── security

StackHPC explicitly describes mixin environments as a way of applying configuration modularly and enabling features mid-release, rather than waiting for the next major configuration release.

This is very similar conceptually to composing Terraform modules.


12. stackhpc.yml

This is where the repository’s own opinionated configuration begins to become particularly visible.

Conceptually:

Kayobe variables
       │
       +
StackHPC variables
       │
       ▼
StackHPC behaviour

For example, StackHPC-specific options control functionality such as:

monitoring
Ceph integration
CIS hardening
release train
Pulp
OpenBao
security
custom automation

A good mental model is:

globals.yml
    ↓
upstream Kayobe configuration

stackhpc.yml
    ↓
StackHPC-specific policy/configuration

13. Kolla configuration is separate

This is an important architectural boundary.

You have:

etc/kayobe/
    *.yml

for Kayobe.

But then:

etc/kayobe/kolla/
    globals.yml
    config/
    ...

for Kolla-Ansible.

The current StackHPC Kolla globals contains logic such as dynamically determining the Kolla base distro from the target host’s Ansible facts, rather than blindly inheriting the control host’s OS. It also controls image tags and monitoring integration.

That’s significant in mixed/migration environments.

For example:

Control host
    Rocky Linux

        │
        │ Kayobe
        ▼

Controller
    Ubuntu

        │
        ▼

Kolla container
    Ubuntu image

The Kolla configuration needs to know what the target host actually is.


14. Kolla image tags

StackHPC has:

kolla-image-tags.yml

and kolla/globals.yml consumes the generated tag definitions.

Conceptually:

kolla-image-tags.yml
        │
        ▼
  image tag mapping
        │
        ▼
 kolla/globals.yml
        │
        ▼
Kolla-Ansible
        │
        ▼
OpenStack containers

This is important for controlled release management.

You don’t necessarily want:

latest

because that destroys deployment reproducibility.

Instead:

Nova → known image version
Neutron → known image version
Keystone → known image version

15. StackHPC Release Train

This is another area where StackHPC adds significant operational maturity.

Instead of every host directly pulling packages and images from the Internet:

Internet
   │
   ▼
Ark
   │
   ▼
Pulp
   │
   ▼
OpenStack infrastructure

Pulp acts as a local synchronisation/cache layer.

StackHPC describes the repositories as versioned snapshots, allowing an environment to remain on a known-good package/container set even after newer artifacts are released.

This gives you:

Development
     │
     ▼
Pulp development distribution
     │
     │ test
     ▼
Production
     │
     ▼
Pulp production distribution

That is essentially promotion-based infrastructure supply-chain management.


16. Ceph integration

StackHPC’s Kayobe configuration also has substantial Ceph integration.

The Ceph architecture is:

Kayobe
   │
   ▼
Cephadm
   │
   ├── MON
   ├── MGR
   ├── OSD
   └── RGW

The repository’s Ceph configuration uses inventory groups such as:

mons
mgrs
osds
rgws

and provides dedicated Cephadm playbooks.

Then:

Ceph
 │
 ├── RBD
 │    ├── Cinder
 │    ├── Nova
 │    └── Glance
 │
 ├── RGW
 │    └── S3
 │
 └── CephFS

17. Ceph → Kolla integration

This is an important workflow.

StackHPC can gather Ceph credentials/configuration:

kayobe playbook run \
  $KAYOBE_CONFIG_PATH/ansible/ceph/cephadm-gather-keys.yml

This generates Ceph configuration and keys beneath the environment’s Kolla configuration:

environments/<env>/kolla/config/

Those are then consumed during:

kayobe overcloud service deploy

So the relationship is:

             Cephadm
                │
       ceph.conf + keyrings
                │
                ▼
       Kayobe configuration
                │
                ▼
         Kolla configuration
                │
                ▼
          OpenStack services

That is a very important boundary to understand.


18. Ceph copy-on-write optimisation

StackHPC has an interesting optimisation here.

If enabled:

stackhpc_enable_ceph_cow_optimisations: true

it can configure Glance with:

[DEFAULT]
show_multiple_locations = true
show_image_direct_url = true

[glance_store]

rbd_thin_provisioning = true

This allows Glance/Nova/Ceph to exploit RBD copy-on-write semantics.

Conceptually:

Glance image
     │
     ▼
Ceph RBD image
     │
     │ clone
     ▼
VM disk

rather than:

image
  │
  │ full copy
  ▼
VM disk

StackHPC deliberately leaves this disabled by default because exposing RADOS location information has security implications.

That’s a good example of StackHPC making an explicit performance vs security trade-off.


19. Monitoring is built into the configuration

This is particularly relevant to your observability background.

StackHPC’s configuration includes:

Prometheus
Alertmanager
Grafana
Fluentd
OpenSearch
OpenSearch Dashboards

and configures exporters and dashboards.

The architecture is roughly:

                    OpenStack
                       │
          ┌────────────┼────────────┐
          │            │            │
       exporters    logs         Ceph
          │            │            │
          ▼            ▼            ▼
      Prometheus    Fluentd     Ceph mgr
          │            │            │
          ▼            ▼            ▼
      Alertmanager  OpenSearch   Prometheus
          │
          ▼
       Grafana

StackHPC also adds hardware-level monitoring.

For example, SMART/NVMe monitoring uses scripts which expose metrics through Node Exporter’s textfile collector.

That’s quite a nice pattern:

SMART / NVMe
      │
      ▼
script
      │
      ▼
.textfile
      │
      ▼
node_exporter
      │
      ▼
Prometheus

20. Firewalld configuration is generated from topology

Another interesting StackHPC feature is its firewall configuration.

Instead of maintaining a giant static list:

allow TCP 5000
allow TCP 9696
allow TCP 8774
...

StackHPC builds firewall rules based on:

host group
+
enabled OpenStack services
+
network topology
+
network zones

The configuration creates templates such as:

common
controllers
compute
storage
monitoring
seed
seed-hypervisor

and then combines applicable rules into:

stackhpc_firewalld_rules

Conflicting rules are validated and non-applicable rules dropped.

That’s an example of policy generated from infrastructure state, rather than manually maintained firewall configuration.


21. Security hardening

StackHPC also has optional CIS hardening.

For example:

kayobe playbook run \
    $KAYOBE_CONFIG_PATH/ansible/maintenance/cis.yml

The hardening is deliberately not enabled by default, because changes can have operational side effects and may require reboots.

It can subsequently be enabled through:

stackhpc_enable_cis_benchmark_hardening_hook: true

This is another example of the repository treating configuration as a controlled lifecycle rather than simply “run Ansible until it works”.


22. Custom playbooks

This is another major difference from a basic Kayobe deployment.

The repository has:

etc/kayobe/ansible/

with custom automation.

Conceptually:

Kayobe CLI
     │
     ├── built-in Kayobe command
     │
     └── custom playbook
             │
             ├── Ceph
             ├── monitoring
             ├── security
             ├── Pulp
             ├── OpenBao
             ├── hardware
             └── operational tasks

You can run these using:

kayobe playbook run <playbook>

For example:

kayobe playbook run \
    ansible/ceph/cephadm-gather-keys.yml

This is how StackHPC extends Kayobe without having to fork Kayobe itself for every piece of operational functionality.


23. Hooks

The repository also contains:

etc/kayobe/hooks/

Hooks allow StackHPC automation to be attached to the lifecycle of Kayobe commands.

Conceptually:

kayobe command
      │
      ▼
pre-hook
      │
      ▼
Kayobe operation
      │
      ▼
post-hook

This is particularly useful for things like:

service deployment
host configuration
monitoring
security
custom post-deployment actions

24. The whole deployment chain

The most useful technical model is this:

                       Git
                        │
                        ▼
             StackHPC Kayobe Config
                        │
           ┌────────────┼────────────┐
           │            │            │
       Inventory      Kayobe       Kolla
           │           YAML          YAML
           │            │            │
           └────────────┼────────────┘
                        │
                        ▼
                    Kayobe CLI
                        │
                        ▼
                    Ansible
                        │
          ┌─────────────┼─────────────┐
          │             │             │
       Bifrost        Kayobe       Kolla-Ansible
          │             │             │
          ▼             ▼             ▼
      Bare metal     Host OS       OpenStack
      provisioning   networking    containers
                                      │
                                      ▼
                                 OpenStack APIs

And underneath:

                    OpenStack
                       │
       ┌───────────────┼────────────────┐
       │               │                │
     Nova            Neutron          Cinder
       │               │                │
     KVM              OVN              Ceph
       │               │                │
       └───────────────┼────────────────┘
                       │
                      RBD
                       │
                     Ceph

25. What I think is particularly important for you

Given that you’re working with OpenStack, Kolla-Ansible, Ceph and Kubernetes, I wouldn’t learn StackHPC Kayobe Config as a list of YAML files.

I’d learn the variable/data flow:

Git
 │
 ▼
Environment selection
 │
 ▼
Kayobe config
 │
 ├── globals.yml
 ├── networks.yml
 ├── inventory
 ├── group_vars
 ├── host_vars
 ├── stackhpc.yml
 │
 ▼
Environment/mixin composition
 │
 ▼
Kayobe variables
 │
 ▼
Generated Ansible inventory
 │
 ▼
Kolla-Ansible configuration
 │
 ├── globals.yml
 ├── passwords
 ├── config/
 │
 ▼
Kolla containers
 │
 ▼
OpenStack

That is the Staff-level mental model.

The key question when troubleshooting shouldn’t be:

“Which YAML file do I edit?”

It should be:

“Where does this value originate, what variable consumes it, what precedence layer overrides it, and which generated Ansible/Kolla configuration ultimately turns it into system state?”

That’s the important conceptual leap.


A concrete example

Suppose you want to change the storage network.

You might start with:

storage_net_name: storage

Then define:

storage_cidr: 10.20.0.0/24
storage_vlan: 200

Then inventory establishes:

storage_interface: ens5f0

The resulting conceptual pipeline is:

networks.yml
    │
    │ storage = VLAN 200
    ▼
Kayobe network model
    │
    │ compute01 → ens5f0
    ▼
Ansible host configuration
    │
    ▼
Linux / NetworkManager
    │
    ▼
ens5f0
    │
    ▼
VLAN 200
    │
    ▼
Ceph / Cinder / storage traffic

If something breaks, you can investigate each layer independently:

1. Is storage_net_name correct?
2. Is the CIDR correct?
3. Is the VLAN correct?
4. Is compute01 in the right inventory group?
5. Is ens5f0 mapped correctly?
6. Did Kayobe render the expected network config?
7. Did NetworkManager apply it?
8. Is VLAN 200 present?
9. Can the host reach the Ceph network?
10. Is Ceph actually listening on that network?

That’s exactly why the StackHPC configuration is interesting: it turns the entire physical OpenStack platform into a composable, version-controlled configuration model.