mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 23:37:01 +00:00
Merge pull request #130574 from natasha41575/drop_proposed_resize_status
[FG:InPlacePodVerticalScaling] Drop `Proposed` resize status
This commit is contained in:
commit
07d66d9c26
@ -19,7 +19,6 @@ package pod
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
metavalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
metavalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
@ -1302,43 +1301,6 @@ func hasInvalidLabelValueInRequiredNodeAffinity(spec *api.PodSpec) bool {
|
|||||||
return helper.HasInvalidLabelValueInNodeSelectorTerms(spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms)
|
return helper.HasInvalidLabelValueInNodeSelectorTerms(spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MarkPodProposedForResize(oldPod, newPod *api.Pod) {
|
|
||||||
if len(newPod.Spec.Containers) != len(oldPod.Spec.Containers) {
|
|
||||||
// Update is invalid: ignore changes and let validation handle it
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.SidecarContainers) && len(newPod.Spec.InitContainers) != len(oldPod.Spec.InitContainers) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, c := range newPod.Spec.Containers {
|
|
||||||
if c.Name != oldPod.Spec.Containers[i].Name {
|
|
||||||
return // Update is invalid (container mismatch): let validation handle it.
|
|
||||||
}
|
|
||||||
if apiequality.Semantic.DeepEqual(oldPod.Spec.Containers[i].Resources, c.Resources) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newPod.Status.Resize = api.PodResizeStatusProposed
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.SidecarContainers) {
|
|
||||||
for i, c := range newPod.Spec.InitContainers {
|
|
||||||
if IsRestartableInitContainer(&c) {
|
|
||||||
if c.Name != oldPod.Spec.InitContainers[i].Name {
|
|
||||||
return // Update is invalid (container mismatch): let validation handle it.
|
|
||||||
}
|
|
||||||
if apiequality.Semantic.DeepEqual(oldPod.Spec.InitContainers[i].Resources, c.Resources) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newPod.Status.Resize = api.PodResizeStatusProposed
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// KEP: https://kep.k8s.io/4639
|
// KEP: https://kep.k8s.io/4639
|
||||||
func dropImageVolumes(podSpec, oldPodSpec *api.PodSpec) {
|
func dropImageVolumes(podSpec, oldPodSpec *api.PodSpec) {
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.ImageVolume) || imageVolumesInUse(oldPodSpec) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.ImageVolume) || imageVolumesInUse(oldPodSpec) {
|
||||||
|
@ -3053,657 +3053,6 @@ func TestDropSidecarContainers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarkPodProposedForResize(t *testing.T) {
|
|
||||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SidecarContainers, true)
|
|
||||||
containerRestartPolicyAlways := api.ContainerRestartPolicyAlways
|
|
||||||
testCases := []struct {
|
|
||||||
desc string
|
|
||||||
newPodSpec api.PodSpec
|
|
||||||
oldPodSpec api.PodSpec
|
|
||||||
expectProposedResize bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
desc: "nil requests",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "resources unchanged",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "requests resized",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "c2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "c2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "limits resized",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "c2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "c2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("500m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "the number of containers in the pod has increased; no action should be taken.",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "c2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "the number of containers in the pod has decreased; no action should be taken.",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "c2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "containers reordered",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "c2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "resources unchanged with sidecar containers",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "requests resized with sidecar containers",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "limits resized with sidecar containers",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("500m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "requests resized should fail with non-sidecar init container",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "limits resized should fail with non-sidecar init containers",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "c1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("500m")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "the number of sidecar containers in the pod has increased; no action should be taken.",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "i2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "the number of sidecar containers in the pod has decreased; no action should be taken.",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "i2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "sidecar containers reordered",
|
|
||||||
newPodSpec: api.PodSpec{
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "i2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
oldPodSpec: api.PodSpec{
|
|
||||||
InitContainers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "i2",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("100m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("200m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "i1",
|
|
||||||
Image: "image",
|
|
||||||
Resources: api.ResourceRequirements{
|
|
||||||
Requests: api.ResourceList{api.ResourceCPU: resource.MustParse("300m")},
|
|
||||||
Limits: api.ResourceList{api.ResourceCPU: resource.MustParse("400m")},
|
|
||||||
},
|
|
||||||
RestartPolicy: &containerRestartPolicyAlways,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectProposedResize: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.desc, func(t *testing.T) {
|
|
||||||
newPod := &api.Pod{Spec: tc.newPodSpec}
|
|
||||||
newPodUnchanged := newPod.DeepCopy()
|
|
||||||
oldPod := &api.Pod{Spec: tc.oldPodSpec}
|
|
||||||
MarkPodProposedForResize(oldPod, newPod)
|
|
||||||
if tc.expectProposedResize {
|
|
||||||
assert.Equal(t, api.PodResizeStatusProposed, newPod.Status.Resize)
|
|
||||||
} else {
|
|
||||||
assert.Equal(t, api.PodResizeStatus(""), newPod.Status.Resize)
|
|
||||||
}
|
|
||||||
newPod.Status.Resize = newPodUnchanged.Status.Resize // Only field that might have changed.
|
|
||||||
assert.Equal(t, newPodUnchanged, newPod, "No fields other than .status.resize should be modified")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDropClusterTrustBundleProjectedVolumes(t *testing.T) {
|
func TestDropClusterTrustBundleProjectedVolumes(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
description string
|
description string
|
||||||
|
@ -2974,8 +2974,6 @@ type PodCondition struct {
|
|||||||
type PodResizeStatus string
|
type PodResizeStatus string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Pod resources resize has been requested and will be evaluated by node.
|
|
||||||
PodResizeStatusProposed PodResizeStatus = "Proposed"
|
|
||||||
// Pod resources resize has been accepted by node and is being actuated.
|
// Pod resources resize has been accepted by node and is being actuated.
|
||||||
PodResizeStatusInProgress PodResizeStatus = "InProgress"
|
PodResizeStatusInProgress PodResizeStatus = "InProgress"
|
||||||
// Node cannot resize the pod at this time and will keep retrying.
|
// Node cannot resize the pod at this time and will keep retrying.
|
||||||
|
@ -404,7 +404,6 @@ func (podResizeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
|
|||||||
oldPod := old.(*api.Pod)
|
oldPod := old.(*api.Pod)
|
||||||
|
|
||||||
*newPod = *dropNonResizeUpdates(newPod, oldPod)
|
*newPod = *dropNonResizeUpdates(newPod, oldPod)
|
||||||
podutil.MarkPodProposedForResize(oldPod, newPod)
|
|
||||||
podutil.DropDisabledPodFields(newPod, oldPod)
|
podutil.DropDisabledPodFields(newPod, oldPod)
|
||||||
updatePodGeneration(newPod, oldPod)
|
updatePodGeneration(newPod, oldPod)
|
||||||
}
|
}
|
||||||
|
@ -3002,7 +3002,6 @@ func TestPodResizePrepareForUpdate(t *testing.T) {
|
|||||||
),
|
),
|
||||||
podtest.SetGeneration(2),
|
podtest.SetGeneration(2),
|
||||||
podtest.SetStatus(podtest.MakePodStatus(
|
podtest.SetStatus(podtest.MakePodStatus(
|
||||||
podtest.SetResizeStatus(api.PodResizeStatusProposed), // Resize status set
|
|
||||||
podtest.SetContainerStatuses(
|
podtest.SetContainerStatuses(
|
||||||
podtest.MakeContainerStatus("init-container1",
|
podtest.MakeContainerStatus("init-container1",
|
||||||
api.ResourceList{
|
api.ResourceList{
|
||||||
|
@ -3335,8 +3335,6 @@ type PodCondition struct {
|
|||||||
type PodResizeStatus string
|
type PodResizeStatus string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Pod resources resize has been requested and will be evaluated by node.
|
|
||||||
PodResizeStatusProposed PodResizeStatus = "Proposed"
|
|
||||||
// Pod resources resize has been accepted by node and is being actuated.
|
// Pod resources resize has been accepted by node and is being actuated.
|
||||||
PodResizeStatusInProgress PodResizeStatus = "InProgress"
|
PodResizeStatusInProgress PodResizeStatus = "InProgress"
|
||||||
// Node cannot resize the pod at this time and will keep retrying.
|
// Node cannot resize the pod at this time and will keep retrying.
|
||||||
|
@ -1159,7 +1159,7 @@ func doPodResizeTests() {
|
|||||||
e2epod.VerifyPodResources(patchedPod, expectedContainers)
|
e2epod.VerifyPodResources(patchedPod, expectedContainers)
|
||||||
|
|
||||||
ginkgo.By(fmt.Sprintf("waiting for %s to be actuated", opStr))
|
ginkgo.By(fmt.Sprintf("waiting for %s to be actuated", opStr))
|
||||||
resizedPod := e2epod.WaitForPodResizeActuation(ctx, f, podClient, newPod)
|
resizedPod := e2epod.WaitForPodResizeActuation(ctx, f, podClient, newPod, expectedContainers)
|
||||||
e2epod.ExpectPodResized(ctx, f, resizedPod, expectedContainers)
|
e2epod.ExpectPodResized(ctx, f, resizedPod, expectedContainers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,17 +386,30 @@ func verifyContainerRestarts(gotStatuses []v1.ContainerStatus, wantStatuses []v1
|
|||||||
return utilerrors.NewAggregate(errs)
|
return utilerrors.NewAggregate(errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WaitForPodResizeActuation(ctx context.Context, f *framework.Framework, podClient *PodClient, pod *v1.Pod) *v1.Pod {
|
func WaitForPodResizeActuation(ctx context.Context, f *framework.Framework, podClient *PodClient, pod *v1.Pod, expectedContainers []ResizableContainerInfo) *v1.Pod {
|
||||||
ginkgo.GinkgoHelper()
|
ginkgo.GinkgoHelper()
|
||||||
// Wait for resize to complete.
|
// Wait for resize to complete.
|
||||||
framework.ExpectNoError(WaitForPodCondition(ctx, f.ClientSet, pod.Namespace, pod.Name, "resize status cleared", f.Timeouts.PodStart,
|
|
||||||
func(pod *v1.Pod) (bool, error) {
|
framework.ExpectNoError(framework.Gomega().
|
||||||
|
Eventually(ctx, framework.RetryNotFound(framework.GetObject(f.ClientSet.CoreV1().Pods(pod.Namespace).Get, pod.Name, metav1.GetOptions{}))).
|
||||||
|
WithTimeout(f.Timeouts.PodStart).
|
||||||
|
Should(framework.MakeMatcher(func(pod *v1.Pod) (func() string, error) {
|
||||||
if pod.Status.Resize == v1.PodResizeStatusInfeasible {
|
if pod.Status.Resize == v1.PodResizeStatusInfeasible {
|
||||||
// This is a terminal resize state
|
// This is a terminal resize state
|
||||||
return false, fmt.Errorf("resize is infeasible")
|
return func() string {
|
||||||
|
return "resize is infeasible"
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
return pod.Status.Resize == "", nil
|
// TODO: Replace this check with a combination of checking the status.observedGeneration
|
||||||
}), "pod should finish resizing")
|
// and the resize status when available.
|
||||||
|
if resourceErrs := VerifyPodStatusResources(pod, expectedContainers); resourceErrs != nil {
|
||||||
|
return func() string {
|
||||||
|
return fmt.Sprintf("container status resources don't match expected: %v", formatErrors(resourceErrs))
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
|
||||||
resizedPod, err := framework.GetObject(podClient.Get, pod.Name, metav1.GetOptions{})(ctx)
|
resizedPod, err := framework.GetObject(podClient.Get, pod.Name, metav1.GetOptions{})(ctx)
|
||||||
framework.ExpectNoError(err, "failed to get resized pod")
|
framework.ExpectNoError(err, "failed to get resized pod")
|
||||||
@ -406,19 +419,6 @@ func WaitForPodResizeActuation(ctx context.Context, f *framework.Framework, podC
|
|||||||
func ExpectPodResized(ctx context.Context, f *framework.Framework, resizedPod *v1.Pod, expectedContainers []ResizableContainerInfo) {
|
func ExpectPodResized(ctx context.Context, f *framework.Framework, resizedPod *v1.Pod, expectedContainers []ResizableContainerInfo) {
|
||||||
ginkgo.GinkgoHelper()
|
ginkgo.GinkgoHelper()
|
||||||
|
|
||||||
// Put each error on a new line for readability.
|
|
||||||
formatErrors := func(err error) error {
|
|
||||||
var agg utilerrors.Aggregate
|
|
||||||
if !errors.As(err, &agg) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
errStrings := make([]string, len(agg.Errors()))
|
|
||||||
for i, err := range agg.Errors() {
|
|
||||||
errStrings[i] = err.Error()
|
|
||||||
}
|
|
||||||
return fmt.Errorf("[\n%s\n]", strings.Join(errStrings, ",\n"))
|
|
||||||
}
|
|
||||||
// Verify Pod Containers Cgroup Values
|
// Verify Pod Containers Cgroup Values
|
||||||
var errs []error
|
var errs []error
|
||||||
if cgroupErrs := VerifyPodContainersCgroupValues(ctx, f, resizedPod, expectedContainers); cgroupErrs != nil {
|
if cgroupErrs := VerifyPodContainersCgroupValues(ctx, f, resizedPod, expectedContainers); cgroupErrs != nil {
|
||||||
@ -460,3 +460,17 @@ func ResizeContainerPatch(containers []ResizableContainerInfo) (string, error) {
|
|||||||
|
|
||||||
return string(patchBytes), nil
|
return string(patchBytes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatErrors(err error) error {
|
||||||
|
// Put each error on a new line for readability.
|
||||||
|
var agg utilerrors.Aggregate
|
||||||
|
if !errors.As(err, &agg) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
errStrings := make([]string, len(agg.Errors()))
|
||||||
|
for i, err := range agg.Errors() {
|
||||||
|
errStrings[i] = err.Error()
|
||||||
|
}
|
||||||
|
return fmt.Errorf("[\n%s\n]", strings.Join(errStrings, ",\n"))
|
||||||
|
}
|
||||||
|
@ -159,7 +159,7 @@ func doPodResizeAdmissionPluginsTests() {
|
|||||||
e2epod.VerifyPodResources(patchedPod, expected)
|
e2epod.VerifyPodResources(patchedPod, expected)
|
||||||
|
|
||||||
ginkgo.By("waiting for resize to be actuated")
|
ginkgo.By("waiting for resize to be actuated")
|
||||||
resizedPod := e2epod.WaitForPodResizeActuation(ctx, f, podClient, newPods[0])
|
resizedPod := e2epod.WaitForPodResizeActuation(ctx, f, podClient, newPods[0], expected)
|
||||||
e2epod.ExpectPodResized(ctx, f, resizedPod, expected)
|
e2epod.ExpectPodResized(ctx, f, resizedPod, expected)
|
||||||
|
|
||||||
ginkgo.By("verifying pod resources after resize")
|
ginkgo.By("verifying pod resources after resize")
|
||||||
|
Loading…
Reference in New Issue
Block a user