Skip to content

Commit

Permalink
nfd-master: process labeling rules from CRs
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
marquiz committed Nov 18, 2021
1 parent 93223b1 commit 0df5b14
Showing 1 changed file with 52 additions and 3 deletions.
55 changes: 52 additions & 3 deletions pkg/nfd-master/nfd-master.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -180,6 +181,7 @@ func (m *nfdMaster) Run() error {
if err != nil {
return err
}
klog.Info("starting nfd LabelRule controller")
m.nfdController = newNfdController(kubeconfig)
}

Expand Down Expand Up @@ -409,15 +411,25 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se
return &pb.SetLabelsReply{}, err
}
switch {
case klog.V(2).Enabled():
utils.KlogDump(2, "REQUEST", " ", r)
case klog.V(4).Enabled():
utils.KlogDump(3, "REQUEST", " ", r)
case klog.V(1).Enabled():
klog.Infof("REQUEST Node: %q NFD-version: %q Labels: %s", r.NodeName, r.NfdVersion, r.Labels)
default:
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 {
// Advertise NFD worker version as an annotation
Expand Down Expand Up @@ -481,6 +493,43 @@ func (m *nfdMaster) UpdateNodeTopology(c context.Context, r *topologypb.NodeTopo
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,
// creating new labels and extended resources where necessary and removing
// outdated ones. Also updates the corresponding annotations.
Expand Down

0 comments on commit 0df5b14

Please sign in to comment.