Merge pull request #122870 from wzshiming/kep-2681

Promote KEP-2681 to GA in 1.30
This commit is contained in:
Kubernetes Prow Robot 2024-02-29 15:11:33 -08:00 committed by GitHub
commit 56a1b075cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 21 additions and 216 deletions

View File

@ -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) {

View File

@ -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) {

View File

@ -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},

View File

@ -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()

View File

@ -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{

View File

@ -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 {