mirror of
https://github.com/kubernetes-sigs/node-feature-discovery.git
synced 2025-03-05 16:27:05 +00:00
nfd-master: process labeling rules from CRs
Enable Custom Resource based label creation in nfd-master. This extends the previously implemented controller stub for watching NodeFeatureRule objects. NFD-master watches NodeFeatureRule objects in the cluster and processes the rules on every incoming labeling request from workers. The functionality relies on the "raw features" (identical to how nfd-worker handles custom rules) submitted by nfd-worker, making it independent of the label source configuration of the worker. This means that the labeling functions as expected even if all sources in the worker are disabled. NOTE: nfd-master is stateless and re-labeling only happens on the reception of SetLabelsRequest from the worker – i.e. on intervals specified by the core.sleepInterval configuration option (or -sleep-interval cmdline flag) of each nfd-worker instance. This means that modification/creation of NodeFeatureRule objects does not automatically update the node labels. Instead, the changes only come visible when workers send their labeling requests.
This commit is contained in:
parent
99d3251c42
commit
33fdf75190
1 changed files with 52 additions and 3 deletions
|
@ -39,6 +39,7 @@ import (
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
@ -179,6 +180,7 @@ func (m *nfdMaster) Run() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
klog.Info("starting nfd LabelRule controller")
|
||||||
m.nfdController = newNfdController(kubeconfig)
|
m.nfdController = newNfdController(kubeconfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,15 +410,25 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se
|
||||||
return &pb.SetLabelsReply{}, err
|
return &pb.SetLabelsReply{}, err
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case klog.V(2).Enabled():
|
case klog.V(4).Enabled():
|
||||||
utils.KlogDump(2, "REQUEST", " ", r)
|
utils.KlogDump(3, "REQUEST", " ", r)
|
||||||
case klog.V(1).Enabled():
|
case klog.V(1).Enabled():
|
||||||
klog.Infof("REQUEST Node: %q NFD-version: %q Labels: %s", r.NodeName, r.NfdVersion, r.Labels)
|
klog.Infof("REQUEST Node: %q NFD-version: %q Labels: %s", r.NodeName, r.NfdVersion, r.Labels)
|
||||||
default:
|
default:
|
||||||
klog.Infof("received labeling request for node %q", r.NodeName)
|
klog.Infof("received labeling request for node %q", r.NodeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
labels, extendedResources := filterFeatureLabels(r.Labels, m.args.ExtraLabelNs, m.args.LabelWhiteList.Regexp, m.args.ResourceLabels)
|
// Mix in CR-originated labels
|
||||||
|
rawLabels := make(map[string]string)
|
||||||
|
if r.Labels != nil {
|
||||||
|
// NOTE: we effectively mangle the request struct by not creating a deep copy of the map
|
||||||
|
rawLabels = r.Labels
|
||||||
|
}
|
||||||
|
for k, v := range m.crLabels(r) {
|
||||||
|
rawLabels[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
labels, extendedResources := filterFeatureLabels(rawLabels, m.args.ExtraLabelNs, m.args.LabelWhiteList.Regexp, m.args.ResourceLabels)
|
||||||
|
|
||||||
if !m.args.NoPublish {
|
if !m.args.NoPublish {
|
||||||
// Advertise NFD worker version as an annotation
|
// Advertise NFD worker version as an annotation
|
||||||
|
@ -480,6 +492,43 @@ func (m *nfdMaster) UpdateNodeTopology(c context.Context, r *topologypb.NodeTopo
|
||||||
return &topologypb.NodeTopologyResponse{}, nil
|
return &topologypb.NodeTopologyResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *nfdMaster) crLabels(r *pb.SetLabelsRequest) map[string]string {
|
||||||
|
if m.nfdController == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l := make(map[string]string)
|
||||||
|
ruleSpecs, err := m.nfdController.lister.List(labels.Everything())
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("failed to list LabelRule resources: %w", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process all rule CRs
|
||||||
|
for _, spec := range ruleSpecs {
|
||||||
|
switch {
|
||||||
|
case klog.V(3).Enabled():
|
||||||
|
h := fmt.Sprintf("executing LabelRule \"%s/%s\":", spec.ObjectMeta.Namespace, spec.ObjectMeta.Name)
|
||||||
|
utils.KlogDump(3, h, " ", spec.Spec)
|
||||||
|
case klog.V(1).Enabled():
|
||||||
|
klog.Infof("executing LabelRule \"%s/%s\"", spec.ObjectMeta.Namespace, spec.ObjectMeta.Name)
|
||||||
|
}
|
||||||
|
for _, rule := range spec.Spec.Rules {
|
||||||
|
ruleOut, err := rule.Execute(r.Features)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("failed to process Rule %q: %w", rule.Name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for k, v := range ruleOut {
|
||||||
|
l[k] = v
|
||||||
|
}
|
||||||
|
utils.KlogDump(1, "", " ", ruleOut)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
// updateNodeFeatures ensures the Kubernetes node object is up to date,
|
// updateNodeFeatures ensures the Kubernetes node object is up to date,
|
||||||
// creating new labels and extended resources where necessary and removing
|
// creating new labels and extended resources where necessary and removing
|
||||||
// outdated ones. Also updates the corresponding annotations.
|
// outdated ones. Also updates the corresponding annotations.
|
||||||
|
|
Loading…
Add table
Reference in a new issue