From 1be5ad3975737612b878e13f0fde2e496ee37506 Mon Sep 17 00:00:00 2001 From: Antti Kervinen Date: Mon, 30 Sep 2024 12:43:19 +0300 Subject: [PATCH] balloons: add ignore container option to policy configuration Signed-off-by: Antti Kervinen --- .../balloons/policy/balloons-policy.go | 11 +++++ .../bases/config.nri_balloonspolicies.yaml | 48 +++++++++++++++++++ .../crds/config.nri_balloonspolicies.yaml | 48 +++++++++++++++++++ .../v1alpha1/resmgr/policy/balloons/config.go | 27 +++++++++++ .../policy/balloons/zz_generated.deepcopy.go | 27 +++++++++++ 5 files changed, 161 insertions(+) diff --git a/cmd/plugins/balloons/policy/balloons-policy.go b/cmd/plugins/balloons/policy/balloons-policy.go index a5e4415f3..a83ffcc02 100644 --- a/cmd/plugins/balloons/policy/balloons-policy.go +++ b/cmd/plugins/balloons/policy/balloons-policy.go @@ -227,6 +227,17 @@ func (p *balloons) AllocateResources(c cache.Container) error { log.Infof("not handling resources of container %s, preserving CPUs %q and memory %q", c.PrettyName(), c.GetCpusetCpus(), c.GetCpusetMems()) return nil } + + if p.bpoptions.Ignore != nil { + rule, err := p.bpoptions.Ignore.MatchContainer(c) + if err != nil { + log.Errorf("error in matching container %s to ignore conditions: %s", c, err) + } else if rule != "" { + log.Debugf("ignore container %s due to matching %s", c, rule) + return nil + } + } + log.Debug("allocating resources for container %s (request %d mCPU, limit %d mCPU)...", c.PrettyName(), p.containerRequestedMilliCpus(c.GetID()), diff --git a/config/crd/bases/config.nri_balloonspolicies.yaml b/config/crd/bases/config.nri_balloonspolicies.yaml index 16f1d3872..ac130a88d 100644 --- a/config/crd/bases/config.nri_balloonspolicies.yaml +++ b/config/crd/bases/config.nri_balloonspolicies.yaml @@ -295,6 +295,54 @@ spec: IdleCpuClass controls how unusded CPUs outside any a balloons are (re)configured. type: string + ignore: + description: |- + Ignore specifies containers that should be completely + ignored by the policy. + properties: + matchExpressions: + description: MatchExpressions specifies one or more expressions. + items: + description: |- + Expression describes some runtime-evaluated condition. An expression + consist of a key, an operator and a set of values. An expressions is + evaluated against an object which implements the Evaluable interface. + Evaluating an expression consists of looking up the value for the key + in the object, then using the operator to check it agains the values + of the expression. The result is a single boolean value. An object is + said to satisfy the evaluated expression if this value is true. An + expression can contain 0, 1 or more values depending on the operator. + properties: + key: + description: Key is the expression key. + type: string + operator: + description: Op is the expression operator. + enum: + - Equals + - NotEqual + - In + - NotIn + - Exists + - NotExist + - AlwaysTrue + - Matches + - MatchesNot + - MatchesAny + - MatchesNone + type: string + values: + description: Values contains the values the key value is + evaluated against. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object instrumentation: description: Config provides runtime configuration for instrumentation. properties: diff --git a/deployment/helm/balloons/crds/config.nri_balloonspolicies.yaml b/deployment/helm/balloons/crds/config.nri_balloonspolicies.yaml index 16f1d3872..ac130a88d 100644 --- a/deployment/helm/balloons/crds/config.nri_balloonspolicies.yaml +++ b/deployment/helm/balloons/crds/config.nri_balloonspolicies.yaml @@ -295,6 +295,54 @@ spec: IdleCpuClass controls how unusded CPUs outside any a balloons are (re)configured. type: string + ignore: + description: |- + Ignore specifies containers that should be completely + ignored by the policy. + properties: + matchExpressions: + description: MatchExpressions specifies one or more expressions. + items: + description: |- + Expression describes some runtime-evaluated condition. An expression + consist of a key, an operator and a set of values. An expressions is + evaluated against an object which implements the Evaluable interface. + Evaluating an expression consists of looking up the value for the key + in the object, then using the operator to check it agains the values + of the expression. The result is a single boolean value. An object is + said to satisfy the evaluated expression if this value is true. An + expression can contain 0, 1 or more values depending on the operator. + properties: + key: + description: Key is the expression key. + type: string + operator: + description: Op is the expression operator. + enum: + - Equals + - NotEqual + - In + - NotIn + - Exists + - NotExist + - AlwaysTrue + - Matches + - MatchesNot + - MatchesAny + - MatchesNone + type: string + values: + description: Values contains the values the key value is + evaluated against. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object instrumentation: description: Config provides runtime configuration for instrumentation. properties: diff --git a/pkg/apis/config/v1alpha1/resmgr/policy/balloons/config.go b/pkg/apis/config/v1alpha1/resmgr/policy/balloons/config.go index 04b582e63..329b7710c 100644 --- a/pkg/apis/config/v1alpha1/resmgr/policy/balloons/config.go +++ b/pkg/apis/config/v1alpha1/resmgr/policy/balloons/config.go @@ -21,6 +21,7 @@ import ( policy "github.com/containers/nri-plugins/pkg/apis/config/v1alpha1/resmgr/policy" resmgr "github.com/containers/nri-plugins/pkg/apis/resmgr/v1alpha1" "github.com/containers/nri-plugins/pkg/cpuallocator" + "github.com/containers/nri-plugins/pkg/resmgr/cache" ) type ( @@ -78,6 +79,9 @@ type Config struct { // Reserved (CPU) resources for kube-system namespace. // +kubebuilder:validation:Required ReservedResources Constraints `json:"reservedResources"` + // Ignore specifies containers that should be completely + // ignored by the policy. + Ignore *ContainerMatchConfig `json:"ignore,omitempty"` } type CPUTopologyLevel string @@ -252,8 +256,31 @@ func (p CPUPriority) Value() cpuallocator.CPUPriority { return cpuallocator.PriorityNone } +// ContainerMatchConfig contains container matching configurations. +// +k8s:deepcopy-gen=true +type ContainerMatchConfig struct { + // MatchExpressions specifies one or more expressions. + MatchExpressions []resmgr.Expression `json:"matchExpressions,omitempty"` +} + +func (cmc *ContainerMatchConfig) MatchContainer(c cache.Container) (string, error) { + for _, expr := range cmc.MatchExpressions { + if expr.Evaluate(c) { + return expr.String(), nil + } + } + return "", nil +} + func (c *Config) Validate() error { errs := []error{} + if c.Ignore != nil { + for _, expr := range c.Ignore.MatchExpressions { + if err := expr.Validate(); err != nil { + errs = append(errs, err) + } + } + } for _, blnDef := range c.BalloonDefs { for _, expr := range blnDef.MatchExpressions { if err := expr.Validate(); err != nil { diff --git a/pkg/apis/config/v1alpha1/resmgr/policy/balloons/zz_generated.deepcopy.go b/pkg/apis/config/v1alpha1/resmgr/policy/balloons/zz_generated.deepcopy.go index ed78429e7..ee03e2d1a 100644 --- a/pkg/apis/config/v1alpha1/resmgr/policy/balloons/zz_generated.deepcopy.go +++ b/pkg/apis/config/v1alpha1/resmgr/policy/balloons/zz_generated.deepcopy.go @@ -118,6 +118,11 @@ func (in *Config) DeepCopyInto(out *Config) { (*out)[key] = val } } + if in.Ignore != nil { + in, out := &in.Ignore, &out.Ignore + *out = new(ContainerMatchConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. @@ -129,3 +134,25 @@ func (in *Config) DeepCopy() *Config { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ContainerMatchConfig) DeepCopyInto(out *ContainerMatchConfig) { + *out = *in + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]v1alpha1.Expression, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerMatchConfig. +func (in *ContainerMatchConfig) DeepCopy() *ContainerMatchConfig { + if in == nil { + return nil + } + out := new(ContainerMatchConfig) + in.DeepCopyInto(out) + return out +}