diff --git a/pkg/api/pod/util_test.go b/pkg/api/pod/util_test.go index e25a84143ca..113529acffd 100644 --- a/pkg/api/pod/util_test.go +++ b/pkg/api/pod/util_test.go @@ -1179,81 +1179,42 @@ func TestDropDisabledPodStatusFields(t *testing.T) { } tests := []struct { - name string - podStatus *api.PodStatus - oldPodStatus *api.PodStatus - wantPodStatus *api.PodStatus - featureEnabled bool + name string + podStatus *api.PodStatus + oldPodStatus *api.PodStatus + wantPodStatus *api.PodStatus }{ { - name: "gate off, old=without, new=without", - oldPodStatus: podWithoutHostIPs(), - podStatus: podWithoutHostIPs(), - featureEnabled: false, + name: "old=without, new=without", + oldPodStatus: podWithoutHostIPs(), + podStatus: podWithoutHostIPs(), wantPodStatus: podWithoutHostIPs(), }, { - name: "gate off, old=without, new=with", - oldPodStatus: podWithoutHostIPs(), - podStatus: podWithHostIPs(), - featureEnabled: false, - - wantPodStatus: podWithoutHostIPs(), - }, - { - name: "gate off, old=with, new=without", - oldPodStatus: podWithHostIPs(), - podStatus: podWithoutHostIPs(), - featureEnabled: false, - - wantPodStatus: podWithoutHostIPs(), - }, - { - name: "gate off, old=with, new=with", - oldPodStatus: podWithHostIPs(), - podStatus: podWithHostIPs(), - featureEnabled: false, + name: "old=without, new=with", + oldPodStatus: podWithoutHostIPs(), + podStatus: podWithHostIPs(), wantPodStatus: podWithHostIPs(), }, { - name: "gate on, old=without, new=without", - oldPodStatus: podWithoutHostIPs(), - podStatus: podWithoutHostIPs(), - featureEnabled: true, + name: "old=with, new=without", + oldPodStatus: podWithHostIPs(), + podStatus: podWithoutHostIPs(), wantPodStatus: podWithoutHostIPs(), }, { - name: "gate on, old=without, new=with", - oldPodStatus: podWithoutHostIPs(), - podStatus: podWithHostIPs(), - featureEnabled: true, - - wantPodStatus: podWithHostIPs(), - }, - { - name: "gate on, old=with, new=without", - oldPodStatus: podWithHostIPs(), - podStatus: podWithoutHostIPs(), - featureEnabled: true, - - wantPodStatus: podWithoutHostIPs(), - }, - { - name: "gate on, old=with, new=with", - oldPodStatus: podWithHostIPs(), - podStatus: podWithHostIPs(), - featureEnabled: true, + name: "old=with, new=with", + oldPodStatus: podWithHostIPs(), + podStatus: podWithHostIPs(), wantPodStatus: podWithHostIPs(), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodHostIPs, tt.featureEnabled)() - dropDisabledPodStatusFields(tt.podStatus, tt.oldPodStatus, &api.PodSpec{}, &api.PodSpec{}) if !reflect.DeepEqual(tt.podStatus, tt.wantPodStatus) { diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index 1ae129e8a4f..a2e09cbb556 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -24590,18 +24590,6 @@ func TestValidateDownwardAPIHostIPs(t *testing.T) { featureEnabled: true, fieldSel: &core.ObjectFieldSelector{FieldPath: "status.hostIPs"}, }, - { - name: "has no hostIPs field, featuregate disabled", - expectError: false, - featureEnabled: false, - fieldSel: &core.ObjectFieldSelector{FieldPath: "status.hostIP"}, - }, - { - name: "has hostIPs field, featuregate disabled", - expectError: true, - featureEnabled: false, - fieldSel: &core.ObjectFieldSelector{FieldPath: "status.hostIPs"}, - }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 549499de179..b181b13f608 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -596,6 +596,7 @@ const ( // kep: http://kep.k8s.io/2681 // alpha: v1.28 // beta: v1.29 + // GA: v1.30 // // Adds pod.status.hostIPs and downward API PodHostIPs featuregate.Feature = "PodHostIPs" @@ -1088,7 +1089,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS PodReadyToStartContainersCondition: {Default: true, PreRelease: featuregate.Beta}, - PodHostIPs: {Default: true, PreRelease: featuregate.Beta}, + PodHostIPs: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.32 PodLifecycleSleepAction: {Default: true, PreRelease: featuregate.Beta}, diff --git a/pkg/kubelet/kubelet_pods_test.go b/pkg/kubelet/kubelet_pods_test.go index 6e8e92c3220..90c42dde60f 100644 --- a/pkg/kubelet/kubelet_pods_test.go +++ b/pkg/kubelet/kubelet_pods_test.go @@ -408,7 +408,6 @@ func TestMakeEnvironmentVariables(t *testing.T) { testCases := []struct { name string // the name of the test case ns string // the namespace to generate environment for - enablePodHostIPs bool // enable PodHostIPs feature gate enableServiceLinks *bool // enabling service links container *v1.Container // the container to use nilLister bool // whether the lister should be nil @@ -643,7 +642,6 @@ func TestMakeEnvironmentVariables(t *testing.T) { }, { name: "downward api pod", - enablePodHostIPs: true, ns: "downward-api", enableServiceLinks: &falseValue, container: &v1.Container{ @@ -737,7 +735,6 @@ func TestMakeEnvironmentVariables(t *testing.T) { }, { name: "downward api pod ips reverse order", - enablePodHostIPs: true, ns: "downward-api", enableServiceLinks: &falseValue, container: &v1.Container{ @@ -791,7 +788,6 @@ func TestMakeEnvironmentVariables(t *testing.T) { }, { name: "downward api pod ips multiple ips", - enablePodHostIPs: true, ns: "downward-api", enableServiceLinks: &falseValue, container: &v1.Container{ @@ -1988,36 +1984,10 @@ func TestMakeEnvironmentVariables(t *testing.T) { }, expectedError: true, }, - { - name: "downward api pod without host ips", - enablePodHostIPs: false, - ns: "downward-api", - enableServiceLinks: &falseValue, - container: &v1.Container{ - Env: []v1.EnvVar{ - { - Name: "HOST_IPS", - ValueFrom: &v1.EnvVarSource{ - FieldRef: &v1.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "status.hostIPs", - }, - }, - }, - }, - }, - podIPs: []string{"1.2.3.4", "fd00::6"}, - nilLister: true, - expectedEnvs: []kubecontainer.EnvVar{ - {Name: "HOST_IPS", Value: ""}, - }, - }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodHostIPs, tc.enablePodHostIPs)() - fakeRecorder := record.NewFakeRecorder(1) testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) testKubelet.kubelet.recorder = fakeRecorder @@ -3304,7 +3274,6 @@ func Test_generateAPIPodStatus(t *testing.T) { tests := []struct { name string - enablePodHostIPs bool // enable PodHostIPs feature gate pod *v1.Pod currentStatus *kubecontainer.PodStatus unreadyContainer []string @@ -3349,6 +3318,7 @@ func Test_generateAPIPodStatus(t *testing.T) { expected: v1.PodStatus{ Phase: v1.PodFailed, HostIP: "127.0.0.1", + HostIPs: []v1.HostIP{{IP: "127.0.0.1"}, {IP: "::1"}}, QOSClass: v1.PodQOSBestEffort, Conditions: []v1.PodCondition{ {Type: v1.PodInitialized, Status: v1.ConditionTrue}, @@ -3390,7 +3360,6 @@ func Test_generateAPIPodStatus(t *testing.T) { runningState("containerB"), }, }, - enablePodHostIPs: true, expected: v1.PodStatus{ Phase: v1.PodRunning, HostIP: "127.0.0.1", @@ -3430,7 +3399,6 @@ func Test_generateAPIPodStatus(t *testing.T) { runningState("containerB"), }, }, - enablePodHostIPs: true, expected: v1.PodStatus{ Phase: v1.PodRunning, HostIP: "127.0.0.1", @@ -3471,7 +3439,6 @@ func Test_generateAPIPodStatus(t *testing.T) { runningState("containerB"), }, }, - enablePodHostIPs: true, expected: v1.PodStatus{ Phase: v1.PodSucceeded, HostIP: "127.0.0.1", @@ -3516,7 +3483,6 @@ func Test_generateAPIPodStatus(t *testing.T) { Reason: "Test", Message: "test", }, - enablePodHostIPs: true, expected: v1.PodStatus{ Phase: v1.PodSucceeded, HostIP: "127.0.0.1", @@ -3570,7 +3536,6 @@ func Test_generateAPIPodStatus(t *testing.T) { Reason: "Test", Message: "test", }, - enablePodHostIPs: true, expected: v1.PodStatus{ Phase: v1.PodSucceeded, HostIP: "127.0.0.1", @@ -3613,7 +3578,6 @@ func Test_generateAPIPodStatus(t *testing.T) { waitingState("containerB"), }, }, - enablePodHostIPs: true, expected: v1.PodStatus{ Phase: v1.PodPending, HostIP: "127.0.0.1", @@ -3667,7 +3631,6 @@ func Test_generateAPIPodStatus(t *testing.T) { runningState("containerB"), }, }, - enablePodHostIPs: true, expected: v1.PodStatus{ Phase: v1.PodPending, Reason: "Test", @@ -3729,7 +3692,6 @@ func Test_generateAPIPodStatus(t *testing.T) { runningState("containerB"), }, }, - enablePodHostIPs: true, expected: v1.PodStatus{ Phase: v1.PodRunning, HostIP: "127.0.0.1", @@ -3756,7 +3718,6 @@ func Test_generateAPIPodStatus(t *testing.T) { for _, enablePodReadyToStartContainersCondition := range []bool{false, true} { t.Run(test.name, func(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodDisruptionConditions, test.enablePodDisruptionConditions)() - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodHostIPs, test.enablePodHostIPs)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodReadyToStartContainersCondition, enablePodReadyToStartContainersCondition)() testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup() diff --git a/test/e2e/network/dual_stack.go b/test/e2e/network/dual_stack.go index bfa1527a268..f3e746875ee 100644 --- a/test/e2e/network/dual_stack.go +++ b/test/e2e/network/dual_stack.go @@ -112,7 +112,7 @@ var _ = common.SIGDescribe(feature.IPv6DualStack, func() { framework.ExpectNoError(err, "failed to delete pod") }) - f.It("should create pod, add ipv6 and ipv4 ip to host ips", feature.PodHostIPs, func(ctx context.Context) { + f.It("should create pod, add ipv6 and ipv4 ip to host ips", func(ctx context.Context) { podName := "pod-dualstack-ips" pod := &v1.Pod{ diff --git a/test/e2e_node/pod_host_ips.go b/test/e2e_node/pod_host_ips.go index d1e5b137718..b4e0b678ace 100644 --- a/test/e2e_node/pod_host_ips.go +++ b/test/e2e_node/pod_host_ips.go @@ -31,7 +31,6 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" kubefeatures "k8s.io/kubernetes/pkg/features" - kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2enetwork "k8s.io/kubernetes/test/e2e/framework/network" @@ -49,55 +48,7 @@ var _ = common.SIGDescribe("DualStack Host IP", framework.WithSerial(), nodefeat f := framework.NewDefaultFramework("dualstack") f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged - ginkgo.Context("when creating a Pod, it has no PodHostIPs feature", func() { - tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) { - initialConfig.FeatureGates = map[string]bool{ - string(kubefeatures.PodHostIPs): false, - } - }) - ginkgo.It("should create pod, add host ips is empty", func(ctx context.Context) { - - podName := "pod-dualstack-host-ips" - - pod := genPodHostIPs(podName+string(uuid.NewUUID()), false) - - ginkgo.By("submitting the pod to kubernetes") - podClient := e2epod.NewPodClient(f) - p := podClient.CreateSync(ctx, pod) - - gomega.Expect(p.Status.HostIP).ShouldNot(gomega.BeEquivalentTo("")) - gomega.Expect(p.Status.HostIPs).Should(gomega.BeNil()) - - ginkgo.By("deleting the pod") - err := podClient.Delete(ctx, pod.Name, *metav1.NewDeleteOptions(1)) - framework.ExpectNoError(err, "failed to delete pod") - }) - - ginkgo.It("should create pod with hostNetwork, add host ips is empty", func(ctx context.Context) { - - podName := "pod-dualstack-host-ips" - - pod := genPodHostIPs(podName+string(uuid.NewUUID()), true) - - ginkgo.By("submitting the pod to kubernetes") - podClient := e2epod.NewPodClient(f) - p := podClient.CreateSync(ctx, pod) - - gomega.Expect(p.Status.HostIP).ShouldNot(gomega.BeEquivalentTo("")) - gomega.Expect(p.Status.HostIPs).Should(gomega.BeNil()) - - ginkgo.By("deleting the pod") - err := podClient.Delete(ctx, pod.Name, *metav1.NewDeleteOptions(1)) - framework.ExpectNoError(err, "failed to delete pod") - }) - }) - - ginkgo.Context("when creating a Pod, it has PodHostIPs feature", func() { - tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) { - initialConfig.FeatureGates = map[string]bool{ - string(kubefeatures.PodHostIPs): true, - } - }) + ginkgo.Context("when creating a Pod", func() { ginkgo.It("should create pod, add ipv6 and ipv4 ip to host ips", func(ctx context.Context) { podName := "pod-dualstack-host-ips" @@ -207,63 +158,6 @@ var _ = common.SIGDescribe("DualStack Host IP", framework.WithSerial(), nodefeat testDownwardAPI(ctx, f, podName, env, expectations) }) }) - - ginkgo.Context("when feature rollback", func() { - tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) { - initialConfig.FeatureGates = map[string]bool{ - string(kubefeatures.PodHostIPs): true, - } - }) - ginkgo.It("should able upgrade and rollback", func(ctx context.Context) { - podName := "pod-dualstack-host-ips" - - pod := genPodHostIPs(podName+string(uuid.NewUUID()), false) - - ginkgo.By("submitting the pod to kubernetes") - podClient := e2epod.NewPodClient(f) - p := podClient.CreateSync(ctx, pod) - - gomega.Expect(p.Status.HostIPs).ShouldNot(gomega.BeNil()) - - ginkgo.By("Disable PodHostIPs feature") - cfg, err := getCurrentKubeletConfig(ctx) - framework.ExpectNoError(err) - - newCfg := cfg.DeepCopy() - newCfg.FeatureGates = map[string]bool{ - string(kubefeatures.PodHostIPs): false, - } - - updateKubeletConfig(ctx, f, newCfg, true) - - gomega.Expect(p.Status.HostIPs).ShouldNot(gomega.BeNil()) - - ginkgo.By("deleting the pod") - err = podClient.Delete(ctx, pod.Name, *metav1.NewDeleteOptions(1)) - framework.ExpectNoError(err, "failed to delete pod") - - ginkgo.By("recreate pod") - pod = genPodHostIPs(podName+string(uuid.NewUUID()), false) - p = podClient.CreateSync(ctx, pod) - // Feature PodHostIPs is disabled, HostIPs should be nil - gomega.Expect(p.Status.HostIPs).Should(gomega.BeNil()) - - newCfg.FeatureGates = map[string]bool{ - string(kubefeatures.PodHostIPs): true, - } - - updateKubeletConfig(ctx, f, newCfg, true) - - p, err = podClient.Get(ctx, pod.Name, metav1.GetOptions{}) - framework.ExpectNoError(err) - // Feature PodHostIPs is enabled, HostIPs should not be nil - gomega.Expect(p.Status.HostIPs).ShouldNot(gomega.BeNil()) - - ginkgo.By("deleting the pod") - err = podClient.Delete(ctx, pod.Name, *metav1.NewDeleteOptions(1)) - framework.ExpectNoError(err, "failed to delete pod") - }) - }) }) func genPodHostIPs(podName string, hostNetwork bool) *v1.Pod {