Skip to content

Add an opt-in TCP keepalive option to the sync client - #2693

Merged
kubernetes-prow[bot] merged 1 commit into
kubernetes-client:masterfrom
chala2001:tcp-keepalive-option
Sep 2, 2026
Merged

kubernetes-prow[bot] merged 1 commit into
kubernetes-client:masterfrom
chala2001:tcp-keepalive-option

Conversation

@chala2001

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind feature

What this PR does / why we need it:

An idle watch sends nothing on its connection, so a proxy or load balancer in
the path is free to drop it, and the client only finds out on the next read.
client-go avoids this by dialling with a keepalive
(transport/cache.go),
while the Python client asks the kernel for nothing.

Configuration.socket_options already reaches urllib3, so the plumbing exists.
What is missing is a supported way to turn keepalive on without hand-writing
platform specific socket tuples.

This adds Configuration.keep_alive, off by default:

configuration = client.Configuration()
configuration.keep_alive = True

The timings match what client-go actually asks the kernel for. Its
Dialer.KeepAlive: 30 * time.Second becomes the idle time, and Go leaves the
probe interval and count at its own defaults, so on Linux client-go ends up
with TCP_KEEPIDLE=30, TCP_KEEPINTVL=15, TCP_KEEPCNT=9. The helper uses
those three values.

Two details worth flagging:

  • The list is built on top of urllib3's default_socket_options rather than
    replacing them. urllib3 swaps its defaults for whatever list it is handed
    instead of merging, so building on them keeps TCP_NODELAY in place.
  • Each option is hasattr guarded. macOS spells the idle time TCP_KEEPALIVE
    and has no TCP_KEEPIDLE, so a bare reference would raise AttributeError
    at import time there.

socket_options still wins when set, so callers already passing their own list
are unaffected.

The layout follows #2671: the logic is hand-written in kubernetes/utils/, and
the generated client gets a small scripts/keepalive_patch.diff that
update-client.sh re-applies after regeneration.

Sync client only. The asyncio client stores socket_options but never reads it

  • _create_connector builds an aiohttp.TCPConnector, which takes no socket
    options - so parity there is a separate change.

Which issue(s) this PR fixes:

Fixes #2067

Special notes for your reviewer:

kubernetes/utils/keepalive_test.py covers the timings, the preserved urllib3
defaults, the macOS fallback and the platform guard, and checks the pool
manager actually receives the options. Not covered: whether probes reach the
wire, which needs a real idle connection.

#2067 is cross-linked from #1841. That one is the websocket exec stream dying
after 300s idle, which needs ping frames in ws_client.py - a different
mechanism, not fixed here.

Does this PR introduce a user-facing change?

Added an opt-in `keep_alive` option to `Configuration`, enabling TCP keepalive on the sync client's sockets with the same timings client-go uses.

Long lived requests such as watches are dropped silently when an idle
proxy or load balancer closes the connection, because the client never
sends anything on it.

Setting keep_alive on the Configuration now asks the kernel for the
same keepalive timings client-go dials with: probe after 30s idle,
then every 15s, giving up after 9 probes. socket_options still wins
if it is set, so existing callers are unaffected.
@kubernetes-prow kubernetes-prow Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. kind/feature Categorizes issue or PR as related to a new feature. labels Aug 29, 2026
@kubernetes-prow
kubernetes-prow Bot requested review from roycaihw and yliaog August 29, 2026 09:09
@kubernetes-prow kubernetes-prow Bot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Aug 29, 2026
@chala2001

Copy link
Copy Markdown
Contributor Author

Hi @yliaog, when you get a chance could you take a look at this one? It's opt-in and off by default, so nothing changes for anyone who doesn't set it. Happy to adjust anything.

@yliaog

yliaog commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

thanks for the PR

/lgtm
/approve

@kubernetes-prow kubernetes-prow Bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Sep 2, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: chala2001, yliaog

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

The pull request process is described 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

@kubernetes-prow kubernetes-prow Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Sep 2, 2026
@kubernetes-prow
kubernetes-prow Bot merged commit e48904a into kubernetes-client:master Sep 2, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Set tcp keepalive for http connections

2 participants