[Kubernetes] In a pod, context=None means this cluster, not the kubeconfig's current-context - #6
Open
tigist-far wants to merge 1 commit into
Open
tigist-far wants to merge 1 commit into
tigist-far wants to merge 1 commit into
Conversation
…econfig's current-context Utilities that accept `context=None` substituted the kubeconfig's current-context name and handed it to the API client explicitly. Inside a pod that is the wrong answer: the client adaptor authenticates an explicit name through the kubeconfig, and the kubeconfig a managed-jobs controller holds is the *client's* (the API server rebuilds it from the client's `KUBECONFIG` at every launch), whose current-context may authenticate through an exec plugin the pod does not have. The provisioner passes `context=None` on the controller (`get_context_from_config` maps the in-cluster context to None so pods are created with in-cluster auth). A launch pinned with `allowed_nodes` names or ips lists nodes per pod through `get_kubernetes_nodes(context=None)`, which substituted the client's current-context and failed every pod with `unknown command "oidc-login" for "kubectl"` -- once per pod, on every retry -- while an unpinned launch of the same task provisioned fine. `resolve_current_context()` returns the in-cluster context name when in-cluster auth is available and the kubeconfig's current-context otherwise; the five substitutions in this module use it. The adaptor takes the in-cluster name through in-cluster auth, and per-context config lookups now key on the cluster the pod is in rather than on whichever context the client had selected. Outside a pod nothing changes. Tests cover both environments and an explicit context. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Collaborator
Author
|
Checks run for this PR (the repository runs no CI on PRs): |
tigist-far
force-pushed
the
farai/main
branch
from
September 9, 2026 12:40
4811d0a to
68ea8ba
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A managed job pinned to nodes (
kubernetes.allowed_nodeswithnamesorips) failed to provision on the jobs controller — every pod, every retry — withunknown command "oidc-login" for "kubectl", while the same task unpinned provisioned fine.Cause. The controller provisions with
context=None:get_context_from_configmaps the in-cluster context toNoneso pods are created with in-cluster auth. Pinning is the only path that lists nodes per pod (inject_allowed_nodes_affinity→get_kubernetes_nodes), andget_kubernetes_nodes(context=None)replacedNonewith the kubeconfig's current-context name before building its client. The adaptor authenticates an explicit name through the kubeconfig, and the kubeconfig on the controller is the client's, rebuilt by the API server from the client'sKUBECONFIGat every launch: its current-context was the developer's other cluster, authenticated with an exec plugin the pod does not have.flowchart LR L["client launch<br/>allowed_nodes set"] --> C["jobs controller pod<br/>context=None (in-cluster auth)"] C --> P["inject_allowed_nodes_affinity"] P --> N["get_kubernetes_nodes(context=None)"] N -- before --> K["current-context NAME from the<br/>client's kubeconfig → exec plugin<br/>oidc-login: not in the pod"] N -- after --> I["resolve_current_context()<br/>→ in-cluster context, in-cluster auth"]Fix.
resolve_current_context()returns the in-cluster context name when in-cluster auth is available and the kubeconfig's current-context otherwise. The five places insky/provision/kubernetes/utils.pythat substituted the current-context name forNoneuse it:get_kubernetes_nodesget_allocated_resources_by_nodeget_kubernetes_node_info(two substitutions)get_skypilot_podsOutside a pod nothing changes: the kubeconfig's current-context is used as before, and an explicit context is used as given.
Areas changed
sky/provision/kubernetes/utils.pyresolve_current_context(); the fiveNone → current-contextsubstitutions above go through ittests/unit_tests/kubernetes/test_kubernetes_utils.pycontext=Nonereaches the client as the in-cluster context and the allowed-nodes filter sees the same name; outside a pod it is still the kubeconfig's current-context; an explicit context is used as givenTesting
tests/unit_tests/kubernetes/test_kubernetes_utils.py: 212 passed (the three new tests included). The fork has no GitHub Actions on pull requests.Upstream
The same code is on upstream
master(get_kubernetes_nodesandget_context_from_configare identical), so this is an upstream bug. The commit is written upstream-first; a copy cherry-picked onto upstream master is ontigist/upstream-in-cluster-current-contextfor an upstream PR (this repository is not a GitHub fork of skypilot-org/skypilot, so that PR must come from one that is).The workaround in nemotron/nemo-rl (forwarding a kubeconfig whose current-context is the pinned cluster) stays; it is harmless and covers today's pinned build.