@@ -20,6 +20,7 @@ import (
2020 "encoding/json"
2121 "fmt"
2222 "net/http"
23+ "net/url"
2324 "os"
2425 "path/filepath"
2526 "regexp"
@@ -38,8 +39,10 @@ import (
3839 "k8s.io/apimachinery/pkg/util/validation"
3940 k8sclient "k8s.io/client-go/kubernetes"
4041 "k8s.io/klog/v2"
42+ kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1"
4143 "k8s.io/utils/ptr"
4244 klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog"
45+ "sigs.k8s.io/node-feature-discovery/pkg/utils/kubeconf"
4346 "sigs.k8s.io/yaml"
4447
4548 apiequality "k8s.io/apimachinery/pkg/api/equality"
@@ -57,6 +60,7 @@ import (
5760 _ "sigs.k8s.io/node-feature-discovery/source/kernel"
5861 _ "sigs.k8s.io/node-feature-discovery/source/local"
5962 _ "sigs.k8s.io/node-feature-discovery/source/memory"
63+ memory "sigs.k8s.io/node-feature-discovery/source/memory"
6064 _ "sigs.k8s.io/node-feature-discovery/source/network"
6165 _ "sigs.k8s.io/node-feature-discovery/source/pci"
6266 _ "sigs.k8s.io/node-feature-discovery/source/storage"
@@ -94,13 +98,16 @@ type Labels map[string]string
9498
9599// Args are the command line arguments of NfdWorker.
96100type Args struct {
97- ConfigFile string
98- Klog map [string ]* utils.KlogFlagVal
99- Kubeconfig string
100- Oneshot bool
101- Options string
102- Port int
103- NoOwnerRefs bool
101+ ConfigFile string
102+ Klog map [string ]* utils.KlogFlagVal
103+ Kubeconfig string
104+ Oneshot bool
105+ Options string
106+ Port int
107+ NoOwnerRefs bool
108+ KubeletConfigPath string
109+ KubeletConfigURI string
110+ APIAuthTokenFile string
104111
105112 Overrides ConfigOverrideArgs
106113}
@@ -124,6 +131,7 @@ type nfdWorker struct {
124131 featureSources []source.FeatureSource
125132 labelSources []source.LabelSource
126133 ownerReference []metav1.OwnerReference
134+ kubeletConfigFunc func () (* kubeletconfigv1beta1.KubeletConfiguration , error )
127135}
128136
129137// This ticker can represent infinite and normal intervals.
@@ -169,12 +177,25 @@ func NewNfdWorker(opts ...NfdWorkerOption) (NfdWorker, error) {
169177 stop : make (chan struct {}),
170178 }
171179
180+ if nfd .args .ConfigFile != "" {
181+ nfd .configFilePath = filepath .Clean (nfd .args .ConfigFile )
182+ }
183+
172184 for _ , o := range opts {
173185 o .apply (nfd )
174186 }
175187
176- if nfd .args .ConfigFile != "" {
177- nfd .configFilePath = filepath .Clean (nfd .args .ConfigFile )
188+ kubeletConfigFunc , err := getKubeletConfigFunc (nfd .args .KubeletConfigURI , nfd .args .APIAuthTokenFile )
189+ if err != nil {
190+ return nil , err
191+ }
192+
193+ nfd = & nfdWorker {
194+ kubeletConfigFunc : kubeletConfigFunc ,
195+ }
196+
197+ for _ , o := range opts {
198+ o .apply (nfd )
178199 }
179200
180201 // k8sClient might've been set via opts by tests
@@ -239,6 +260,8 @@ func (w *nfdWorker) runFeatureDiscovery() error {
239260 }
240261 // Get the set of feature labels.
241262 labels := createFeatureLabels (w .labelSources , w .config .Core .LabelWhiteList .Regexp )
263+ // Append a label with app=nfd
264+ labels ["app" ] = "nfd"
242265
243266 // Update the node with the feature labels.
244267 if ! w .config .Core .NoPublish {
@@ -255,9 +278,10 @@ func (w *nfdWorker) setOwnerReference() error {
255278 if ! w .config .Core .NoOwnerRefs {
256279 // Get pod owner reference
257280 podName := os .Getenv ("POD_NAME" )
281+ podNamespace := os .Getenv ("POD_NAMESPACE" )
258282 // Add pod owner reference if it exists
259283 if podName != "" {
260- if selfPod , err := w .k8sClient .CoreV1 ().Pods (w . kubernetesNamespace ).Get (context .TODO (), podName , metav1.GetOptions {}); err != nil {
284+ if selfPod , err := w .k8sClient .CoreV1 ().Pods (podNamespace ).Get (context .TODO (), podName , metav1.GetOptions {}); err != nil {
261285 klog .ErrorS (err , "failed to get self pod, cannot inherit ownerReference for NodeFeature" )
262286 return err
263287 } else {
@@ -312,6 +336,12 @@ func (w *nfdWorker) Run() error {
312336 httpMux .Handle ("/metrics" , promhttp .HandlerFor (promRegistry , promhttp.HandlerOpts {}))
313337 registerVersion (version .Get ())
314338
339+ klConfig , err := w .kubeletConfigFunc ()
340+ if err != nil {
341+ return err
342+ }
343+ memory .SetSwapMode (klConfig .MemorySwap .SwapBehavior )
344+
315345 err = w .runFeatureDiscovery ()
316346 if err != nil {
317347 return err
@@ -464,6 +494,7 @@ func (w *nfdWorker) configureCore(c coreConfig) error {
464494func (w * nfdWorker ) configure (filepath string , overrides string ) error {
465495 // Create a new default config
466496 c := newDefaultConfig ()
497+
467498 confSources := source .GetAllConfigurableSources ()
468499 c .Sources = make (map [string ]source.Config , len (confSources ))
469500 for _ , s := range confSources {
@@ -624,7 +655,7 @@ func (m *nfdWorker) updateNodeFeatureObject(labels Labels) error {
624655 return err
625656 }
626657 nodename := utils .NodeName ()
627- namespace := m . kubernetesNamespace
658+ namespace := os . Getenv ( "POD_NAMESPACE" )
628659
629660 features := source .GetAllFeatures ()
630661
@@ -720,3 +751,38 @@ func (c *sourcesConfig) UnmarshalJSON(data []byte) error {
720751
721752 return nil
722753}
754+
755+ func getKubeletConfigFunc (uri , apiAuthTokenFile string ) (func () (* kubeletconfigv1beta1.KubeletConfiguration , error ), error ) {
756+ u , err := url .ParseRequestURI (uri )
757+ if err != nil {
758+ return nil , fmt .Errorf ("failed to parse -kubelet-config-uri: %w" , err )
759+ }
760+
761+ // init kubelet API client
762+ var klConfig * kubeletconfigv1beta1.KubeletConfiguration
763+ switch u .Scheme {
764+ case "file" :
765+ return func () (* kubeletconfigv1beta1.KubeletConfiguration , error ) {
766+ klConfig , err = kubeconf .GetKubeletConfigFromLocalFile (u .Path )
767+ if err != nil {
768+ return nil , fmt .Errorf ("failed to read kubelet config: %w" , err )
769+ }
770+ return klConfig , err
771+ }, nil
772+ case "https" :
773+ restConfig , err := kubeconf .InsecureConfig (u .String (), apiAuthTokenFile )
774+ if err != nil {
775+ return nil , fmt .Errorf ("failed to initialize rest config for kubelet config uri: %w" , err )
776+ }
777+
778+ return func () (* kubeletconfigv1beta1.KubeletConfiguration , error ) {
779+ klConfig , err = kubeconf .GetKubeletConfiguration (restConfig )
780+ if err != nil {
781+ return nil , fmt .Errorf ("failed to get kubelet config from configz endpoint: %w" , err )
782+ }
783+ return klConfig , nil
784+ }, nil
785+ }
786+
787+ return nil , fmt .Errorf ("unsupported URI scheme: %v" , u .Scheme )
788+ }
0 commit comments