Kine is an etcdshim that translates etcd API to:
- SQLite
- Postgres
- MySQL/MariaDB
- NATS
- Can be ran standalone so any k8s (not just K3s) can use Kine
- Implements a subset of etcdAPI (not usable at all for general purpose etcd)
- Translates etcdTX calls into the desired API (Create, Update, Delete)
See an example.
loft-sh/kine is a fork of k3s-io/kine maintained by vCluster Labs.
On top of upstream it adds:
- AWS RDS IAM authentication for PostgreSQL
- Kerberos/GSSAPI authentication for PostgreSQL
Fork images are published to ghcr.io/loft-sh/kine. The Go module path stays github.com/k3s-io/kine so the
fork is a drop-in replacement for upstream.
The fork follows a strict branching, commit, and release model so the delta against upstream stays small and reviewable, and upstream syncs stay clean. Most of this is enforced automatically (see "What CI enforces").
mastertracks upstreamk3s-io/kine. We do not build releases frommaster.- Each release line lives on its own branch
release/vcluster/vX.Y.Z, cut from the matching upstream release tagvX.Y.Z, with the fork commits replayed on top.
All commits use Conventional Commits. Fork-specific changes carry the
literal scope fork:
feat(fork): add kerberos gssapi auth for postgresql
fix(fork): close mysql connection after create database
ci(fork): apply loft-sh fork release infrastructure
Two rules apply depending on the target branch of a pull request:
- PRs into
master/mainmay not contain product(fork)commits (feat(fork),fix(fork),perf(fork),refactor(fork)). Those belong on arelease/vcluster/v*branch. Tooling(fork)commits (ci,chore,docs,style,test,build,revert) are allowed only when every changed file is in the tooling allowlist:.github/**,updatecli/**,docs/**,README.md,CONTRIBUTING.md,Dockerfile.release,.golangci.json. Plain upstream-sync commits (noforkscope) are always allowed. - PRs into
release/vcluster/v*must consist solely of Conventional Commits that carry theforkscope.
Fork releases are tagged vX.Y.Z.vcluster.N, where vX.Y.Z is the upstream release the line is based on and
N increments per fork release on that line. The first fork release of upstream v0.16.2 is
v0.16.2.vcluster.0, the next is v0.16.2.vcluster.1, and so on.
release.yml is the only publisher. A version tag push starts it; creating a Release in the UI or
dispatching the removed legacy workflow does not publish an image. It builds from the tagged checkout,
uploads binaries to a draft Release, pushes and attests the images, then publishes the Release last.
The clone-based Dockerfile.release publisher has been removed.
Before any release work, the shared GHCR guard checks every version tag this workflow will push. An existing tag always fails, even on a retry. Auth failures, API errors, and ambiguous missing-tag responses fail closed. Runs for the same tag share one concurrency group with cancellation disabled. Draft retries are allowed only while all version image tags are absent. After a partial push, cut a new version or obtain separate recovery approval that preserves the published digests.
The shared ghcr-tag-guard/v1 action must be merged and its version tag published before these caller
changes can be used for a release. A green caller PR does not prove that deployment step happened.
version-policy.yaml and the publisher validate the vX.Y.Z.vcluster.N scheme. The offline
release-guard-test.yml check verifies the actual tooling snapshot, including removal of both legacy
triggers. Copy that check and the guarded publisher when creating a new release branch.
See release repair and rollback for the approval boundary, evidence, Platform upgrade checks, and interrupted-run recovery.
To cut a new release line from a fresh upstream version:
# 1. Make sure the upstream remote and tags are available
git remote add upstream https://github.com/k3s-io/kine.git # once
git fetch upstream --tags
# 2. Branch from the upstream release tag (NOT from master)
git checkout -b release/vcluster/v0.16.2 v0.16.2
# 3. Replay ALL fork commits from the previous release line (see "Replay rule")
# plus the loft-sh CI/release tooling snapshot, then commit.
# 4. Push the branch and the first fork tag
git push origin release/vcluster/v0.16.2
git tag v0.16.2.vcluster.0
git push origin v0.16.2.vcluster.0 # fires release.yml + version-policy.yamlFor a follow-up release on an existing line, add the fix commits to the branch and push the next tag
(v0.16.2.vcluster.1).
A new release/vcluster/vX.Y.Z branch starts from a clean upstream tag and therefore carries none of our work.
When you cut it you must replay the complete set of (fork)-scoped commits the previous release line
carried (for example AWS RDS IAM auth and Kerberos/GSSAPI auth), plus the loft-sh CI/release tooling snapshot,
on top of the new upstream base. Bumping to a newer upstream version never drops fork changes, it only rebases
them forward. The previous release branch is the authoritative inventory of what must be replayed:
# List the fork commits carried by the previous release line
git log --grep '(fork)' release/vcluster/<previous-version>
git log --oneline v<previous-upstream>..release/vcluster/<previous-version>fork-policy.ymlruns on every pull request and applies the per-branch commit rules above: it rejects product(fork)commits on PRs intomaster/main, rejects tooling(fork)commits there that touch non-allowlisted paths, and on PRs intorelease/vcluster/v*requires every commit to be a Conventional Commit with theforkscope.version-policy.yamlruns on every version tag push and fails if the tag does not matchvX.Y.Z.vcluster.N. It runs alongsiderelease.yaml(which is left as-is) rather than gating it, so a mis-named tag turns the check red instead of being blocked outright.
Cutting the release/vcluster/v* branch from the correct upstream tag and replaying the full fork commit set
(the replay rule) is not automated and remains a human responsibility.
The replay must also carry the shared publication guard and release-guard-test.yml. Run
uv run --with pytest==8.3.5 --with PyYAML==6.0.2 pytest .github/tests/test_release_guard.py -q
on the new branch before pushing its first version tag. Use the previous maintained line's publisher
so any -nocgo variant remains covered by the guard.
A high level flow diagram and overview of code structure is available at docs/flow.md.