Resolved latest review comments

This commit is contained in:
vivzbansal 2024-12-17 07:56:13 +00:00
parent 242dec3e34
commit 5889da1bbc
4 changed files with 86 additions and 53 deletions

View File

@ -5649,22 +5649,29 @@ func ValidatePodResize(newPod, oldPod *core.Pod, opts PodValidationOptions) fiel
originalCPUMemPodSpec.Containers = newContainers originalCPUMemPodSpec.Containers = newContainers
// Ensure that only CPU and memory resources are mutable for restartable init containers. // Ensure that only CPU and memory resources are mutable for restartable init containers.
// Also ensure that resources are immutable for non-restartable init containers.
var newInitContainers []core.Container var newInitContainers []core.Container
if utilfeature.DefaultFeatureGate.Enabled(features.SidecarContainers) { if utilfeature.DefaultFeatureGate.Enabled(features.SidecarContainers) {
for ix, container := range originalCPUMemPodSpec.InitContainers { for ix, container := range originalCPUMemPodSpec.InitContainers {
if isRestartableInitContainer(&container) { // restartable init container if isRestartableInitContainer(&container) { // restartable init container
dropCPUMemoryResourcesFromContainer(&container, &oldPod.Spec.InitContainers[ix]) dropCPUMemoryResourcesFromContainer(&container, &oldPod.Spec.InitContainers[ix])
if !apiequality.Semantic.DeepEqual(container, oldPod.Spec.InitContainers[ix]) {
// This likely means that the user has made changes to resources other than CPU and memory for sidecar container.
specDiff := cmp.Diff(oldPod.Spec.InitContainers[ix], container)
errs := field.Forbidden(specPath, fmt.Sprintf("only cpu and memory resources for sidecar containers are mutable\n%v", specDiff))
allErrs = append(allErrs, errs)
return allErrs
}
} else if !apiequality.Semantic.DeepEqual(container, oldPod.Spec.InitContainers[ix]) { // non-restartable init container
// This likely means that the user has modified resources of non-sidecar init container.
specDiff := cmp.Diff(oldPod.Spec.InitContainers[ix], container)
errs := field.Forbidden(specPath, fmt.Sprintf("resources for non-sidecar init containers are immutable\n%v", specDiff))
allErrs = append(allErrs, errs)
return allErrs
} }
newInitContainers = append(newInitContainers, container) newInitContainers = append(newInitContainers, container)
} }
originalCPUMemPodSpec.InitContainers = newInitContainers originalCPUMemPodSpec.InitContainers = newInitContainers
if !apiequality.Semantic.DeepEqual(originalCPUMemPodSpec.InitContainers, oldPod.Spec.InitContainers) {
// This likely means that the user has modified non-sidecar container resources.
specDiff := cmp.Diff(oldPod.Spec.InitContainers, originalCPUMemPodSpec.InitContainers)
errs := field.Forbidden(specPath, fmt.Sprintf("cpu and memory resources for only sidecar containers are mutable\n%v", specDiff))
allErrs = append(allErrs, errs)
return allErrs
}
} }
if !apiequality.Semantic.DeepEqual(originalCPUMemPodSpec, oldPod.Spec) { if !apiequality.Semantic.DeepEqual(originalCPUMemPodSpec, oldPod.Spec) {

View File

@ -25911,7 +25911,7 @@ func TestValidatePodResize(t *testing.T) {
test: "Pod QoS unchanged, burstable -> burstable, remove cpu and memory requests", test: "Pod QoS unchanged, burstable -> burstable, remove cpu and memory requests",
old: mkPodWithInitContainers(getResources("100m", "100Mi", "", ""), getResources("100m", "", "", ""), ""), old: mkPodWithInitContainers(getResources("100m", "100Mi", "", ""), getResources("100m", "", "", ""), ""),
new: mkPodWithInitContainers(core.ResourceList{}, getResources("100m", "", "", ""), ""), new: mkPodWithInitContainers(core.ResourceList{}, getResources("100m", "", "", ""), ""),
err: "spec: Forbidden: cpu and memory resources for only sidecar containers are mutable", err: "spec: Forbidden: resources for non-sidecar init containers are immutable",
}, { }, {
test: "Pod with nil Resource field in Status", test: "Pod with nil Resource field in Status",
old: mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetStatus(core.PodStatus{ old: mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetStatus(core.PodStatus{
@ -25993,7 +25993,7 @@ func TestValidatePodResize(t *testing.T) {
test: "storage limit change for sidecar containers", test: "storage limit change for sidecar containers",
old: mkPodWithInitContainers(core.ResourceList{}, getResources("100m", "100Mi", "2Gi", ""), core.ContainerRestartPolicyAlways), old: mkPodWithInitContainers(core.ResourceList{}, getResources("100m", "100Mi", "2Gi", ""), core.ContainerRestartPolicyAlways),
new: mkPodWithInitContainers(core.ResourceList{}, getResources("100m", "100Mi", "1Gi", ""), core.ContainerRestartPolicyAlways), new: mkPodWithInitContainers(core.ResourceList{}, getResources("100m", "100Mi", "1Gi", ""), core.ContainerRestartPolicyAlways),
err: "spec: Forbidden: cpu and memory resources for only sidecar containers are mutable", err: "spec: Forbidden: only cpu and memory resources for sidecar containers are mutable",
}, { }, {
test: "cpu request change for sidecar containers", test: "cpu request change for sidecar containers",
old: mkPodWithInitContainers(getResources("200m", "0", "", ""), core.ResourceList{}, core.ContainerRestartPolicyAlways), old: mkPodWithInitContainers(getResources("200m", "0", "", ""), core.ResourceList{}, core.ContainerRestartPolicyAlways),
@ -26008,7 +26008,7 @@ func TestValidatePodResize(t *testing.T) {
test: "storage request change for sidecar containers", test: "storage request change for sidecar containers",
old: mkPodWithInitContainers(getResources("100m", "0", "1Gi", ""), core.ResourceList{}, core.ContainerRestartPolicyAlways), old: mkPodWithInitContainers(getResources("100m", "0", "1Gi", ""), core.ResourceList{}, core.ContainerRestartPolicyAlways),
new: mkPodWithInitContainers(getResources("100m", "0", "2Gi", ""), core.ResourceList{}, core.ContainerRestartPolicyAlways), new: mkPodWithInitContainers(getResources("100m", "0", "2Gi", ""), core.ResourceList{}, core.ContainerRestartPolicyAlways),
err: "spec: Forbidden: cpu and memory resources for only sidecar containers are mutable", err: "spec: Forbidden: only cpu and memory resources for sidecar containers are mutable",
}, },
} }

View File

@ -6880,44 +6880,59 @@ func TestAllocatedResourcesMatchStatus(t *testing.T) {
}} }}
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { for _, isSidecarContainer := range []bool{false, true} {
allocatedPod := v1.Pod{ t.Run(test.name, func(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{ var podStatus *kubecontainer.PodStatus
Name: "test", state := kubecontainer.ContainerStateRunning
}, if test.statusTerminated {
Spec: v1.PodSpec{ state = kubecontainer.ContainerStateExited
Containers: []v1.Container{{ }
Name: "c",
Resources: test.allocatedResources, allocatedPod := v1.Pod{
}}, ObjectMeta: metav1.ObjectMeta{
InitContainers: []v1.Container{{ Name: "test",
Name: "c1-init",
Resources: test.allocatedResources,
RestartPolicy: &containerRestartPolicyAlways,
}},
},
}
state := kubecontainer.ContainerStateRunning
if test.statusTerminated {
state = kubecontainer.ContainerStateExited
}
podStatus := &kubecontainer.PodStatus{
Name: "test",
ContainerStatuses: []*kubecontainer.Status{
{
Name: "c",
State: state,
Resources: test.statusResources,
}, },
{ }
Name: "c1-init",
State: state, if isSidecarContainer {
Resources: test.statusResources, allocatedPod.Spec = v1.PodSpec{
}, InitContainers: []v1.Container{{
}, Name: "c1-init",
} Resources: test.allocatedResources,
match := allocatedResourcesMatchStatus(&allocatedPod, podStatus) RestartPolicy: &containerRestartPolicyAlways,
assert.Equal(t, test.expectMatch, match) }},
}) }
podStatus = &kubecontainer.PodStatus{
Name: "test",
ContainerStatuses: []*kubecontainer.Status{
{
Name: "c1-init",
State: state,
Resources: test.statusResources,
},
},
}
} else {
allocatedPod.Spec = v1.PodSpec{
Containers: []v1.Container{{
Name: "c",
Resources: test.allocatedResources,
}},
}
podStatus = &kubecontainer.PodStatus{
Name: "test",
ContainerStatuses: []*kubecontainer.Status{
{
Name: "c",
State: state,
Resources: test.statusResources,
},
},
}
}
match := allocatedResourcesMatchStatus(&allocatedPod, podStatus)
assert.Equal(t, test.expectMatch, match)
})
}
} }
} }

View File

@ -45,16 +45,15 @@ func podRequests(pod *corev1.Pod) corev1.ResourceList {
for i := range pod.Status.ContainerStatuses { for i := range pod.Status.ContainerStatuses {
containerStatuses[pod.Status.ContainerStatuses[i].Name] = &pod.Status.ContainerStatuses[i] containerStatuses[pod.Status.ContainerStatuses[i].Name] = &pod.Status.ContainerStatuses[i]
} }
for i := range pod.Status.InitContainerStatuses {
containerStatuses[pod.Status.InitContainerStatuses[i].Name] = &pod.Status.InitContainerStatuses[i]
}
for _, container := range pod.Spec.Containers { for _, container := range pod.Spec.Containers {
containerReqs := container.Resources.Requests containerReqs := container.Resources.Requests
cs, found := containerStatuses[container.Name] cs, found := containerStatuses[container.Name]
if found && cs.Resources != nil { if found && cs.Resources != nil {
if pod.Status.Resize == corev1.PodResizeStatusInfeasible { containerReqs = determineContainerReqs(pod, &container, cs)
containerReqs = cs.Resources.Requests.DeepCopy()
} else {
containerReqs = max(container.Resources.Requests, cs.Resources.Requests)
}
} }
addResourceList(reqs, containerReqs) addResourceList(reqs, containerReqs)
} }
@ -66,6 +65,10 @@ func podRequests(pod *corev1.Pod) corev1.ResourceList {
containerReqs := container.Resources.Requests containerReqs := container.Resources.Requests
if container.RestartPolicy != nil && *container.RestartPolicy == corev1.ContainerRestartPolicyAlways { if container.RestartPolicy != nil && *container.RestartPolicy == corev1.ContainerRestartPolicyAlways {
cs, found := containerStatuses[container.Name]
if found && cs.Resources != nil {
containerReqs = determineContainerReqs(pod, &container, cs)
}
// and add them to the resulting cumulative container requests // and add them to the resulting cumulative container requests
addResourceList(reqs, containerReqs) addResourceList(reqs, containerReqs)
@ -137,6 +140,14 @@ func podLimits(pod *corev1.Pod) corev1.ResourceList {
return limits return limits
} }
// determineContainerReqs will return a copy of the container requests based on if resizing is feasible or not.
func determineContainerReqs(pod *corev1.Pod, container *corev1.Container, cs *corev1.ContainerStatus) corev1.ResourceList {
if pod.Status.Resize == corev1.PodResizeStatusInfeasible {
return cs.Resources.Requests.DeepCopy()
}
return max(container.Resources.Requests, cs.Resources.Requests)
}
// max returns the result of max(a, b) for each named resource and is only used if we can't // max returns the result of max(a, b) for each named resource and is only used if we can't
// accumulate into an existing resource list // accumulate into an existing resource list
func max(a corev1.ResourceList, b corev1.ResourceList) corev1.ResourceList { func max(a corev1.ResourceList, b corev1.ResourceList) corev1.ResourceList {