github.com/kubewharf/katalyst-core@v0.5.3/cmd/katalyst-controller/app/options/controllerbase.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package options
    18  
    19  import (
    20  	"fmt"
    21  	"time"
    22  
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/apimachinery/pkg/labels"
    25  	"k8s.io/apimachinery/pkg/util/sets"
    26  	cliflag "k8s.io/component-base/cli/flag"
    27  	election "k8s.io/component-base/config"
    28  
    29  	controllerconfig "github.com/kubewharf/katalyst-core/pkg/config/controller"
    30  	"github.com/kubewharf/katalyst-core/pkg/util"
    31  )
    32  
    33  // WorkloadProfilingOptions holds the configurations for spd lifecycle
    34  type WorkloadProfilingOptions struct {
    35  	ExplicitChecking bool
    36  
    37  	// the requirements below work as 'and' rather than 'or'
    38  	AnnoSelector   string
    39  	LabelSelector  string
    40  	Namespaces     []string
    41  	AntiNamespaces []string
    42  }
    43  
    44  func (w WorkloadProfilingOptions) getWorkloadEnableFunc() (util.WorkloadSPDEnabledFunc, bool, error) {
    45  	if !w.ExplicitChecking {
    46  		return nil, false, nil
    47  	}
    48  
    49  	var rules []util.WorkloadSPDEnabledFunc
    50  
    51  	if len(w.Namespaces) > 0 {
    52  		ns := sets.NewString(w.Namespaces...)
    53  		rules = append(rules, func(workload metav1.Object) bool {
    54  			return ns.Has(workload.GetNamespace())
    55  		})
    56  
    57  	}
    58  
    59  	if len(w.AntiNamespaces) > 0 {
    60  		ns := sets.NewString(w.AntiNamespaces...)
    61  		rules = append(rules, func(workload metav1.Object) bool {
    62  			return !ns.Has(workload.GetNamespace())
    63  		})
    64  
    65  	}
    66  
    67  	if w.AnnoSelector != "" {
    68  		if selector, err := labels.Parse(w.AnnoSelector); err != nil {
    69  			return nil, false, err
    70  		} else {
    71  			rules = append(rules, func(workload metav1.Object) bool {
    72  				return selector.Matches(labels.Set(workload.GetAnnotations()))
    73  			})
    74  		}
    75  	}
    76  
    77  	if w.LabelSelector != "" {
    78  		if selector, err := labels.Parse(w.LabelSelector); err != nil {
    79  			return nil, false, err
    80  		} else {
    81  			rules = append(rules, func(workload metav1.Object) bool {
    82  				return selector.Matches(labels.Set(workload.GetLabels()))
    83  			})
    84  		}
    85  	}
    86  
    87  	return func(workload metav1.Object) bool {
    88  		for _, f := range rules {
    89  			if !f(workload) {
    90  				return false
    91  			}
    92  		}
    93  		return true
    94  	}, true, nil
    95  }
    96  
    97  // GenericControllerOptions holds the configurations for controller based configurations.
    98  type GenericControllerOptions struct {
    99  	Controllers        []string
   100  	LabelSelector      string
   101  	DynamicGVResources []string
   102  
   103  	election.LeaderElectionConfiguration
   104  
   105  	WorkloadProfilingOptions
   106  }
   107  
   108  // NewGenericControllerOptions creates a new Options with a default config.
   109  func NewGenericControllerOptions() *GenericControllerOptions {
   110  	return &GenericControllerOptions{
   111  		LeaderElectionConfiguration: election.LeaderElectionConfiguration{
   112  			LeaderElect:       true,
   113  			LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   114  			RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   115  			RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   116  			ResourceLock:      "leases",
   117  			ResourceName:      "katalyst-controller",
   118  			ResourceNamespace: "kube-system",
   119  		},
   120  		WorkloadProfilingOptions: WorkloadProfilingOptions{
   121  			ExplicitChecking: false,
   122  		},
   123  	}
   124  }
   125  
   126  // AddFlags adds flags  to the specified FlagSet.
   127  func (o *GenericControllerOptions) AddFlags(fss *cliflag.NamedFlagSets) {
   128  	fs := fss.FlagSet("generic-controller")
   129  
   130  	fs.BoolVar(&o.LeaderElect, "leader-elect", o.LeaderElect, ""+
   131  		"Start a leader election client and gain leadership before "+
   132  		"executing the main loop. Enable this when running replicated "+
   133  		"components for high availability.")
   134  	fs.DurationVar(&o.LeaseDuration.Duration, "leader-elect-lease-duration", o.LeaseDuration.Duration, ""+
   135  		"The duration that non-leader candidates will wait after observing a leadership "+
   136  		"renewal until attempting to acquire leadership of a led but unrenewed leader "+
   137  		"slot. This is effectively the maximum duration that a leader can be stopped "+
   138  		"before it is replaced by another candidate. This is only applicable if leader "+
   139  		"election is enabled.")
   140  	fs.DurationVar(&o.RenewDeadline.Duration, "leader-elect-renew-deadline", o.RenewDeadline.Duration, ""+
   141  		"The interval between attempts by the acting master to renew a leadership slot "+
   142  		"before it stops leading. This must be less than or equal to the lease duration. "+
   143  		"This is only applicable if leader election is enabled.")
   144  	fs.DurationVar(&o.RetryPeriod.Duration, "leader-elect-retry-period", o.RetryPeriod.Duration, ""+
   145  		"The duration the clients should wait between attempting acquisition and renewal "+
   146  		"of a leadership. This is only applicable if leader election is enabled.")
   147  	fs.StringVar(&o.ResourceLock, "leader-elect-resource-lock", o.ResourceLock, ""+
   148  		"The type of resource object that is used for locking during "+
   149  		"leader election. Supported options are `endpoints` (default) and `configmaps`.")
   150  	fs.StringVar(&o.ResourceName, "leader-elect-resource-name", o.ResourceName, ""+
   151  		"The name of resource object that is used for locking during leader election.")
   152  	fs.StringVar(&o.ResourceNamespace, "leader-elect-resource-namespace", o.ResourceNamespace, ""+
   153  		"The namespace of resource object that is used for locking during leader election. ")
   154  
   155  	fs.StringSliceVar(&o.Controllers, "controllers", o.Controllers, fmt.Sprintf(""+
   156  		"A list of controllers to enable. '*' enables all on-by-default controllers, 'foo' enables the controller "+
   157  		"named 'foo', '-foo' disables the controller named 'foo'"))
   158  
   159  	fs.StringVar(&o.LabelSelector, "label-selector", o.LabelSelector, fmt.Sprintf(""+
   160  		"A selector to restrict the list of returned objects by their labels. this selector is used in informer factory."))
   161  
   162  	fs.StringSliceVar(&o.DynamicGVResources, "dynamic-resources", o.DynamicGVResources, fmt.Sprintf(""+
   163  		"A list of resources to be list and watched. "+
   164  		"DynamicGVResources should be in the format of `resource.version.group.com` like 'deployments.v1.apps'."))
   165  
   166  	fs.BoolVar(&o.ExplicitChecking, "spd-workload-explicit-checking", o.ExplicitChecking, fmt.Sprintf(""+
   167  		"If set as true, we will use default judgements to check whether workload need auto-profiing; "+
   168  		"otherwise we will switch to check by the given checking requirements."))
   169  	fs.StringSliceVar(&o.Namespaces, "spd-workload-namespaces", o.Namespaces, fmt.Sprintf(""+
   170  		"Workload should be in the given namespaces if it wants service-profiling"))
   171  	fs.StringSliceVar(&o.AntiNamespaces, "spd-workload-anti-namespaces", o.AntiNamespaces, fmt.Sprintf(""+
   172  		"Workload should [not] be in the given namespaces if it wants service-profiling"))
   173  	fs.StringVar(&o.AnnoSelector, "spd-workload-anno-selector", o.AnnoSelector, fmt.Sprintf(""+
   174  		"Workload should match with the selector for annotations if it wants service-profiling"))
   175  	fs.StringVar(&o.LabelSelector, "spd-workload-label-selector", o.LabelSelector, fmt.Sprintf(""+
   176  		"Workload should match with the selector for labels if it wants service-profiling"))
   177  }
   178  
   179  // ApplyTo fills up config with options
   180  func (o *GenericControllerOptions) ApplyTo(c *controllerconfig.GenericControllerConfiguration) error {
   181  	c.LeaderElection.LeaderElect = o.LeaderElect
   182  	c.LeaderElection.LeaseDuration = o.LeaseDuration
   183  	c.LeaderElection.RenewDeadline = o.RenewDeadline
   184  	c.LeaderElection.RetryPeriod = o.RetryPeriod
   185  	c.LeaderElection.ResourceLock = o.ResourceLock
   186  	c.LeaderElection.ResourceName = o.ResourceName
   187  	c.LeaderElection.ResourceNamespace = o.ResourceNamespace
   188  
   189  	c.Controllers = o.Controllers
   190  	c.LabelSelector = o.LabelSelector
   191  	c.DynamicGVResources = o.DynamicGVResources
   192  
   193  	if f, ok, err := o.getWorkloadEnableFunc(); err != nil {
   194  		return fmt.Errorf("failed to construct workload-enable func: %v", err)
   195  	} else if ok {
   196  		util.SetWorkloadEnableFunc(f)
   197  	}
   198  
   199  	return nil
   200  }
   201  
   202  func (o *GenericControllerOptions) Config() (*controllerconfig.GenericControllerConfiguration, error) {
   203  	c := controllerconfig.NewGenericControllerConfiguration()
   204  	if err := o.ApplyTo(c); err != nil {
   205  		return nil, err
   206  	}
   207  	return c, nil
   208  }