Skip to content

fix(k8s): pin kubernetes client below 36 and self-heal on 401 - #74

Merged
aron-muon merged 1 commit into
mainfrom
fix/k8s-client-401-recovery
Sep 16, 2026
Merged

aron-muon merged 1 commit into
mainfrom
fix/k8s-client-401-recovery

Conversation

@aron-muon

Copy link
Copy Markdown
Owner

Summary

Background: #72 reported continuous 401s from the Kubernetes API after upgrading to 3.6.0 on AKS, surviving pod restarts, with the only auth-relevant change being the kubernetes client bump 34.1.0 -> 36.0.0. I went looking for the actual regression instead of just pinning blind, and it turned out to be worse than a stale-token bug - client 36.0.0 can't authenticate in-cluster at all. The regenerated Configuration.auth_settings() gates on api_key['BearerToken'], while load_incluster_config's loader (byte-identical across 34/35/36) still writes api_key['authorization'] - so auth_settings() returns {} and every request goes out with no Authorization header. The reported "ran fine for ~3.5 days then broke" was likely the old ReplicaSet still serving until something forced the new image to actually take over.

  • pinned kubernetes>=34.1.0,<36 (resolves to 35.0.0, which I verified behaves like 34.1.0)
  • added regression tests that exercise the real installed client library: auth_settings() must be non-empty for in-cluster config, and a kubelet-rotated token must be served after the cached one expires. these fail on 36.0.0, so a future lockfile bump can't silently reintroduce this class of breakage
  • added throttled reset-on-401 recovery: ApiException handlers in pool.py/job_executor.py now call handle_unauthorized(e.status), which drops the cached CoreV1Api/BatchV1Api so the next call reloads config and re-reads the on-disk SA token instead of failing until restart. throttled to once per 30s so a persistent RBAC problem doesn't turn into config-reload thrash

Testing

I reproduced the regression directly against all 3 client versions with fake in-cluster token files (rewrite token, expire the cache, re-read auth settings):

version: 34.1.0 | auth keys: ['BearerToken'] | after rotation: bearer TOKEN_V2
version: 35.0.0 | auth keys: ['BearerToken'] | after rotation: bearer TOKEN_V2
version: 36.0.0 | auth keys: []              | after rotation: NO AUTH SETTINGS

Full unit suite passes with the pin in place: 1529 passed. The new tests/unit/test_kubernetes_client_auth.py covers the loader regression plus the 401 reset/throttle behavior.

Review Strategy

The pin is the actual fix; the 401 recovery is belt-and-braces for future stale-token failures - if you'd rather ship the pin alone, the recovery commit is separable.

Fixes #72

🤖 Generated with Claude Code

kubernetes-client 36.0.0 breaks in-cluster auth outright: the regenerated
Configuration.auth_settings() reads api_key['BearerToken'] while
load_incluster_config's loader still writes api_key['authorization'], so
auth_settings() returns {} and every API request is sent with no
Authorization header. The API server answers 401 forever (observed on AKS
as continuous 401s that survive pod restarts). Verified empirically:
34.1.0 and 35.0.0 emit the bearer header and pick up kubelet-rotated
tokens; 36.0.0 emits no auth settings at all.

- Pin kubernetes>=34.1.0,<36 (resolves to 35.0.0, verified good).
- Add tests that fail if a future bump reintroduces this class of
  regression (auth_settings empty, or rotated token not refreshed).
- Add throttled reset-on-401 recovery: ApiException handlers now call
  handle_unauthorized(e.status), which drops the cached CoreV1Api/
  BatchV1Api so the next call reloads config and re-reads the on-disk
  ServiceAccount token instead of failing until restart.

Fixes #72

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@aron-muon
aron-muon merged commit 272f2bf into main Sep 16, 2026
32 checks passed
@aron-muon
aron-muon deleted the fix/k8s-client-401-recovery branch September 16, 2026 21:45
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 3.6.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.6.0: kubernetes client 34→36 bump breaks in-cluster auth on AKS after SA token rotation (continuous 401 on pod creation)

1 participant