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.
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,tokenandauth_schemeinside 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 bycredential_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.
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.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.
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.
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.
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.