github kubernetes-sigs/node-feature-discovery v0.20.0

3 hours ago

Highlights

  • nfd-topology-updater writes NodeResourceTopology objects with server-side apply (field manager node-feature-discovery-topology-updater, forced) instead of a GET followed by an UPDATE: one API request per update instead of two, which lowers kube-apiserver and etcd load at scale (#2564). Requires an RBAC update, see Action Required.
  • nfd-topology-updater caches the kubelet configuration and CPU core attributes and refreshes them on interval-based scans. Reads from the kubelet configz endpoint now time out after 2 minutes (previously no timeout), and a failed read no longer stops the process (#2564). See Action Required.
  • Built with Go 1.27: go.mod declares go 1.27 and the builder image is golang:1.27-trixie (#2583).
  • Built against the Kubernetes v1.37 libraries: k8s.io/* v0.35.3 -> v0.37.1, k8s.io/kubernetes v1.35.3 -> v1.37.1 (#2584).
  • nfd-gc no longer deletes the NodeFeatures and NodeResourceTopology of a Node that was deleted and created again with the same name before nfd-gc handled the delete event (#2628).
  • Documentation pass: the quick start, deployment, usage, reference and developer guide pages were re-checked against a live deployment of master (Helm chart and kustomize overlays) and corrected (#2601, #2605, #2609, #2610, #2611, #2612, #2613, #2614).

Action Required / Behavior Changes

  1. nfd-topology-updater RBAC (#2564): the ClusterRole rule for noderesourcetopologies (API group topology.node.k8s.io) changes from create, get, update to create, patch. The Helm chart and the kustomize base ship the new rule, but a deployment that bumps only the image exits on its first NodeResourceTopology update with failed to apply NodeResourceTopology: noderesourcetopologies.topology.node.k8s.io "<node>" is forbidden: User "system:serviceaccount:<namespace>:<serviceaccount>" cannot patch resource "noderesourcetopologies" in API group "topology.node.k8s.io" at the cluster scope and crash-loops until the new ClusterRole is applied. The reverse also holds: a v0.19 topology-updater under the new ClusterRole is denied get on noderesourcetopologies, so pods still running v0.19 during the DaemonSet rollout, or after a rollback, fail until they run the matching version. If you manage RBAC outside the chart or kustomize, grant create, get, update and patch for the upgrade (and for any rollback), then drop get and update.
  2. nfd-topology-updater when the kubelet configuration is unavailable (#2564): previously a failed kubelet configuration read made nfd-topology-updater exit. Now it keeps the last cached configuration; if none was ever read, it skips the publish, logs skipping NodeResourceTopology publish, increments nfd_topology_updater_scan_errors_total and retries on the next event. With -oneshot it still exits with the error. Alerts that relied on topology-updater restarts should watch the metric instead.
  3. kustomize prune overlay (#2607): the prune Job now runs as its own nfd-prune ServiceAccount, ClusterRole and ClusterRoleBinding (get, list, patch, update on nodes and nodes/status), and the overlay no longer includes base/rbac. Applying or deleting the overlay no longer creates or deletes the nfd-master ServiceAccount, ClusterRole and ClusterRoleBinding. The documented uninstall commands are unchanged.
  4. Full image base (#2632): the full image variant is based on debian:trixie-slim (Debian 13) instead of debian:bookworm-slim (Debian 12), which no longer publishes linux/s390x images. The NFD binaries are statically linked; anything you add on top of the full image now builds against Debian 13. The minimal image (scratch) is unchanged.
  5. nfd-topology-updater rollout pace (#2586): the Helm chart adds topologyUpdater.updateStrategy and sets rollingUpdate.maxUnavailable: "10%", the same default as worker.updateStrategy. Upgrades now replace up to 10% of the topology-updater pods at a time instead of one (the Kubernetes DaemonSet default). Set topologyUpdater.updateStrategy.rollingUpdate.maxUnavailable: 1 to keep the old pace.

Fixes

  • nfd-gc: before deleting the NodeFeatures and NodeResourceTopology of a deleted Node, check the Node informer cache and keep the objects if a Node with that name exists again. nfd-gc can handle delete events minutes late after a mass Node deletion (client-go default 5 QPS); a Node re-created in that window lost its NodeFeature-derived labels and dropped out of NodeFeatureGroups until the publisher re-created its NodeFeatures (#2628).
  • Helm: pass gc.port to nfd-gc as -port. Previously nfd-gc always listened on 8080, so any other gc.port pointed the probes at a closed port and the pod crash-looped. With default values the only change is an added -port=8080 argument (#2608).
  • Helm: set metadata.namespace on the PodMonitor. When the chart is rendered through Kustomize's Helm integration (Kustomize 5.8 and later), the PodMonitor had no namespace and Argo CD refused to sync it with InvalidSpecError: Namespace for ... PodMonitor is missing (#2577, fixes #2576).
  • Helm: render priorityClassName once in the nfd-worker pod spec. With both the top-level priorityClassName and worker.priorityClassName set, the key was emitted twice and the effective value depended on the YAML decoder; worker.priorityClassName now takes precedence and falls back to the top-level value. The nfd-gc container securityContext is now configurable with gc.securityContext, which defaults to the previously hardcoded settings (#2624, fixes #2622).
  • kustomize: the prune overlay works again. It removed /rules/1 from the nfd-master ClusterRole with a JSON patch, and since v0.17.0 that index is the nodes rule, so the prune Job failed with nodes is forbidden: ... cannot list resource "nodes" and left all NFD labels, annotations and extended resources on the nodes (#2607).
  • nfd-master: NodeFeatureGroup status lists member nodes by Node name. It used the system.name feature's nodename element, so nodes whose features came only from third-party NodeFeature objects were listed with an empty name (#2621).
  • nfd-master: NodeFeatureGroups outside nfd-master's own namespace get their status populated. The update queue was keyed by object name only, so same-name NodeFeatureGroups in different namespaces collided, and the lookup and status write were pinned to nfd-master's namespace (#2559).
  • nfd-master: register the nfd_master_node_feature_group_update_requests_total counter. It was incremented but never registered, so it was missing from /metrics (#2625).
  • nfd compat validate-node: return the error when the registry referrers lookup fails (#2619), and fail on incomplete registry credential flags (--registry-username without --registry-password-stdin or --registry-token-stdin, or the reverse) instead of falling back to the default registry auth (#2620).

Documentation

  • Quick start, introduction and deployment guides: quick start commands and expected output, Helm parameter descriptions (regenerated chart README and values.schema.json; no default values changed), kustomize uninstall steps, metrics page, and a note that the OperatorHub NFD Operator is outdated (#2609).
  • Command line and configuration references for nfd-master, nfd-worker, nfd-topology-updater, nfd-gc and kubectl-nfd, compared flag by flag against the binaries' -help output; all klog flags documented (#2610).
  • API reference rendered with repository crd-ref-docs templates; scope, short names and status types of NodeFeature, NodeFeatureRule and NodeFeatureGroup documented; feature gates page and e2e configuration reference updated. The CRD manifests were regenerated with description-only changes: the schemas are unchanged, so no CRD re-apply is needed for this change (#2611).
  • Customization guide: NodeFeatureGroup, feature file and rule examples fixed and applied against a live cluster; the NodeFeatureGroup example is created in the nfd-master namespace so its status is populated (#2612).
  • Built-in feature label names and the image compatibility guide corrected (#2613).
  • Developer guide build and local-run commands fixed; contributing instructions point to the CNCF CLA (#2614).
  • Broken links and anchors fixed, the misspelled label domain in customization examples corrected, and -kubeconfig documented for nfd-topology-updater and nfd-gc (#2601).
  • Worker configuration reference: the sources.local section now states that the local source has no configuration options (#2605).
  • README rewritten with a components overview, Kubernetes version requirement, compatibility and community sections, and a nodeSelector example (#2623).
  • Helm chart: shorter worker.updateStrategy and topologyUpdater.updateStrategy descriptions, and the upgrade note on rolling-update pace now covers nfd-topology-updater (#2635).
  • README and the netlify redirect point to v0.19 (#2557).

Dependencies

  • Go 1.26 -> 1.27, builder image golang:1.26-trixie -> golang:1.27-trixie (#2583).
  • Kubernetes libraries v0.35.3 -> v0.37.1, including k8s.io/kubernetes v1.35.3 -> v1.37.1 and the replace pins (#2584). The PR changes only go.mod, go.sum and the podresources client call signature; no manifest or API version changes.
  • github.com/k8stopologyawareschedwg/noderesourcetopology-api 0.1.2 -> 0.1.4 (#2564, #2592).
  • Go module and GitHub Actions updates (Dependabot, and the merge train #2594 that consolidated Dependabot #2567, #2568, #2570, #2571, #2593, #2596, #2597):
    • github.com/jaypipes/ghw 0.24.0 -> 0.26.0 (#2563, #2618)
    • google.golang.org/grpc 1.82.0 -> 1.84.0 (#2581, #2617)
    • github.com/opencontainers/runc 1.5.0 -> 1.5.2 (#2594, #2615)
    • github.com/onsi/ginkgo/v2 2.32.0 -> 2.33.0 (#2580, #2594)
    • github.com/onsi/gomega 1.42.1 -> 1.44.0 (#2594, #2616)
    • github.com/prometheus/client_golang 1.23.2 -> 1.24.1 (#2594)
    • github.com/stretchr/testify 1.11.1 -> 1.12.1 (#2594)
    • github.com/google/cel-go 0.26.0 -> 0.29.0, indirect (#2594)
    • github.com/google/uuid is now indirect: nfd-master and the e2e utilities use the Go standard library uuid package (#2583)
    • go.opentelemetry.io/otel/exporters/otlp/otlptrace 1.34.0 -> 1.45.0, indirect (#2590)
    • go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc 1.34.0 -> 1.45.0, indirect (#2589)
    • golang.org/x/time 0.15.0 -> 0.16.0 (#2588)
    • github.com/jedib0t/go-pretty/v6 6.8.2 -> 6.8.3 (#2587)
    • oras.land/oras-go/v2 2.6.1 -> 2.6.2 (#2562)
    • sigs.k8s.io/structured-merge-diff/v6 6.4.0 -> 6.4.2 (#2561)
    • actions/checkout 7.0.0 -> 7.0.1 in the gh-pages and release workflows (#2594)

Other

  • CI: bump the Cloud Build gcb-docker-gcloud builder to v20260729-0b834bafc6. The previously pinned tag was pruned from the registry, and every master image push had failed since 2026-04-13 (#2555).
  • Release process: the release issue templates call out promoting the Helm chart digest to registry.k8s.io, and hack/verify-release-artifacts.sh <version> checks the images, the OCI chart, the gh-pages Helm index and the GitHub release assets (#2560).
  • e2e: stop deleting and re-creating the NodeResourceTopology CRD before each topology-updater spec and in the nfd-gc specs, which made the NodeResourceTopology garbage-collection spec fail intermittently (#2595, #2598).
  • Pull request template added (#2599); logcheck in scripts/test-infra/verify.sh pinned to v0.10.1 (#2600).
  • CI: golangci-lint v2.11.4 -> v2.14.0, installed from the release tarball with a pinned SHA-256 instead of the upstream install.sh (#2583).
  • nfd-master: drop the unused MetricsPort field from the internal Args struct; no behavior change (#2626).
  • Enhancement proposal: NFD image compatibility scheduler plugin (enhancements/2403-nfd-image-compatibility-scheduler) (#2403).
  • OWNERS: add @faganihajizada as a reviewer (#2630).
  • examples: the Grafana dashboard takes the Prometheus datasource as a template variable (DS_PROMETHEUS) (#2575).

Don't miss a new node-feature-discovery release

NewReleases is sending notifications on new releases.