Summary
Explore consuming the Cluster Inventory API's PlacementDecision (multicluster.x-k8s.io/v1alpha1, KEP-5313) to let this controller reflect scheduler-chosen subsets of the fleet onto the SveltosClusters it manages, so Sveltos ClusterProfile/Profile can target exactly the clusters an external scheduler picked.
Background
PlacementDecision is a vendor-neutral, data-only object: a namespaced list of ClusterDecision entries, each a ClusterProfileRef (+ optional Reason), published by any multicluster scheduler and consumable by any downstream tool without scheduler-specific integration. A single logical decision can fan out to multiple slices, correlated via the multicluster.x-k8s.io/decision-key label, optionally scoped to a workload via multicluster.x-k8s.io/placement-key.
Today this controller has no concept of placement at all: every ClusterProfile unconditionally gets a SveltosCluster (1:1), and sveltosClusterLabels() mirrors the ClusterProfile's own labels onto it so Sveltos ClusterSelector expressions can match. There is no existing signal for "this cluster is currently selected for workload/placement X."
Proposed direction
Watch PlacementDecision and, for each ClusterProfileRef in its Decisions, reflect the selection onto the corresponding SveltosCluster's labels — reusing the exact mechanism sveltosClusterLabels() already provides for ClusterSelector matching. This would let a Sveltos ClusterProfile/Profile deploy only to the clusters a given scheduler currently selects, closing the loop between any KEP-5313-compliant scheduler and Sveltos add-on delivery, with no manual label bookkeeping required on the ClusterProfile side.
Open design questions to resolve before implementing
-
Label representation. A ClusterProfile can be selected by multiple independent decisions at once (different workloads/schedulers selecting overlapping cluster sets). Options:
- One label per decision, dynamic key (e.g.
decision.clusterinventory.projectsveltos.io/<placement-key-or-decision-name>=true) — supports simultaneous selection by N decisions, but needs sanitizing/hashing when the key segment isn't a valid Kubernetes label name (>63 chars, invalid characters).
- Single fixed label, last-writer-wins (e.g.
clusterinventory.projectsveltos.io/placement=<name>) — simple, but a second decision silently overwrites the first.
- Single boolean label (
clusterinventory.projectsveltos.io/placed=true) plus a status annotation listing decision name(s)/reasons for observability — simplest selector story, but can't target "selected by decision A specifically" vs. "any decision."
-
Opt-in gate. PlacementDecision is a newer, optional part of the Cluster Inventory API — the CRD may not be installed everywhere this controller runs. Should the watch be behind a flag (matching the existing --clusterprofile-provider-file precedent for optional capabilities), or always-on with graceful degradation if the CRD is missing?
-
Correlating key. Which field identifies a "placement" for labeling purposes — SchedulerName, DecisionKeyLabel, PlacementKeyLabel, or the PlacementDecision object's own name/namespace? Slices sharing a decision-key need to be treated as one logical decision, not N.
-
Reason surfacing. Should ClusterDecision.Reason (why a cluster was chosen) be surfaced anywhere on the SveltosCluster (annotation?) for observability/debugging, or dropped as scheduler-internal detail?
-
Cleanup semantics. When a ClusterProfile is removed from a decision (decision updated, cluster still exists) the corresponding label must be removed — likely means recomputing desired placement labels from all PlacementDecisions in the namespace on each relevant reconcile, consistent with how the rest of this controller already recomputes desired state rather than diffing incrementally.
Non-goals (for this issue)
This is exploratory — filed to capture the idea and open questions, not a commitment to a specific design. No code changes are proposed here.
Summary
Explore consuming the Cluster Inventory API's
PlacementDecision(multicluster.x-k8s.io/v1alpha1, KEP-5313) to let this controller reflect scheduler-chosen subsets of the fleet onto theSveltosClusters it manages, so SveltosClusterProfile/Profilecan target exactly the clusters an external scheduler picked.Background
PlacementDecisionis a vendor-neutral, data-only object: a namespaced list ofClusterDecisionentries, each aClusterProfileRef(+ optionalReason), published by any multicluster scheduler and consumable by any downstream tool without scheduler-specific integration. A single logical decision can fan out to multiple slices, correlated via themulticluster.x-k8s.io/decision-keylabel, optionally scoped to a workload viamulticluster.x-k8s.io/placement-key.Today this controller has no concept of placement at all: every
ClusterProfileunconditionally gets aSveltosCluster(1:1), andsveltosClusterLabels()mirrors theClusterProfile's own labels onto it so SveltosClusterSelectorexpressions can match. There is no existing signal for "this cluster is currently selected for workload/placement X."Proposed direction
Watch
PlacementDecisionand, for eachClusterProfileRefin itsDecisions, reflect the selection onto the correspondingSveltosCluster's labels — reusing the exact mechanismsveltosClusterLabels()already provides forClusterSelectormatching. This would let a SveltosClusterProfile/Profiledeploy only to the clusters a given scheduler currently selects, closing the loop between any KEP-5313-compliant scheduler and Sveltos add-on delivery, with no manual label bookkeeping required on theClusterProfileside.Open design questions to resolve before implementing
Label representation. A
ClusterProfilecan be selected by multiple independent decisions at once (different workloads/schedulers selecting overlapping cluster sets). Options:decision.clusterinventory.projectsveltos.io/<placement-key-or-decision-name>=true) — supports simultaneous selection by N decisions, but needs sanitizing/hashing when the key segment isn't a valid Kubernetes label name (>63 chars, invalid characters).clusterinventory.projectsveltos.io/placement=<name>) — simple, but a second decision silently overwrites the first.clusterinventory.projectsveltos.io/placed=true) plus a status annotation listing decision name(s)/reasons for observability — simplest selector story, but can't target "selected by decision A specifically" vs. "any decision."Opt-in gate.
PlacementDecisionis a newer, optional part of the Cluster Inventory API — the CRD may not be installed everywhere this controller runs. Should the watch be behind a flag (matching the existing--clusterprofile-provider-fileprecedent for optional capabilities), or always-on with graceful degradation if the CRD is missing?Correlating key. Which field identifies a "placement" for labeling purposes —
SchedulerName,DecisionKeyLabel,PlacementKeyLabel, or thePlacementDecisionobject's own name/namespace? Slices sharing adecision-keyneed to be treated as one logical decision, not N.Reason surfacing. Should
ClusterDecision.Reason(why a cluster was chosen) be surfaced anywhere on theSveltosCluster(annotation?) for observability/debugging, or dropped as scheduler-internal detail?Cleanup semantics. When a
ClusterProfileis removed from a decision (decision updated, cluster still exists) the corresponding label must be removed — likely means recomputing desired placement labels from allPlacementDecisions in the namespace on each relevant reconcile, consistent with how the rest of this controller already recomputes desired state rather than diffing incrementally.Non-goals (for this issue)
This is exploratory — filed to capture the idea and open questions, not a commitment to a specific design. No code changes are proposed here.