diff --git a/pkg/controllers/provisioning/scheduling/nodeclaim.go b/pkg/controllers/provisioning/scheduling/nodeclaim.go index 0ccaf397df..7521be6e5e 100644 --- a/pkg/controllers/provisioning/scheduling/nodeclaim.go +++ b/pkg/controllers/provisioning/scheduling/nodeclaim.go @@ -39,6 +39,7 @@ type NodeClaim struct { topology *Topology hostPortUsage *scheduling.HostPortUsage daemonResources v1.ResourceList + hostname string } var nodeID int64 @@ -59,6 +60,7 @@ func NewNodeClaim(nodeClaimTemplate *NodeClaimTemplate, topology *Topology, daem hostPortUsage: scheduling.NewHostPortUsage(), topology: topology, daemonResources: daemonResources, + hostname: hostname, } } @@ -119,6 +121,10 @@ func (n *NodeClaim) Add(pod *v1.Pod) error { return nil } +func (n *NodeClaim) Destroy() { + n.topology.Unregister(v1.LabelHostname, n.hostname) +} + // FinalizeScheduling is called once all scheduling has completed and allows the node to perform any cleanup // necessary before its requirements are used for instance launching func (n *NodeClaim) FinalizeScheduling() { diff --git a/pkg/controllers/provisioning/scheduling/scheduler.go b/pkg/controllers/provisioning/scheduling/scheduler.go index 4cdb31b32e..3b8dcc91c4 100644 --- a/pkg/controllers/provisioning/scheduling/scheduler.go +++ b/pkg/controllers/provisioning/scheduling/scheduler.go @@ -289,6 +289,7 @@ func (s *Scheduler) add(ctx context.Context, pod *corev1.Pod) error { } nodeClaim := NewNodeClaim(nodeClaimTemplate, s.topology, s.daemonOverhead[nodeClaimTemplate], instanceTypes) if err := nodeClaim.Add(pod); err != nil { + nodeClaim.Destroy() // Ensure we cleanup any changes that we made while mocking out a NodeClaim errs = multierr.Append(errs, fmt.Errorf("incompatible with nodepool %q, daemonset overhead=%s, %w", nodeClaimTemplate.NodePoolName, resources.String(s.daemonOverhead[nodeClaimTemplate]), diff --git a/pkg/controllers/provisioning/scheduling/topology.go b/pkg/controllers/provisioning/scheduling/topology.go index e110e32cb7..436fd89fc6 100644 --- a/pkg/controllers/provisioning/scheduling/topology.go +++ b/pkg/controllers/provisioning/scheduling/topology.go @@ -201,6 +201,20 @@ func (t *Topology) Register(topologyKey string, domain string) { } } +// Unregister is used to unregister a domain as available across topologies for the given topology key. +func (t *Topology) Unregister(topologyKey string, domain string) { + for _, topology := range t.topologies { + if topology.Key == topologyKey { + topology.Unregister(domain) + } + } + for _, topology := range t.inverseTopologies { + if topology.Key == topologyKey { + topology.Unregister(domain) + } + } +} + // updateInverseAffinities is used to identify pods with anti-affinity terms so we can track those topologies. We // have to look at every pod in the cluster as there is no way to query for a pod with anti-affinity terms. func (t *Topology) updateInverseAffinities(ctx context.Context) error { diff --git a/pkg/controllers/provisioning/scheduling/topologygroup.go b/pkg/controllers/provisioning/scheduling/topologygroup.go index 1249636ad8..551e3de7b5 100644 --- a/pkg/controllers/provisioning/scheduling/topologygroup.go +++ b/pkg/controllers/provisioning/scheduling/topologygroup.go @@ -128,6 +128,14 @@ func (t *TopologyGroup) Register(domains ...string) { } } +// Unregister removes the topology group from being aware of the domain +func (t *TopologyGroup) Unregister(domains ...string) { + for _, domain := range domains { + delete(t.domains, domain) + t.emptyDomains.Delete(domain) + } +} + func (t *TopologyGroup) AddOwner(key types.UID) { t.owners[key] = struct{}{} }