Skip to content

Changelog

All notable changes to kinder since forking from kind at commit 89ff06bd.


Released: April 10, 2026

Four cluster capabilities that fill the gap between plain kind and a production-like local environment: multi-version per-node Kubernetes, offline/air-gapped cluster creation, local-path-provisioner dynamic storage, and host-directory mounting — plus a provider-abstracted kinder load images utility that ties the offline and multi-version workflows together. Zero new Go module dependencies.

  • Per-node image preservation--image flag no longer overrides explicit per-node image: entries. Explicit image assignments capture pre-defaults via ExplicitImage sentinel in encoding/convert.go
  • Version-skew validation — config parse rejects workers more than 3 minor versions behind the control-plane before any containers are created, with a precise error message stating the violating node and version delta
  • HA consistency check — control-plane nodes at different versions are rejected at config validation time
  • Doctor cluster-skew checkkinder doctor reports a warning when a running multi-version cluster violates version-skew policy; injectable node reader enables test coverage without a live runtime
  • New kinder get nodes columns — output now includes VERSION, IMAGE, and SKEW columns sourced via container inspect (avoids import cycle with pkg/cluster)
  • Non-semver image tags (e.g. latest) skip version-skew validation to preserve backward compatibility with test/dev configs
  • --air-gapped flag — new flag on kinder create cluster disables all network calls for image pulls across docker, podman, and nerdctl providers
  • Fast-fail with actionable error — missing images produce a complete list of what must be pre-loaded, instead of timing out or hanging on failed pulls. Per-runtime pre-load instructions via formatMissingImagesError(binaryName)
  • Addon image warning — non-air-gapped creation prints a NOTE listing every addon image that will be pulled, so users know what to pre-load before switching to offline mode
  • Doctor offline-readiness checkkinder doctor lists which required images are absent from the local image store, serving as a pre-flight offline readiness check. Skips gracefully when no container runtime is found
  • RequiredAddonImages utility — centralised image inventory imported from addon packages (no import cycle, since addon packages don’t import common)
  • Working Offline guide — new working-offline guide documenting the two-mode offline workflow: pre-create image baking vs. post-create kinder load images
  • New default addonlocal-path-provisioner v0.0.35 installed by default; local-path is the only default StorageClass (the legacy standard StorageClass from installstorage is gated off)
  • Automatic dynamic PVC provisioningPersistentVolumeClaim resources transition to Bound automatically in both single-node and multi-node clusters without manual operator action
  • Opt-out configaddons.localPath: false in the cluster config skips the addon and restores the legacy standard StorageClass (exact pre-v1.4 behavior)
  • CVE-2025-62878 doctor checkkinder doctor warns when local-path-provisioner is below v0.0.34 (the fix version; strictly less-than triggers warn)
  • Air-gapped compatible — embedded manifest pins busybox:1.37.0 with imagePullPolicy: IfNotPresent, ensuring PVC operations work in air-gapped clusters where busybox:latest cannot be pulled
  • Uses boolVal (opt-out, default true) consistent with MetalLB/CertManager pattern
  • Pre-flight path validationextraMounts entries with non-existent host paths are rejected before any containers are created, with an error message identifying the missing path. Relative paths resolved via filepath.Abs before os.Stat
  • Platform propagation warningspropagation: HostToContainer or Bidirectional on macOS or Windows now emits a visible warning explaining that propagation is unsupported on Docker Desktop and defaults to None
  • Doctor host-mount check — on macOS, kinder doctor verifies that configured host mount paths exist and that Docker Desktop file sharing is enabled for that path, reporting actionable guidance when either check fails. Falls back to Docker Desktop default dirs when settings-store.json is absent
  • --config flag on doctorkinder doctor --config cluster.yaml extracts extraMounts paths from the config and wires them into mount checks; mountPathConfigurable interface allows per-check mount path injection
  • Host Directory Mounting guide — new guide walks through the two-hop mount pattern (host directory → node extraMount → pod hostPath PV) with complete YAML examples
  • New kinder load images <image> [<image>...] subcommand — loads one or more local images into every node of a running cluster with a single command
  • Provider-abstractedproviderBinaryName() resolves the actual binary for docker, podman, nerdctl, finch, and nerdctl.lima. save() and imageID() take binaryName as a parameter instead of hardcoding docker save
  • Docker Desktop 27+ containerd fallbackLoadImageArchiveWithFallback in nodeutils detects the “content digest: not found” error from ctr images import --all-platforms and retries without --all-platforms. Factory pattern (openArchive func() (io.ReadCloser, error)) provides a fresh reader for the retry since tar streams cannot be rewound
  • Smart-load skip — re-running with an image already present on all nodes completes without re-importing and logs "Image ... found to be already present on all nodes."
  • Load Images CLI reference — new CLI reference page with per-provider examples, smart-load behavior, and the Docker Desktop 27+ compatibility note
  • Local Path Provisioner addon page documenting config, verification, CVE check, and air-gapped image list
  • Working Offline guide with pre-load and post-create workflows
  • Host Directory Mounting tutorial with two-hop mount walkthrough
  • Load Images CLI reference covering all three providers, smart-load behavior, and Docker Desktop 27+ fallback
  • Landing page updated with local-path in Core Addons
  • Configuration reference gained the localPath addon field
  • ExplicitImage captured pre-defaults in encoding/convert.go (SetDefaultsCluster fills empty Image fields before Convertv1alpha4, making post-defaults detection impossible)
  • stderrors alias for stdlib errors avoids conflict with sigs.k8s.io/kind/pkg/errors import
  • isContentDigestError checks RunError.Output before falling back to err.Error() string
  • LoadImageArchive (existing public API) unchanged — new LoadImageArchiveWithFallback coexists for kinder load images usage
  • realListNodes / realGetProvisionerVersion / realListNodes in doctor checks use the low-level container exec CLI approach to avoid import cycles with pkg/cluster/internal

v1.3 — Known Issues & Proactive Diagnostics

Section titled “v1.3 — Known Issues & Proactive Diagnostics”

Released: March 6, 2026

Expanded kinder doctor from 3 to 18 diagnostic checks across 8 categories, wired automatic mitigations into kinder create cluster, and added a comprehensive Known Issues documentation page.

  • Check interface — unified Check contract with Name(), Category(), Platforms(), Run() methods. All checks return structured Result values with ok/warn/fail/skip status
  • Category-grouped outputkinder doctor groups checks by category (Runtime, Docker, Tools, GPU, Kernel, Security, Platform, Network) with Unicode status icons
  • JSON outputkinder doctor --output json produces an envelope with checks array and summary object (total/ok/warn/fail/skip counts)
  • Platform filtering — checks declare target platforms; non-matching platforms get skip status instead of crashing
  • SafeMitigation system — tier-based mitigation infrastructure wired into kinder create cluster before provisioning. Errors logged as warnings, never fatal
  • Disk space — warns at <5GB, fails at <2GB using Docker’s data root path. Build-tagged statfs for Linux/macOS
  • daemon.json init flag — detects "init": true across 6 candidate paths (native Linux, Docker Desktop macOS, rootless, Snap, Rancher Desktop, Windows)
  • Docker snap — detects Docker installed via snap through symlink resolution. Warns about TMPDIR issues
  • kubectl version skew — parses kubectl version --client -o json and warns when skew exceeds +/-1 minor version from reference (v1.31)
  • Docker socket permissions — detects permission denied on Linux and suggests usermod -aG docker $USER fix
  • inotify limits — warns when max_user_watches < 524288 or max_user_instances < 512 with exact sysctl fix commands
  • Kernel version — fails on kernels below 4.6 (cgroup namespace support is a hard blocker for kind)
  • AppArmor — detects enabled AppArmor and warns about stale profile interference (moby/moby#7512)
  • SELinux — detects enforcing mode on Fedora and warns about /dev/dma_heap denials
  • firewalld — detects nftables backend (Fedora 32+ default) and warns about Docker networking issues
  • WSL2 — multi-signal detection (microsoft in /proc/version + WSL_DISTRO_NAME or WSLInterop) prevents Azure VM false positives. Checks cgroup v2 controllers (cpu, memory, pids)
  • Rootfs device — detects BTRFS as Docker storage driver or backing filesystem
  • Subnet clash — detects Docker network subnet overlaps with host routing table using netip.Prefix.Overlaps. Handles macOS abbreviated CIDR notation
  • kinder create cluster calls ApplySafeMitigations() after containerd config patches and before provisioning
  • Only tier-1 mitigations applied (env vars, cluster config adjustments) — never calls sudo or modifies system files
  • Mitigation errors are informational warnings, never block cluster creation
  • Known Issues page documenting all 18 diagnostic checks across 8 categories with What/Why/Platforms/Fix structure
  • Known Issues added to sidebar navigation
  • Cross-linked from Troubleshooting page
  • golang.org/x/sys/unix promoted from indirect to direct dependency for unix.Statfs and unix.Uname
  • Deps struct injection pattern for all checks: injectable readFile, execCmd, lookPath for unit testing without system calls
  • Build-tagged platform pairs: kernel_linux.go/kernel_other.go, disk_unix.go/disk_other.go
  • 80+ new unit tests across 10 check files with table-driven parallel execution

Released: March 5, 2026

First stable release with automated binary distribution via GoReleaser, Homebrew tap, and NVIDIA GPU addon.

  • GoReleaser pipeline — automated cross-platform binary builds for linux/darwin (amd64 + arm64) and windows (amd64) with SHA-256 checksums and categorized changelog
  • GitHub Releases — tagged releases automatically publish platform archives to GitHub Releases
  • Homebrew tapbrew install patrykquantumnomad/kinder/kinder installs a pre-built binary on macOS. Cask auto-published on each stable release via GoReleaser
  • goreleaser-action — replaces legacy cross.sh + softprops release workflow; cross.sh retired
  • NVIDIA device plugin (v0.17.0) — DaemonSet installed via go:embed + kubectl apply when addons.nvidiaGPU: true. RuntimeClass nvidia created for GPU pod scheduling
  • Opt-in configNvidiaGPU *bool field in v1alpha4 config API, defaults to false (unlike other addons which default to true)
  • Platform guard — GPU addon skips with informational message on non-Linux platforms without failing cluster creation
  • Pre-flight validation — checks for nvidia-smi, nvidia-ctk, and nvidia runtime in Docker config before applying manifests. Fails fast with actionable error messages
  • Doctor checkskinder doctor reports NVIDIA driver version, container toolkit presence, and Docker runtime configuration (Linux only, warn-not-fail)
  • Documentation — GPU addon page at kinder.patrykgolabek.dev/addons/nvidia-gpu with prerequisites, configuration, usage, and troubleshooting
  • Installation page updated with Homebrew install instructions and GitHub Releases download links
  • project_name: kinder and gomod.proxy: false in GoReleaser config for fork safety
  • skip_upload: auto on Homebrew cask to prevent publishing pre-release builds
  • HOMEBREW_TAP_TOKEN fine-grained PAT scoped to homebrew-kinder repo for cross-repo cask push

v0.4.1-alpha — Website Use Cases & Documentation

Section titled “v0.4.1-alpha — Website Use Cases & Documentation”

Released: March 4, 2026

Expanded the documentation site with 3 tutorials, 3 CLI reference pages, and enriched all 7 addon pages with examples, troubleshooting, and configuration details.

  • TLS Web App — deploy a web app with TLS termination using cert-manager + Envoy Gateway
  • HPA Auto-Scaling — set up Horizontal Pod Autoscaler with Metrics Server and load-test it
  • Local Dev Workflow — build, push to local registry, and deploy with hot-reload iteration
  • Profile Comparison — side-by-side table of all 4 addon profiles (minimal, full, gateway, ci)
  • JSON Output — schema reference for --output json on env, doctor, get clusters, get nodes
  • Troubleshooting — common issues with kinder env and kinder doctor, exit codes
  • All 7 addon pages updated with: configuration examples, version pinning details, symptom/cause/fix troubleshooting tables, and verification commands
  • Core vs optional addon grouping on landing page and configuration reference
  • Quick-start guide updated with all 7 addon verifications and --profile tip

Released: March 4, 2026

Modernized the Go toolchain, added context.Context cancellation plumbing, built a comprehensive unit test suite, implemented wave-based parallel addon execution, and shipped JSON output and cluster profile presets for the CLI.

  • Go 1.24 baseline — go.mod bumped to 1.24.0, golang.org/x/sys updated to v0.41.0, rand.NewSource dead code cleaned up
  • golangci-lint v2 — migrated from v1.62.2 to v2.10.1 with full config conversion, 55+ lint violations fixed across 60+ files
  • Layer violation fix — version package moved from pkg/cmd/kind/version to pkg/internal/kindversion to enforce clean cmd -> cluster -> internal import direction
  • SHA-256 subnet hashing — SHA-1 replaced with SHA-256 for Docker/Podman/Nerdctl subnet generation
  • Code quality — log directory permissions 07770755, dashboard token at V(1), error naming convention (ErrNoNodeProviderDetected)
  • context.Context plumbingContext field added to ActionContext and propagated through all 7 addon Execute() methods via node.CommandContext(). waitForReady/tryUntil are now cancellation-aware with select on ctx.Done()
  • Centralized addon registry — 7 hard-coded runAddon() calls replaced with a data-driven []AddonEntry registry loop in create.go
  • Test infrastructure — shared testutil package with FakeNode, FakeCmd, and FakeProvider types for testing addon actions without a live cluster
  • Addon test coverage — 30+ table-driven tests covering installenvoygw, installmetricsserver, installcertmanager, installdashboard, and installlocalregistry
  • Race-detector clean — all tests pass under go test -race
  • Wave-based execution — 6 independent addons run concurrently via errgroup.WithContext + SetLimit(3) in Wave 1; EnvoyGateway runs sequentially in Wave 2 (depends on MetalLB)
  • Race-free node cachingRWMutex-based cachedData replaced with sync.OnceValues for exactly-once node caching, eliminating a TOCTOU race
  • Install timing — per-addon install duration printed in the creation summary (e.g., “MetalLB: 12.3s”)
  • Added golang.org/x/sync dependency and make test-race Makefile target
  • --output json — added to kinder env, kinder doctor, kinder get clusters, and kinder get nodes. All produce clean, jq-parseable JSON on stdout; logger output redirected to stderr in JSON mode
  • --profile flagkinder create cluster --profile <name> selects a named addon preset:
    • minimal — no kinder addons (core kind only)
    • full — all addons enabled
    • gateway — MetalLB + Envoy Gateway only
    • ci — Metrics Server + cert-manager (CI-optimized)
  • Default behavior (no --profile) is fully preserved
  • Added golang.org/x/sync v0.19.0 for errgroup
  • CreateWithAddonProfile nil-guards o.Config by loading default config when no --config flag given
  • --profile applied after withConfig so profile addons override config-file addon settings

Released: March 3, 2026

Fixed 4 correctness bugs, eliminated ~525 lines of provider code duplication, and added batteries-included local registry, cert-manager, and CLI diagnostic tools.

  • Port leak fix — port listeners in generatePortMappings are now released at loop iteration end, not deferred to function return, across docker/nerdctl/podman providers
  • Tar truncation fixextractTarball returns a descriptive error on truncated archives instead of silently succeeding
  • Cluster name fixListInternalNodes wraps empty cluster names with defaultName() for consistent resolution across all providers
  • Network sort fix — network sort comparator uses strict weak ordering with != guard for deterministic results
  • Local Registry (localhost:5001) — a registry:2 container is created on the kind network during cluster creation. All nodes are patched with containerd certs.d configuration. A kube-public/local-registry-hosting ConfigMap is applied for Tilt/Skaffold/dev-tool discovery. Disable with addons.localRegistry: false
  • cert-manager (v1.16.3) — embedded manifest applied via --server-side. All three components (controller, webhook, cainjector) reach Available status before the cluster is reported ready. A self-signed ClusterIssuer (selfsigned-issuer) is created automatically so Certificate resources work immediately. Disable with addons.certManager: false
  • kinder env — prints KINDER_PROVIDER, KIND_CLUSTER_NAME, and KUBECONFIG in eval-safe key=value format. Warnings go to stderr. Use with eval $(kinder env) in shell scripts
  • kinder doctor — checks binary prerequisites (docker/podman/nerdctl, kubectl) and prints actionable fix messages. Exit codes: 0 = all good, 1 = hard failure, 2 = warnings only
  • Added LocalRegistry and CertManager fields to the v1alpha4 Addons struct (both *bool, default true)
  • Wired through all 5 config pipeline locations: types, defaults, deepcopy, conversion, validation
  • Extracted shared docker/podman/nerdctl logic to common/ package (common/node.go, common/provision.go)
  • Deleted per-provider provision.go files (~525 lines eliminated)
  • Updated go.mod to go 1.21.0 with toolchain go1.26.0
  • Added Provider.Name() method via fmt.Stringer type assertion

Released: March 2, 2026

Established kinder’s visual identity with a custom logo, SEO discoverability, documentation rewrite, and dark-only theme enforcement.

  • Kinder logo — modified kind robot with “er” in cyan, exported as SVG, PNG, favicon.ico, and OG image
  • Original kind logo preserved in logo/ directory
  • Logo displayed in hero section of landing page
  • llms.txt and llms-full.txt for AI crawler discovery
  • JSON-LD SoftwareApplication structured data
  • Complete Open Graph and Twitter Card meta tags
  • Author backlinks and attribution to patrykgolabek.dev
  • Root README rewritten from kind boilerplate to kinder identity
  • kinder-site/ README updated with project-specific documentation
  • Dark-only theme enforced site-wide (light mode toggle removed)
  • Terminal aesthetic with cyan accents as core visual identity

Released: March 2, 2026

Launched the documentation website at kinder.patrykgolabek.dev with dark terminal aesthetic, interactive landing page, and comprehensive documentation.

  • Astro v5 + Starlight documentation site
  • GitHub Actions deployment to GitHub Pages
  • Custom domain: kinder.patrykgolabek.dev with HTTPS
  • Dark terminal aesthetic (cyan accents, hsl(185))
  • Installation — pre-built binary and build-from-source instructions
  • Quick Start — create your first cluster walkthrough
  • Configuration — v1alpha4 config reference with addon fields
  • MetalLB — LoadBalancer addon documentation
  • Envoy Gateway — Gateway API routing documentation
  • Metrics Serverkubectl top and HPA documentation
  • CoreDNS — DNS tuning documentation
  • Headlamp — dashboard addon documentation
  • Hero section with feature overview
  • Copy-to-clipboard install command
  • Kind vs Kinder feature comparison grid
  • Addon feature cards for all 5 default addons
  • Mobile responsive at 375px viewport
  • Lighthouse 90+ on all metrics
  • robots.txt and Pagefind search index
  • Custom 404 page

Released: March 1, 2026

Forked kind into kinder with 5 default addons that work out of the box. One command gives you a fully functional Kubernetes development environment.

  • Binary renamed from kind to kinder (backward compatible)
  • Config schema extended with addons section in v1alpha4
  • Existing kind configs work unchanged
  • Each addon individually disableable via addons.<name>: false
  • All addons wait for readiness before the cluster is reported ready
  • MetalLB (v0.15.3) — auto-detects Docker/Podman/Nerdctl subnet and assigns LoadBalancer IPs without user input. Platform warning on macOS/Windows
  • Envoy Gateway (v1.3.1) — Gateway API CRDs installed, HTTP routing via LoadBalancer IPs. Uses --server-side apply for large CRDs
  • Metrics Server (v0.8.1) — kubectl top nodes and kubectl top pods work immediately. Configured with --kubelet-insecure-tls for local clusters
  • CoreDNS tuning — in-place Corefile modification: autopath, pods verified, cache 60
  • Headlamp (v0.40.1) — web dashboard with auto-generated admin token and printed port-forward command
  • Addons implemented as creation actions (follows kind’s installcni/installstorage pattern)
  • All manifests embedded via go:embed (offline-capable)
  • Runtime apply via kubectl (not baked into node image)
  • *bool addon fields: nil defaults to true, explicit false disables