Kubernetes Configuration storage
Use this reference to configure tenant placement and Kubernetes permissions for Configuration resources and immutable version snapshots.
Kubernetes placement and RBAC
KubernetesConfigurationDriver creates exactly one ConfigMap per Configuration
in the verified tenant namespace for its exact logical Namespace. Single-cluster
Compute shares this target with Gateway and Harness workloads, including an
operator-owned existingNamespace. Only the two-cluster profile uses a separate
control-cluster storage target. Wait for Namespace readiness and grant API ConfigMap access there
before creating Configuration resources. The ConfigMap remains OCC-owned.
See namespace requirements.
Its data contains exactly one entry:
{ "data": { "openclaw.json": "<JSON-serialized values document>" }}The driver validates and parses that document when reading it; malformed JSON,
extra data entries, excessive size, or incorrect ownership fail closed. It
cannot select another tenant namespace, share tenant objects,
read Kubernetes Secrets, create Pods, or store Installation settings. ConfigMap
updates are not watched or automatically reloaded into saved AgentRevisions.
The serialized values must be smaller than 1 MiB, or a write is refused with
400 INVALID_REQUEST naming the limit; Kubernetes may also reject an object
that exceeds its total object limit. Reads reject invalid kind or
generation and binary ConfigMap data. Updates require a resource version and a
generation difference of exactly one; the reverse direction is reserved for OCC
rollback. Deletion checks ownership and uses the observed UID as a precondition
when available. Missing objects, conflicts, or unavailable access fail without
adopting another object.
PostgreSQL stores only server-owned Configuration metadata: its identifier,
owning Namespace, immutable kind, current generation, and creation time. The
ConfigMap in the tenant namespace carries matching kind and generation
annotations and stores only the live native configuration document in openclaw.json; values
are not duplicated in Configuration metadata. Deployment separately persists
its immutable version snapshot.
When Kubernetes Compute prepares a saved AgentRevision, it creates a
separate, immutable, Agent-owned snapshot ConfigMap containing the version's
native configuration with Driver-owned proxy trust
rendered from the Installation. This rendering does not rewrite the stored
Configuration or AgentRevision. The Agent gateway mounts this
snapshot read-only at /etc/openclaw/openclaw.json; its environment contains
only the file path in OPENCLAW_CONFIG_PATH. It never mounts the mutable
Configuration Driver ConfigMap or copies raw configuration into Pod
environment. When OpenClaw starts from this read-only file, the startup wrapper
also sets OPENCLAW_CONFIG_READONLY=1, so OpenClaw treats the file as externally
managed and does not try to write its last-known-good backup beside it. A new
saved version receives a different immutable snapshot and rolls the same
Agent gateway. Old snapshots remain until Namespace deletion;
safe earlier garbage collection is not implemented.
Startup validates the selected Configuration Driver's closed schema and
authentication options but does not probe tenant ConfigMaps or their RBAC:
such a preflight would require a known object or broader access. OCC validates
native Configuration semantics before calling the Driver; Drivers enforce their
backing-storage ownership and identity checks. Kubernetes namespace existence
and exact ConfigMap authorization are checked lazily on the first requested CRUD
operation. An authorized Configuration request can return 503 while a
driver-managed provisioning Namespace's Kubernetes namespace or API RoleBinding
does not yet exist; retry after provisioning and its exact grants are ready. An
explicitly selected existing Namespace instead rejects creation with 409
until it is ready; after readiness, a missing API RoleBinding returns 503.
Use the existing cluster-scoped namespace-observer get/list grant to
discover the exact tenant namespace. Provision tenant-data access through
namespaced ConfigMap CRUD only. Kubernetes cannot restrict create by
resourceNames; keep it in a separate namespaced rule. Scope the remaining
verbs to exact object names when those names are known:
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: occ-configuration namespace: <tenant-storage-namespace>rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["create"] - apiGroups: [""] resources: ["configmaps"] resourceNames: ["cfg-123e4567-e89b-42d3-a456-426614174000-0123456789ab"] verbs: ["get", "update", "delete"]The object name is illustrative; use the exact name generated by the selected
implementation. Bind this Role only to its intended bootstrap identity in the
same tenant namespace. OCC still verifies exact Namespace placement, object
naming, and ownership before every mutation. Never add ConfigMap list/watch,
cluster-wide tenant-resource access, Secret access, or Pod-creation privileges;
the existing Namespace-only observer grant does not permit any of them.
The separately selected Kubernetes Compute Driver also requires tenant-local
ConfigMap get, create, and patch to prepare its immutable Agent-owned
version snapshots. Those Compute permissions and snapshots are independent of
the Configuration Driver's cfg-* object allowlist and CRUD identity. Keep
Compute create in its own namespaced rule because Kubernetes cannot scope
creation by resourceNames; restrict get and patch to known exact
Agent-owned snapshot names when practical. These Configuration and snapshot
operations do not require Kubernetes Secret access. Secret CRUD and delivery
validation use the separately selected SecretDriver and the API's tenant-local
Secret RBAC. The separately authorized provider-managed service-account
credential path uses exact account-owned Secrets through Compute; see
service accounts.
