Deployment spaces
How ZopDay represents a Kubernetes cluster; registered, probed, and addressable.
A deployment space is a registered Kubernetes cluster on a connected cloud account. It’s the unit of “where things run.” Environments bind to spaces; deployments push manifests through spaces; the autoscaler scales targets inside spaces. Everything cluster-shaped goes through this abstraction.

Deployment Spaces; registered clusters across GCP, AWS, and Azure with region and health status.
Anatomy of a space
A space carries:
| Field | What it is |
|---|---|
id | UUID. Stable across renames / re-registrations. |
org_id | The org that owns the registration. |
provider | aws · gcp · azure |
space_type | kubernetes today; future types reserved. |
cloud_account_id | The connected cloud account ZopDay authenticates against. |
config JSON | Provider-specific identifiers (cluster name, region, resource group on Azure). |
status | active · inactive · unknown from the 60-second reachability probe. |
Spaces are not the cluster itself; they are ZopDay’s pointer to the cluster + the kubeauth permission to talk to it.
Provider-specific config
The config JSON varies per provider because each cloud identifies clusters differently:
{ "clusterName": "prod-eks-1", "region": "us-east-1"}{ "clusterName": "prod-gke-1", "region": "us-central1", "projectId": "acme-prod-12345"}{ "clusterName": "prod-aks-1", "resourceGroup": "rg-prod-eus", "subscriptionId": "00000000-0000-0000-0000-000000000000"}These fields are not editable on an existing space; they’re the cluster’s identity, not its config. If you need to point at a different cluster, deregister and re-register.
How spaces get created
Two paths:
BYOC; existing cluster
Cluster already exists in your cloud. Connect the cloud account, pick the cluster, click Register. See Cluster registration.
Provisioned; fresh cluster
Cluster doesn’t exist yet. Provisioning job creates the cluster end-to-end (EKS / GKE / AKS) and registers it as a space automatically on success. See Cluster provisioning.
Either path lands the same deployment_space row.
Endpoint surface
Catalog operations live on the config service (/spaces*):
GET /spaces ListPOST /spaces Add; register an existing clusterGET /spaces/{id} Get onePATCH /spaces/{id}/status Update status (internal use)DELETE /spaces/{id} Soft-delete (deregister)Cluster-side operations that need a kubeconfig live under /space-discovery/*:
GET /space-discovery/{spaceID}/namespaces List existing namespaces on the clusterPOST /space-discovery/{spaceID}/namespaces Create a new namespaceMulti-cluster orgs
Most ZopDay orgs end up with multiple spaces. Common patterns:
- Per-environment: one cluster per environment (
prod,staging,dev). Highest isolation, highest cost. - Per-region: one cluster per region for latency or compliance. Often paired with a global ingress in front.
- Per-team / per-product: one cluster per major team or product line. Useful when teams want full autonomy.
- Shared dev + dedicated prod: common cost-optimisation: a single shared dev cluster, dedicated prod clusters per environment.
ZopDay doesn’t enforce any of these; the space picker in the environment wizard accepts any registered space, regardless of which other environments already point at it.
Reachability probe
Every 60 seconds, ZopDay calls GET /version on each space’s API server using a freshly-minted kubeconfig. The result updates status:
| Probe outcome | Status |
|---|---|
| 200 with parseable version | active |
| 3 consecutive failures | inactive |
| Less than 1 probe interval since registration | unknown |
Status drives gating in the UI:
- Inactive spaces don’t show up in the autoscaler picker, event-readiness picker, or environment picker: they’re filtered before render
- Active deployments on an inactive space continue running; ZopDay just can’t push new revisions until it recovers
- Queued revisions retry up to 3 times against an inactive space, then stop. Re-enqueue from the Provisioning Jobs view once the space recovers.
Synthetic vs real spaces
Some places in the UI need a “space-shaped” object that isn’t a real cluster (topology grouping, picker placeholders). These synthetic entries are filtered out of the autoscaler picker, event-readiness picker, and any scaling-aware UI; those operate only on real, scalable clusters.
Cascading effects of deregistration
Deregistering a space (DELETE /spaces/{id}):
| Object | Effect |
|---|---|
| Environments bound to this space | Gate cleanly with “Space deregistered”; re-bind to another space to recover |
| Pending deployment revisions | Move to DLQ on next claim attempt |
| Active deployments (already deployed) | Continue running on the cluster. ZopDay just can’t push new revisions |
| Autoscaler policies targeting resources in this cluster | Stop being applied. The underlying cloud-side scaling policy remains as written before deregistration. |
| Kubeauth grant | Removed. ZopDay can no longer mint kubeconfigs for this cluster. |
Deregistration is reversible by re-registering the cluster; the id field on the new registration will be different (new UUID), so any environments that referenced the old id still need to be re-bound manually.