Unique cluster identifier. Used as the YAML filename (clusters/<name>.yaml) and injected as HYVE_CLUSTER_NAME into module operations.
Cluster Concepts
Overview
Hyve manages Kubernetes clusters through declarative YAML definitions stored in Git repositories. Each cluster references a module (driver) that implements its lifecycle operations — create, delete, status, and auth. The driver is versioned and locked in hyve.lock, ensuring reproducibility across your team and CI/CD.
Declarative
Define clusters as YAML files in Git
Driver-based
Any cloud provider via the module system
Version Controlled
Full history of every cluster change
Lifecycle Hooks
beforeCreate, onCreate, onDelete, afterDelete
Cluster Definition
Clusters are defined using YAML files stored in the clusters/ directory of your Git state repository. The driver determines which module handles all cloud operations.
apiVersion: v1kind: Clustermetadata: name: my-cluster region: us-east-1spec: driver: source: github.com/hyve-modules/eks version: v1.0.0 params: vpc_id: vpc-0abc123456789 eks_role_arn: arn:aws:iam::123456789012:role/eks-role node_role_arn: arn:aws:iam::123456789012:role/node-role instance_type: t3.medium node_count: "3" workflows: beforeCreate: - provision-network onCreate: - deploy-monitoring onDelete: - drain-workloads afterDelete: - cleanup-network delete: false pause: false expiresAt: "" pendingWorkflows: [] workflowSchedules: []Metadata fields
metadata.name string required metadata.region string required Cloud provider region (e.g. PHX1, us-east-1, us-central1, eastus). Injected as HYVE_CLUSTER_REGION into module operations.
Driver fields
spec.driver.source string required Module source string. Examples:
github.com/hyve-modules/civogithub.com/org/repo//path/to/module./local-module
spec.driver.version string required Module version. Must be locked in hyve.lock. Examples: v1.0.0, v2.1.3, local
Params
spec.params object Module-specific key-value parameters. Each param is injected as HYVE_PARAM_<UPPERCASED_KEY> into module operations. The set of valid params is defined by the module’s module.yaml.
Params are set when creating a template (--set KEY=VALUE) or can be overridden at cluster-creation time.
driverOutputs
spec.driverOutputs object Key-value pairs emitted by module operations as HYVE_KEY=value stdout lines during reconciliation. These are stored and re-injected on the next reconcile, allowing operations to pass data forward (e.g. cluster endpoint, VPC ID, last param hash).
Do not edit this field manually. It is managed exclusively by the reconciler, and — like spec.appliedResources — physically lives in a separate file from the one you edit. See Reconciler state file below.
Reconciler state file
driverOutputs and appliedResources (see Cluster Resources) are both reconciler-owned: values the reconciler produced, not something a person decides. Keeping them in the same file as spec.driver, spec.params, spec.resources, and the rest of what you actually author would mean every routine reconcile — even one where nothing you declared changed — rewrites that file, mixing machine bookkeeping (content hashes, timestamps, tracked-object lists) into the same diff as your real changes.
Instead, they’re stored in a sidecar file in cluster-state/, a sibling of clusters/ — not next to the cluster’s desired-state YAML, but in its own directory entirely, so ls clusters/ only ever shows files you actually wrote:
clusters/└── my-cluster.yaml # what you author and reviewcluster-state/└── my-cluster.state.yaml # driverOutputs + appliedResources — reconciler-owneddriverOutputs: HYVE_EKS_CLUSTER_ENDPOINT: https://abc123.gr7.us-east-1.eks.amazonaws.com HYVE_LAST_PARAMS_HASH: abc123...appliedResources: cert-manager: sourceSHA256: a1b2c3d4e5f6... helm: true namespace: cert-manager appliedAt: "2026-07-03T10:00:00Z" objects: - apiVersion: apps/v1 kind: Deployment namespace: cert-manager name: cert-managerThis file is entirely derived from clusters/<name>.yaml plus what the reconciler observes — if it’s ever missing, the reconciler recreates it on the next reconcile with no manual migration step. An older cluster file that still has driverOutputs/appliedResources inline (from before this split existed) keeps working exactly as before; the very next reconcile that touches the cluster splits it into the two-file layout automatically. Likewise, an existing sidecar still sitting directly in clusters/ (from before it moved to its own directory) needs no migration step either — it’s just written back out to cluster-state/ on the next reconcile that touches that cluster.
Lifecycle control
spec.delete boolean default: false When true, the reconciler runs onDelete workflows, calls the module’s delete operation, runs afterDelete workflows, and removes the YAML file. Set this field (rather than deleting the file directly) to ensure lifecycle hooks run.
spec.pause boolean default: false When true, the reconciler skips this cluster entirely. The cloud cluster continues running; Hyve does not compare or modify it until pause is set to false.
spec.expiresAt string RFC 3339 timestamp (e.g. "2026-09-01T00:00:00Z"). When the current time passes this value, the reconciler treats the cluster as if spec.delete: true is set — running lifecycle hooks, deleting from the cloud, and removing the YAML file. A paused cluster is never checked for expiry.
Workflow hooks
spec.workflows.beforeCreate string[] Workflow names to run before the cluster is provisioned. The cluster does not exist yet — no kubeconfig is available. Use for provisioning prerequisites (VPCs, IAM roles, security groups). Workflow output variables (HYVE_KEY=value) are captured and can populate driverOutputs before create.
spec.workflows.onCreate string[] Workflow names to run after the cluster is created and the module reports status active. The cluster exists; run hyve cluster auth first if your workflows need kubectl access. Runs before spec.resources applies for this cycle — a workflow here can’t assume any resource-created object (a namespace, a Deployment) already exists.
spec.workflows.afterCreate string[] Workflow names to run after the cluster is created, authenticated, and — unlike onCreate — after spec.resources has applied for this cycle. Use this when a workflow needs something a resource created (e.g. a namespace) to already exist, such as creating a Kubernetes Secret that a resource-managed Deployment references.
spec.workflows.onDelete string[] Workflow names to run before the cluster is deleted. Cluster is still running; kubeconfig is available.
spec.workflows.afterDelete string[] Workflow names to run after the cluster has been deleted. No kubeconfig available. Use for tearing down cloud prerequisites provisioned by beforeCreate workflows.
spec.workflows.preReconcile string[] Workflow names to run at the start of every reconcile loop for this cluster, before any create/update/delete logic. Runs on every reconcile regardless of whether the cluster definition changed.
Cluster lifecycle
Creation
Execute a template
hyve cluster create my-cluster --template my-civo-templateGenerates clusters/my-cluster.yaml and commits it to Git.
Reconcile
hyve reconcileRuns beforeCreate workflows, calls the module’s create operation, waits for active status, runs onCreate workflows, applies spec.resources, then runs afterCreate workflows.
Authenticate
hyve cluster auth my-clusterkubectl config use-context my-clusterkubectl get nodesDeletion
To delete a cluster and run lifecycle hooks:
# Mark for deletion — runs onDelete, calls module delete, runs afterDeletehyve cluster delete my-clusterThis sets spec.delete: true in the cluster YAML, commits to Git, and runs reconciliation.
Pausing
Pause a cluster to stop Hyve from touching it during reconciliation (useful for maintenance windows):
# Edit clusters/my-cluster.yaml, set spec.pause: true# Commit and push — reconciler will skip this clusterTo resume, set spec.pause: false and commit.
Auto-expiry
Set spec.expiresAt to automatically delete a cluster at a future time:
spec: expiresAt: "2026-09-01T00:00:00Z"Or use a template with a schedule to compute the expiry automatically at cluster-creation time.
Lifecycle workflow hooks
| Hook | When | Cluster exists? | Kubeconfig? |
|---|---|---|---|
beforeCreate | Before cloud provisioning | No | No |
onCreate | After cluster reaches active status, before spec.resources applies | Yes | After auth |
afterCreate | After cluster creation, after spec.resources has applied | Yes | After auth |
onDelete | Before cloud deprovisioning | Yes | Yes |
afterDelete | After cloud deprovisioning | No | No |
preReconcile | Start of every reconcile loop | Depends | Depends |
beforeCreate use cases
spec: workflows: beforeCreate: - provision-vpc # Create VPC and subnets for EKS - create-iam-roles # Create EKS cluster and node IAM rolesThese workflows can emit HYVE_KEY=value outputs that are stored in driverOutputs and used by the module’s create operation.
onCreate use cases
spec: workflows: onCreate: - setup-monitoring # Install Prometheus/Grafana - configure-networking # Apply network policies - deploy-app # Deploy application workloadsafterCreate use cases
spec: workflows: afterCreate: - create-app-secrets # Create a Secret a resource-managed Deployment references - point-dns-at-cluster # DNS management once the app is actually deployedUse afterCreate instead of onCreate whenever a workflow depends on something spec.resources creates — most commonly, a Kubernetes Secret whose real values can’t be committed to Git as a resource, but which a resource-managed Deployment already expects to exist (in its own namespace, also resource-managed). onCreate runs too early for this: the namespace/Deployment don’t exist yet.
onDelete use cases
spec: workflows: onDelete: - backup-data # Final backup before deletion - drain-workloads # Gracefully drain workloads - notify-team # Send deletion notificationafterDelete use cases
spec: workflows: afterDelete: - destroy-vpc # Remove VPC and subnets created in beforeCreate - delete-iam-roles # Clean up IAM roles - cleanup-dns # Remove DNS recordsReconciliation
Reconciliation reads all cluster YAMLs from Git and calls the appropriate module to bring the cloud state in line with the desired state.
# Reconcile from local machine (local mode)hyve reconcile
# Reconcile from a checked-out repo path (CI/CD mode)hyve reconcile --path .What the reconciler does
Creates missing clusters
If a cluster YAML exists in Git but the cluster does not exist in the cloud, the reconciler calls the module’s create operation and runs beforeCreate → create → onCreate workflows.
Checks existing clusters
For each cluster that exists in both Git and the cloud, the reconciler calls the module’s status operation. If the cluster’s params have changed (detected via HYVE_LAST_PARAMS_HASH), the reconciler may update or recreate the cluster depending on the module.
Deletes marked clusters
If spec.delete: true is set, or if spec.expiresAt has passed, the reconciler runs onDelete workflows, calls the module’s delete operation, and then runs afterDelete workflows before removing the YAML file.
Skips paused clusters
If spec.pause: true is set, the cluster is skipped entirely. No status check, no create, no delete.
Storage
Cluster definitions are stored in:
~/.hyve/repositories/<repository-name>/├── clusters/│ ├── my-cluster.yaml # desired state — what you author│ ├── staging.yaml│ └── dev.yaml└── cluster-state/ ├── my-cluster.state.yaml # driverOutputs + appliedResources — reconciler-owned ├── staging.state.yaml └── dev.state.yamlA cluster with no reconciler-owned state yet (freshly created, nothing applied) has no .state.yaml file — it appears in cluster-state/ on the first save that has something to record. These files are version-controlled in your Git repository. Every change is committed and pushed — providing a full audit trail of all cluster modifications.