OpenClaw EnterpriseDOCSGitHub

Existing Kubernetes Namespace Placement Flow

Overview

An Installation administrator explicitly selects an operator-owned Kubernetes namespace while creating its platform Namespace. The running worker verifies authorization and isolation, binds exact tenant identity, and preserves the namespace after deletion. Other tenants retain deterministic managed placement; existing managed namespaces created with the previous deterministic name remain in place when their tenant markers and OpenClaw manager label are exact.

Entry Points

Before this flow starts, API and worker startup load the Installation YAML and Kubernetes Compute validates resources.namespace.quota. Counted resources must pass the native integer-precision rule: pods: "1.5" is refused with a quota diagnostic before persistence or namespace operations. CPU "500m" and whole-count suffixes retain their values. See the configuration reference.

Flow

graph TD
  A["Create platform Namespace"] --> B{"existingNamespace selected"}
  B -->|no| C["Provision deterministic managed namespace"]
  C --> J{"Tenant marker already exists"}
  J -->|current or previous managed name| H
  J -->|wrong name or ownership conflict| K["Fail closed"]
  B -->|yes| D["Authorize administer and persist unique selection"]
  D --> E["Running worker reauthorizes and verifies exact external namespace"]
  E --> F["Bind generated tenant identity while preserving external manager"]
  F --> G["Provision owned infrastructure and mark Namespace ready"]
  G --> H["Place workloads and ConfigMaps in the bound namespace"]
  H --> I["Delete orphans and owned infrastructure; retain external ownership"]

Execution Trace

1. Authorize and persist explicit external selection

packages/occ/src/index.ts:OpenClawController.createNamespace

internal/occcli/cli.go:namespaceCommand checks whether the caller supplied --existing-namespace before creating its HTTP client. An explicitly supplied value, including an empty string, must be a DNS-1123 label of 1 through 63 characters. Invalid values return a local error without a request. Omitting the flag retains managed placement; an empty adoption flag cannot select it. internal/occclient/client.go:Client.CreateNamespace sends an admitted nonempty selection to the same API operation below.

POST /namespaces accepts { "name": "support", "existingNamespace": "customer-support-prod" }. Omitting existingNamespace keeps ordinary managed placement and creates the current oce-<hash15> namespace name when no tenant namespace already exists. Existing-namespace selection requires ordinary Namespace-create permission plus Installation-level administer and the selected bundled Kubernetes Compute Driver; Docker or external Compute selections reject it with 409. OCC persists the exact physical name with its generated platform Namespace ID before queuing worker provisioning. Partial database uniqueness prevents simultaneous active claims for the same name.

2. Reauthorize and bind the exact external namespace

apps/controller/src/drivers/compute/kubernetes/index.ts:KubernetesComputeDriver.ensureNamespace

The running worker rechecks Installation administer immediately before adoption. Compute reads the exact selected Kubernetes namespace and requires Active status, openclaw.dev/namespace-lifecycle: external, all three restricted Pod Security labels, and no foreign tenant markers or NetworkPolicies. It binds its full Namespace-ID label and matching Namespace-ID annotation together through a resourceVersion-guarded, non-forced patch; concurrent ownership changes fail safely while preserving the manager and unrelated metadata. Missing targets, termination, foreign ownership or additive policies, ambiguous identity, and revoked authorization fail closed without managed fallback. A missing worker RoleBinding keeps provisioning pending; a missing API RoleBinding instead makes subsequent Configuration operations return 503. KubernetesComputeDriver.validateConfiguration checks counted quota precision through resource-quantities.ts:hasIntegerQuotaPrecision during startup, before ensureNamespace can copy these values into the ResourceQuota. Invalid counts therefore do not enter this adoption phase. This does not validate quota capacity or establish that a cluster is reachable.

Compute reconciles its owned quota, limit range, and isolation policies; no worker pause, restart, or Installation setting is needed.

apps/controller/src/drivers/compute/kubernetes/index.ts:KubernetesComputeDriver.networkPolicies renders allow-dns with UDP and TCP ports 53 and 5353, scoped to the configured DNS peer.

For the separate preprovisioned Namespace profile, KubernetesComputeDriver.verifyExistingNetworkPolicies compares admitted specs with the declared operator policies before initialization. The operator-owned OpenShellSandboxDriver.ensureNamespaceWorkspace check uses the same drivers/kubernetes/network-policy.ts:networkPolicySpecToJson projection on both observed and configured specs. It restores the SDK ingress alias and accepts omitted empty rule lists only for explicitly selected policy directions. Other spec differences still stop preparation; neither check repairs the policy.

3. Colocate Configuration and workload resources

apps/controller/src/drivers/compute/kubernetes/index.ts:KubernetesComputeDriver.reconcileDnsPorts

When preparing an Agent in a ready Namespace, Compute extends the installed tenant and dedicated Gateway DNS policies with missing ports. It verifies exact ownership and the configured DNS peer, then patches with the observed UID and resource version. The patch preserves the installed Pod selector, existing ports, peers, and other rules; policies from before network profiles continue to admit other Agents' unprofiled Pods. Conflicts fail the preparation pass without overwriting concurrent changes. A complete DNS grant causes no write.

apps/controller/src/drivers/configuration/kubernetes/index.ts:KubernetesConfigurationDriver

Configuration discovers the bound backing namespace by tenant label for each ConfigMap operation. Managed discovery fails closed when multiple Kubernetes Namespaces claim the tenant, when the claiming object lacks the full openclaw.dev/namespace label and openclaw.dev/namespace-id annotation, or when a managed namespace name is neither the current oce-<hash15> form nor the previous oce-<slug>-<hash12> form. The previous form is accepted only for an already discovered namespace with app.kubernetes.io/managed-by=openclaw-enterprise; new managed namespaces still use the current name. Explicitly external Namespace provisioning rejects Configuration creation with 409 until the worker marks the Namespace ready. Compute uses the same resolved namespace for workloads, dedicated Agent-owned shared PersistentVolumeClaims, private gateway state claims, credentials, and deletion cleanup. Existing exact Namespace, Agent, version, service-account, and child-resource ownership checks remain unchanged. Version retirement preserves the current gateway and its owned claims; final gateway teardown removes the exact-owned private and shared claims by UID.

4. Preserve externally owned namespaces during deletion

apps/controller/src/drivers/compute/kubernetes/index.ts:KubernetesComputeDriver.deleteNamespace

OCC first rejects deletion while Agents, Configurations, Secrets, service accounts, or other Namespace contents remain. Any object still carrying this Namespace's ownership (the app.kubernetes.io/managed-by=openclaw-enterprise and openclaw.dev/namespace labels plus the openclaw.dev/namespace-id annotation) is therefore an orphan, for example a Configuration ConfigMap whose create applied but whose transaction then failed. Compute deletes such ConfigMaps and ServiceAccounts by UID, and such Secrets too when repository credentials are enabled, the only setup in which the single-cluster chart lets the worker list Secrets. Two-cluster Compute keeps Secrets and Configurations in the control-plane namespace, which it deletes. A failed list or delete keeps the Namespace deleting. Compute then removes its owned openclaw-quota, openclaw-limits, allow-dns, allow-gateway-ingress, and default-deny objects, preserving default-deny until last. External namespace objects, their tenant markers, RoleBindings, the operator's Secrets, and unrelated resources remain untouched. Deleting a failed selection that was never bound to either tenant marker also leaves the external namespace untouched; partial or foreign markers fail closed. An already-missing namespace counts as deleted. After deleting an unclaimed failed tenant, an administrator can correct preparation and retry. Previously claimed namespaces cannot be readopted until an operator deliberately clears the old openclaw.dev/namespace label, openclaw.dev/namespace-id annotation and, in single-cluster Compute, openclaw.dev/gateway-namespace label. Deleting a failed selection whose namespace still carries another tenant's openclaw.dev/namespace label or namespace-id annotation fails permanently and leaves the Namespace deleting; clear those markers, then have the initiator repeat DELETE. Managed namespaces retain their existing complete-deletion lifecycle.

Debugging and Verification

Search documentation