Skip to content

Commit

Permalink
graduate PodLifecycleSleepAction to beta
Browse files Browse the repository at this point in the history
  • Loading branch information
AxeZhan committed Jan 24, 2024
1 parent 09a5049 commit 072b4e9
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 3 deletions.
3 changes: 2 additions & 1 deletion pkg/features/kube_features.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ const (
// owner: @AxeZhan
// kep: http://kep.k8s.io/3960
// alpha: v1.29
// beta: v1.30
//
// Enables SleepAction in container lifecycle hooks
PodLifecycleSleepAction featuregate.Feature = "PodLifecycleSleepAction"
Expand Down Expand Up @@ -1064,7 +1065,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS

PodHostIPs: {Default: true, PreRelease: featuregate.Beta},

PodLifecycleSleepAction: {Default: false, PreRelease: featuregate.Alpha},
PodLifecycleSleepAction: {Default: true, PreRelease: featuregate.Beta},

PodSchedulingReadiness: {Default: true, PreRelease: featuregate.Beta},

Expand Down
1 change: 1 addition & 0 deletions pkg/kubelet/lifecycle/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func (hr *handlerRunner) runSleepHandler(ctx context.Context, seconds int64) err
select {
case <-ctx.Done():
// unexpected termination
metrics.LifecycleHandlerSleepTerminated.Inc()
return fmt.Errorf("container terminated before sleep hook finished")
case <-c:
return nil
Expand Down
13 changes: 13 additions & 0 deletions pkg/kubelet/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,15 @@ var (
StabilityLevel: metrics.ALPHA,
},
)

LifecycleHandlerSleepTerminated = metrics.NewCounter(
&metrics.CounterOpts{
Subsystem: KubeletSubsystem,
Name: "lifecycle_handler_sleep_terminated_total",
Help: "The number of times lifecycle sleep handler got terminated before it finishes",
StabilityLevel: metrics.ALPHA,
},
)
)

var registerMetrics sync.Once
Expand Down Expand Up @@ -904,6 +913,10 @@ func Register(collectors ...metrics.StableCollector) {
}

legacyregistry.MustRegister(LifecycleHandlerHTTPFallbacks)

if utilfeature.DefaultFeatureGate.Enabled(features.PodLifecycleSleepAction) {
legacyregistry.MustRegister(LifecycleHandlerSleepTerminated)
}
})
}

Expand Down
47 changes: 45 additions & 2 deletions test/e2e/common/node/lifecycle_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,12 +547,12 @@ func getSidecarPodWithHook(name string, image string, lifecycle *v1.Lifecycle) *
}
}

var _ = SIGDescribe(feature.PodLifecycleSleepAction, func() {
var _ = SIGDescribe(nodefeature.PodLifecycleSleepAction, feature.PodLifecycleSleepAction, "Container Lifycycle hook sleep action", func() {
f := framework.NewDefaultFramework("pod-lifecycle-sleep-action")
f.NamespacePodSecurityEnforceLevel = admissionapi.LevelBaseline
var podClient *e2epod.PodClient

ginkgo.Context("when create a pod with lifecycle hook using sleep action", func() {
ginkgo.Context("when create a pod with lifecycle hook", func() {
ginkgo.BeforeEach(func(ctx context.Context) {
podClient = e2epod.NewPodClient(f)
})
Expand Down Expand Up @@ -593,5 +593,48 @@ var _ = SIGDescribe(feature.PodLifecycleSleepAction, func() {
framework.Failf("unexpected delay duration before killing the pod")
}
})

ginkgo.It("ignore terminated container", func(ctx context.Context) {
lifecycle := &v1.Lifecycle{
PreStop: &v1.LifecycleHandler{
Sleep: &v1.SleepAction{Seconds: 10},
},
}
name := "pod-with-prestop-sleep-hook"
podWithHook := getPodWithHook(name, imageutils.GetE2EImage(imageutils.BusyBox), lifecycle)
podWithHook.Spec.Containers[0].Command = []string{"/bin/sh"}
podWithHook.Spec.Containers[0].Args = []string{"-c", "exit 0"}
podWithHook.Spec.RestartPolicy = v1.RestartPolicyNever
ginkgo.By("create the pod with lifecycle hook using sleep action")
p := podClient.Create(ctx, podWithHook)
framework.ExpectNoError(e2epod.WaitForContainerTerminated(ctx, f.ClientSet, f.Namespace.Name, p.Name, name, 3*time.Minute))
ginkgo.By("delete the pod with lifecycle hook using sleep action")
start := time.Now()
podClient.DeleteSync(ctx, podWithHook.Name, metav1.DeleteOptions{}, e2epod.DefaultPodDeletionTimeout)
cost := time.Since(start)
// verify that deletion was not delayed by sleep seconds
if cost >= time.Second*7 {
framework.Failf("unexpected delay duration before killing the pod")
}
})

ginkgo.It("sleep duration boundary", func(ctx context.Context) {
lifecycle := &v1.Lifecycle{
PreStop: &v1.LifecycleHandler{
Sleep: &v1.SleepAction{Seconds: 1},
},
}
podWithHook := getPodWithHook("pod-with-prestop-sleep-hook", imageutils.GetPauseImageName(), lifecycle)
ginkgo.By("create the pod with lifecycle hook using sleep action")
podClient.CreateSync(ctx, podWithHook)
ginkgo.By("delete the pod with lifecycle hook using sleep action")
start := time.Now()
podClient.DeleteSync(ctx, podWithHook.Name, metav1.DeleteOptions{}, e2epod.DefaultPodDeletionTimeout)
cost := time.Since(start)
// verify that deletion was delayed by sleep seconds
if cost < time.Second*1 || cost > time.Second*3 {
framework.Failf("unexpected delay duration before killing the pod")
}
})
})
})
15 changes: 15 additions & 0 deletions test/e2e/framework/pod/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,3 +779,18 @@ func WaitForContainerRunning(ctx context.Context, c clientset.Interface, namespa
return false, nil
})
}

// WaitForContainerRunning waits for the given Pod container to have a state of terminated
func WaitForContainerTerminated(ctx context.Context, c clientset.Interface, namespace, podName, containerName string, timeout time.Duration) error {
conditionDesc := fmt.Sprintf("container %s terminated", containerName)
return WaitForPodCondition(ctx, c, namespace, podName, conditionDesc, timeout, func(pod *v1.Pod) (bool, error) {
for _, statuses := range [][]v1.ContainerStatus{pod.Status.ContainerStatuses, pod.Status.InitContainerStatuses, pod.Status.EphemeralContainerStatuses} {
for _, cs := range statuses {
if cs.Name == containerName {
return cs.State.Terminated != nil, nil
}
}
}
return false, nil
})
}
1 change: 1 addition & 0 deletions test/e2e/nodefeature/nodefeature.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ var (
RuntimeHandler = framework.WithNodeFeature(framework.ValidNodeFeatures.Add("RuntimeHandler"))
SidecarContainers = framework.WithNodeFeature(framework.ValidNodeFeatures.Add("SidecarContainers"))
SystemNodeCriticalPod = framework.WithNodeFeature(framework.ValidNodeFeatures.Add("SystemNodeCriticalPod"))
PodLifecycleSleepAction = framework.WithNodeFeature(framework.ValidNodeFeatures.Add("PodLifecycleSleepAction"))
)

func init() {
Expand Down

0 comments on commit 072b4e9

Please sign in to comment.