Skip to content

pod LifecycleHandler should support a sleep option #114465

@thockin

Description

@thockin

Many people use exec to run sleep in their container. This works, but it's kludgey and requirtes them to have a sleep binary in the image. We should offer sleep as a first-class thing.

I hacked up a quick POC. This is obviopusly incomplete (no tests, no feature gate, poor API docs, etc) but could be a starting point for someone who wants to contribute. I assume it would have to sit in Alpha for a while to deal with back-rev kubelets, so the sooner it gets in the sooner it van be used.

This might warrant a micro KEP, but that's not something to be afraid of. Happy to help if someone wants to pick this up.

My hacky POC:

diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go
index fbbecb00d58..67a16fe629c 100644
--- a/pkg/apis/core/types.go
+++ b/pkg/apis/core/types.go
@@ -2316,6 +2316,8 @@ type LifecycleHandler struct {
 	// lifecycle hooks will fail in runtime when tcp handler is specified.
 	// +optional
 	TCPSocket *TCPSocketAction
+	// Sleep pauses further lifecycle progress for a defined time period.
+	Sleep *SleepAction
 }
 
 type GRPCAction struct {
@@ -2353,6 +2355,12 @@ type Lifecycle struct {
 	PreStop *LifecycleHandler
 }
 
+// SleepAction describes an action which simply sleeps.
+type SleepAction struct {
+	// Seconds is the number of seconds to sleep.
+	Seconds int32
+}
+
 // The below types are used by kube_client and api_server.
 
 // ConditionStatus defines conditions of resources
diff --git a/pkg/kubelet/lifecycle/handlers.go b/pkg/kubelet/lifecycle/handlers.go
index 910c7a42edc..8b56aada182 100644
--- a/pkg/kubelet/lifecycle/handlers.go
+++ b/pkg/kubelet/lifecycle/handlers.go
@@ -26,6 +26,7 @@ import (
 	"net/url"
 	"strconv"
 	"strings"
+	"time"
 
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/types"
@@ -86,6 +87,9 @@ func (hr *handlerRunner) Run(ctx context.Context, containerID kubecontainer.Cont
 			klog.V(1).ErrorS(err, "HTTP lifecycle hook for Container in Pod failed", "path", handler.HTTPGet.Path, "containerName", container.Name, "pod", klog.KObj(pod))
 		}
 		return msg, err
+	case handler.Sleep != nil:
+		hr.runSleepHandler(ctx, handler.Sleep.Seconds)
+		return "", nil
 	default:
 		err := fmt.Errorf("invalid handler: %v", handler)
 		msg := fmt.Sprintf("Cannot run handler: %v", err)
@@ -201,6 +205,10 @@ func discardHTTPRespBody(resp *http.Response) {
 	}
 }
 
+func (hr *handlerRunner) runSleepHandler(ctx context.Context, seconds int32) {
+	time.Sleep(time.Duration(seconds) * time.Second)
+}
+
 // NewAppArmorAdmitHandler returns a PodAdmitHandler which is used to evaluate
 // if a pod can be admitted from the perspective of AppArmor.
 func NewAppArmorAdmitHandler(validator apparmor.Validator) PodAdmitHandler {
diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go
index 0d491bdf84f..2971306c998 100644
--- a/staging/src/k8s.io/api/core/v1/types.go
+++ b/staging/src/k8s.io/api/core/v1/types.go
@@ -2536,6 +2536,8 @@ type LifecycleHandler struct {
 	// lifecycle hooks will fail in runtime when tcp handler is specified.
 	// +optional
 	TCPSocket *TCPSocketAction `json:"tcpSocket,omitempty" protobuf:"bytes,3,opt,name=tcpSocket"`
+	// Sleep pauses further lifecycle progress for a defined time period.
+	Sleep *SleepAction
 }
 
 // Lifecycle describes actions that the management system should take in response to container lifecycle
@@ -2561,6 +2563,12 @@ type Lifecycle struct {
 	PreStop *LifecycleHandler `json:"preStop,omitempty" protobuf:"bytes,2,opt,name=preStop"`
 }
 
+// SleepAction describes an action which simply sleeps.
+type SleepAction struct {
+	// Seconds is the number of seconds to sleep.
+	Seconds int32 `json:"seconds" protobuf:"varint,1,opt,name=seconds"`
+}
+
 type ConditionStatus string
 
 // These are valid condition statuses. "ConditionTrue" means a resource is in the condition.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/apiIndicates an issue on api area.help wantedDenotes an issue that needs help from a contributor. Must meet "help wanted" guidelines.kind/featureCategorizes issue or PR as related to a new feature.needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.priority/backlogHigher priority than priority/awaiting-more-evidence.sig/nodeCategorizes an issue or PR as relevant to SIG Node.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions