Skip to content

feat(crr): implement TCPSocket preStop hook in ContainerRecreateRequest#2506

Open
om7057 wants to merge 2 commits into
openkruise:masterfrom
om7057:feat/tcpsocket-prestop-crr
Open

feat(crr): implement TCPSocket preStop hook in ContainerRecreateRequest#2506
om7057 wants to merge 2 commits into
openkruise:masterfrom
om7057:feat/tcpsocket-prestop-crr

Conversation

@om7057

@om7057 om7057 commented Jul 10, 2026

Copy link
Copy Markdown

What this PR does

Closes #2505

Adds support for executing TCPSocket preStop hooks in the kruise-daemon during ContainerRecreateRequest handling.

TCPSocket was already supported through the CRR flow (webhook injection → CRR spec → daemon pod reconstruction), but the daemon-side lifecycle execution did not handle it. Since the upstream kubelet handler runner only executes Exec, HTTPGet, and Sleep hooks, TCPSocket hooks were skipped.

This PR adds the missing execution path.

Changes

pkg/daemon/kuberuntime/kuberuntime_container.go

  • Handles TCPSocket hooks before falling back to the existing lifecycle hook runner.
  • Adds TCP hook execution by opening a connection to the configured address and closing it after a successful connection.
  • Adds support for resolving both numeric and named ports from the container spec.

pkg/webhook/containerrecreaterequest/mutating/crr_mutating_handler.go

  • Includes container ports when a TCPSocket hook is present, allowing named port references to be resolved correctly by the daemon.

apis/apps/v1alpha1/containerrecreaterequest_types.go

  • Updates outdated comments now that TCPSocket hooks are supported.

Behavior

A TCPSocket preStop hook now succeeds when a connection can be established to the configured host and port. No data is exchanged, matching the existing Kubernetes TCP probe behavior.

This enables CRR lifecycle handling for workloads that rely on TCP-based shutdown coordination instead of HTTP or exec hooks.

The TCPSocket field in ProbeHandler was wired through the entire CRR
pipeline (webhook → spec → daemon) but was never executed, because the
upstream kubelet HandlerRunner only handles Exec, HTTPGet, and Sleep
for lifecycle hooks.

This commit adds first-class TCPSocket support:

- pkg/daemon/kuberuntime/kuberuntime_container.go
  - executeTCPSocketHook: dials the target TCP address using
    net.DialTimeout, treating a successful connection (immediately
    closed) as success — matching Kubernetes probe semantics.
  - resolveTCPSocketPort: resolves IntOrString ports; integer ports
    are validated and used directly; named ports are looked up in
    containerSpec.Ports.
  - executePreStopHook: intercepts TCPSocket before delegating to
    the upstream runner.Run so TCPSocket is no longer a silent no-op.

- pkg/webhook/containerrecreaterequest/mutating/crr_mutating_handler.go
  - Populate c.Ports for TCPSocket hooks (same as HTTPGet) so that
    named port references in TCPSocket.Port can be resolved by the
    daemon.

- apis/apps/v1alpha1/containerrecreaterequest_types.go
  - Remove stale TODO comments from ProbeHandler.TCPSocket and replace
    with accurate documentation of the implemented behaviour.

Fixes openkruise#2505

Signed-off-by: om7057 <kulkarniom7057@gmail.com>
Copilot AI review requested due to automatic review settings July 10, 2026 10:28
@kruise-bot kruise-bot requested review from Fei-Guo and veophi July 10, 2026 10:28
@kruise-bot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign zmberg for approval by writing /assign @zmberg in a comment. For more information see:The Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kruise-bot

Copy link
Copy Markdown

Welcome @om7057! It looks like this is your first PR to openkruise/kruise 🎉

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds execution support for TCPSocket preStop hooks in the kruise-daemon when processing ContainerRecreateRequest (CRR), so TCP-based lifecycle notifications are no longer silently treated as no-ops. It also ensures CRR mutation includes container ports needed for named-port resolution and updates API docs to reflect the now-supported behavior.

Changes:

  • Add explicit handling of TCPSocket in executePreStopHook by dialing the configured TCP host/port within the remaining grace period.
  • Populate CRR container Ports when the preStop hook is HTTPGet or TCPSocket, enabling named-port resolution by the daemon.
  • Update CRR API type comments to document actual TCPSocket preStop semantics.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
pkg/webhook/containerrecreaterequest/mutating/crr_mutating_handler.go Includes container ports in CRR when preStop uses TCPSocket, enabling named port resolution.
pkg/daemon/kuberuntime/kuberuntime_container.go Implements TCPSocket preStop execution via TCP dial and port resolution logic.
apis/apps/v1alpha1/containerrecreaterequest_types.go Updates documentation/comments for TCPSocket hook support and semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +289 to +295
// Fall back to the pod IP when no explicit host is provided. This mirrors
// how the HTTPGet probe handler resolves the target address.
if pod.Status.PodIP != "" {
host = pod.Status.PodIP
} else {
host = "localhost"
}
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.62745% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 50.02%. Comparing base (c9ada9a) to head (a2fd3d7).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
pkg/daemon/kuberuntime/kuberuntime_container.go 76.19% 10 Missing ⚠️
.../daemon/containerrecreate/crr_daemon_controller.go 0.00% 4 Missing ⚠️
...errecreaterequest/mutating/crr_mutating_handler.go 0.00% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2506      +/-   ##
==========================================
+ Coverage   49.91%   50.02%   +0.11%     
==========================================
  Files         325      325              
  Lines       28437    28482      +45     
==========================================
+ Hits        14194    14248      +54     
+ Misses      12588    12577      -11     
- Partials     1655     1657       +2     
Flag Coverage Δ
unittests 50.02% <68.62%> (+0.11%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

… tests

The fake pod built by convertCRRToPod had no Status.PodIP, so the
TCPSocket hook executor would always fall back to 'localhost' when no
explicit Host was set in TCPSocketAction — causing the hook to dial
the kruise-daemon's node address instead of the container's pod IP.

Changes:
- crr_daemon_controller.go: fetch the real Pod before calling
  convertCRRToPod and pass its Status.PodIP.
- crr_daemon_util.go: convertCRRToPod now accepts a podIP string
  and sets Status.PodIP on the fake pod.
- crr_daemon_util_test.go: unit tests for convertCRRToPod covering
  pod IP propagation, grace period defaults, TCPSocket lifecycle
  reconstruction, and no-preStop cases.
- kuberuntime_container_test.go: unit tests for executeTCPSocketHook
  and resolveTCPSocketPort covering success, failure, named ports,
  explicit host, pod IP fallback, localhost fallback, invalid ports,
  and zero grace period clamping.

Signed-off-by: om7057 <kulkarniom7057@gmail.com>
@kruise-bot kruise-bot added size/XL size/XL: 500-999 and removed size/M size/M: 30-99 labels Jul 10, 2026
@om7057

om7057 commented Jul 10, 2026

Copy link
Copy Markdown
Author

E2E failure analysis

The E2E-1.28 / operation failure is not related to this PR.

Root cause: The only actual test failure is PodProbeMarker ... pod probe marker exec test, which timed out with context deadline exceeded while waiting for pod annotations to be updated. This is a pre-existing flaky test in the PodProbeMarker suite — it has nothing to do with ContainerRecreateRequest or TCPSocket hooks.

The other 3 [INTERRUPTED] entries (ContainerRecreateRequest x2, PersistentPodState) were never actually executed — they were killed because --fail-fast aborts the entire suite when any spec fails.

Evidence that this is a pre-existing flake:

  • The E2E-1.28 / operation job passed on our first push (run 29086441331) with identical code minus the pod IP fix and tests
  • The failure appears in the PodProbeMarker suite, which touches no code modified in this PR
  • All other K8s version variants (1.24, 1.26, 1.30, 1.32) passed the operation job cleanly

The failure is a CI timing flake on a shared runner. No code changes needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL size/XL: 500-999

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature request] Support TCPSocket preStop hooks in ContainerRecreateRequest

3 participants