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
configzendpoint 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.moddeclaresgo 1.27and the builder image isgolang:1.27-trixie(#2583). - Built against the Kubernetes v1.37 libraries:
k8s.io/*v0.35.3 -> v0.37.1,k8s.io/kubernetesv1.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
- nfd-topology-updater RBAC (#2564): the ClusterRole rule for
noderesourcetopologies(API grouptopology.node.k8s.io) changes fromcreate, get, updatetocreate, 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 withfailed 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 scopeand crash-loops until the new ClusterRole is applied. The reverse also holds: a v0.19 topology-updater under the new ClusterRole is deniedgetonnoderesourcetopologies, 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, grantcreate,get,updateandpatchfor the upgrade (and for any rollback), then dropgetandupdate. - 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, incrementsnfd_topology_updater_scan_errors_totaland retries on the next event. With-oneshotit still exits with the error. Alerts that relied on topology-updater restarts should watch the metric instead. - kustomize prune overlay (#2607): the prune Job now runs as its own
nfd-pruneServiceAccount, ClusterRole and ClusterRoleBinding (get,list,patch,updateonnodesandnodes/status), and the overlay no longer includesbase/rbac. Applying or deleting the overlay no longer creates or deletes thenfd-masterServiceAccount, ClusterRole and ClusterRoleBinding. The documented uninstall commands are unchanged. - Full image base (#2632): the full image variant is based on
debian:trixie-slim(Debian 13) instead ofdebian: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. - nfd-topology-updater rollout pace (#2586): the Helm chart adds
topologyUpdater.updateStrategyand setsrollingUpdate.maxUnavailable: "10%", the same default asworker.updateStrategy. Upgrades now replace up to 10% of the topology-updater pods at a time instead of one (the Kubernetes DaemonSet default). SettopologyUpdater.updateStrategy.rollingUpdate.maxUnavailable: 1to 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.portto nfd-gc as-port. Previously nfd-gc always listened on 8080, so any othergc.portpointed the probes at a closed port and the pod crash-looped. With default values the only change is an added-port=8080argument (#2608). - Helm: set
metadata.namespaceon 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 withInvalidSpecError: Namespace for ... PodMonitor is missing(#2577, fixes #2576). - Helm: render
priorityClassNameonce in the nfd-worker pod spec. With both the top-levelpriorityClassNameandworker.priorityClassNameset, the key was emitted twice and the effective value depended on the YAML decoder;worker.priorityClassNamenow takes precedence and falls back to the top-level value. The nfd-gc containersecurityContextis now configurable withgc.securityContext, which defaults to the previously hardcoded settings (#2624, fixes #2622). - kustomize: the prune overlay works again. It removed
/rules/1from the nfd-master ClusterRole with a JSON patch, and since v0.17.0 that index is thenodesrule, so the prune Job failed withnodes 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.namefeature'snodenameelement, 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_totalcounter. 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-usernamewithout--registry-password-stdinor--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'
-helpoutput; 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
-kubeconfigdocumented for nfd-topology-updater and nfd-gc (#2601). - Worker configuration reference: the
sources.localsection 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.updateStrategyandtopologyUpdater.updateStrategydescriptions, 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/kubernetesv1.35.3 -> v1.37.1 and thereplacepins (#2584). The PR changes onlygo.mod,go.sumand the podresources client call signature; no manifest or API version changes. github.com/k8stopologyawareschedwg/noderesourcetopology-api0.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/ghw0.24.0 -> 0.26.0 (#2563, #2618)google.golang.org/grpc1.82.0 -> 1.84.0 (#2581, #2617)github.com/opencontainers/runc1.5.0 -> 1.5.2 (#2594, #2615)github.com/onsi/ginkgo/v22.32.0 -> 2.33.0 (#2580, #2594)github.com/onsi/gomega1.42.1 -> 1.44.0 (#2594, #2616)github.com/prometheus/client_golang1.23.2 -> 1.24.1 (#2594)github.com/stretchr/testify1.11.1 -> 1.12.1 (#2594)github.com/google/cel-go0.26.0 -> 0.29.0, indirect (#2594)github.com/google/uuidis now indirect: nfd-master and the e2e utilities use the Go standard libraryuuidpackage (#2583)go.opentelemetry.io/otel/exporters/otlp/otlptrace1.34.0 -> 1.45.0, indirect (#2590)go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc1.34.0 -> 1.45.0, indirect (#2589)golang.org/x/time0.15.0 -> 0.16.0 (#2588)github.com/jedib0t/go-pretty/v66.8.2 -> 6.8.3 (#2587)oras.land/oras-go/v22.6.1 -> 2.6.2 (#2562)sigs.k8s.io/structured-merge-diff/v66.4.0 -> 6.4.2 (#2561)actions/checkout7.0.0 -> 7.0.1 in the gh-pages and release workflows (#2594)
Other
- CI: bump the Cloud Build
gcb-docker-gcloudbuilder 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);
logcheckinscripts/test-infra/verify.shpinned 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
MetricsPortfield from the internalArgsstruct; 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).