Skip to content

Configuration Landscape

This page compares CobaltCore's configuration approach with four major OpenStack deployment tools and one general-purpose configuration management platform. The goal is to document architectural trade-offs and explain which ideas C5C3 adopts, adapts, or avoids.

Challenge Framework

Any OpenStack configuration system must address these challenges:

ChallengeDescription
Config GenerationHow are INI config files produced from higher-level input?
Secret ManagementHow are credentials injected without exposing them in source control?
ValidationWhen and how are configuration errors detected?
CustomizationHow do operators apply site-specific or tuning overrides?
Multi-Node ConfigHow do per-node differences (IP addresses, host names) get handled?
Config DriftHow is divergence between desired and actual configuration detected?
Upgrade MigrationHow does configuration change when upgrading OpenStack releases?

YAOOK

YAOOK (Yet Another OpenStack on Kubernetes) is developed within the ALASCA ecosystem. It uses CUE as its configuration language and defines a layered architecture for config generation.

YAOOK Architecture

text
┌─────────────────────────────────────────────────────────────────────────────┐
│                       YAOOK CONFIG ARCHITECTURE                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  CUE Source Layers (merged via CUE unification):                            │
│                                                                             │
│  ┌─────────────────┐                                                        │
│  │ SpecLayer       │  User-facing: desired service config                   │
│  │ (from CR spec)  │  e.g. database host, replicas, cache                   │
│  └────────┬────────┘                                                        │
│           │ unify                                                           │
│  ┌────────▼────────┐                                                        │
│  │ SecretInjection │  Injects credentials from K8s Secrets                  │
│  │ Layer           │  into config data structures                           │
│  └────────┬────────┘                                                        │
│           │ unify                                                           │
│  ┌────────▼────────┐                                                        │
│  │ ConfigSecret    │  Final merged config → K8s Secret                      │
│  │ Layer           │  (not ConfigMap — YAOOK stores config in Secrets)      │
│  └────────┬────────┘                                                        │
│           │                                                                 │
│           ▼                                                                 │
│  K8s Secret (immutable, copy-on-write)                                      │
│  Mounted into pod as /etc/<service>/<service>.conf                          │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

YAOOK Characteristics

AspectDetail
Config languageCUE — a constraint-based data language. Merging is commutative and conflict-rejecting (if two layers set the same field to different values, it is an error, not a silent override)
Config storageKubernetes Secrets (not ConfigMaps) — enables treating config as sensitive data
ImmutabilityCopy-on-write: a config change creates a new K8s Secret, old one is retained for rollback
Per-node configconfigTemplates with Go template expressions evaluated per node
ValidationCUE schema validation + metadata-derived checks from oslo.config option definitions
OperatorsState-machine-based Python operators (not reconciliation-loop style)

YAOOK Strengths and Limitations

StrengthsLimitations
CUE unification prevents silent override conflictsCUE has a steep learning curve
Immutable Secrets with history enable reliable rollbackState-machine operators are more complex than reconciliation loops
Config-as-Secret treats all config as potentially sensitiveSmaller community and ecosystem compared to Helm-based approaches

Kolla-Ansible

Kolla-Ansible is the most widely deployed OpenStack lifecycle management tool. It uses Ansible + Jinja2 templates for configuration and INI merge for combining configuration layers.

Kolla-Ansible Architecture

text
┌─────────────────────────────────────────────────────────────────────────────┐
│                    KOLLA-ANSIBLE CONFIG ARCHITECTURE                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  Configuration Hierarchy (last-write-wins):                                 │
│                                                                             │
│  ┌──────────────────┐                                                       │
│  │ globals.yml      │  Site-wide settings (IPs, passwords, features)        │
│  └────────┬─────────┘                                                       │
│           │                                                                 │
│  ┌────────▼─────────┐                                                       │
│  │ Jinja2 Templates │  Per-service .conf.j2 templates                       │
│  │ (per service)    │  Reference globals.yml variables                      │
│  └────────┬─────────┘                                                       │
│           │                                                                 │
│  ┌────────▼─────────┐                                                       │
│  │ INI Merge        │  merge_configs.py (Python ConfigParser)               │
│  │                  │  Merges: base template + globals overrides            │
│  │                  │        + host-specific overrides                      │
│  └────────┬─────────┘                                                       │
│           │                                                                 │
│           ▼                                                                 │
│  Final .conf file deployed to /etc/kolla/<service>/                         │
│  via Docker volume mount or file copy                                       │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Kolla-Ansible Characteristics

AspectDetail
Config languageJinja2 templates rendering INI files
Merge strategyPython ConfigParser merge — last-write-wins. If multiple sources set the same key, the last one applied wins silently
Override hierarchyglobals.yml → service-specific variables → host-specific overrides → <service>.conf manual overrides
Validationkolla-ansible validate-config runs oslo-config-validator against rendered configs (post-render check)
Secret handlingansible-vault encrypted variables in passwords.yml, decrypted at deploy time and merged into templates
Config strategyKOLLA_CONFIG_STRATEGYCOPY_ALWAYS (overwrite on deploy) or COPY_ONCE (keep manual changes)

Kolla-Ansible Strengths and Limitations

StrengthsLimitations
Mature, widely deployed, battle-testedJinja2 + INI merge is error-prone (silent overrides, whitespace issues)
oslo-config-validator integration for post-render validationNo declarative desired-state — Ansible is imperative
Flexible override hierarchy for multi-environmentConfig drift between runs is possible with COPY_ONCE
Large community and documentationNot Kubernetes-native — requires separate adoption of K8s patterns

OpenStack K8s Operators (Red Hat)

OpenStack K8s Operators are Red Hat's Kubernetes-native approach, developed for RHOSO (Red Hat OpenStack Services on OpenShift). Each service has a Go-based operator with CRD-driven configuration.

Red Hat Architecture

The architecture uses a CRD fields + customServiceConfig pattern:

yaml
apiVersion: nova.openstack.org/v1beta1
kind: Nova
metadata:
  name: nova
spec:
  # Structured CRD fields for common settings
  apiDatabaseInstance: openstack
  cellDatabaseInstance: openstack
  keystoneInstance: keystone

  # Raw INI passthrough for anything not covered by CRD fields
  customServiceConfig: |
    [DEFAULT]
    debug = true
    api_workers = 8

Red Hat Characteristics

AspectDetail
Config languageGo templates inside operators
CRD fieldsTyped fields for common settings (database, keystoneInstance, transport)
Raw escape hatchcustomServiceConfig — raw INI string appended after operator-generated config
Merge pattern.conf.d/ directory: operator writes 00-config.conf, user customServiceConfig becomes 01-custom.conf. oslo.config reads both, last-file-wins per option
ValidationOpenAPI v3.0 schema for CRD fields + CEL validation rules
Secret handlingK8s Secrets referenced in CRD fields, created by operators or external tools
Migration toolos-diff — compares TripleO (legacy) configs with operator-generated configs to assist migration

Red Hat Strengths and Limitations

StrengthsLimitations
CRD fields provide typed, validated config for common settingscustomServiceConfig bypasses all validation (raw INI)
.conf.d/ pattern cleanly separates operator and user configOperators must maintain CRD field parity with upstream config options
CEL validation rules enable cross-field checks in the CRDComplex multi-operator dependency graph
os-diff tool eases migration from TripleOTightly coupled to OpenShift platform

Vexxhost Atmosphere

Atmosphere is Vexxhost's opinionated OpenStack distribution built on Helm charts (primarily OpenStack-Helm) with Ansible orchestration.

Atmosphere Characteristics

AspectDetail
Config languageGo templates (via Helm / OpenStack-Helm charts)
Config sourceHelm values.yaml — service configuration is expressed as Helm values
Merge strategyHelm value merging (deep merge of YAML). OpenStack-Helm charts have a conf: section that maps to INI config
ValidationImplicit — template logic checks some conditions, but no explicit schema validation
Secret handlingK8s Secrets generated by Helm charts or Ansible
Override patternHelm value overrides (--set, -f custom-values.yaml)
DeploymentAnsible orchestrates Helm deployments in dependency order

Helm values to INI mapping (OpenStack-Helm pattern):

yaml
# values.yaml
conf:
  nova:
    DEFAULT:
      debug: true
      api_workers: 8
    database:
      connection: mysql+pymysql://nova:password@mariadb/nova

The Helm chart template iterates over the conf.nova map and renders it as an INI file.

Atmosphere Strengths and Limitations

StrengthsLimitations
Leverages established OpenStack-Helm chartsNo typed config validation — any YAML key is accepted in conf:
Familiar Helm workflow for Kubernetes operatorsAnsible + Helm layering adds complexity
Actively maintained with regular upstream trackingConfig errors only surface at runtime
Supports multiple Linux distributionsLess opinionated about secret management

ConfigHub

ConfigHub is a SaaS configuration management platform (not specific to OpenStack) that treats Configuration as Data. It is included here not as a deployment tool but as an informative conceptual comparison.

ConfigHub Characteristics

AspectDetail
Config sourceStructured YAML/JSON stored in a centralized data store
ValidationJSON Schema + custom validation functions
Secret handlingExternal — workers pull secrets at deploy time
Revision historyFull version history of all configuration changes
DistributionWorkers on target hosts pull configuration from the central store

Comprehensive Concept Mapping

ConfigHub defines 15+ configuration management concepts. The following table maps each to its Kubernetes-native equivalent in CobaltCore:

ConfigHub ConceptC5C3 EquivalentCoverage
UnitsCRD spec fields (typed, validated via OpenAPI schema)Full
RevisionsGit history (FluxCD) + hash-named ConfigMapsPartial — no queryable revision history on CRD level
MutationsCRD updates via kubectl apply / FluxCD reconciliationPartial — no semantic change descriptions
ResourcesImmutable ConfigMaps with content-hash namesFull
SpacesK8s Namespaces + 4-Cluster topology (Management, Control Plane, Hypervisor, Storage)Full
TargetsCluster types + workload types (Deployment, DaemonSet, CronJob)Full
WorkersKubernetes Operators (controller-runtime reconciliation loops)Full
BridgesFluxCD HelmReleases, ESO ExternalSecrets, cert-manager CertificatesFull
ChangeSetsGit commits in FluxCD repo + ControlPlane.status.updatePhasePartial — no atomic multi-service change primitive
GatesGitOps PR reviews + validation webhooks + operator reconciliation checksPartial — no formal gate between "rendered" and "deployed"
FunctionsValidation webhooks + operator semantic checks (CEL rules, cross-field validation)Full
Triggerscontroller-runtime Watches / Owns / For predicatesFull
Change Flow5-step config pipeline (Read CRD → Resolve → Defaults → Render → ConfigMap) + 3-layer validationFull
Drift DetectionK8s reconciliation loop (automatically corrects drift)Partial — no explicit drift reporting
Impact AnalysisNot implementedGap

Gaps and Kubernetes-Native Solutions

For each "Partial" or "Gap" entry above, the following describes design concepts for how C5C3 could address the limitation using Kubernetes-native patterns. These are future possibilities, not committed implementations.

Revisions — CRDs do not natively track a revision history. Two possible approaches:

  • status.configHistory field on service CRs: The operator records the last N ConfigMap hashes with timestamps, enabling rollback auditing.
  • ConfigRevision condition: Each reconciliation records a generation number in a status condition, correlating with the Git commit that triggered the change.

ChangeSets — Git commits provide atomic versioning, but applying changes across multiple service CRs is not transactional. The c5c3-operator's phased rollout (ControlPlane.status.updatePhase) provides ordering guarantees: infrastructure → Keystone → remaining services. See c5c3-operator — Rollout Strategy for details.

Gates — The current pipeline validates at apply time (webhooks) and reconciliation time (operator checks), but there is no explicit "staging → production" gate. A formal gate could be implemented as an oslo-config-validator init container that runs against the rendered config before the main service container starts. See Validation — oslo-config-validator Integration for the design concept.

Drift Detection — Kubernetes reconciliation automatically corrects drift (the operator regenerates the ConfigMap if the actual state diverges from desired state). For explicit drift reporting, a ConfigDrift condition on service CRs could compare the hash of the currently mounted ConfigMap against the expected hash and report discrepancies.

Impact Analysis — A dry-run mode in the c5c3-operator would allow users to preview the effect of a ControlPlane CR change before applying it. This would compute which services are affected, which ConfigMaps would change, and whether any validation rules would be violated.

Relevance to C5C3

The "Configuration as Data" principle — that configuration should be structured, validated, versioned, and distributed through a well-defined pipeline — is the philosophical foundation of C5C3's CRD-driven approach. ConfigHub validates this principle in a SaaS context; C5C3 implements it entirely within the Kubernetes ecosystem, trading centralized SaaS convenience for Kubernetes-native integration and avoiding external dependencies.

Comprehensive Comparison

ChallengeC5C3YAOOKKolla-AnsibleRed Hat K8s OperatorsAtmosphereConfigHub
Config GenerationGo operator renders from CRD fieldsCUE unification of layersJinja2 templates + INI mergeGo operator + customServiceConfigHelm/Go templatesWorkers pull structured data from central store
Secret ManagementOpenBao + ESO (fully separated)SecretInjectionLayer (CUE)ansible-vault (merged at deploy)K8s Secrets (CRD refs)K8s Secrets (Helm)External — workers pull at deploy time
ValidationOpenAPI + operator checks + runtimeCUE schema + metadata-derivedoslo-config-validator (post-render)OpenAPI + CEL + runtimeImplicit (template logic)JSON Schema + custom validation functions
CustomizationStructured CRD (override under design, see Customization)CUE merging (open, composable)globals.yml + file overridescustomServiceConfig (raw INI)Helm value overridesStructured YAML/JSON with context resolution
Multi-Node ConfigEnv vars (Downward API) + shared ConfigMap (see Per-Node Configuration)configTemplates (Go templates per node)Host-specific vars in inventoryPer-node CRs or DaemonSet envHelm per-node valuesContext-aware targeting (Spaces x Targets)
Config DriftGitOps + operator reconciliation (continuous)Operator reconciliationOnly on playbook re-runOperator reconciliationHelm diff on upgradeDrift detection with reporting
Upgrade MigrationOperator embeds per-release defaultsCUE schema per releaseTemplate changes per releaseOperator + os-diff toolChart updates per releaseRevision history with rollback

What C5C3 Adopts

SourceAdopted ConceptC5C3 Implementation
YAOOKImmutable config artifactsHash-named ConfigMaps (new config = new ConfigMap, old retained for rollback)
YAOOKSchema awareness from oslo.config metadataOperator-embedded defaults derived from upstream oslo.config option definitions
Red Hat K8s OperatorsCRD-driven, typed fieldsv1alpha1 CRDs with OpenAPI schema for all service configuration
Red Hat K8s OperatorsPer-service Go operatorsIndependent operator per OpenStack service (keystone-operator, nova-operator, ...)
oslo ecosystemMetadata-driven config schemasOperators know valid options, types, and defaults from oslo.config metadata
ConfigHub"Configuration as Data" principleCRDs as structured, validated, versioned configuration stored in etcd

What C5C3 Does Differently

DifferenceDetail
Go operators (not CUE/Jinja2/Helm)Config rendering is Go code inside operators — no external template language. This keeps the rendering logic close to the reconciliation logic and avoids template debugging
Secrets fully separated via OpenBao + ESOUnlike YAOOK (config-in-Secrets), Kolla (vault-merged), or Red Hat (Secrets-in-CRD-refs), C5C3 stores all secrets in OpenBao and syncs them via ESO. Operators read K8s Secrets but never manage credential lifecycle
Structured-first (no raw INI passthrough in v1alpha1)Unlike Red Hat's customServiceConfig, C5C3 v1alpha1 does not include a raw INI escape hatch. All configuration goes through typed CRD fields. Override mechanisms are under design (see Customization)
ConfigMap-based (not Secret-based)Unlike YAOOK which stores config in K8s Secrets, C5C3 uses ConfigMaps for non-sensitive configuration. Credentials flow separately through the ESO secret pipeline
Single operator per serviceEach service has exactly one operator. No meta-operators, no shared controller runtime, no operator-of-operators pattern. The c5c3-operator handles orchestration but does not generate service configs