Skip to content

Commit

Permalink
Implements NodeInfoProcessor Builder function
Browse files Browse the repository at this point in the history
The `nodeinfos.builder` package contains:
* the `Register()` function use to register `nodeinfos.NodeInfoProcessor`
  implementation.
* the `Build()` function use to instanciate the requested
  `nodeinfos.NodeInfoProcessor` implementation from `AutoscalerOptions`.
  • Loading branch information
clamoriniere committed Apr 9, 2021
1 parent 4ad17cf commit 228614f
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 12 deletions.
4 changes: 2 additions & 2 deletions cluster-autoscaler/config/autoscaling_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,6 @@ type AutoscalingOptions struct {
DaemonSetEvictionForEmptyNodes bool
// User agent to use for HTTP calls.
UserAgent string
// ExtraDaemonsetsFromPodTemplates enable ExtraDaemonset Processor to consider specific PodTemplate as DaemonSet.
ExtraDaemonsetsFromPodTemplates bool
// NodeInfoProcessorName sets the type of the NodeInfo processor. Allowed value: podtemplates.
NodeInfoProcessorName string
}
18 changes: 12 additions & 6 deletions cluster-autoscaler/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ import (
"k8s.io/autoscaler/cluster-autoscaler/metrics"
ca_processors "k8s.io/autoscaler/cluster-autoscaler/processors"
"k8s.io/autoscaler/cluster-autoscaler/processors/nodegroupset"
"k8s.io/autoscaler/cluster-autoscaler/processors/nodeinfos/podtemplates"
nodeinfobuilder "k8s.io/autoscaler/cluster-autoscaler/processors/nodeinfos/builder"
_ "k8s.io/autoscaler/cluster-autoscaler/processors/nodeinfos/podtemplates"
"k8s.io/autoscaler/cluster-autoscaler/simulator"
"k8s.io/autoscaler/cluster-autoscaler/utils/errors"
kube_util "k8s.io/autoscaler/cluster-autoscaler/utils/kubernetes"
Expand Down Expand Up @@ -180,7 +181,7 @@ var (
cordonNodeBeforeTerminate = flag.Bool("cordon-node-before-terminating", false, "Should CA cordon nodes before terminating during downscale process")
daemonSetEvictionForEmptyNodes = flag.Bool("daemonset-eviction-for-empty-nodes", false, "DaemonSet pods will be gracefully terminated from empty nodes")
userAgent = flag.String("user-agent", "cluster-autoscaler", "User agent used for HTTP calls.")
extraDaemonsetsFromPodTemplates = flag.Bool("extra-daemonsets-from-pod-templates", false, "Enable ExtraDaemonset Processor to consider specific PodTemplate as DaemonSet")
nodeInfoProcessorName = flag.String("node-info-processor", "", "node-info processor type. Available values: ["+strings.Join(nodeinfobuilder.GetAvailableNodeInfoProcessors(), ",")+"]")
)

func createAutoscalingOptions() config.AutoscalingOptions {
Expand Down Expand Up @@ -256,7 +257,7 @@ func createAutoscalingOptions() config.AutoscalingOptions {
ClusterAPICloudConfigAuthoritative: *clusterAPICloudConfigAuthoritative,
CordonNodeBeforeTerminate: *cordonNodeBeforeTerminate,
DaemonSetEvictionForEmptyNodes: *daemonSetEvictionForEmptyNodes,
ExtraDaemonsetsFromPodTemplates: *extraDaemonsetsFromPodTemplates,
NodeInfoProcessorName: *nodeInfoProcessorName,
}
}

Expand Down Expand Up @@ -331,9 +332,14 @@ func buildAutoscaler() (core.Autoscaler, error) {
Comparator: nodeInfoComparatorBuilder(autoscalingOptions.BalancingExtraIgnoredLabels),
}

// Enable PodTemplateListProcessor if needed
if autoscalingOptions.ExtraDaemonsetsFromPodTemplates {
opts.Processors.NodeInfoProcessor = podtemplates.NewNodeInfoWithPodTemplateProcessor(kubeClient)
// Enable a NodeInfoProcessorName if requested.
if autoscalingOptions.NodeInfoProcessorName != "" {
processor, err := nodeinfobuilder.Build(&opts)
if err != nil {
klog.Errorf("Unable to instantiate the requested NodeInfoProcessor, err: %w", err)
} else {
opts.Processors.NodeInfoProcessor = processor
}
}

// These metrics should be published only once.
Expand Down
51 changes: 51 additions & 0 deletions cluster-autoscaler/processors/nodeinfos/builder/build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package builder

import (
"fmt"

"k8s.io/autoscaler/cluster-autoscaler/core"
"k8s.io/autoscaler/cluster-autoscaler/processors/nodeinfos"
)

var availableNodeInfoProcessors = map[string]BuilderFunc{}

// Build returns a new nodeinfos.NodeInfoProcessor instance with the requested implementation
func Build(opts *core.AutoscalerOptions) (nodeinfos.NodeInfoProcessor, error) {
if buildFunc, found := availableNodeInfoProcessors[opts.AutoscalingOptions.NodeInfoProcessorName]; found {
return buildFunc(opts), nil
}
return nodeinfos.NewDefaultNodeInfoProcessor(), fmt.Errorf("NodeInfoProcessor %s not found", opts.AutoscalingOptions.NodeInfoProcessorName)
}

// BuilderFunc corresponds to nodeinfos.NodeInfoProcessor
type BuilderFunc func(opts *core.AutoscalerOptions) nodeinfos.NodeInfoProcessor

// Register used to register a nodeinfos.NodeInfoProcessor implementation.
func Register(name string, builderFunc BuilderFunc) {
availableNodeInfoProcessors[name] = builderFunc
}

// GetAvailableNodeInfoProcessors returns the list of registered NodeInfoProcessor implementation.
func GetAvailableNodeInfoProcessors() []string {
output := make([]string, 0, len(availableNodeInfoProcessors))
for key := range availableNodeInfoProcessors {
output = append(output, key)
}
return output
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ import (
"k8s.io/client-go/tools/cache"

ca_context "k8s.io/autoscaler/cluster-autoscaler/context"
"k8s.io/autoscaler/cluster-autoscaler/core"
"k8s.io/autoscaler/cluster-autoscaler/processors/nodeinfos"
"k8s.io/autoscaler/cluster-autoscaler/processors/nodeinfos/builder"
"k8s.io/autoscaler/cluster-autoscaler/simulator"
"k8s.io/autoscaler/cluster-autoscaler/utils/errors"
schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework"
Expand All @@ -44,16 +46,22 @@ const (
PodTemplateDaemonSetLabelKey = "cluster-autoscaler.kubernetes.io/daemonset-pod"
// PodTemplateDaemonSetLabelValueTrue use as PodTemplateDaemonSetLabelKey label value.
PodTemplateDaemonSetLabelValueTrue = "true"
// processorsName use to identify the PodTemplate NodeInfoProcessor
processorName = "podtemplates"
)

func init() {
builder.Register(processorName, NewNodeInfoWithPodTemplateProcessor)
}

// NewNodeInfoWithPodTemplateProcessor returns a default instance of NodeInfoProcessor.
func NewNodeInfoWithPodTemplateProcessor(kubeClient client.Interface) nodeinfos.NodeInfoProcessor {
func NewNodeInfoWithPodTemplateProcessor(opts *core.AutoscalerOptions) nodeinfos.NodeInfoProcessor {
internalContext, cancelFunc := context.WithCancel(context.Background())

return &nodeInfoWithPodTemplateProcessor{
ctx: internalContext,
cancelFunc: cancelFunc,
podTemplateLister: newPodTemplateLister(kubeClient, internalContext.Done()),
podTemplateLister: newPodTemplateLister(opts.KubeClient, internalContext.Done()),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ import (
schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework"

ca_context "k8s.io/autoscaler/cluster-autoscaler/context"
"k8s.io/autoscaler/cluster-autoscaler/core"
"k8s.io/autoscaler/cluster-autoscaler/simulator"
)

func TestNewNodeInfoWithPodTemplateProcessor(t *testing.T) {
client := fake.NewSimpleClientset()
processor := NewNodeInfoWithPodTemplateProcessor(client)
opts := newtTestAutoscalerOptions()
processor := NewNodeInfoWithPodTemplateProcessor(opts)
defer processor.CleanUp()
}

Expand Down Expand Up @@ -204,6 +205,12 @@ func Test_nodeInfoWithPodTemplateProcessor_Process(t *testing.T) {
}
}

func newtTestAutoscalerOptions() *core.AutoscalerOptions {
return &core.AutoscalerOptions{
KubeClient: fake.NewSimpleClientset(),
}
}

func newTestDaemonSetLister(pts []*apiv1.PodTemplate) (v1lister.PodTemplateLister, error) {
store := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
for _, pt := range pts {
Expand Down

0 comments on commit 228614f

Please sign in to comment.