Skip to main content

CI Coverage PyPI License

Kodman

A command-line tool that provides a Docker-like experience with a Kubernetes backend.

An example use case would be to facilitate a single CI script where the runner may sometimes be a host with Docker (possibly run locally) and other times a Kubernetes executor where Docker-in-Docker is not possible (such as a Gitlab runner).

What Where
Source https://github.com/epics-containers/Kodman
PyPI pip install kodman
Releases https://github.com/epics-containers/Kodman/releases

Some examples:

Hello-world:

kodman run --rm hello-world

Handling exit codes:

kodman run --entrypoint bash --rm ubuntu -c "echo Enter; exit 1" && echo "You shall not pass"

Add files or directories into the pod filesystem:

mkdir demo
echo "Mellon" > demo/token.txt
kodman run -v ./demo:/demo --rm ubuntu bash -c "cat demo/token.txt"

The files are copied in, not bind mounted, so changes made in the container are not seen on the host. Add :ro (-v ./demo:/demo:ro) to make the copy read-only in the container - for a single file this covers just that file, as docker does. docker's SELinux (:z, :Z), mount-propagation and consistency (:cached, :delegated, :consistent) options are accepted and ignored; any other option is an error.

Ask for CPU, for work that needs more than the namespace hands out by default:

kodman run --cpus 4 --rm ubuntu nproc

Note that nproc still answers with the node's core count - a container is shown every core whether or not it may use them - so a build parallelised from that number will oversubscribe whatever --cpus allows.

Usage:

From outside of the cluster kodman will use your current Kubernetes context (the same as your current kubectl context).

To run somewhere else without switching your kubectl context, set KODMAN_CONTEXT to another context in your kubeconfig and/or KODMAN_NAMESPACE to another namespace:

KODMAN_CONTEXT=staging KODMAN_NAMESPACE=ci kodman run --rm ubuntu true

A context with no namespace uses default, as kubectl does. KODMAN_NAMESPACE also applies in-cluster, where the namespace otherwise comes from the service account.

From inside the cluster kodman will use the serviceAccount mounted by default.

Pod cleanup

--rm removes the pod when the run ends, whatever its exit code - as docker run --rm does. Without it the pod is left behind for inspection, and because Kubernetes has no garbage collector for a bare Pod (only a Job gets ttlSecondsAfterFinished), it would otherwise stay in the namespace forever.

So every run first sweeps up after the ones before it. Pods kodman created - they carry app.kubernetes.io/managed-by=kodman - that have finished (Succeeded or Failed) and are older than a TTL are deleted. Pods that are still Pending or Running are never touched, whatever their age, since they may belong to a run happening right now.

The TTL is one hour by default, leaving a window in which to inspect a failed run. Set KODMAN_POD_TTL to change it: seconds, 0 to reap finished pods immediately, or a negative value to disable the sweep.

KODMAN_POD_TTL=600 kodman run ubuntu true   # keep finished pods for 10 minutes

Pods created by kodman before this behaviour existed are unlabelled and so invisible to the sweep. Remove any strays once with:

kubectl get pods -o name | grep '^pod/kodman-run-' | xargs -r kubectl delete

An interrupted run (Ctrl-C, or the SIGTERM a cancelled CI job gets) deletes its pod even without --rm. Kubernetes cannot stop a pod short of deleting it, so the alternative is leaving it running and consuming the CPU it was given long after the client that asked for it has gone.

Permissions

A minimal Kubernetes RBAC role definition can be found in .github/manifests

Design decisions

Why argparse over click/typer?

The docker cli api is not POSIX compliant.

For example: docker run --network=host imageID dnf -y install java

Click/Typer does not allow this (and is correct). They would expect: docker run --network=host imageID -- dnf -y install java

See Section 12.2 Guideline 10 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02

Metadata

Release files for kodman 1.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kodman 1.5.0
File Size Uploaded Provenance
kodman-1.5.0.tar.gz 177.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for kodman 1.5.0
File Interpreter ABI Platform
kodman-1.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 204.8 kB

Release files / kodman-1.5.0.tar.gz

Download URL kodman-1.5.0.tar.gz
Size 177.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5bd4bd31fbaa3d7f2c6f43f30de460035efef8d3db70775f9a3cb9ef7a50565b
BLAKE2b-256 checksum
How to use checksums
50c3480528cbecfa2453484cd71362d76d8f53dee739ced6a14a11963e02fe65
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / kodman-1.5.0-py3-none-any.whl

Download URL kodman-1.5.0-py3-none-any.whl
Size 27.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
acc3d9a7608a812819396b65e266f8656e9c0e50679163698782913931b61845
BLAKE2b-256 checksum
How to use checksums
0cede6b145ac5445a134f34853dd9cb81c75e74b971ce9d639a2ca7337bf87b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Security for kodman 1.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page