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:
parent
e4dfa2d916
commit
87c2d7e184
4 changed files with 112 additions and 21 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue