Day 1: Cluster Creation¶
Day 1 involves the instantiation and initialization of the OpenBao cluster itself.
User Guide
For details on configuring the cluster, see the Cluster Configuration and Security Fundamentals.
Initialization Strategies¶
When spec.selfInit.enabled = true, the cluster uses OpenBao's native self-initialization feature:
- User creates an
OpenBaoClusterCR withspec.selfInitconfigured. - Cert Manager (workload controller) bootstraps PKI (CA + leaf certs).
- If image verification is enabled, the operator verifies the container image signature before proceeding.
- Infrastructure Manager (workload controller) ensures a per-cluster auto-unseal configuration (static seal by default, or external KMS if configured).
- Infrastructure Manager renders
config.hclwith TLS, Raft storage,retry_join,service_registration "kubernetes", and the appropriatesealstanza. - The init container appends the self-init
initializestanzas (rendered fromspec.selfInit.requests[]) to the rendered config for pod-0 only. - Infrastructure Manager creates the StatefulSet with 1 replica initially.
- OpenBao automatically initializes itself on first start using the
initializestanzas: - Auto-unseals using the static key.
- Executes all configured
initializerequests (audit, auth, secrets, policies). - The root token is NOT returned and is automatically revoked after use.
- Init Manager detects initialization via Kubernetes service registration labels (preferred) and sets
Status.Initialized = true. - Infrastructure Manager scales the StatefulSet to the desired
spec.replicas. - Additional OpenBao pods start, auto-unseal, and join the Raft cluster.
Self-Initialization vs Root Token
Self-initialization requires an auto-unseal mechanism (which the Operator provides via static auto-unseal by default, or external KMS if configured). No root token Secret is created when self-init is enabled.
Version Requirement
The static auto-unseal feature requires OpenBao v2.4.0 or later. Earlier versions do not support the seal "static" configuration. External KMS seals may have different version requirements depending on the provider.
Sequence Diagram:
sequenceDiagram
autonumber
participant U as User
participant K as Kubernetes API
participant Op as OpenBao Operator
participant Bao as OpenBao Pods
U->>K: Create OpenBaoCluster (selfInit.enabled=true)
K-->>Op: Watch OpenBaoCluster
Op->>K: Create TLS Secrets (CA, server)
Op->>K: Create config ConfigMap (config.hcl)
Op->>K: Create self-init ConfigMap (initialize blocks)
Op->>K: Create StatefulSet (replicas=1)
Bao-->>Bao: Auto-init and run initialize requests
Bao-->>Bao: Auto-unseal using static or KMS seal
Bao-->>K: Update Pod labels (service_registration)
Op->>K: Observe pod-0 labels (initialized/sealed)
Op->>K: Update OpenBaoCluster.status.initialized=true
Op->>K: Scale StatefulSet to spec.replicas
Bao-->>Op: Additional pods auto-unseal and join Raft
- User creates an
OpenBaoClusterCR in a namespace (withoutspec.selfInit). - Cert Manager (workload controller) bootstraps PKI (CA + leaf certs).
- If image verification is enabled (
spec.imageVerification.enabled), the operator verifies the container image signature using Cosign before proceeding. - Infrastructure Manager (workload controller) ensures a per-cluster auto-unseal configuration:
- If
spec.unsealis omitted orspec.unseal.typeis"static", creates a static auto-unseal key Secret (<cluster>-unseal-key) if missing. - If
spec.unseal.typeis an external KMS provider (awskms,gcpckms,azurekeyvault,transit), configures the seal with the provided options and credentials (if specified). - Infrastructure Manager renders
config.hclwith TLS, Raft storage,retry_join,service_registration "kubernetes", and the appropriatesealstanza (static or external KMS). - The Operator injects
BAO_K8S_NAMESPACEinto the OpenBao container environment so service registration can determine the Pod namespace. - Infrastructure Manager creates the StatefulSet with 1 replica initially (regardless of
spec.replicas), mounting TLS and unseal Secrets (if using static seal) or KMS credentials (if using external KMS). - Init Manager waits for pod-0 to be running, then:
- Prefers Kubernetes service registration Pod labels (
openbao-initialized,openbao-sealed) when available. - Falls back to the HTTP health endpoint (
GET /v1/sys/health) when labels are not yet available. - If not, calls the HTTP initialization endpoint (
PUT /v1/sys/init) against pod-0 to initialize the cluster. - Stores the root token in a per-cluster Secret (
<cluster>-root-token). - Sets
Status.Initialized = true. - Once initialized, Infrastructure Manager scales the StatefulSet to the desired
spec.replicas. - Additional OpenBao pods start, auto-unseal using the static key, join the Raft cluster via
retry_join, and become Ready.
Sequence Diagram:
sequenceDiagram
autonumber
participant U as User
participant K as Kubernetes API
participant Op as OpenBao Operator
participant Bao as OpenBao Pods
U->>K: Create OpenBaoCluster (no selfInit)
K-->>Op: Watch OpenBaoCluster
Op->>K: Create TLS Secrets (CA, server)
Op->>K: Create config ConfigMap (config.hcl)
Op->>K: Create StatefulSet (replicas=1)
Bao-->>K: Update Pod labels (service_registration)
Op->>K: Observe pod-0 labels (initialized/sealed)
alt labels not yet available
Op->>Bao: Call /v1/sys/health (check initialized)
end
Op->>Bao: Call /v1/sys/init (initialize cluster)
Op->>K: Store root token Secret
Op->>K: Update OpenBaoCluster.status.initialized=true
Op->>K: Scale StatefulSet to spec.replicas
Bao-->>Op: Pods auto-unseal and join Raft