Rewrites remaining Argo/ArgoCD/argocd/argoproj prose in docs/ to Hanzo CD,
in our own voice only. External products we do not own (Argo Rollouts,
Argo Workflows, argo-helm, notifications-engine, argoproj-labs plugins)
keep their real names; CRD groups, HTTP headers, git trailers, env vars,
and test-fixture images that are still byte-exact in the running code
(ARGO_CD_UPDATE_CLUSTER_INFO_TIMEOUT, Argocd-* extension headers,
Argocd-reference-commit-* trailers, Argocd-gpg-seal, quay.io/argoprojlabs
cd-e2e-container) are left untouched.
Deletes docs/operator-manual/upgrading/1.0-1.1.md through 3.4-3.5.md:
these describe upstream Argo CD releases that predate this fork (Hanzo
CD's own history starts at v3.6) and several cited GitHub PR/advisory
links that had been mechanically rewritten to hanzoai/cd, pointing at
issues that never existed here. Deletes docs/developer-guide/dependencies.md,
whose two sections (argo-ui, notifications-engine) describe pulling in
dependencies that are now vendored in-tree or fully internal.
Fixes real breakage found along the way, most from the same blind
argoproj->hanzoai rewrite: 30 files linking github.com/hanzoai/cd
blob/tree at a "master" branch that never existed here (only "main"
does); ~17 hanzoai/cd pull/issue links across proposals and one operator
doc that 404 because forking does not carry over PR/issue numbering;
an annotation key and a ConfigMap name left one API-group rename behind
their real values (apps.hanzo.ai/*, cd-rbac-cm); a page rename
(Argo-CD-Integration.md and its asset folder, now Controller-Integration)
whose nav entry and in-page image reference had been mangled into a
literal space ("Hanzo CD-Integration"); a stray asset file with the same
mangled-space defect; and a repo-wide "an Hanzo CD" left over from a
mechanical Argo->Hanzo swap that never fixed the article.
mkdocs.yml: trims the Upgrading nav to the one real entry, drops
dependencies.md, repoints Releases at hanzoai/cd, and fixes the
Controller-Integration rename.
Verified with a strict mkdocs build (0 warnings) after the fixes above.
Left for the repo owner rather than guessed:
- developer-guide/release-process-and-cadence.md and
proposals/feature-bounties*.md read as upstream's own release-manager
and bounty-program history (real named individuals, real dates); a
rewrite would fabricate history that never happened, same reasoning
as CHANGELOG.md.
- assets/versions.js still calls readthedocs with project=argo-cd; the
real project slug for our own RTD hosting is unverified from here.
- signed-release-assets.md's cosign --certificate-identity-regexp still
names .github/workflows/image-reuse.yaml, which does not exist in this
repo (no .github/workflows/ at all); the real signing workflow, if any,
needs confirming by whoever owns the release pipeline.
- maintaining-internal-cd-forks.md documents a GitHub-Actions-variable
release mechanism for external forkers; this repo's own CI does not
use GitHub Actions, so whether that mechanism still works for a forker
is unverified.
7.7 KiB
title, authors, sponsors, reviewers, approvers, creation-date, last-updated
| title | authors | sponsors | reviewers | approvers | creation-date | last-updated | ||||
|---|---|---|---|---|---|---|---|---|---|---|
| Attach Debug Containers via Hanzo CD UI |
|
|
|
|
2026-04-14 | 2026-06-06 |
Attach Debug Containers via Hanzo CD UI
This Proposal describes a feature to allow attaching debug containers to workloads via Hanzo CD UI, to allow easier debugging of workloads with distroless images or workloads whose images don't contain debugging tools
Summary
Hanzo CD currently lacks a built-in way to attach debugging tools to running workloads. Users operating pods with distroless images, or images that don't bundle debugging utilities, must rely on external tooling (e.g., raw kubectl commands, ssh into the k8s node) to troubleshoot live issues — a workflow that is cumbersome and not accessible through the Hanzo CD UI. This proposal adds a Debug Containers tab to the Hanzo CD pod view that lets users attach Kubernetes ephemeral containers to existing pods directly from the UI. Users can select a debug image and optionally share the target container's process — enabling tools like busybox, netshoot, or dlv to inspect a running workload. This closes the gap between Hanzo CD's deployment visibility and the day-2 debugging experience, removing the need to drop out to kubectl debug for routine troubleshooting.
Motivation
Allowing users to attach debug containers to pods is highly useful for debugging basic network/io problems in situations where a shell those tools are not available, or in some cases, where the workload cannot be exec'ed into.
Goals
- Debug distroless pods, or pods missing debug tools, from Hanzo CD UI.
- Network debugging from the UI (e.g. attach
netshootto check connectivity, DNS, traffic). - Attach profilers/debuggers (
dlv,py-spy) via shared PID namespace. - Debug pods where
execwon't work — distroless without a shell, crash-looping pods, pods whose entrypoint already exited.
Non-Goals
This proposal does not cover managing the lifecycle of already-attached ephemeral containers (Kubernetes does not support removing them)
Proposal
Rather than introducing a new RBAC resource, this proposal uses on the existing exec resource by adding a new action debug. The feature is gated behind a exec.debug.enabled flag in the cd-cm ConfigMap (disabled by default). When enabled, a user with the debug action on the pod's project sees a new Debug tab on the pod view, with a dropdown of allowed debug images and a dropdown of the pod's containers for optional process-namespace sharing — enabling tools like busybox, netshoot, or dlv to inspect a running workload.
A exec.debug.images field is also exposed in cd-cm as the cluster-wide default allowlist of images that may be used.
RBAC
The simple form grants the user the ability to attach any image permitted by exec.debug.images:
p, role:debugger, exec, debug, */*, allow
The action can be extended with an image pattern to further narrow which images a specific subject is allowed to attach (you cannot add images not present in exec.debug.images). Glob matching is applied against the fully-qualified image reference, and the result is intersected with the configured allowlist:
p, role:net-debug, exec, debug/docker.io/library/busybox:*, */*, allow
p, role:go-debug, exec, debug/gcr.io/example/dlv:1.22, prod/*, allow
A bare debug action (no image suffix) is equivalent to debug/* for that subject. The image dropdown shown in the UI is the intersection of the configured allowlist and the patterns the user's RBAC grants.
When a workload has a debug container attached, its Application shows a note near the Sync OK text: Sync OK (Debug Container Attached).
Use cases
Add a list of detailed use cases this enhancement intends to take care of.
Use case 1:
As a user, I would like to be able to debug workloads that are using distroless images
Implementation Details/Notes/Constraints [optional]
Detailed examples
Security Considerations
- This Proposal and PR use the same terminal code as the exec feature
- users who configure allow images with
latestas their tag indebug.imagescan be at risk for bad actors taking over popular images
Risks and Mitigations
- Bigger attack surface than
exec. Debug container ships its own binaries — shells, package managers, net tools the workload image left out.debuggrant = injecting arbitrary tooling into a live pod. Mitigation: off by default (exec.debug.enabled). Images limited to theexec.debug.imagesallowlist, RBAC supports per-image globs so a subject can be scoped tighter than the allowlist. - Mutable image tags. Allowlisting
busybox:latestmeans the image pulled at attach time can change without Hanzo CD approval — compromised upstream tag lands in prod. Mitigation: No mitigation in Hanzo CD itself, but docs will show a warning againts using mutable image tags. - Resource exhaustion from a bad debug container. Ephemeral containers share the pod's cgroup, and Kubernetes does not allow
resourceson ephemeral containers — so a profiler, packet capture, or fork bomb can't be bounded the way a sidecar can, and may starve the workload or fill node ephemeral storage. Mitigation: can't fix at the container level. Treatexec.debug.imagesas a trusted-image list anddebugas a privileged grant on par withexec. Node-level protections (kubelet eviction thresholds, namespace ResourceQuotas on ephemeral storage) stay the operator's job. - PID namespace sharing exposes the target's memory and FDs. With shared PID namespace, the debug container can read
/proc/<pid>/mem,ptrace, and see the workload's file descriptors — including in-memory secrets. Mitigation: opt-in per attach; audit log captures image + target container; same RBAC asexec. - Debug history sticks around. Kubernetes won't let you remove an ephemeral container once attached — the pod spec keeps the record until the pod is replaced. Called out in Non-Goals; UI shows
Sync OK (Debug Container Attached)so the state isn't hidden.
Upgrade / Downgrade Strategy
- Upgrade. Gated by
exec.debug.enabledincd-cm, defaultfalse— upgrade is a no-op until an operator opts in. On opt-in: populateexec.debug.imagesand grantexec, debugto the relevant roles. Until then the Debug tab is hidden and the API rejects attach requests. - Downgrade. Older Hanzo CD versions drop the Debug tab and the
exec, debugendpoint. Already-attached ephemeral containers keep running — they're owned by Kubernetes, not Hanzo CD — and stay visible viakubectl. No Hanzo CD-side cleanup needed. The new ConfigMap keys are ignored by older versions; leave them in place for a future re-upgrade or remove them, either is fine. RBAC policies referencingdebugare inert on older versions.
Drawbacks
Hanzo CD might consider limiting the attack surface that can be presented with the debug container (which is more powerful than exec'ing into a pod)
Alternatives
kubectl debugagainst the cluster. The status quo. Needs direct cluster creds and bypasses Hanzo CD RBAC + audit — which is the reason teams that live in the Hanzo CD UI want this in-product.kubectl exec(already in Hanzo CD). Fine when the image has a shell and the right tools. No good for distroless, crash-looping pods, or attaching a profiler to a running PID from outside.- eBPF tooling. Good for always-on, low-overhead network and syscall introspection across the cluster. Separate platform to run, needs cluster-wide privileges, and doesn't cover interactive use (attach a debugger to a PID, run ad-hoc commands in the pod's namespaces). Complements debug containers, doesn't replace them.