Skip to main content
The ImportCluster manifest is the declarative entry point for onboarding a cluster into Ankra and describing its stacks. Apply it with the CLI:
--cluster targets the cluster you name, by name or id; without it the target is the manifest’s metadata.name. cluster apply honours --cluster from CLI v0.16.0 - earlier versions ignore it and use metadata.name. The same schema is what Ankra reads from a connected GitOps repository.

Full Example

Top Level

spec.git_repository

Connect a Git repository so stacks are stored and synced from Git. Omit the block entirely for a non-GitOps import. Applying a changed git_repository block repoints the cluster. Ankra first writes the cluster’s current state - every stack, add-on and manifest it manages, with secrets sealed under your organisation’s key - to the new repository and branch as a commit, overwriting the files it manages there, and only then syncs from it. The new source does not need to be seeded by hand: the switch itself brings it to parity. Any branch works - a cluster is not tied to its repository’s default branch, so one repository with a branch per environment is a supported layout - but the branch must already exist; Ankra does not create branches. A repoint is refused until you acknowledge it: ankra cluster apply --allow-repoint, plus --allow-repoint-destroying-data when the cluster holds PersistentVolumeClaims. The refusal lists what the cluster runs today; it is not a diff against the target.
The switch is atomic. If the first write to the new source fails - the branch does not exist, the branch is protected against direct pushes, the credential’s GitHub App installation cannot reach the repository - nothing changes: the cluster keeps syncing from its current source and the error names the cause. A missing branch is reported together with the branches the repository does have.From the switch on, the new source is authoritative: anything that later leaves it is pruned from the cluster, PersistentVolumeClaims included. Keep the repository’s history if you may need to roll a change back.

Observability sources in Git

spec.prometheus_metrics and spec.log_source connect the cluster’s metrics and log data sources. Both are read back from the cluster document on every sync, so authoring or editing either block in Git connects the source and updates it - the same result as filling in the platform’s metrics or log source settings. Three rules apply to both members:
  • Credentials are never in Git. username, password, token and auth_scheme inside a source block are refused by name, because ignoring them would leave a live secret sitting in your repository while you believe it is in effect. Create the credential in the platform and reference it by credential_name.
  • Unknown top-level fields are refused, not ignored, and the error names the offending key and the accepted set. A mistyped field fails the sync rather than silently doing nothing.
  • Removing the block does not disconnect the source. Git can create and update a source; only the platform can disconnect one.
Deleting prometheus_metrics or log_source from the file is not a disconnect. The source survives the sync, and the next time Ankra regenerates the cluster document the block comes back. To disconnect, remove the source in the cluster’s Settings → Integrations; the platform then drops the block from Git on its own.This asymmetry is deliberate: reading “disconnect” out of an absent key is what deleted hand-written blocks before these members round-tripped, so a destructive change stays a platform action.

spec.prometheus_metrics

The cluster’s metrics data source. See Prometheus for endpoint examples per product.

spec.log_source

The cluster’s log data source. See Log Sources for provider endpoints and field-mapping defaults.

spec.helm_registries[]

Declare the Helm registries the file’s add-ons depend on, so the repository is self-contained: applying the file connects any registry that is not already present before add-ons deploy. A declaration matching an existing registry (same name, same URL - org-scoped or global) is an idempotent no-op; a declaration whose name is taken by a registry with a different URL fails the apply before anything is written. Credentials are referenced by name and must already exist, so secrets stay out of Git.

spec.stacks[]

Each stack groups related manifests, add-ons, and applications.

spec.stacks[].backup

Protecting a stack is one block. Ankra turns it into scheduled restore points in the backup vault you name - a Velero Schedule for the volumes you selected, a CloudNativePG ScheduledBackup and object store for each Postgres cluster, and a schedule entry inside each Percona cluster. ankra cluster stacks protect <stack> writes this same block without editing the file; ankra cluster stacks unprotect <stack> sets enabled: false. See Protect a stack.
Protecting a stack does not sweep every volume in it. Databases are captured by default, because a restore point without the database contents is the one nobody forgives. Volumes are captured only when you name them in selection.persistent_volume_claims, because a stack’s namespaces routinely hold caches, scratch space and metrics storage that nobody wants copied to object storage every night. Use the stack’s data inventory - ankra cluster stacks data list <stack> - to see the asset names.
Excluding databases needs an acknowledgement. Setting selection.databases: false requires selection.confirm_exclude_databases: true in the same block, and the stack then carries a standing warning: its restore points bring back volumes and configuration, but no database contents. The acknowledgement covers the write that carried it - a later edit that keeps databases excluded has to say so again.
An omitted block never removes protection. A file that does not mention backup leaves the stored policy exactly as it was. That is deliberate: ankra cluster apply replaces a stack with what the file says, and an older CLI or a hand-written file that simply did not know about the block would otherwise unprotect the stack in silence. Removing protection is backup: {enabled: false} - something a person typed. When an apply does narrow protection, the result carries a warning naming what is no longer covered. The objects that implement the policy are never stored as stack members. They are derived from this block every time the stack renders, so no apply, clone or profile capture can leave a stack with a schedule that no longer matches its policy - or remove the schedule while leaving the block.

Deploy waves

deploy_wave sequences whole stacks: a stack in wave N starts deploying only after every stack in a lower wave finished successfully, and teardown unwinds in reverse wave order. Stacks in the same wave deploy in parallel, and stacks without a deploy_wave stay independent of the ordering entirely - existing clusters keep their current behaviour.
Wave numbers do not need to be contiguous - 1, 5, 20 works and leaves room to slot stacks in later. If a stack in wave N fails, later waves stay blocked until it is fixed or removed. Within a stack, parents still control resource-level order.

Include paths

Instead of inline entries, reference files or folders in the repository. Ankra loads every YAML file found:

spec.stacks[].manifests[]

Raw Kubernetes YAML resources.
Renaming a manifest deletes its resources. Ankra identifies a manifest by its name, not by its content. When a stack is applied (with ankra cluster apply, a GitOps sync, or an edit in the portal) and a manifest name is no longer present, Ankra removes that manifest and runs the equivalent of kubectl delete on every object in its stored YAML. A manifest that appears under a new name is applied as a new manifest, and nothing orders that apply against the delete of the old one.For a manifest that holds a Namespace, this deletes the namespace and every PersistentVolumeClaim in it. For a manifest that holds PVCs, the delete removes the PVCs the new manifest has just applied. With a StorageClass whose reclaimPolicy is Delete (the default for most CSI drivers, including AWS EBS gp3), the underlying volumes are destroyed as well.Keep the names of manifests that own namespaces or stateful resources fixed. If you must rename one, move its data first, or make sure the PersistentVolumes behind it use reclaimPolicy: Retain. See Protect Persistent Data Before Changing a Stack.

spec.stacks[].addons[]

Helm releases.

settings defaults

Sync behaviour defaults to fully automated. See Add-on Settings for semantics.

spec.stacks[].applications[]

Deployments of Applications created in Ankra.

Parents

parents are the dependency edges that control deployment order: a resource deploys only after all of its parents succeed. Every parent is a kind + name pair - write both keys:
kind must be manifest or addon, and the parent must be defined somewhere in the same file. Namespace manifests must be parents of everything deployed into that namespace. Parents reference the other resource by name. Because a rename is a delete plus a create (see the manifests warning), renaming a parent also means updating every parents entry that points at it in the same change.
The shorthand - manifest: <name> does not work. It parses to an empty parent and the dependency edge is silently dropped - the resource deploys unordered, and both local and server-side validation still pass, because parent names are never resolved. Verify what was actually stored with ankra cluster stacks list <stack> -o json, which echoes each resource’s real parents.

Validation

ankra cluster apply validates the file before sending anything: unknown fields, missing parents, and invalid parent kinds are rejected with the offending path. Use --dry-run to validate without applying. ankra cluster validate -f cluster.yaml is the server-side pre-flight gate, built for CI: it runs every rule apply enforces without touching the cluster. That covers structure (duplicate names, missing parents, dependency cycles), chart resolution (registry connected, chart exists, pinned version exists), plaintext-secret detection, and the per-resource field rules - add-on namespaces (Kubernetes DNS label: 1-63 characters, lowercase letters, digits and -, starting and ending with a letter or digit), group names, and empty manifest bodies. Pass --cluster <id> to additionally validate against that cluster’s live resources, exactly as an apply to it would. validate also warns when a declared encrypted_paths entry seals more keys than the one it names (category encrypted_paths_over_match, see What an Entry Actually Matches). The warning is computed from the entries you declare, so a resource with an empty declaration never produces one, and ankra cluster apply does not report it - run validate first when a pipeline drives the API.