Skip to content

fix(probe): named-port resolution + IntOrString port deserialization#49

Open
indyjonesnl wants to merge 5 commits into
calfonso:mainfrom
indyjonesnl:upstream/probe-fixes
Open

fix(probe): named-port resolution + IntOrString port deserialization#49
indyjonesnl wants to merge 5 commits into
calfonso:mainfrom
indyjonesnl:upstream/probe-fixes

Conversation

@indyjonesnl
Copy link
Copy Markdown

Problem

Probe action types (`HTTPGet`, `TCPSocket`, `GRPC`) hard-coded `port` as `i32`. The K8s spec says `port` is `IntOrString` — either a numeric port or a named port from `container.ports[].name`. Any pod YAML using named-port probes (e.g. `port: http`) failed at deserialization with "invalid type: string, expected i32", blocking a core Kubernetes feature.

Fix

Two commits:

`fix(probe): make HTTPGet/TCPSocket/GRPC port IntOrString per K8s spec`

Change the `port` field on each probe action type from `i32` to `IntOrString`. Deserialization now accepts both numeric and named ports.

`feat(probe): resolve named ports via container.ports[].name at call sites`

At every probe call site in the kubelet, resolve named ports against the container's `ports[]` definition before dialing. Falls back to error if a named port isn't declared on the container.

Stacking note

This PR is stacked on top of #47 (`kubelet-improvements`) — both touch `crates/kubelet/src/runtime.rs` and cherry-picking onto raw `main` produces context-overlap conflicts in the preStop hook region. Once #47 lands, the diff on this PR collapses to just the two probe commits. Please review #47 first.

Verification

`cargo build --workspace --locked` clean. Depends on #32 + #47 for green CI.

indyjonesnl and others added 5 commits May 14, 2026 18:27
EmptyDir conformance tests [Conformance].*EmptyDir.*(mode|0644|0666|0777)
rely on the volume directory being mode 0o777 on the host. The
chmod was already in create_volume but inlined and untested, so a
silent regression would only surface during a full conformance run.

- Extract the create_dir_all + chmod 0o777 path into a pure
  setup_emptydir_dir helper, idempotent for stale dirs.
- Add four unit tests covering new dir, stale-perms re-chmod,
  nested parents, and the full Linux rwx bit pattern.

The 4 failing macOS conformance tests are a virtiofs limitation
(host mode bits not propagated through Podman Machine / Docker
Desktop shared FS); on Linux CI the chmod path verified here is
sufficient.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WebSocket exec now implements v5.channel.k8s.io protocol with stdin (channel 0),
stdout (1), stderr (2), error (3), resize (4), plus v5 close-stream control.
Kubelet runtime captures container exit code via bollard inspect for
lastState.terminated.exitCode. PreStop lifecycle handler invoked before SIGTERM
and respects terminationGracePeriodSeconds.

Closes conformance gap (Unit 12): preStop, container exit status,
exec over websockets.
Persist init container status updates between actions so watches observe
each transition (Running, Terminated, CrashLoopBackOff). Without these
updates, a failing init container's Terminated state was never written
before container removal, so get_init_container_statuses fell back to
the Running prev state on retry. That suppressed CrashLoopBackOff
reporting and pinned restart_count at 0, hanging the K8s conformance
tests that wait for restart_count >= 3 and for the failed-init pod
to reach Failed.

- Publish Running state after start_container, Terminated after a
  successful wait, Terminated/error before remove_container on failure.
- Extract refresh_init_container_statuses helper to eliminate four
  near-identical pod-read / get_init_container_statuses / pod-write
  blocks.
- RestartPolicy=Never still propagates the error immediately, so
  remaining init containers do not run and the pod transitions to
  Failed via the existing kubelet.rs error handler.

Targets Kubernetes v1.35 conformance:
- [Conformance] InitContainer should not start app containers if init
  containers fail on a RestartNever pod
- [Conformance] InitContainer should restart with CrashLoopBackOff on
  a RestartAlways pod
Probe action types hard-coded port as i32. K8s spec defines these as
IntOrString — int port OR named port from container.ports[].name. Any pod
YAML using named-port probes (e.g. `port: http`) failed at deserialization
with "invalid type: string, expected i32", blocking a core K8s feature.

- Change HTTPGetAction.port, TCPSocketAction.port, GRPCAction.port to
  IntOrString.
- Add resolve_probe_port(&IntOrString, &Container) helper that looks up
  named ports against the container's declared ports[].name; ints pass
  through with u16 range check; unknown named ports fall back to parsing
  the string as a number, else return None.
- Derive PartialEq/Eq on IntOrString so tests can assert ports directly.
- Update test sites + lifecycle-hook helper to wrap with IntOrString::Int.
- Add three unit tests pinning the YAML/JSON parse contract + the
  resolver semantics.

Probe execution sites in runtime.rs still pass IntOrString through
Display in format!() — that produces "http" for named ports, which
fails at connect time but no longer crashes pod creation. Resolving
named ports through container.ports is a follow-up at the call sites.
…ites

Follow-up to f7bb64e — wires the resolve_probe_port helper through
check_http_probe / check_tcp_probe / check_grpc_probe and the lifecycle
handler (postStart / preStop hooks). Named ports referenced from probes
or lifecycle handlers now look up the container's declared ports[].name
to obtain a u16 at connect time. Unresolvable named ports cause the probe
to fail (Ok(false)) or the lifecycle hook to error out, both matching
K8s kubelet behavior.

- check_probe now takes &Container in addition to container_name; the four
  callers (startup + liveness in two reconcile paths) pass it through.
- execute_lifecycle_handler now takes &Container; both call sites updated.
- stop_pod_for builds a name -> Container lookup from the pod spec so
  the preStop hook futures carry the matching spec for each container.

Probe execution end-to-end now respects K8s IntOrString port semantics.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant