mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
Always set status Resources, default to allocated
This commit is contained in:
parent
0f0e27d226
commit
61c1beeda2
@ -2074,24 +2074,18 @@ func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecon
|
||||
}
|
||||
|
||||
convertContainerStatusResources := func(cName string, status *v1.ContainerStatus, cStatus *kubecontainer.Status, oldStatuses map[string]v1.ContainerStatus) *v1.ResourceRequirements {
|
||||
var requests, limits v1.ResourceList
|
||||
// oldStatus should always exist if container is running
|
||||
oldStatus, oldStatusFound := oldStatuses[cName]
|
||||
// Initialize limits/requests from container's spec upon transition to Running state
|
||||
// For cpu & memory, values queried from runtime via CRI always supercedes spec values
|
||||
// For ephemeral-storage, a running container's status.limit/request equals spec.limit/request
|
||||
determineResource := func(rName v1.ResourceName, v1ContainerResource, oldStatusResource, resource v1.ResourceList) {
|
||||
if oldStatusFound {
|
||||
if oldStatus.State.Running == nil || status.ContainerID != oldStatus.ContainerID {
|
||||
if r, exists := v1ContainerResource[rName]; exists {
|
||||
resource[rName] = r.DeepCopy()
|
||||
}
|
||||
} else {
|
||||
if oldStatusResource != nil {
|
||||
if r, exists := oldStatusResource[rName]; exists {
|
||||
resource[rName] = r.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
// If the new status is missing resources, then if the container is running and previous
|
||||
// status was also running, preserve the resources previously reported.
|
||||
preserveOldResourcesValue := func(rName v1.ResourceName, oldStatusResource, resource v1.ResourceList) {
|
||||
if cStatus.State == kubecontainer.ContainerStateRunning &&
|
||||
oldStatusFound && oldStatus.State.Running != nil &&
|
||||
status.ContainerID == oldStatus.ContainerID &&
|
||||
oldStatusResource != nil {
|
||||
if r, exists := oldStatusResource[rName]; exists {
|
||||
resource[rName] = r.DeepCopy()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2100,73 +2094,43 @@ func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecon
|
||||
// allocation used by the current sync loop.
|
||||
alloc, found := kl.statusManager.GetContainerResourceAllocation(string(pod.UID), cName)
|
||||
if !found {
|
||||
// This case is expected for non-resizeable containers.
|
||||
// This case is expected for non-resizable containers.
|
||||
// Don't set status.Resources in this case.
|
||||
return nil
|
||||
}
|
||||
if cStatus.State != kubecontainer.ContainerStateRunning {
|
||||
// If the container isn't running, just use the allocated resources.
|
||||
return &alloc
|
||||
}
|
||||
if oldStatus.Resources == nil {
|
||||
oldStatus.Resources = &v1.ResourceRequirements{}
|
||||
}
|
||||
|
||||
convertCustomResources := func(inResources, outResources v1.ResourceList) {
|
||||
for resourceName, resourceQuantity := range inResources {
|
||||
if resourceName == v1.ResourceCPU || resourceName == v1.ResourceMemory ||
|
||||
resourceName == v1.ResourceStorage || resourceName == v1.ResourceEphemeralStorage {
|
||||
continue
|
||||
}
|
||||
|
||||
outResources[resourceName] = resourceQuantity.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
// Convert Limits
|
||||
if alloc.Limits != nil {
|
||||
limits = make(v1.ResourceList)
|
||||
// Status resources default to the allocated resources.
|
||||
// For non-running containers this will be the reported values.
|
||||
// For non-resizable resources, these values will also be used.
|
||||
resources := alloc
|
||||
if resources.Limits != nil {
|
||||
if cStatus.Resources != nil && cStatus.Resources.CPULimit != nil {
|
||||
limits[v1.ResourceCPU] = cStatus.Resources.CPULimit.DeepCopy()
|
||||
resources.Limits[v1.ResourceCPU] = cStatus.Resources.CPULimit.DeepCopy()
|
||||
} else {
|
||||
determineResource(v1.ResourceCPU, alloc.Limits, oldStatus.Resources.Limits, limits)
|
||||
preserveOldResourcesValue(v1.ResourceCPU, oldStatus.Resources.Limits, resources.Limits)
|
||||
}
|
||||
if cStatus.Resources != nil && cStatus.Resources.MemoryLimit != nil {
|
||||
limits[v1.ResourceMemory] = cStatus.Resources.MemoryLimit.DeepCopy()
|
||||
resources.Limits[v1.ResourceMemory] = cStatus.Resources.MemoryLimit.DeepCopy()
|
||||
} else {
|
||||
determineResource(v1.ResourceMemory, alloc.Limits, oldStatus.Resources.Limits, limits)
|
||||
preserveOldResourcesValue(v1.ResourceMemory, oldStatus.Resources.Limits, resources.Limits)
|
||||
}
|
||||
if ephemeralStorage, found := alloc.Limits[v1.ResourceEphemeralStorage]; found {
|
||||
limits[v1.ResourceEphemeralStorage] = ephemeralStorage.DeepCopy()
|
||||
}
|
||||
if storage, found := alloc.Limits[v1.ResourceStorage]; found {
|
||||
limits[v1.ResourceStorage] = storage.DeepCopy()
|
||||
}
|
||||
|
||||
convertCustomResources(alloc.Limits, limits)
|
||||
}
|
||||
// Convert Requests
|
||||
if alloc.Requests != nil {
|
||||
requests = make(v1.ResourceList)
|
||||
if resources.Requests != nil {
|
||||
if cStatus.Resources != nil && cStatus.Resources.CPURequest != nil {
|
||||
requests[v1.ResourceCPU] = cStatus.Resources.CPURequest.DeepCopy()
|
||||
resources.Requests[v1.ResourceCPU] = cStatus.Resources.CPURequest.DeepCopy()
|
||||
} else {
|
||||
determineResource(v1.ResourceCPU, alloc.Requests, oldStatus.Resources.Requests, requests)
|
||||
preserveOldResourcesValue(v1.ResourceCPU, oldStatus.Resources.Requests, resources.Requests)
|
||||
}
|
||||
if memory, found := alloc.Requests[v1.ResourceMemory]; found {
|
||||
requests[v1.ResourceMemory] = memory.DeepCopy()
|
||||
}
|
||||
if ephemeralStorage, found := alloc.Requests[v1.ResourceEphemeralStorage]; found {
|
||||
requests[v1.ResourceEphemeralStorage] = ephemeralStorage.DeepCopy()
|
||||
}
|
||||
if storage, found := alloc.Requests[v1.ResourceStorage]; found {
|
||||
requests[v1.ResourceStorage] = storage.DeepCopy()
|
||||
}
|
||||
|
||||
convertCustomResources(alloc.Requests, requests)
|
||||
}
|
||||
|
||||
resources := &v1.ResourceRequirements{
|
||||
Limits: limits,
|
||||
Requests: requests,
|
||||
}
|
||||
return resources
|
||||
return &resources
|
||||
}
|
||||
|
||||
convertContainerStatusUser := func(cStatus *kubecontainer.Status) *v1.ContainerUser {
|
||||
@ -2335,9 +2299,7 @@ func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecon
|
||||
}
|
||||
status := convertContainerStatus(cStatus, oldStatusPtr)
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) {
|
||||
if status.State.Running != nil {
|
||||
status.Resources = convertContainerStatusResources(cName, status, cStatus, oldStatuses)
|
||||
}
|
||||
status.Resources = convertContainerStatusResources(cName, status, cStatus, oldStatuses)
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScalingAllocatedStatus) {
|
||||
if alloc, found := kl.statusManager.GetContainerResourceAllocation(string(pod.UID), cName); found {
|
||||
@ -2345,6 +2307,7 @@ func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.SupplementalGroupsPolicy) {
|
||||
status.User = convertContainerStatusUser(cStatus)
|
||||
}
|
||||
|
@ -4567,26 +4567,39 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
||||
ContainerStatuses: []v1.ContainerStatus{testContainerStatus},
|
||||
},
|
||||
}
|
||||
testKubeContainerStatus := kubecontainer.Status{
|
||||
Name: testContainerName,
|
||||
ID: testContainerID,
|
||||
Image: "img",
|
||||
ImageID: "1234",
|
||||
ImageRef: "img1234",
|
||||
State: kubecontainer.ContainerStateRunning,
|
||||
StartedAt: nowTime,
|
||||
}
|
||||
testPodStatus := &kubecontainer.PodStatus{
|
||||
ID: testPod.UID,
|
||||
Name: testPod.Name,
|
||||
Namespace: testPod.Namespace,
|
||||
ContainerStatuses: []*kubecontainer.Status{&testKubeContainerStatus},
|
||||
|
||||
testPodStatus := func(state kubecontainer.State, resources *kubecontainer.ContainerResources) *kubecontainer.PodStatus {
|
||||
cStatus := kubecontainer.Status{
|
||||
Name: testContainerName,
|
||||
ID: testContainerID,
|
||||
Image: "img",
|
||||
ImageID: "1234",
|
||||
ImageRef: "img1234",
|
||||
State: state,
|
||||
Resources: resources,
|
||||
}
|
||||
switch state {
|
||||
case kubecontainer.ContainerStateRunning:
|
||||
cStatus.StartedAt = nowTime
|
||||
case kubecontainer.ContainerStateExited:
|
||||
cStatus.StartedAt = nowTime
|
||||
cStatus.FinishedAt = nowTime
|
||||
}
|
||||
return &kubecontainer.PodStatus{
|
||||
ID: testPod.UID,
|
||||
Name: testPod.Name,
|
||||
Namespace: testPod.Namespace,
|
||||
ContainerStatuses: []*kubecontainer.Status{&cStatus},
|
||||
}
|
||||
}
|
||||
|
||||
CPU1AndMem1G := v1.ResourceList{v1.ResourceCPU: resource.MustParse("1"), v1.ResourceMemory: resource.MustParse("1Gi")}
|
||||
CPU2AndMem2G := v1.ResourceList{v1.ResourceCPU: resource.MustParse("2"), v1.ResourceMemory: resource.MustParse("2Gi")}
|
||||
CPU1AndMem1GAndStorage2G := CPU1AndMem1G.DeepCopy()
|
||||
CPU1AndMem1GAndStorage2G[v1.ResourceEphemeralStorage] = resource.MustParse("2Gi")
|
||||
CPU1AndMem1GAndStorage2G[v1.ResourceStorage] = resource.MustParse("2Gi")
|
||||
CPU1AndMem2GAndStorage2G := CPU1AndMem1GAndStorage2G.DeepCopy()
|
||||
CPU1AndMem2GAndStorage2G[v1.ResourceMemory] = resource.MustParse("2Gi")
|
||||
CPU2AndMem2GAndStorage2G := CPU2AndMem2G.DeepCopy()
|
||||
CPU2AndMem2GAndStorage2G[v1.ResourceEphemeralStorage] = resource.MustParse("2Gi")
|
||||
CPU2AndMem2GAndStorage2G[v1.ResourceStorage] = resource.MustParse("2Gi")
|
||||
@ -4612,254 +4625,298 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
||||
|
||||
idx := 0
|
||||
for tdesc, tc := range map[string]struct {
|
||||
Resources []v1.ResourceRequirements
|
||||
OldStatus []v1.ContainerStatus
|
||||
Expected []v1.ContainerStatus
|
||||
State kubecontainer.State // Defaults to Running
|
||||
Resources v1.ResourceRequirements
|
||||
AllocatedResources *v1.ResourceRequirements // Defaults to Resources
|
||||
OldStatus v1.ContainerStatus
|
||||
Expected v1.ContainerStatus
|
||||
}{
|
||||
"GuaranteedQoSPod with CPU and memory CRI status": {
|
||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
},
|
||||
"BurstableQoSPod with CPU and memory CRI status": {
|
||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
},
|
||||
"GuaranteedQoSPod with CPU and memory CRI status, with ephemeral storage": {
|
||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
},
|
||||
"BurstableQoSPod with CPU and memory CRI status, with ephemeral storage": {
|
||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2GAndStorage2G, Requests: CPU2AndMem2GAndStorage2G},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2GAndStorage2G, Requests: CPU2AndMem2GAndStorage2G},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
},
|
||||
"BurstableQoSPod with CPU and memory CRI status, with ephemeral storage, nil resources in OldStatus": {
|
||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
},
|
||||
"BestEffortQoSPod": {
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
},
|
||||
"BestEffort QoSPod with extended resources": {
|
||||
Resources: []v1.ResourceRequirements{{Requests: addExtendedResource(v1.ResourceList{})}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Requests: addExtendedResource(v1.ResourceList{})},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: addExtendedResource(v1.ResourceList{}),
|
||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(v1.ResourceList{})},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: addExtendedResource(v1.ResourceList{}),
|
||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(v1.ResourceList{})},
|
||||
},
|
||||
},
|
||||
"BurstableQoSPod with extended resources": {
|
||||
Resources: []v1.ResourceRequirements{{Requests: addExtendedResource(CPU1AndMem1G)}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G)},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: addExtendedResource(CPU1AndMem1G),
|
||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G)},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: addExtendedResource(CPU1AndMem1G),
|
||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G)},
|
||||
},
|
||||
},
|
||||
"BurstableQoSPod with storage, ephemeral storage and extended resources": {
|
||||
Resources: []v1.ResourceRequirements{{Requests: addExtendedResource(CPU1AndMem1GAndStorage2G)}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1GAndStorage2G)},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: addExtendedResource(CPU1AndMem1GAndStorage2G),
|
||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1GAndStorage2G)},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: addExtendedResource(CPU1AndMem1GAndStorage2G),
|
||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1GAndStorage2G)},
|
||||
},
|
||||
},
|
||||
"GuaranteedQoSPod with extended resources": {
|
||||
Resources: []v1.ResourceRequirements{{Requests: addExtendedResource(CPU1AndMem1G), Limits: addExtendedResource(CPU1AndMem1G)}},
|
||||
OldStatus: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G), Limits: addExtendedResource(CPU1AndMem1G)},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{},
|
||||
},
|
||||
Expected: []v1.ContainerStatus{
|
||||
{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: addExtendedResource(CPU1AndMem1G),
|
||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G), Limits: addExtendedResource(CPU1AndMem1G)},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: addExtendedResource(CPU1AndMem1G),
|
||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G), Limits: addExtendedResource(CPU1AndMem1G)},
|
||||
},
|
||||
},
|
||||
"newly created Pod": {
|
||||
State: kubecontainer.ContainerStateCreated,
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
OldStatus: v1.ContainerStatus{},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}},
|
||||
AllocatedResources: CPU1AndMem1GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
},
|
||||
"newly running Pod": {
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Waiting: &v1.ContainerStateWaiting{}},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU1AndMem1GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
},
|
||||
"newly terminated Pod": {
|
||||
State: kubecontainer.ContainerStateExited,
|
||||
// Actual resources were different, but they should be ignored once the container is terminated.
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
AllocatedResources: &v1.ResourceRequirements{Limits: CPU2AndMem2GAndStorage2G, Requests: CPU2AndMem2GAndStorage2G},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Terminated: &v1.ContainerStateTerminated{
|
||||
ContainerID: testContainerID.String(),
|
||||
StartedAt: metav1.NewTime(nowTime),
|
||||
FinishedAt: metav1.NewTime(nowTime),
|
||||
}},
|
||||
AllocatedResources: CPU2AndMem2GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2GAndStorage2G, Requests: CPU2AndMem2GAndStorage2G},
|
||||
},
|
||||
},
|
||||
"resizing Pod": {
|
||||
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
AllocatedResources: &v1.ResourceRequirements{Limits: CPU2AndMem2GAndStorage2G, Requests: CPU2AndMem2GAndStorage2G},
|
||||
OldStatus: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||
},
|
||||
Expected: v1.ContainerStatus{
|
||||
Name: testContainerName,
|
||||
ContainerID: testContainerID.String(),
|
||||
Image: "img",
|
||||
ImageID: "img1234",
|
||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{StartedAt: metav1.NewTime(nowTime)}},
|
||||
AllocatedResources: CPU2AndMem2GAndStorage2G,
|
||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem2GAndStorage2G},
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(tdesc, func(t *testing.T) {
|
||||
tPod := testPod.DeepCopy()
|
||||
tPod.Name = fmt.Sprintf("%s-%d", testPod.Name, idx)
|
||||
for i := range tPod.Spec.Containers {
|
||||
if tc.Resources != nil {
|
||||
tPod.Spec.Containers[i].Resources = tc.Resources[i]
|
||||
}
|
||||
kubelet.statusManager.SetPodAllocation(tPod)
|
||||
if tc.Resources != nil {
|
||||
testPodStatus.ContainerStatuses[i].Resources = &kubecontainer.ContainerResources{
|
||||
MemoryLimit: tc.Resources[i].Limits.Memory(),
|
||||
CPULimit: tc.Resources[i].Limits.Cpu(),
|
||||
CPURequest: tc.Resources[i].Requests.Cpu(),
|
||||
}
|
||||
}
|
||||
|
||||
if tc.AllocatedResources != nil {
|
||||
tPod.Spec.Containers[0].Resources = *tc.AllocatedResources
|
||||
} else {
|
||||
tPod.Spec.Containers[0].Resources = tc.Resources
|
||||
}
|
||||
kubelet.statusManager.SetPodAllocation(tPod)
|
||||
resources := &kubecontainer.ContainerResources{
|
||||
MemoryLimit: tc.Resources.Limits.Memory(),
|
||||
CPULimit: tc.Resources.Limits.Cpu(),
|
||||
CPURequest: tc.Resources.Requests.Cpu(),
|
||||
}
|
||||
state := kubecontainer.ContainerStateRunning
|
||||
if tc.State != "" {
|
||||
state = tc.State
|
||||
}
|
||||
podStatus := testPodStatus(state, resources)
|
||||
|
||||
for _, enableAllocatedStatus := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("AllocatedStatus=%t", enableAllocatedStatus), func(t *testing.T) {
|
||||
@ -4867,15 +4924,12 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
||||
|
||||
expected := tc.Expected
|
||||
if !enableAllocatedStatus {
|
||||
for i, status := range expected {
|
||||
noAllocated := *status.DeepCopy()
|
||||
noAllocated.AllocatedResources = nil
|
||||
expected[i] = noAllocated
|
||||
}
|
||||
expected = *expected.DeepCopy()
|
||||
expected.AllocatedResources = nil
|
||||
}
|
||||
|
||||
cStatuses := kubelet.convertToAPIContainerStatuses(tPod, testPodStatus, tc.OldStatus, tPod.Spec.Containers, false, false)
|
||||
assert.Equal(t, expected, cStatuses)
|
||||
cStatuses := kubelet.convertToAPIContainerStatuses(tPod, podStatus, []v1.ContainerStatus{tc.OldStatus}, tPod.Spec.Containers, false, false)
|
||||
assert.Equal(t, expected, cStatuses[0])
|
||||
})
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user