Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for node pool placement group config #6999

Merged
merged 5 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions cluster-autoscaler/cloudprovider/hetzner/hetzner_cloud_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package hetzner

import (
"context"
"fmt"
"regexp"
"strconv"
Expand Down Expand Up @@ -179,6 +180,31 @@ func (d *HetznerCloudProvider) Refresh() error {
return nil
}

// Check if any defined placement groups could potentially have more than the maximum allowed number of nodes
func getLargePlacementGroups(nodeGroups map[string]*hetznerNodeGroup, threshold int) []int64 {
placementGroupTotals := make(map[int64]int)

// Calculate totals for each placement group
for _, nodeGroup := range nodeGroups {
if nodeGroup.placementGroup == nil || nodeGroup.placementGroup.ID == 0 {
continue
}

placementGroupID := nodeGroup.placementGroup.ID
placementGroupTotals[placementGroupID] += nodeGroup.maxSize
}

// Collect placement groups with total maxSize > threshold
var largePlacementGroupIDs []int64
for id, totalMaxSize := range placementGroupTotals {
if totalMaxSize > threshold {
largePlacementGroupIDs = append(largePlacementGroupIDs, id)
}
}

return largePlacementGroupIDs
}

// BuildHetzner builds the Hetzner cloud provider.
func BuildHetzner(_ config.AutoscalingOptions, do cloudprovider.NodeGroupDiscoveryOptions, rl *cloudprovider.ResourceLimiter) cloudprovider.CloudProvider {
manager, err := newManager()
Expand Down Expand Up @@ -226,6 +252,57 @@ func BuildHetzner(_ config.AutoscalingOptions, do cloudprovider.NodeGroupDiscove
targetSize: len(servers),
clusterUpdateMutex: &clusterUpdateLock,
}

// If a placement group was specified, check with the API to see if it exists
if manager.clusterConfig.IsUsingNewFormat {

placementGroupRef := manager.clusterConfig.NodeConfigs[spec.name].PlacementGroup

if placementGroupRef == "" {
continue
}

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

placementGroup, _, err := manager.client.PlacementGroup.Get(ctx, placementGroupRef)

// Check if an error occurred
if err != nil {
if err == context.DeadlineExceeded {
klog.Fatalf("Timed out checking if placement group `%s` exists.", placementGroupRef)
} else {
klog.Fatalf("Failed to verify if placement group `%s` exists error: %v", placementGroupRef, err)
}
}

// If the placement group exists, add it to the node group config
if placementGroup != nil {
manager.nodeGroups[spec.name].placementGroup = placementGroup
} else {
klog.Fatalf("The requested placement group `%s` does not appear to exist.", placementGroupRef)
}
}
}

// Get placement groups with total maxSize over the maximum allowed
maxPlacementGroupSize := 10

largePlacementGroups := getLargePlacementGroups(manager.nodeGroups, maxPlacementGroupSize)

// Fail if we have placement groups over the max size
if len(largePlacementGroups) > 0 {

// Gather placement group names
var placementGroupIDs string
for i, placementGroupID := range largePlacementGroups {
if i > 0 {
placementGroupIDs += ", "
}
placementGroupIDs += strconv.FormatInt(placementGroupID, 10)
}

klog.Fatalf("The following placement groups have a potential size over the allowed maximum of %d: %s.", maxPlacementGroupSize, placementGroupIDs)
}

return provider
Expand Down
7 changes: 4 additions & 3 deletions cluster-autoscaler/cloudprovider/hetzner/hetzner_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ type ImageList struct {

// NodeConfig holds the configuration for a single nodepool
type NodeConfig struct {
CloudInit string
Taints []apiv1.Taint
Labels map[string]string
CloudInit string
PlacementGroup string
Taints []apiv1.Taint
Labels map[string]string
}

// LegacyConfig holds the configuration in the legacy format
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type hetznerNodeGroup struct {
instanceType string

clusterUpdateMutex *sync.Mutex
placementGroup *hcloud.PlacementGroup
}

type hetznerNodeGroupSpec struct {
Expand Down Expand Up @@ -444,6 +445,7 @@ func createServer(n *hetznerNodeGroup) error {
EnableIPv4: n.manager.publicIPv4,
EnableIPv6: n.manager.publicIPv6,
},
PlacementGroup: n.placementGroup,
}
if n.manager.sshKey != nil {
opts.SSHKeys = []*hcloud.SSHKey{n.manager.sshKey}
Expand Down
Loading