Skip to content

fix: enable rootless podman for harbor-bootc freeze workflow#2

Open
bupd wants to merge 6 commits intomainfrom
feat/harbor-rootless-and-kind
Open

fix: enable rootless podman for harbor-bootc freeze workflow#2
bupd wants to merge 6 commits intomainfrom
feat/harbor-rootless-and-kind

Conversation

@bupd
Copy link
Copy Markdown
Owner

@bupd bupd commented Apr 20, 2026

Why rootless podman failed before

Two independent blockers:

1. cpuset cgroup controller not delegated to user sessions

k3s checks for the cpuset controller at startup and aborts with:

failed to find cpuset cgroup (v2)

On cgroupv2 hosts (Arch, Ubuntu 22+), systemd only delegates cpu memory pids to user sessions by default — not cpuset. Even --privileged can't escape this: rootless UID mapping bounds the container to the host user's delegated controllers.

Fix: /etc/systemd/system/user@.service.d/delegate.conf adds cpuset to the user delegate list. One-time root operation on the host; added as a CI step.

2. SystemdCgroup/kubelet cgroup driver mismatch

k3s auto-detects systemd on the host and sets SystemdCgroup = true in its generated containerd config. But the kubelet generates cgroupfs-format cgroup paths (/k8s.io/<sandbox-id>). runc in systemd mode expects slice:prefix:name format → every pod sandbox fails:

expected cgroupsPath to be of format "slice:prefix:name" for systemd cgroups,
got "/k8s.io/..." instead

Fix: containerd config drop-in in config-v3.toml.d/ forces SystemdCgroup = false. Works for:

  • Rootless: private cgroupns gives the container a writable cgroup subtree; cgroupfs paths resolve within it
  • Rootful: real root has direct cgroup fs write access

Changes

  • harbor-images-stage.sh — drops SystemdCgroup = false override into config-v3.toml.d/ before k3s starts
  • k3s-harbor.service — cleaned up (removed rootless-workaround kubelet args that no longer apply)
  • harbor-run.sh — back to rootless podman run (no sudo); documents the one-time host cpuset setup
  • harbor-freeze.sh — rootless podman commit
  • harbor-freeze.yaml CI — adds cpuset delegation step; uses rootless podman throughout

Test plan

  • Local: run scripts/harbor-run.sh after one-time cpuset delegation setup → Harbor up at :30080
  • Local: scripts/harbor-freeze.sh → frozen image committed
  • Frozen image: podman run ... harbor-frozen:v2.14.3 /sbin/init → Harbor up without Helm install
  • CI: workflow builds, seeds, commits, pushes to GHCR, smoke tests frozen image

🤖 Generated with Claude Code

bupd added 6 commits April 20, 2026 06:52
…config

Two issues prevented rootless podman from running k3s inside a container:

1. cpuset not delegated to user sessions (k3s aborts at startup):
   Fix: /etc/systemd/system/user@.service.d/delegate.conf adds cpuset.
   In CI this is done as a workflow step; locally it is a one-time host setup.

2. k3s auto-sets SystemdCgroup=true in containerd but kubelet generates
   cgroupfs-format cgroup paths (/k8s.io/...) causing a format mismatch
   in runc when using --cgroupns=host. Fix: drop-in config forces
   SystemdCgroup=false. Works for both rootless (private cgroupns is
   writable within the container's delegated slice) and rootful.

Run flags: --privileged --systemd=always --device /dev/null:/dev/kmsg
No --cgroupns=host needed; default private cgroupns is correct.

Signed-off-by: Prasanth Baskar <bupdprasanth@gmail.com>
- fix pre-existing shellcheck warnings in build.sh, flash-disk.sh,
  repair-esp.sh, verify-disk.sh (SC2012 ls→find, SC2086 quoting,
  SC2162 read -r, SC2024 sudo+redirect)
- harbor-freeze.yaml: add pull_request trigger so CI runs on PRs
- harbor-freeze.yaml: skip GHCR push step on pull_request events

Signed-off-by: Prasanth Baskar <bupdprasanth@gmail.com>
Signed-off-by: Prasanth Baskar <bupdprasanth@gmail.com>
…outs

- sudo podman throughout: root has full cgroup access, no cpuset delegation
  needed (user@.service.d only affects new sessions, not the CI runner)
- Cache harbor-dev image by Containerfile.harbor hash: avoids re-downloading
  ~2GB of Harbor images on every CI run
- Remove trivy from image downloads and values.yaml: one less large image
  to pull/load, cuts startup time significantly
- timeout-minutes on k3s and Harbor waits: fail fast instead of hanging
- Debug step on failure: k3s status, pods, and logs for diagnosis
- Skip GHCR push and login on PRs

Signed-off-by: Prasanth Baskar <bupdprasanth@gmail.com>
Air-gap tar loading on GitHub Actions runners is too slow (disk IO
bottleneck): 9 tars take 12-15+ min to import into containerd, causing
helm --wait --timeout 10m to expire before pods start.

AIRGAP=false skips baking Harbor images into the build layer. k3s
pulls Harbor images from Docker Hub at pod startup (~2-3 min on fast
CI network) instead, cutting Harbor-ready time from 20+ min to ~8 min.

- Containerfile.harbor: AIRGAP build arg (default true), conditionally
  downloads Harbor tars
- harbor-images-stage.sh: tolerates missing tars (|| true)
- harbor-init.sh: raise helm --timeout from 10m to 25m
- CI: --build-arg AIRGAP=false, timeout-minutes 15→30 for Harbor wait

Signed-off-by: Prasanth Baskar <bupdprasanth@gmail.com>
Accidentally committed Claude Code's internal scheduled_tasks.lock.
Not sensitive (session ID + PID only, no credentials) but shouldn't
be tracked.

Signed-off-by: Prasanth Baskar <bupdprasanth@gmail.com>
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