Skip to content

feat(deploy): document a k3d dev loop for the robot Kubernetes rendering - #464

Merged
Minipada merged 3 commits into
jazzyfrom
feature/451-k3d-cluster-for-local-development-iterat
Sep 1, 2026
Merged

feat(deploy): document a k3d dev loop for the robot Kubernetes rendering#464
Minipada merged 3 commits into
jazzyfrom
feature/451-k3d-cluster-for-local-development-iterat

Conversation

@Minipada

@Minipada Minipada commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds deploy/robot/k3d/, a Kustomize overlay over deploy/robot/kubernetes/robot-pod.yaml
    that pins dc-ros/dc-uploader to the :jazzy tag (this branch's own published tag —
    never :latest, the same convention ROS's own images use: distro codename, not
    :latest) and sets imagePullPolicy: Never, so a disposable k3d
    cluster can run the robot Pod for real (a scheduler, Services, DNS) with no registry
    reachable from inside the cluster.
  • No wrapper script: deploy/robot/README.md's "k3d development loop" section documents
    the loop as plain, commented podman run / k3d cluster create / k3d image import /
    kubectl kustomize | kubectl apply -f - commands. podman run --entrypoint true ghcr.io/.../dc-ros:jazzy gets the already-published image into local Podman storage —
    no local build needed just to try the loop; building your own image for local changes
    needs no doc change, just tag it identically. kubectl apply -k itself refuses a base
    outside its own directory, which is why the apply step pipes through kubectl kustomize --load-restrictor LoadRestrictionsNone instead.
  • Adds a "Deployment renderings and a local Kubernetes loop" subsection to
    doc/src/dc/setup.md (the mdbook) pointing at that README section.
  • Records the Docker dependency (k3d wraps k3s in Docker containers) as scoped to this
    loop alone in CLAUDE.md's Podman-not-Docker section — building and shipping
    dc-ros/dc-uploader is unchanged, and this is explicitly not the production-parity
    check that's kind validation of the three-tier topology with NetworkPolicy #452's kind + NetworkPolicy cluster.

Verification

Ran the full documented sequence twice: once end to end with lightweight stand-in images
(cluster create ~15-20s, image-reload-and-recreate ~10s, teardown ~2s — proves the
mechanics: hostPath volume staging, the Kustomize overlay, the readiness wait, the
delete-and-reapply iteration path), and again against the real published images
(podman run --entrypoint true ghcr.io/minipada/ros2_data_collection/dc-ros:jazzy and
dc-uploader:jazzy both pull and exit cleanly; the overlay correctly renders
image: ghcr.io/minipada/ros2_data_collection/dc-ros:jazzy + imagePullPolicy: Never).

One thing I couldn't finish live: the podman save + k3d image import step against the
real images, which are ~17 GB each — my sandbox has under 4 GB free disk, and that step
needs the image's size again as a temporary tar on top of Podman's own copy. That's a
sandbox limit, not a defect in the commands, but it's a real cost on any machine, so the
docs now call out the image size and that it's specifically the loading step that's
slow, not cluster creation or iterating on the manifest afterward. Also caught and fixed
along the way: podman save refusing to overwrite an existing tar on a repeat iteration,
k3s failing to boot in restricted/rootless container environments without /dev/kmsg
(fixed with the KubeletInUserNamespace kubelet feature gate), and a Markdown line-wrap
in the mdbook page that was rendering as an accidental bullet list.

prek run --all-files --skip build-doc passes, and mdbook build renders cleanly.

Closes #451

https://claude.ai/code/session_011mBacgaX1VbBvWUfK3RQKU

Adds deploy/robot/scripts/k3d_up.sh and k3d_down.sh (#451): a disposable
single-node k3d cluster running deploy/robot/kubernetes/robot-pod.yaml with a
real scheduler, Services and DNS, unlike verify_kube_play.sh's `podman kube
play` (#450), which has none of those. k3d_up.sh imports locally-built
dc-ros/dc-uploader images via `podman save` + `k3d image import` (no
registry), retagging past Podman's `localhost/` namespacing so the image the
node ends up with actually matches what the Pod asks for, and is idempotent:
rerunning it after rebuilding an image reloads it and recreates the Pod
without recreating the cluster. Verified end to end (stub images standing in
for dc-ros/dc-uploader): cluster create ~16s, image-reload-and-recreate ~10s,
teardown ~2s — fast enough for repeated iteration. Also carries the
KubeletInUserNamespace kubelet feature gate, needed for k3s to boot in
restricted/rootless container environments that don't expose /dev/kmsg to the
node (verified against that exact cluster-creation failure).

Documents the loop in deploy/robot/README.md as the fast inner loop,
explicitly not the production-parity check that's #452's kind + NetworkPolicy
cluster, and records the Docker dependency both harnesses introduce as scoped
to themselves in CLAUDE.md's Podman-not-Docker section.

Closes #451

Signed-off-by: David Bensoussan <d.bensoussan@proton.me>

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011mBacgaX1VbBvWUfK3RQKU
Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.46%. Comparing base (d9340bb) to head (ea6d7e3).

Additional details and impacted files
@@            Coverage Diff             @@
##            jazzy     #464      +/-   ##
==========================================
+ Coverage   71.44%   71.46%   +0.02%     
==========================================
  Files         124      124              
  Lines        7563     7563              
==========================================
+ Hits         5403     5404       +1     
+ Misses       2160     2159       -1     
Flag Coverage Δ
cpp-jazzy 71.46% <ø> (+0.02%) ⬆️

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.

…ustomize

Drops deploy/robot/scripts/k3d_up.sh/k3d_down.sh in favor of documenting the
loop as plain podman/k3d/kubectl commands (deploy/robot/README.md), so what
each step does is never hidden behind a script. Adds deploy/robot/k3d/, a
Kustomize overlay over kubernetes/robot-pod.yaml that swaps in the locally
built dc-ros/dc-uploader images and sets imagePullPolicy: Never — `kubectl
apply -k` itself refuses a base outside its own directory, so the documented
command pipes `kubectl kustomize --load-restrictor LoadRestrictionsNone`
into `kubectl apply -f -` instead. Re-verified the full sequence end to end
with stub images after the rewrite (same timings as before: cluster create
~15-20s, image-reload-and-recreate ~10s, teardown ~2s), and found and
documented two more gotchas only a live run surfaces: podman's
`localhost/name:tag` namespacing versus containerd's `docker.io/library/`
default (fixed by building with the fully-qualified tag directly, no retag
step needed), and `podman save` refusing to overwrite an existing tar.

Also adds a "Deployment renderings and a local Kubernetes loop" subsection to
doc/src/dc/setup.md pointing at deploy/robot/README.md, and updates
CLAUDE.md's scoped-Docker-exception note to no longer reference the removed
scripts.

Closes #451

Signed-off-by: David Bensoussan <d.bensoussan@proton.me>

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011mBacgaX1VbBvWUfK3RQKU
Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
@Minipada Minipada changed the title feat(deploy): add k3d dev loop for the robot Kubernetes rendering feat(deploy): document a k3d dev loop for the robot Kubernetes rendering Sep 1, 2026
…he k3d loop

Replaces the k3d loop's `podman build` step with `podman run --entrypoint
true ghcr.io/minipada/ros2_data_collection/dc-ros:jazzy` (and dc-uploader):
this repository already publishes these images on every push to jazzy, so
trying the loop doesn't require a full workspace build first. Also drops the
:dev tag and the docker.io/library/ retag it needed — ROS images are tagged
by distro codename, never :latest (ros:jazzy-ros-base, never ros:latest), and
this repo's own images follow the same convention (branch name, not
:latest), so the overlay now just repoints the base manifest's ghcr.io
:latest ref at :jazzy instead of introducing a separate local naming scheme.

Verified against the real published images (not stand-ins this time):
`podman run --entrypoint true` pulls and exits cleanly for both, and the
Kustomize overlay renders the correct ghcr.io/.../dc-ros:jazzy +
imagePullPolicy: Never. Confirmed cluster create is still ~15-20s. Couldn't
complete a live save+import+apply run with the real ~17 GB images in this
sandbox (a save needs that much disk again, on top of Podman's own copy, and
free disk here is under 4 GB) — that limit is sandbox-specific, not a defect
in the documented commands, but it's a real cost on any machine, so the docs
now call out the image size and what step it actually slows down (loading,
not the cluster or the manifest iteration after it).

Closes #451

Signed-off-by: David Bensoussan <d.bensoussan@proton.me>

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011mBacgaX1VbBvWUfK3RQKU
Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
@Minipada
Minipada merged commit b4aedca into jazzy Sep 1, 2026
15 checks passed
@github-actions
github-actions Bot deleted the feature/451-k3d-cluster-for-local-development-iterat branch September 1, 2026 23:02
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