Promote PodIndexLabel for Statefulset and IndexedJob stable (#128387)

* lock feature gate for PodIndexLabel and mark it GA

Signed-off-by: Alay Patel <alayp@nvidia.com>

* add emulated version if testing disabling of PodIndexLabel FG

Signed-off-by: Alay Patel <alayp@nvidia.com>

---------

Signed-off-by: Alay Patel <alayp@nvidia.com>
This commit is contained in:
Alay Patel 2024-11-04 14:11:28 -05:00 committed by GitHub
parent b4d91d1b8a
commit 3e3276e9fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 47 additions and 15 deletions

View File

@ -38,6 +38,7 @@ import (
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/uuid"
utilversion "k8s.io/apimachinery/pkg/util/version"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/apiserver/pkg/util/feature"
@ -1249,6 +1250,10 @@ func TestControllerSyncJob(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
logger, _ := ktesting.NewTestContext(t)
if tc.podIndexLabelDisabled {
// TODO: this will be removed in 1.35 when 1.31 will fall out of support matrix
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultFeatureGate, utilversion.MustParse("1.31"))
}
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.PodIndexLabel, !tc.podIndexLabelDisabled)
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobPodReplacementPolicy, tc.jobPodReplacementPolicy)
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobSuccessPolicy, tc.jobSuccessPolicy)

View File

@ -39,6 +39,7 @@ import (
"k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/intstr"
utilversion "k8s.io/apimachinery/pkg/util/version"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
appsinformers "k8s.io/client-go/informers/apps/v1"
@ -165,7 +166,8 @@ func TestStatefulSetControl(t *testing.T) {
fn func(*testing.T, *apps.StatefulSet, invariantFunc)
obj func() *apps.StatefulSet
}{
{CreatesPods, simpleSetFn},
{CreatesPodsWithPodIndexLabelFeature, simpleSetFn},
{CreatesPodsWithoutPodIndexLabelFeature, simpleSetFn},
{ScalesUp, simpleSetFn},
{ScalesDown, simpleSetFn},
{ReplacesPods, largeSetFn},
@ -208,7 +210,20 @@ func TestStatefulSetControl(t *testing.T) {
}
}
func CreatesPods(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) {
func CreatesPodsWithPodIndexLabelFeature(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) {
createPods(t, set, invariants, true)
}
func CreatesPodsWithoutPodIndexLabelFeature(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) {
createPods(t, set, invariants, false)
}
func createPods(t *testing.T, set *apps.StatefulSet, invariants invariantFunc, isPodIndexLabelEnabled bool) {
if !isPodIndexLabelEnabled {
// TODO: this will be removed in 1.35
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, utilversion.MustParse("1.31"))
}
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodIndexLabel, isPodIndexLabelEnabled)
client := fake.NewSimpleClientset(set)
om, _, ssc := setupController(client)
@ -229,20 +244,21 @@ func CreatesPods(t *testing.T, set *apps.StatefulSet, invariants invariantFunc)
if set.Status.UpdatedReplicas != 3 {
t.Error("Failed to set UpdatedReplicas correctly")
}
// Check all pods have correct pod index label.
if utilfeature.DefaultFeatureGate.Enabled(features.PodIndexLabel) {
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
if err != nil {
t.Error(err)
}
pods, err := om.podsLister.Pods(set.Namespace).List(selector)
if err != nil {
t.Error(err)
}
if len(pods) != 3 {
t.Errorf("Expected 3 pods, got %d", len(pods))
}
for _, pod := range pods {
selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector)
if err != nil {
t.Error(err)
}
pods, err := om.podsLister.Pods(set.Namespace).List(selector)
if err != nil {
t.Error(err)
}
if len(pods) != 3 {
t.Errorf("Expected 3 pods, got %d", len(pods))
}
for _, pod := range pods {
if isPodIndexLabelEnabled {
podIndexFromLabel, exists := pod.Labels[apps.PodIndexLabel]
if !exists {
t.Errorf("Missing pod index label: %s", apps.PodIndexLabel)
@ -252,6 +268,12 @@ func CreatesPods(t *testing.T, set *apps.StatefulSet, invariants invariantFunc)
if podIndexFromLabel != podIndexFromName {
t.Errorf("Pod index label value (%s) does not match pod index in pod name (%s)", podIndexFromLabel, podIndexFromName)
}
} else {
_, exists := pod.Labels[apps.PodIndexLabel]
if exists {
t.Errorf("Pod index label should not exist when feature gate is disabled: %s", apps.PodIndexLabel)
continue
}
}
}
}

View File

@ -559,6 +559,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
PodIndexLabel: {
{Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.35
},
PodLifecycleSleepAction: {

View File

@ -884,6 +884,10 @@
lockToDefault: false
preRelease: Beta
version: "1.28"
- default: true
lockToDefault: true
preRelease: GA
version: "1.32"
- name: PodLifecycleSleepAction
versionedSpecs:
- default: false