mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 09:49:50 +00:00
Always set status Resources, default to allocated
This commit is contained in:
parent
0f0e27d226
commit
61c1beeda2
@ -2074,99 +2074,63 @@ 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 {
|
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 should always exist if container is running
|
||||||
oldStatus, oldStatusFound := oldStatuses[cName]
|
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
|
// If the new status is missing resources, then if the container is running and previous
|
||||||
// For ephemeral-storage, a running container's status.limit/request equals spec.limit/request
|
// status was also running, preserve the resources previously reported.
|
||||||
determineResource := func(rName v1.ResourceName, v1ContainerResource, oldStatusResource, resource v1.ResourceList) {
|
preserveOldResourcesValue := func(rName v1.ResourceName, oldStatusResource, resource v1.ResourceList) {
|
||||||
if oldStatusFound {
|
if cStatus.State == kubecontainer.ContainerStateRunning &&
|
||||||
if oldStatus.State.Running == nil || status.ContainerID != oldStatus.ContainerID {
|
oldStatusFound && oldStatus.State.Running != nil &&
|
||||||
if r, exists := v1ContainerResource[rName]; exists {
|
status.ContainerID == oldStatus.ContainerID &&
|
||||||
resource[rName] = r.DeepCopy()
|
oldStatusResource != nil {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if oldStatusResource != nil {
|
|
||||||
if r, exists := oldStatusResource[rName]; exists {
|
if r, exists := oldStatusResource[rName]; exists {
|
||||||
resource[rName] = r.DeepCopy()
|
resource[rName] = r.DeepCopy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always set the status to the latest allocated resources, even if it differs from the
|
// Always set the status to the latest allocated resources, even if it differs from the
|
||||||
// allocation used by the current sync loop.
|
// allocation used by the current sync loop.
|
||||||
alloc, found := kl.statusManager.GetContainerResourceAllocation(string(pod.UID), cName)
|
alloc, found := kl.statusManager.GetContainerResourceAllocation(string(pod.UID), cName)
|
||||||
if !found {
|
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.
|
// Don't set status.Resources in this case.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if cStatus.State != kubecontainer.ContainerStateRunning {
|
||||||
|
// If the container isn't running, just use the allocated resources.
|
||||||
|
return &alloc
|
||||||
|
}
|
||||||
if oldStatus.Resources == nil {
|
if oldStatus.Resources == nil {
|
||||||
oldStatus.Resources = &v1.ResourceRequirements{}
|
oldStatus.Resources = &v1.ResourceRequirements{}
|
||||||
}
|
}
|
||||||
|
|
||||||
convertCustomResources := func(inResources, outResources v1.ResourceList) {
|
// Status resources default to the allocated resources.
|
||||||
for resourceName, resourceQuantity := range inResources {
|
// For non-running containers this will be the reported values.
|
||||||
if resourceName == v1.ResourceCPU || resourceName == v1.ResourceMemory ||
|
// For non-resizable resources, these values will also be used.
|
||||||
resourceName == v1.ResourceStorage || resourceName == v1.ResourceEphemeralStorage {
|
resources := alloc
|
||||||
continue
|
if resources.Limits != nil {
|
||||||
}
|
|
||||||
|
|
||||||
outResources[resourceName] = resourceQuantity.DeepCopy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert Limits
|
|
||||||
if alloc.Limits != nil {
|
|
||||||
limits = make(v1.ResourceList)
|
|
||||||
if cStatus.Resources != nil && cStatus.Resources.CPULimit != 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 {
|
} 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 {
|
if cStatus.Resources != nil && cStatus.Resources.MemoryLimit != nil {
|
||||||
limits[v1.ResourceMemory] = cStatus.Resources.MemoryLimit.DeepCopy()
|
resources.Limits[v1.ResourceMemory] = cStatus.Resources.MemoryLimit.DeepCopy()
|
||||||
} else {
|
} 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 {
|
if resources.Requests != nil {
|
||||||
limits[v1.ResourceStorage] = storage.DeepCopy()
|
|
||||||
}
|
|
||||||
|
|
||||||
convertCustomResources(alloc.Limits, limits)
|
|
||||||
}
|
|
||||||
// Convert Requests
|
|
||||||
if alloc.Requests != nil {
|
|
||||||
requests = make(v1.ResourceList)
|
|
||||||
if cStatus.Resources != nil && cStatus.Resources.CPURequest != 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 {
|
} 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)
|
return &resources
|
||||||
}
|
|
||||||
|
|
||||||
resources := &v1.ResourceRequirements{
|
|
||||||
Limits: limits,
|
|
||||||
Requests: requests,
|
|
||||||
}
|
|
||||||
return resources
|
|
||||||
}
|
}
|
||||||
|
|
||||||
convertContainerStatusUser := func(cStatus *kubecontainer.Status) *v1.ContainerUser {
|
convertContainerStatusUser := func(cStatus *kubecontainer.Status) *v1.ContainerUser {
|
||||||
@ -2335,9 +2299,7 @@ func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecon
|
|||||||
}
|
}
|
||||||
status := convertContainerStatus(cStatus, oldStatusPtr)
|
status := convertContainerStatus(cStatus, oldStatusPtr)
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScaling) {
|
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 utilfeature.DefaultFeatureGate.Enabled(features.InPlacePodVerticalScalingAllocatedStatus) {
|
||||||
if alloc, found := kl.statusManager.GetContainerResourceAllocation(string(pod.UID), cName); found {
|
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) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.SupplementalGroupsPolicy) {
|
||||||
status.User = convertContainerStatusUser(cStatus)
|
status.User = convertContainerStatusUser(cStatus)
|
||||||
}
|
}
|
||||||
|
@ -4567,26 +4567,39 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
ContainerStatuses: []v1.ContainerStatus{testContainerStatus},
|
ContainerStatuses: []v1.ContainerStatus{testContainerStatus},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
testKubeContainerStatus := kubecontainer.Status{
|
|
||||||
|
testPodStatus := func(state kubecontainer.State, resources *kubecontainer.ContainerResources) *kubecontainer.PodStatus {
|
||||||
|
cStatus := kubecontainer.Status{
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ID: testContainerID,
|
ID: testContainerID,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "1234",
|
ImageID: "1234",
|
||||||
ImageRef: "img1234",
|
ImageRef: "img1234",
|
||||||
State: kubecontainer.ContainerStateRunning,
|
State: state,
|
||||||
StartedAt: nowTime,
|
Resources: resources,
|
||||||
}
|
}
|
||||||
testPodStatus := &kubecontainer.PodStatus{
|
switch state {
|
||||||
|
case kubecontainer.ContainerStateRunning:
|
||||||
|
cStatus.StartedAt = nowTime
|
||||||
|
case kubecontainer.ContainerStateExited:
|
||||||
|
cStatus.StartedAt = nowTime
|
||||||
|
cStatus.FinishedAt = nowTime
|
||||||
|
}
|
||||||
|
return &kubecontainer.PodStatus{
|
||||||
ID: testPod.UID,
|
ID: testPod.UID,
|
||||||
Name: testPod.Name,
|
Name: testPod.Name,
|
||||||
Namespace: testPod.Namespace,
|
Namespace: testPod.Namespace,
|
||||||
ContainerStatuses: []*kubecontainer.Status{&testKubeContainerStatus},
|
ContainerStatuses: []*kubecontainer.Status{&cStatus},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CPU1AndMem1G := v1.ResourceList{v1.ResourceCPU: resource.MustParse("1"), v1.ResourceMemory: resource.MustParse("1Gi")}
|
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")}
|
CPU2AndMem2G := v1.ResourceList{v1.ResourceCPU: resource.MustParse("2"), v1.ResourceMemory: resource.MustParse("2Gi")}
|
||||||
CPU1AndMem1GAndStorage2G := CPU1AndMem1G.DeepCopy()
|
CPU1AndMem1GAndStorage2G := CPU1AndMem1G.DeepCopy()
|
||||||
CPU1AndMem1GAndStorage2G[v1.ResourceEphemeralStorage] = resource.MustParse("2Gi")
|
CPU1AndMem1GAndStorage2G[v1.ResourceEphemeralStorage] = resource.MustParse("2Gi")
|
||||||
CPU1AndMem1GAndStorage2G[v1.ResourceStorage] = resource.MustParse("2Gi")
|
CPU1AndMem1GAndStorage2G[v1.ResourceStorage] = resource.MustParse("2Gi")
|
||||||
|
CPU1AndMem2GAndStorage2G := CPU1AndMem1GAndStorage2G.DeepCopy()
|
||||||
|
CPU1AndMem2GAndStorage2G[v1.ResourceMemory] = resource.MustParse("2Gi")
|
||||||
CPU2AndMem2GAndStorage2G := CPU2AndMem2G.DeepCopy()
|
CPU2AndMem2GAndStorage2G := CPU2AndMem2G.DeepCopy()
|
||||||
CPU2AndMem2GAndStorage2G[v1.ResourceEphemeralStorage] = resource.MustParse("2Gi")
|
CPU2AndMem2GAndStorage2G[v1.ResourceEphemeralStorage] = resource.MustParse("2Gi")
|
||||||
CPU2AndMem2GAndStorage2G[v1.ResourceStorage] = resource.MustParse("2Gi")
|
CPU2AndMem2GAndStorage2G[v1.ResourceStorage] = resource.MustParse("2Gi")
|
||||||
@ -4612,23 +4625,22 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
|
|
||||||
idx := 0
|
idx := 0
|
||||||
for tdesc, tc := range map[string]struct {
|
for tdesc, tc := range map[string]struct {
|
||||||
Resources []v1.ResourceRequirements
|
State kubecontainer.State // Defaults to Running
|
||||||
OldStatus []v1.ContainerStatus
|
Resources v1.ResourceRequirements
|
||||||
Expected []v1.ContainerStatus
|
AllocatedResources *v1.ResourceRequirements // Defaults to Resources
|
||||||
|
OldStatus v1.ContainerStatus
|
||||||
|
Expected v1.ContainerStatus
|
||||||
}{
|
}{
|
||||||
"GuaranteedQoSPod with CPU and memory CRI status": {
|
"GuaranteedQoSPod with CPU and memory CRI status": {
|
||||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G}},
|
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4638,20 +4650,16 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"BurstableQoSPod with CPU and memory CRI status": {
|
"BurstableQoSPod with CPU and memory CRI status": {
|
||||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G}},
|
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2G, Requests: CPU1AndMem1G},
|
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2G, Requests: CPU1AndMem1G},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4661,20 +4669,16 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"GuaranteedQoSPod with CPU and memory CRI status, with ephemeral storage": {
|
"GuaranteedQoSPod with CPU and memory CRI status, with ephemeral storage": {
|
||||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G}},
|
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1G, Requests: CPU1AndMem1G},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4684,20 +4688,16 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"BurstableQoSPod with CPU and memory CRI status, with ephemeral storage": {
|
"BurstableQoSPod with CPU and memory CRI status, with ephemeral storage": {
|
||||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G}},
|
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2GAndStorage2G, Requests: CPU2AndMem2GAndStorage2G},
|
Resources: &v1.ResourceRequirements{Limits: CPU2AndMem2GAndStorage2G, Requests: CPU2AndMem2GAndStorage2G},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4707,19 +4707,15 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"BurstableQoSPod with CPU and memory CRI status, with ephemeral storage, nil resources in OldStatus": {
|
"BurstableQoSPod with CPU and memory CRI status, with ephemeral storage, nil resources in OldStatus": {
|
||||||
Resources: []v1.ResourceRequirements{{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G}},
|
Resources: v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4729,19 +4725,15 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
Resources: &v1.ResourceRequirements{Limits: CPU1AndMem1GAndStorage2G, Requests: CPU1AndMem1GAndStorage2G},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"BestEffortQoSPod": {
|
"BestEffortQoSPod": {
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{},
|
Resources: &v1.ResourceRequirements{},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4750,20 +4742,16 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{},
|
Resources: &v1.ResourceRequirements{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"BestEffort QoSPod with extended resources": {
|
"BestEffort QoSPod with extended resources": {
|
||||||
Resources: []v1.ResourceRequirements{{Requests: addExtendedResource(v1.ResourceList{})}},
|
Resources: v1.ResourceRequirements{Requests: addExtendedResource(v1.ResourceList{})},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{},
|
Resources: &v1.ResourceRequirements{},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4773,20 +4761,16 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(v1.ResourceList{})},
|
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(v1.ResourceList{})},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"BurstableQoSPod with extended resources": {
|
"BurstableQoSPod with extended resources": {
|
||||||
Resources: []v1.ResourceRequirements{{Requests: addExtendedResource(CPU1AndMem1G)}},
|
Resources: v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G)},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{},
|
Resources: &v1.ResourceRequirements{},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4796,20 +4780,16 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G)},
|
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"BurstableQoSPod with storage, ephemeral storage and extended resources": {
|
"BurstableQoSPod with storage, ephemeral storage and extended resources": {
|
||||||
Resources: []v1.ResourceRequirements{{Requests: addExtendedResource(CPU1AndMem1GAndStorage2G)}},
|
Resources: v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1GAndStorage2G)},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{},
|
Resources: &v1.ResourceRequirements{},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4819,20 +4799,16 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1GAndStorage2G)},
|
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1GAndStorage2G)},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
"GuaranteedQoSPod with extended resources": {
|
"GuaranteedQoSPod with extended resources": {
|
||||||
Resources: []v1.ResourceRequirements{{Requests: addExtendedResource(CPU1AndMem1G), Limits: addExtendedResource(CPU1AndMem1G)}},
|
Resources: v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G), Limits: addExtendedResource(CPU1AndMem1G)},
|
||||||
OldStatus: []v1.ContainerStatus{
|
OldStatus: v1.ContainerStatus{
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
Image: "img",
|
Image: "img",
|
||||||
ImageID: "img1234",
|
ImageID: "img1234",
|
||||||
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||||
Resources: &v1.ResourceRequirements{},
|
Resources: &v1.ResourceRequirements{},
|
||||||
},
|
},
|
||||||
},
|
Expected: v1.ContainerStatus{
|
||||||
Expected: []v1.ContainerStatus{
|
|
||||||
{
|
|
||||||
Name: testContainerName,
|
Name: testContainerName,
|
||||||
ContainerID: testContainerID.String(),
|
ContainerID: testContainerID.String(),
|
||||||
Image: "img",
|
Image: "img",
|
||||||
@ -4842,24 +4818,105 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
Resources: &v1.ResourceRequirements{Requests: addExtendedResource(CPU1AndMem1G), Limits: 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) {
|
t.Run(tdesc, func(t *testing.T) {
|
||||||
tPod := testPod.DeepCopy()
|
tPod := testPod.DeepCopy()
|
||||||
tPod.Name = fmt.Sprintf("%s-%d", testPod.Name, idx)
|
tPod.Name = fmt.Sprintf("%s-%d", testPod.Name, idx)
|
||||||
for i := range tPod.Spec.Containers {
|
|
||||||
if tc.Resources != nil {
|
if tc.AllocatedResources != nil {
|
||||||
tPod.Spec.Containers[i].Resources = tc.Resources[i]
|
tPod.Spec.Containers[0].Resources = *tc.AllocatedResources
|
||||||
|
} else {
|
||||||
|
tPod.Spec.Containers[0].Resources = tc.Resources
|
||||||
}
|
}
|
||||||
kubelet.statusManager.SetPodAllocation(tPod)
|
kubelet.statusManager.SetPodAllocation(tPod)
|
||||||
if tc.Resources != nil {
|
resources := &kubecontainer.ContainerResources{
|
||||||
testPodStatus.ContainerStatuses[i].Resources = &kubecontainer.ContainerResources{
|
MemoryLimit: tc.Resources.Limits.Memory(),
|
||||||
MemoryLimit: tc.Resources[i].Limits.Memory(),
|
CPULimit: tc.Resources.Limits.Cpu(),
|
||||||
CPULimit: tc.Resources[i].Limits.Cpu(),
|
CPURequest: tc.Resources.Requests.Cpu(),
|
||||||
CPURequest: tc.Resources[i].Requests.Cpu(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
state := kubecontainer.ContainerStateRunning
|
||||||
|
if tc.State != "" {
|
||||||
|
state = tc.State
|
||||||
}
|
}
|
||||||
|
podStatus := testPodStatus(state, resources)
|
||||||
|
|
||||||
for _, enableAllocatedStatus := range []bool{true, false} {
|
for _, enableAllocatedStatus := range []bool{true, false} {
|
||||||
t.Run(fmt.Sprintf("AllocatedStatus=%t", enableAllocatedStatus), func(t *testing.T) {
|
t.Run(fmt.Sprintf("AllocatedStatus=%t", enableAllocatedStatus), func(t *testing.T) {
|
||||||
@ -4867,15 +4924,12 @@ func TestConvertToAPIContainerStatusesForResources(t *testing.T) {
|
|||||||
|
|
||||||
expected := tc.Expected
|
expected := tc.Expected
|
||||||
if !enableAllocatedStatus {
|
if !enableAllocatedStatus {
|
||||||
for i, status := range expected {
|
expected = *expected.DeepCopy()
|
||||||
noAllocated := *status.DeepCopy()
|
expected.AllocatedResources = nil
|
||||||
noAllocated.AllocatedResources = nil
|
|
||||||
expected[i] = noAllocated
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cStatuses := kubelet.convertToAPIContainerStatuses(tPod, testPodStatus, tc.OldStatus, tPod.Spec.Containers, false, false)
|
cStatuses := kubelet.convertToAPIContainerStatuses(tPod, podStatus, []v1.ContainerStatus{tc.OldStatus}, tPod.Spec.Containers, false, false)
|
||||||
assert.Equal(t, expected, cStatuses)
|
assert.Equal(t, expected, cStatuses[0])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user