Skip to main content

Tool for building and deploying software on HPC clusters

Project description

Karsk - Keeping Auditable Release Selection Known

Karsk (pronounced kashk) is a Norwegian cocktail from Trøndelag county mixing coffee with moonshine. It is also a tool for deploying software on our NFS-backed Linux cluster.

Karsk solves the following problems for us:

  1. Continuous upgrades: Users reliably access the latest versions of software without needing to update anything themselves.

  2. User-controlled versioning: Each deploy persists on disk. Users can select any existing version anytime.

  3. Simple rollbacks: Because releases are symbolic links, rollbacks are quick and painless.

How it works

Karsk has three stages: build, install, and sync. Each stage writes to a different location, and the destination is strictly append-only — nothing is ever overwritten.

┌─────────────────────────────────────────────────────────────────────────┐
│                          karsk build                                    │
│                                                                         │
│  Builds packages in containers, then assembles an environment           │
│  (symlink tree + manifest) in the staging directory.                    │
│                                                                         │
│  staging/                                                               │
│  ├── store/                                                             │
│  │   └── a1b2c3-myapp-1.0.0/       ← built package artifacts            │
│  ├── versions/                                                          │
│  │   ├── 1.0.0+1/                   ← environment (symlinks into store) │
│  │   │   ├── bin/myapp -> ../../store/a1b2c3-myapp-1.0.0/bin/myapp      │
│  │   │   └── manifest                                                   │
│  │   ├── latest -> 1.0.0+1                                              │
│  │   └── stable -> latest                                               │
│  └── bin/run                        ← wrapper script                    │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                          karsk install                                  │
│                                                                         │
│  Copies store packages from staging to destination and builds the       │
│  environment there. Destination is append-only: the build ID is         │
│  allocated against what already exists in destination.                  │
│                                                                         │
│  destination/  (/opt/karsk/myapp)                                       │
│  ├── store/                                                             │
│  │   ├── a1b2c3-myapp-1.0.0/       ← first build                        │
│  │   └── d4e5f6-myapp-1.0.0/       ← second build (new hash)            │
│  ├── versions/                                                          │
│  │   ├── 1.0.0+1/                   ← first build env                   │
│  │   ├── 1.0.0+2/                   ← second build env                  │
│  │   ├── latest -> 1.0.0+2                                              │
│  │   └── stable -> latest                                               │
│  └── bin/run                                                            │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                          karsk sync                                     │
│                                                                         │
│  Replicates the destination to remote hosts via rsync + SSH.            │
│  Build IDs are identical across all sync locations.                     │
└─────────────────────────────────────────────────────────────────────────┘

Build IDs

Each environment directory is named <version>+<build_id>, e.g. 1.0.0+1. The + prefix follows semver build metadata conventions. The build ID is a monotonically increasing counter scoped to its target directory. Because staging is typically cleared between builds while destination is not, the same build may get different IDs in staging vs destination:

staging:      1.0.0+1  (staging was cleared, starts from 1)
destination:  1.0.0+3  (two previous builds already exist)

This is by design. The key invariant is:

  • Destination is append-only — existing builds are never overwritten or removed.
  • Sync locations are identicalkarsk sync replicates the destination layout exactly, so build IDs match across all remote hosts.
  • Same manifest = same build — if a build with an identical manifest already exists at the target, it is skipped.

Installing

Karsk is written in Python and requires uv and some container engine. Currently, only Podman is supported, but Docker may work as well.

To get started, clone this repository and run uv sync to get the karsk executable.

Using

See examples directory for examples. Use karsk --help to view documentation.

Developing

Karsk entrypoint

Karsk entrypoint is a Rust application that is deployed and serves as the user-facing entrypoint.

Testing

This project uses pytest for tests, mypy for type-checking and ruff for linting and formatting.

# Run tests
uv run pytest tests

# Typecheck (note: we don't typecheck test code)
uv run mypy --strict src

# Lint and format
uv run ruff format
uv run ruff check --fix

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

karsk-0.3.0.tar.gz (124.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

karsk-0.3.0-py3-none-any.whl (46.9 kB view details)

Uploaded Python 3

File details

Details for the file karsk-0.3.0.tar.gz.

File metadata

  • Download URL: karsk-0.3.0.tar.gz
  • Upload date:
  • Size: 124.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for karsk-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f244352fdf748b5723869ce89a2e6be005c1c0c3ce60155e0f099ea2ad2fba5b
MD5 2050a2e020ed2439ad02fb5ffb829867
BLAKE2b-256 dcd53bedc86bb4d2c133b2874bda5d6284b689789a94daaf20393427b17f9b0f

See more details on using hashes here.

File details

Details for the file karsk-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: karsk-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 46.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for karsk-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b4bc89a7c09afd03de2db200c3c944febb6cc966d2268bfab679863bb4bad6a7
MD5 863841258996467289d875cd9c4efb03
BLAKE2b-256 7c50c0159eb07f9f64d401efb5d8b9a3463d22fcc6b8d070dcee4612c9ed6b2a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page