From 9fd706ccd90dd4596ef5d92796b6e058dd4f51ad Mon Sep 17 00:00:00 2001 From: Antti Kervinen Date: Wed, 25 Mar 2026 17:25:15 +0200 Subject: [PATCH] kubelet: do not destroy nodeAllocatableResourceClaimStatuses The kubelet status manager was not preserving the pod.status.nodeAllocatableResourceClaimStatuses field set by the scheduler during pod status merges. This caused the information to the to be destroyed by the kubelet's next status sync, making the field always appear empty. Add the same preservation pattern already used for ResourceClaimStatuses and ExtendedResourceClaimStatus to both mergePodStatus() and isPodStatusByKubeletEqual(). Signed-off-by: Antti Kervinen --- pkg/kubelet/status/status_manager.go | 7 ++++++- pkg/kubelet/status/status_manager_test.go | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/kubelet/status/status_manager.go b/pkg/kubelet/status/status_manager.go index f047e9a68d3..bac491cb7d2 100644 --- a/pkg/kubelet/status/status_manager.go +++ b/pkg/kubelet/status/status_manager.go @@ -224,7 +224,8 @@ func NewManager(kubeClient clientset.Interface, podManager PodManager, podDeleti // isPodStatusByKubeletEqual returns true if the given pod statuses are equal, ignoring // fields not managed by the kubelet (including non-kubelet-owned pod conditions, -// ResourceClaimStatuses, and ExtendedResourceClaimStatus). Statuses are assumed to be +// ResourceClaimStatuses, ExtendedResourceClaimStatus, and +// NodeAllocatableResourceClaimStatuses). Statuses are assumed to be // normalized before calling this function. func isPodStatusByKubeletEqual(oldStatus, status *v1.PodStatus) bool { oldCopy := oldStatus.DeepCopy() @@ -257,6 +258,8 @@ func isPodStatusByKubeletEqual(oldStatus, status *v1.PodStatus) bool { oldCopy.ResourceClaimStatuses = status.ResourceClaimStatuses // ExtendedResourceClaimStatus is not owned and not modified by kubelet. oldCopy.ExtendedResourceClaimStatus = status.ExtendedResourceClaimStatus + // NodeAllocatableResourceClaimStatuses is not owned and not modified by kubelet. + oldCopy.NodeAllocatableResourceClaimStatuses = status.NodeAllocatableResourceClaimStatuses return apiequality.Semantic.DeepEqual(oldCopy, status) } @@ -1393,6 +1396,8 @@ func mergePodStatus(pod *v1.Pod, oldPodStatus, newPodStatus v1.PodStatus, couldH newPodStatus.ResourceClaimStatuses = oldPodStatus.ResourceClaimStatuses // ExtendedResourceClaimStatus is not owned and not modified by kubelet. newPodStatus.ExtendedResourceClaimStatus = oldPodStatus.ExtendedResourceClaimStatus + // NodeAllocatableResourceClaimStatuses is not owned and not modified by kubelet. + newPodStatus.NodeAllocatableResourceClaimStatuses = oldPodStatus.NodeAllocatableResourceClaimStatuses // Delay transitioning a pod to a terminal status unless the pod is actually terminal. // The Kubelet should never transition a pod to terminal status that could have running diff --git a/pkg/kubelet/status/status_manager_test.go b/pkg/kubelet/status/status_manager_test.go index 43e0d8056a5..74b31866b7e 100644 --- a/pkg/kubelet/status/status_manager_test.go +++ b/pkg/kubelet/status/status_manager_test.go @@ -33,6 +33,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -525,6 +526,13 @@ func TestStatusEquality(t *testing.T) { } oldPodStatus.ResourceClaimStatuses = []v1.PodResourceClaimStatus{claimStatusA} oldPodStatus.ExtendedResourceClaimStatus = extendedClaimStatusA + oldPodStatus.NodeAllocatableResourceClaimStatuses = []v1.NodeAllocatableResourceClaimStatus{ + { + ResourceClaimName: "my-claim", + Containers: []string{"ctr0"}, + Resources: map[v1.ResourceName]resource.Quantity{v1.ResourceMemory: resource.MustParse("100Mi")}, + }, + } normalizeStatus(&pod, &oldPodStatus) normalizeStatus(&pod, &podStatus)