Skip to content

Commit 62f96d2

Browse files
set AllocatedResourcesStatus in the Pod Status
1 parent 3790ee2 commit 62f96d2

20 files changed

+614
-32
lines changed

api/openapi-spec/swagger.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/openapi-spec/v3/api__v1_openapi.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6817,6 +6817,7 @@
68176817
"properties": {
68186818
"name": {
68196819
"default": "",
6820+
"description": "Name of the resource. Must be unique within the pod and match one of the resources from the pod spec.",
68206821
"type": "string"
68216822
},
68226823
"resources": {

pkg/api/pod/util.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,22 +1172,6 @@ func rroInUse(podSpec *api.PodSpec) bool {
11721172
return inUse
11731173
}
11741174

1175-
func allocatedResourcesStatusInUse(podSpec *api.PodStatus) bool {
1176-
if podSpec == nil {
1177-
return false
1178-
}
1179-
inUse := func(csl []api.ContainerStatus) bool {
1180-
for _, cs := range csl {
1181-
if len(cs.AllocatedResourcesStatus) > 0 {
1182-
return true
1183-
}
1184-
}
1185-
return false
1186-
}
1187-
1188-
return inUse(podSpec.ContainerStatuses) || inUse(podSpec.InitContainerStatuses) || inUse(podSpec.EphemeralContainerStatuses)
1189-
}
1190-
11911175
func dropDisabledClusterTrustBundleProjection(podSpec, oldPodSpec *api.PodSpec) {
11921176
if utilfeature.DefaultFeatureGate.Enabled(features.ClusterTrustBundleProjection) {
11931177
return

pkg/apis/core/validation/validation.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8209,11 +8209,10 @@ func validateContainerStatusNoAllocatedResourcesStatus(containerStatuses []core.
82098209
allErrors := field.ErrorList{}
82108210

82118211
for i, containerStatus := range containerStatuses {
8212-
if containerStatus.AllocatedResourcesStatus == nil {
8212+
if len(containerStatus.AllocatedResourcesStatus) == 0 {
82138213
continue
8214-
} else {
8215-
allErrors = append(allErrors, field.Forbidden(fldPath.Index(i).Child("allocatedResourcesStatus"), "cannot be set for a container status"))
82168214
}
8215+
allErrors = append(allErrors, field.Forbidden(fldPath.Index(i).Child("allocatedResourcesStatus"), "must not be specified in container status"))
82178216
}
82188217

82198218
return allErrors
@@ -8263,12 +8262,18 @@ func validateContainerStatusAllocatedResourcesStatus(containerStatuses []core.Co
82638262
uniqueResources := sets.New[core.ResourceID]()
82648263
// check resource IDs are unique
82658264
for k, r := range allocatedResource.Resources {
8266-
if r.Health != core.ResourceHealthStatusHealthy && r.Health != core.ResourceHealthStatusUnhealthy && r.Health != core.ResourceHealthStatusUnknown {
8267-
allErrors = append(allErrors, field.Invalid(fldPath.Index(i).Child("allocatedResourcesStatus").Index(j).Child("resources").Index(k).Child("health"), r.Health, "must be one of Healthy, Unhealthy, Unknown"))
8265+
8266+
var supportedResourceHealthValues = sets.New(
8267+
core.ResourceHealthStatusHealthy,
8268+
core.ResourceHealthStatusUnhealthy,
8269+
core.ResourceHealthStatusUnknown)
8270+
8271+
if !supportedResourceHealthValues.Has(r.Health) {
8272+
allErrors = append(allErrors, field.NotSupported(fldPath.Index(i).Child("allocatedResourcesStatus").Index(j).Child("resources").Index(k).Child("health"), r.Health, sets.List(supportedResourceHealthValues)))
82688273
}
82698274

82708275
if uniqueResources.Has(r.ResourceID) {
8271-
allErrors = append(allErrors, field.Invalid(fldPath.Index(i).Child("allocatedResourcesStatus").Index(j).Child("resources").Index(k).Child("resourceID"), r.ResourceID, "must be unique"))
8276+
allErrors = append(allErrors, field.Duplicate(fldPath.Index(i).Child("allocatedResourcesStatus").Index(j).Child("resources").Index(k).Child("resourceID"), r.ResourceID))
82728277
} else {
82738278
uniqueResources.Insert(r.ResourceID)
82748279
}

pkg/apis/core/validation/validation_test.go

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24457,11 +24457,11 @@ func TestValidateContainerStatusNoAllocatedResourcesStatus(t *testing.T) {
2445724457

2445824458
errs := validateContainerStatusNoAllocatedResourcesStatus(containerStatuses, fldPath)
2445924459

24460-
assert.Equal(t, 2, len(errs))
24460+
assert.Len(t, errs, 2)
2446124461
assert.Equal(t, "spec.containers[1].allocatedResourcesStatus", errs[0].Field)
24462-
assert.Equal(t, "cannot be set for a container status", errs[0].Detail)
24462+
assert.Equal(t, "must not be specified in container status", errs[0].Detail)
2446324463
assert.Equal(t, "spec.containers[2].allocatedResourcesStatus", errs[1].Field)
24464-
assert.Equal(t, "cannot be set for a container status", errs[1].Detail)
24464+
assert.Equal(t, "must not be specified in container status", errs[1].Detail)
2446524465
}
2446624466

2446724467
func TestValidateContainerStatusAllocatedResourcesStatus(t *testing.T) {
@@ -24580,7 +24580,7 @@ func TestValidateContainerStatusAllocatedResourcesStatus(t *testing.T) {
2458024580
},
2458124581
},
2458224582
wantFieldErrors: field.ErrorList{
24583-
field.Invalid(fldPath.Index(0).Child("allocatedResourcesStatus").Index(0).Child("resources").Index(1).Child("resourceID"), core.ResourceID("resource-1"), "must be unique"),
24583+
field.Duplicate(fldPath.Index(0).Child("allocatedResourcesStatus").Index(0).Child("resources").Index(1).Child("resourceID"), core.ResourceID("resource-1")),
2458424584
},
2458524585
},
2458624586

@@ -24619,6 +24619,38 @@ func TestValidateContainerStatusAllocatedResourcesStatus(t *testing.T) {
2461924619
field.Invalid(fldPath.Index(0).Child("allocatedResourcesStatus").Index(1).Child("name"), core.ResourceName("test.device/test2"), "must match one of the container's resource requirements"),
2462024620
},
2462124621
},
24622+
24623+
"don't allow health status outside the known values": {
24624+
containers: []core.Container{
24625+
{
24626+
Name: "container-1",
24627+
Resources: core.ResourceRequirements{
24628+
Requests: core.ResourceList{
24629+
"test.device/test": resource.MustParse("1"),
24630+
},
24631+
},
24632+
},
24633+
},
24634+
containerStatuses: []core.ContainerStatus{
24635+
{
24636+
Name: "container-1",
24637+
AllocatedResourcesStatus: []core.ResourceStatus{
24638+
{
24639+
Name: "test.device/test",
24640+
Resources: []core.ResourceHealth{
24641+
{
24642+
ResourceID: "resource-1",
24643+
Health: "invalid-health-value",
24644+
},
24645+
},
24646+
},
24647+
},
24648+
},
24649+
},
24650+
wantFieldErrors: field.ErrorList{
24651+
field.NotSupported(fldPath.Index(0).Child("allocatedResourcesStatus").Index(0).Child("resources").Index(0).Child("health"), core.ResourceHealthStatus("invalid-health-value"), []string{"Healthy", "Unhealthy", "Unknown"}),
24652+
},
24653+
},
2462224654
}
2462324655
for name, tt := range testCases {
2462424656
t.Run(name, func(t *testing.T) {

pkg/features/kube_features.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,13 @@ const (
664664
// No effect for other cases such as using serverTLSbootstap.
665665
ReloadKubeletServerCertificateFile featuregate.Feature = "ReloadKubeletServerCertificateFile"
666666

667+
// owner: @SergeyKanzhelev
668+
// kep: https://kep.k8s.io/4680
669+
// alpha: v1.31
670+
//
671+
// Adds the AllocatedResourcesStatus to the container status.
672+
ResourceHealthStatus featuregate.Feature = "ResourceHealthStatus"
673+
667674
// owner: @mikedanese
668675
// alpha: v1.7
669676
// beta: v1.12
@@ -1150,6 +1157,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
11501157

11511158
ReloadKubeletServerCertificateFile: {Default: true, PreRelease: featuregate.Beta},
11521159

1160+
ResourceHealthStatus: {Default: false, PreRelease: featuregate.Alpha},
1161+
11531162
RotateKubeletServerCertificate: {Default: true, PreRelease: featuregate.Beta},
11541163

11551164
RuntimeClassInImageCriAPI: {Default: false, PreRelease: featuregate.Alpha},

pkg/kubelet/cm/container_manager.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
3333
"k8s.io/kubernetes/pkg/kubelet/apis/podresources"
3434
"k8s.io/kubernetes/pkg/kubelet/cm/devicemanager"
35+
"k8s.io/kubernetes/pkg/kubelet/cm/resourceupdates"
3536
"k8s.io/kubernetes/pkg/kubelet/config"
3637
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
3738
evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api"
@@ -132,6 +133,12 @@ type ContainerManager interface {
132133
// might need to unprepare resources.
133134
PodMightNeedToUnprepareResources(UID types.UID) bool
134135

136+
// UpdateAllocatedResourcesStatus updates the status of allocated resources for the pod.
137+
UpdateAllocatedResourcesStatus(pod *v1.Pod, status *v1.PodStatus)
138+
139+
// Updates returns a channel that receives an Update when the device changed its status.
140+
Updates() <-chan resourceupdates.Update
141+
135142
// Implements the PodResources Provider API
136143
podresources.CPUsProvider
137144
podresources.DevicesProvider

pkg/kubelet/cm/container_manager_linux.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import (
5353
"k8s.io/kubernetes/pkg/kubelet/cm/dra"
5454
"k8s.io/kubernetes/pkg/kubelet/cm/memorymanager"
5555
memorymanagerstate "k8s.io/kubernetes/pkg/kubelet/cm/memorymanager/state"
56+
"k8s.io/kubernetes/pkg/kubelet/cm/resourceupdates"
5657
"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager"
5758
cmutil "k8s.io/kubernetes/pkg/kubelet/cm/util"
5859
"k8s.io/kubernetes/pkg/kubelet/config"
@@ -1027,3 +1028,16 @@ func (cm *containerManagerImpl) UnprepareDynamicResources(pod *v1.Pod) error {
10271028
func (cm *containerManagerImpl) PodMightNeedToUnprepareResources(UID types.UID) bool {
10281029
return cm.draManager.PodMightNeedToUnprepareResources(UID)
10291030
}
1031+
1032+
func (cm *containerManagerImpl) UpdateAllocatedResourcesStatus(pod *v1.Pod, status *v1.PodStatus) {
1033+
1034+
// For now we only support Device Plugin
1035+
cm.deviceManager.UpdateAllocatedResourcesStatus(pod, status)
1036+
1037+
// TODO(SergeyKanzhelev, https://kep.k8s.io/4680): add support for DRA resources which is planned for the next iteration of a KEP.
1038+
}
1039+
1040+
func (cm *containerManagerImpl) Updates() <-chan resourceupdates.Update {
1041+
// TODO(SergeyKanzhelev, https://kep.k8s.io/4680): add support for DRA resources, for now only use device plugin updates. DRA support is planned for the next iteration of a KEP.
1042+
return cm.deviceManager.Updates()
1043+
}

pkg/kubelet/cm/container_manager_stub.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
podresourcesapi "k8s.io/kubelet/pkg/apis/podresources/v1"
2929
"k8s.io/kubernetes/pkg/kubelet/cm/cpumanager"
3030
"k8s.io/kubernetes/pkg/kubelet/cm/memorymanager"
31+
"k8s.io/kubernetes/pkg/kubelet/cm/resourceupdates"
3132
"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager"
3233
"k8s.io/kubernetes/pkg/kubelet/config"
3334
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
@@ -181,6 +182,13 @@ func (cm *containerManagerStub) PodMightNeedToUnprepareResources(UID types.UID)
181182
return false
182183
}
183184

185+
func (cm *containerManagerStub) UpdateAllocatedResourcesStatus(pod *v1.Pod, status *v1.PodStatus) {
186+
}
187+
188+
func (cm *containerManagerStub) Updates() <-chan resourceupdates.Update {
189+
return nil
190+
}
191+
184192
func NewStubContainerManager() ContainerManager {
185193
return &containerManagerStub{shouldResetExtendedResourceCapacity: false}
186194
}

pkg/kubelet/cm/container_manager_windows.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
"k8s.io/kubernetes/pkg/kubelet/cm/cpumanager"
4242
"k8s.io/kubernetes/pkg/kubelet/cm/devicemanager"
4343
"k8s.io/kubernetes/pkg/kubelet/cm/memorymanager"
44+
"k8s.io/kubernetes/pkg/kubelet/cm/resourceupdates"
4445
"k8s.io/kubernetes/pkg/kubelet/cm/topologymanager"
4546
"k8s.io/kubernetes/pkg/kubelet/config"
4647
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
@@ -205,6 +206,19 @@ func (cm *containerManagerImpl) GetResources(pod *v1.Pod, container *v1.Containe
205206
return opts, nil
206207
}
207208

209+
func (cm *containerManagerImpl) UpdateAllocatedResourcesStatus(pod *v1.Pod, status *v1.PodStatus) {
210+
// For now we only support Device Plugin
211+
212+
cm.deviceManager.UpdateAllocatedResourcesStatus(pod, status)
213+
214+
// TODO(SergeyKanzhelev, https://kep.k8s.io/4680): add support for DRA resources when DRA supports Windows
215+
}
216+
217+
func (cm *containerManagerImpl) Updates() <-chan resourceupdates.Update {
218+
// TODO(SergeyKanzhelev, https://kep.k8s.io/4680): add support for DRA resources, for now only use device plugin updates
219+
return cm.deviceManager.Updates()
220+
}
221+
208222
func (cm *containerManagerImpl) UpdatePluginResources(node *schedulerframework.NodeInfo, attrs *lifecycle.PodAdmitAttributes) error {
209223
return cm.deviceManager.UpdatePluginResources(node, attrs)
210224
}

0 commit comments

Comments
 (0)