1
0
Fork 0
mirror of https://github.com/kubernetes-sigs/node-feature-discovery.git synced 2024-12-14 11:57:51 +00:00

nfd-master: fix resync period config option

This PR fixes the resync-period configuration option of the nfd-master.
In fact, previously, changes were not reflected in the nfd-master at
runtime. e2e tests are also implemented to make sure that the fix is
already working as expected.

Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com>
This commit is contained in:
AhmedGrati 2023-04-25 03:03:02 +02:00
parent e4dfa2d916
commit 87c2d7e184
4 changed files with 112 additions and 21 deletions

View file

@ -68,7 +68,7 @@ func main() {
args.Overrides.EnableTaints = overrides.EnableTaints args.Overrides.EnableTaints = overrides.EnableTaints
case "no-publish": case "no-publish":
args.Overrides.NoPublish = overrides.NoPublish args.Overrides.NoPublish = overrides.NoPublish
case "-resync-period": case "resync-period":
args.Overrides.ResyncPeriod = overrides.ResyncPeriod args.Overrides.ResyncPeriod = overrides.ResyncPeriod
} }
}) })

View file

@ -31,6 +31,7 @@ import (
nfdscheme "sigs.k8s.io/node-feature-discovery/pkg/generated/clientset/versioned/scheme" nfdscheme "sigs.k8s.io/node-feature-discovery/pkg/generated/clientset/versioned/scheme"
nfdinformers "sigs.k8s.io/node-feature-discovery/pkg/generated/informers/externalversions" nfdinformers "sigs.k8s.io/node-feature-discovery/pkg/generated/informers/externalversions"
nfdlisters "sigs.k8s.io/node-feature-discovery/pkg/generated/listers/nfd/v1alpha1" nfdlisters "sigs.k8s.io/node-feature-discovery/pkg/generated/listers/nfd/v1alpha1"
"sigs.k8s.io/node-feature-discovery/pkg/utils"
) )
type nfdController struct { type nfdController struct {
@ -44,8 +45,8 @@ type nfdController struct {
} }
type nfdApiControllerOptions struct { type nfdApiControllerOptions struct {
disableNodeFeature bool DisableNodeFeature bool
resyncPeriod time.Duration ResyncPeriod time.Duration
} }
func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiControllerOptions) (*nfdController, error) { func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiControllerOptions) (*nfdController, error) {
@ -56,10 +57,12 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC
} }
nfdClient := nfdclientset.NewForConfigOrDie(config) nfdClient := nfdclientset.NewForConfigOrDie(config)
informerFactory := nfdinformers.NewSharedInformerFactory(nfdClient, nfdApiControllerOptions.resyncPeriod) utils.KlogDump(2, "NFD API controller options:", " ", nfdApiControllerOptions)
informerFactory := nfdinformers.NewSharedInformerFactory(nfdClient, nfdApiControllerOptions.ResyncPeriod)
// Add informer for NodeFeature objects // Add informer for NodeFeature objects
if !nfdApiControllerOptions.disableNodeFeature { if !nfdApiControllerOptions.DisableNodeFeature {
featureInformer := informerFactory.Nfd().V1alpha1().NodeFeatures() featureInformer := informerFactory.Nfd().V1alpha1().NodeFeatures()
if _, err := featureInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ if _, err := featureInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) { AddFunc: func(obj interface{}) {
@ -89,7 +92,7 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC
AddFunc: func(object interface{}) { AddFunc: func(object interface{}) {
key, _ := cache.MetaNamespaceKeyFunc(object) key, _ := cache.MetaNamespaceKeyFunc(object)
klog.V(2).Infof("NodeFeatureRule %v added", key) klog.V(2).Infof("NodeFeatureRule %v added", key)
if !nfdApiControllerOptions.disableNodeFeature { if !nfdApiControllerOptions.DisableNodeFeature {
c.updateAllNodes() c.updateAllNodes()
} }
// else: rules will be processed only when gRPC requests are received // else: rules will be processed only when gRPC requests are received
@ -97,7 +100,7 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC
UpdateFunc: func(oldObject, newObject interface{}) { UpdateFunc: func(oldObject, newObject interface{}) {
key, _ := cache.MetaNamespaceKeyFunc(newObject) key, _ := cache.MetaNamespaceKeyFunc(newObject)
klog.V(2).Infof("NodeFeatureRule %v updated", key) klog.V(2).Infof("NodeFeatureRule %v updated", key)
if !nfdApiControllerOptions.disableNodeFeature { if !nfdApiControllerOptions.DisableNodeFeature {
c.updateAllNodes() c.updateAllNodes()
} }
// else: rules will be processed only when gRPC requests are received // else: rules will be processed only when gRPC requests are received
@ -105,7 +108,7 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC
DeleteFunc: func(object interface{}) { DeleteFunc: func(object interface{}) {
key, _ := cache.MetaNamespaceKeyFunc(object) key, _ := cache.MetaNamespaceKeyFunc(object)
klog.V(2).Infof("NodeFeatureRule %v deleted", key) klog.V(2).Infof("NodeFeatureRule %v deleted", key)
if !nfdApiControllerOptions.disableNodeFeature { if !nfdApiControllerOptions.DisableNodeFeature {
c.updateAllNodes() c.updateAllNodes()
} }
// else: rules will be processed only when gRPC requests are received // else: rules will be processed only when gRPC requests are received
@ -119,7 +122,6 @@ func newNfdController(config *restclient.Config, nfdApiControllerOptions nfdApiC
informerFactory.Start(c.stopChan) informerFactory.Start(c.stopChan)
utilruntime.Must(nfdv1alpha1.AddToScheme(nfdscheme.Scheme)) utilruntime.Must(nfdv1alpha1.AddToScheme(nfdscheme.Scheme))
return c, nil return c, nil
} }

View file

@ -98,7 +98,6 @@ type Args struct {
Prune bool Prune bool
VerifyNodeName bool VerifyNodeName bool
Options string Options string
ResyncPeriod utils.DurationVal
Overrides ConfigOverrideArgs Overrides ConfigOverrideArgs
} }
@ -163,7 +162,6 @@ func NewNfdMaster(args *Args) (NfdMaster, error) {
if args.ConfigFile != "" { if args.ConfigFile != "" {
nfd.configFilePath = filepath.Clean(args.ConfigFile) nfd.configFilePath = filepath.Clean(args.ConfigFile)
} }
return nfd, nil return nfd, nil
} }
@ -199,18 +197,10 @@ func (m *nfdMaster) Run() error {
} }
if m.args.CrdController { if m.args.CrdController {
kubeconfig, err := m.getKubeconfig() err := m.startNfdApiController()
if err != nil { if err != nil {
return err return err
} }
klog.Info("starting nfd api controller")
m.nfdController, err = newNfdController(kubeconfig, nfdApiControllerOptions{
disableNodeFeature: !m.args.EnableNodeFeatureApi,
resyncPeriod: m.args.ResyncPeriod.Duration,
})
if err != nil {
return fmt.Errorf("failed to initialize CRD controller: %w", err)
}
} }
// Create watcher for config file // Create watcher for config file
@ -249,8 +239,20 @@ func (m *nfdMaster) Run() error {
if err := m.configure(m.configFilePath, m.args.Options); err != nil { if err := m.configure(m.configFilePath, m.args.Options); err != nil {
return err return err
} }
// Update all nodes when the configuration changes
// restart NFD API controller
if m.nfdController != nil { if m.nfdController != nil {
klog.Info("stopping the nfd api controller")
m.nfdController.stop()
}
if m.args.CrdController {
err := m.startNfdApiController()
if err != nil {
return nil
}
}
// Update all nodes when the configuration changes
if m.nfdController != nil && m.args.EnableNodeFeatureApi {
m.nfdController.updateAllNodesChan <- struct{}{} m.nfdController.updateAllNodesChan <- struct{}{}
} }
case <-m.stop: case <-m.stop:
@ -1152,6 +1154,7 @@ func (m *nfdMaster) configure(filepath string, overrides string) error {
} }
m.apihelper = apihelper.K8sHelpers{Kubeconfig: kubeconfig} m.apihelper = apihelper.K8sHelpers{Kubeconfig: kubeconfig}
} }
// Pre-process DenyLabelNS into 2 lists: one for normal ns, and the other for wildcard ns // Pre-process DenyLabelNS into 2 lists: one for normal ns, and the other for wildcard ns
normalDeniedNs, wildcardDeniedNs := preProcessDeniedNamespaces(c.DenyLabelNs) normalDeniedNs, wildcardDeniedNs := preProcessDeniedNamespaces(c.DenyLabelNs)
m.deniedNs.normal = normalDeniedNs m.deniedNs.normal = normalDeniedNs
@ -1219,3 +1222,19 @@ func (m *nfdMaster) instanceAnnotation(name string) string {
} }
return m.args.Instance + "." + name return m.args.Instance + "." + name
} }
func (m *nfdMaster) startNfdApiController() error {
kubeconfig, err := m.getKubeconfig()
if err != nil {
return err
}
klog.Info("starting nfd api controller")
m.nfdController, err = newNfdController(kubeconfig, nfdApiControllerOptions{
DisableNodeFeature: !m.args.EnableNodeFeatureApi,
ResyncPeriod: m.config.ResyncPeriod.Duration,
})
if err != nil {
return fmt.Errorf("failed to initialize CRD controller: %w", err)
}
return nil
}

View file

@ -18,6 +18,7 @@ package e2e
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"path/filepath" "path/filepath"
"strings" "strings"
@ -33,6 +34,7 @@ import (
extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
resourcev1 "k8s.io/apimachinery/pkg/api/resource" resourcev1 "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
taintutils "k8s.io/kubernetes/pkg/util/taints" taintutils "k8s.io/kubernetes/pkg/util/taints"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
@ -41,6 +43,7 @@ import (
e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
admissionapi "k8s.io/pod-security-admission/api" admissionapi "k8s.io/pod-security-admission/api"
"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1" nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
nfdclient "sigs.k8s.io/node-feature-discovery/pkg/generated/clientset/versioned" nfdclient "sigs.k8s.io/node-feature-discovery/pkg/generated/clientset/versioned"
"sigs.k8s.io/node-feature-discovery/source/custom" "sigs.k8s.io/node-feature-discovery/source/custom"
@ -909,6 +912,73 @@ denyLabelNs: []
)).NotTo(HaveOccurred()) )).NotTo(HaveOccurred())
}) })
}) })
Context("and test whether resyncPeriod is passed successfully or not", func() {
BeforeEach(func(ctx context.Context) {
extraMasterPodSpecOpts = []testpod.SpecOption{
testpod.SpecWithConfigMap("nfd-master-conf", "/etc/kubernetes/node-feature-discovery"),
}
cm := testutils.NewConfigMap("nfd-master-conf", "nfd-master.conf", `
resyncPeriod: "1s"
`)
_, err := f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, cm, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
})
It("labels should be restored to the original ones", func(ctx context.Context) {
// deploy node feature object
if !useNodeFeatureApi {
Skip("NodeFeature API not enabled")
}
nodes, err := getNonControlPlaneNodes(ctx, f.ClientSet)
Expect(err).NotTo(HaveOccurred())
targetNodeName := nodes[0].Name
Expect(targetNodeName).ToNot(BeEmpty(), "No suitable worker node found")
// Apply Node Feature object
By("Creating NodeFeature object")
nodeFeatures, err := testutils.CreateOrUpdateNodeFeaturesFromFile(ctx, nfdClient, "nodefeature-1.yaml", f.Namespace.Name, targetNodeName)
Expect(err).NotTo(HaveOccurred())
By("Verifying node labels from NodeFeature object #1")
expectedLabels := map[string]k8sLabels{
targetNodeName: {
nfdv1alpha1.FeatureLabelNs + "/e2e-nodefeature-test-1": "obj-1",
nfdv1alpha1.FeatureLabelNs + "/e2e-nodefeature-test-2": "obj-1",
nfdv1alpha1.FeatureLabelNs + "/fake-fakefeature3": "overridden",
},
}
Expect(checkForNodeLabels(ctx, f.ClientSet,
expectedLabels, nodes,
)).NotTo(HaveOccurred())
patches, err := json.Marshal(
[]apihelper.JsonPatch{
apihelper.NewJsonPatch(
"replace",
"/metadata/labels",
nfdv1alpha1.FeatureLabelNs+"/e2e-nodefeature-test-1",
"randomValue",
),
},
)
Expect(err).NotTo(HaveOccurred())
_, err = f.ClientSet.CoreV1().Nodes().Patch(ctx, targetNodeName, types.JSONPatchType, patches, metav1.PatchOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(checkForNodeLabels(ctx,
f.ClientSet,
expectedLabels,
nodes,
)).NotTo(HaveOccurred())
By("Deleting NodeFeature object")
err = nfdClient.NfdV1alpha1().NodeFeatures(f.Namespace.Name).Delete(ctx, nodeFeatures[0], metav1.DeleteOptions{})
Expect(err).NotTo(HaveOccurred())
})
})
}) })
} }