mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 12:07:47 +00:00
integration tests for pod resize
This commit is contained in:
parent
33a3d7578b
commit
f1093962b6
@ -23,6 +23,7 @@ import (
|
||||
"testing"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
@ -678,6 +679,253 @@ func TestPodUpdateEphemeralContainers(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodResize(t *testing.T) {
|
||||
// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
|
||||
server := kubeapiservertesting.StartTestServerOrDie(t, nil,
|
||||
append(framework.DefaultTestServerFlags(), "--feature-gates=InPlacePodVerticalScaling=true"),
|
||||
framework.SharedEtcd())
|
||||
defer server.TearDownFn()
|
||||
|
||||
client := clientset.NewForConfigOrDie(server.ClientConfig)
|
||||
|
||||
ns := framework.CreateNamespaceOrDie(client, "pod-create-ephemeral-containers", t)
|
||||
defer framework.DeleteNamespaceOrDie(client, ns, t)
|
||||
|
||||
testPod := func(name string) *v1.Pod {
|
||||
return &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "fake-name",
|
||||
Image: "fakeimage",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
resizeCases := []struct {
|
||||
name string
|
||||
originalRes v1.ResourceRequirements
|
||||
resize v1.ResourceRequirements
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
name: "cpu request change",
|
||||
originalRes: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceCPU: resource.MustParse("10m"),
|
||||
},
|
||||
},
|
||||
resize: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceCPU: resource.MustParse("20m"),
|
||||
},
|
||||
},
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
name: "memory request change",
|
||||
originalRes: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceMemory: resource.MustParse("1Gi"),
|
||||
},
|
||||
},
|
||||
resize: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceMemory: resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
name: "storage request change",
|
||||
originalRes: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceEphemeralStorage: resource.MustParse("1Gi"),
|
||||
},
|
||||
},
|
||||
resize: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceEphemeralStorage: resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range resizeCases {
|
||||
pod := testPod("resize")
|
||||
pod.Spec.Containers[0].Resources = tc.originalRes
|
||||
resp, err := client.CoreV1().Pods(ns.Name).Create(context.TODO(), pod, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error when creating pod: %v", err)
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
|
||||
// Part 1. Resize
|
||||
resp.Spec.Containers[0].Resources = tc.resize
|
||||
if _, err := client.CoreV1().Pods(ns.Name).Update(context.TODO(), resp, metav1.UpdateOptions{}); err == nil {
|
||||
t.Fatalf("Unexpected allowed pod update")
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
} else if !strings.Contains(err.Error(), "spec: Forbidden: pod updates may not change fields other than") {
|
||||
t.Fatalf("Unexpected error when updating pod container resources: %v", err)
|
||||
}
|
||||
|
||||
resp, err = client.CoreV1().Pods(ns.Name).Resize(context.TODO(), resp.Name, resp, metav1.UpdateOptions{})
|
||||
if tc.valid && err != nil {
|
||||
t.Fatalf("Unexpected pod resize failure: %v", err)
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
if !tc.valid && err == nil {
|
||||
t.Fatalf("Unexpected pod resize success")
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
|
||||
// Part 2. Rollback
|
||||
if !tc.valid {
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
continue
|
||||
}
|
||||
resp.Spec.Containers[0].Resources = tc.originalRes
|
||||
_, err = client.CoreV1().Pods(ns.Name).Resize(context.TODO(), resp.Name, resp, metav1.UpdateOptions{})
|
||||
if tc.valid && err != nil {
|
||||
t.Fatalf("Unexpected pod resize failure: %v", err)
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
if !tc.valid && err == nil {
|
||||
t.Fatalf("Unexpected pod resize success")
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
|
||||
patchCases := []struct {
|
||||
name string
|
||||
originalRes v1.ResourceRequirements
|
||||
patchBody string
|
||||
patchType types.PatchType
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
name: "cpu request change (strategic)",
|
||||
originalRes: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceCPU: resource.MustParse("10m"),
|
||||
},
|
||||
},
|
||||
patchType: types.StrategicMergePatchType,
|
||||
patchBody: `{
|
||||
"spec":{
|
||||
"containers":[
|
||||
{
|
||||
"name":"fake-name",
|
||||
"resources": {
|
||||
"requests": {
|
||||
"cpu":"20m"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
name: "cpu request change (merge)",
|
||||
originalRes: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceCPU: resource.MustParse("10m"),
|
||||
},
|
||||
},
|
||||
patchType: types.MergePatchType,
|
||||
patchBody: `{
|
||||
"spec":{
|
||||
"containers":[
|
||||
{
|
||||
"name":"fake-name",
|
||||
"resources": {
|
||||
"requests": {
|
||||
"cpu":"20m"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
name: "cpu request change (JSON)",
|
||||
originalRes: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceCPU: resource.MustParse("10m"),
|
||||
},
|
||||
},
|
||||
patchType: types.JSONPatchType,
|
||||
patchBody: `[{
|
||||
"op":"add",
|
||||
"path":"/spec/containers",
|
||||
"value":[{
|
||||
"name":"fake-name",
|
||||
"resources": {
|
||||
"requests": {
|
||||
"cpu":"20m"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}]`,
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
name: "storage request change (merge)",
|
||||
originalRes: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceCPU: resource.MustParse("10m"),
|
||||
},
|
||||
},
|
||||
patchType: types.MergePatchType,
|
||||
patchBody: `{
|
||||
"spec":{
|
||||
"containers":[
|
||||
{
|
||||
"name":"fake-name",
|
||||
"resources": {
|
||||
"requests": {
|
||||
"ephemeral-storage":"20m"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range patchCases {
|
||||
pod := testPod("resize")
|
||||
pod.Spec.Containers[0].Resources = tc.originalRes
|
||||
if _, err := client.CoreV1().Pods(ns.Name).Create(context.TODO(), pod, metav1.CreateOptions{}); err != nil {
|
||||
t.Fatalf("Unexpected error when creating pod: %v", err)
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
|
||||
if _, err := client.CoreV1().Pods(ns.Name).Patch(context.TODO(), pod.Name, tc.patchType, []byte(tc.patchBody), metav1.PatchOptions{}, "resize"); tc.valid && err != nil {
|
||||
t.Fatalf("Unexpected pod resize failure: %v", err)
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
} else if !tc.valid && err == nil {
|
||||
t.Fatalf("Unexpected pod resize success")
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMutablePodSchedulingDirectives(t *testing.T) {
|
||||
// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
|
||||
server := kubeapiservertesting.StartTestServerOrDie(t, nil, framework.DefaultTestServerFlags(), framework.SharedEtcd())
|
||||
|
@ -406,8 +406,8 @@ func TestCoreResourceEnqueue(t *testing.T) {
|
||||
triggerFn: func(testCtx *testutils.TestContext) (map[framework.ClusterEvent]uint64, error) {
|
||||
// Trigger a PodUpdate event by reducing cpu requested by pod1.
|
||||
// It makes Pod1 schedulable.
|
||||
if _, err := testCtx.ClientSet.CoreV1().Pods(testCtx.NS.Name).Update(testCtx.Ctx, st.MakePod().Name("pod1").Req(map[v1.ResourceName]string{v1.ResourceCPU: "2"}).Container("image").Obj(), metav1.UpdateOptions{}); err != nil {
|
||||
return nil, fmt.Errorf("failed to update the pod: %w", err)
|
||||
if _, err := testCtx.ClientSet.CoreV1().Pods(testCtx.NS.Name).Resize(testCtx.Ctx, "pod1", st.MakePod().Name("pod1").Req(map[v1.ResourceName]string{v1.ResourceCPU: "2"}).Container("image").Obj(), metav1.UpdateOptions{}); err != nil {
|
||||
return nil, fmt.Errorf("failed to resize the pod: %w", err)
|
||||
}
|
||||
return map[framework.ClusterEvent]uint64{{Resource: unschedulablePod, ActionType: framework.UpdatePodScaleDown}: 1}, nil
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user