Adolfo Delorenzo 4e3f1d6cf0
Some checks failed
CI / Go Tests (push) Has been cancelled
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
CI / Shellcheck (push) Has been cancelled
Release / Test (push) Has been cancelled
Release / Build Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
Release / Build Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
Release / Build ISO (amd64) (push) Has been cancelled
Release / Create Release (push) Has been cancelled
fix: use kernel-built DTBs for RPi SD card driver probe
The sdhci-iproc driver (RPi 4 SD card controller) probes via Device
Tree matching. Using DTBs from the firmware repo instead of the
kernel build caused a mismatch — the driver silently failed to probe,
resulting in zero block devices after boot.

Changes:
- Use DTBs from custom-kernel-arm64/dtbs/ (matches the kernel)
- Firmware blobs (start4.elf, fixup4.dat) still from firmware repo
- Also includes prior fix for LABEL= resolution in persistent mount

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:27:54 -06:00
2026-02-12 16:36:05 -06:00
2026-02-12 16:36:05 -06:00

KubeSolo OS

An immutable, bootable Linux distribution purpose-built for KubeSolo — Portainer's ultra-lightweight single-node Kubernetes.

Status: All 6 phases complete. Boots and runs K8s workloads. Portainer Edge Agent tested and connected.

What is this?

KubeSolo OS combines Tiny Core Linux (~11 MB) with KubeSolo (single-binary Kubernetes) to create an appliance-like K8s node that:

  • Boots to a functional Kubernetes cluster in ~35 seconds
  • Runs entirely from RAM with a read-only SquashFS root
  • Persists K8s state across reboots via a dedicated data partition
  • Uses a custom kernel (6.18.2-tinycore64) optimized for containers
  • Supports first-boot configuration via cloud-init YAML
  • Performs atomic A/B updates with automatic GRUB-based rollback
  • Signs update images with Ed25519 for integrity verification
  • Exposes Prometheus metrics for monitoring
  • Integrates with Portainer Edge for fleet management
  • Ships as ISO, raw disk image, or OCI container
  • Requires no SSH, no package manager, no writable system files

Target use cases: IoT/IIoT edge, air-gapped deployments, single-node K8s appliances, kiosk/POS systems, resource-constrained hardware.

Quick Start

# Fetch Tiny Core ISO + KubeSolo binary
make fetch

# Build custom kernel (first time only, ~25 min, cached)
make kernel

# Build Go binaries
make build-cloudinit build-update-agent

# Build bootable ISO
make rootfs initramfs iso

# Test in QEMU
make dev-vm

Or build everything at once inside Docker:

make docker-build

After boot, retrieve the kubeconfig and manage your cluster from the host:

curl -s http://localhost:8080 > ~/.kube/kubesolo-config
export KUBECONFIG=~/.kube/kubesolo-config
kubectl get nodes

Portainer Edge Agent

Pass Edge credentials via boot parameters:

./hack/dev-vm.sh --edge-id=YOUR_EDGE_ID --edge-key=YOUR_EDGE_KEY

Or configure via cloud-init YAML.

Requirements

Build host:

  • Linux x86_64 with root/sudo (for loop mounts)
  • Go 1.22+ (for cloud-init and update agent)
  • Tools: cpio, gzip, wget, curl, syslinux (or use make docker-build)

Runtime:

  • x86_64 hardware or VM (ARM64 cross-compilation available)
  • 512 MB RAM minimum (1 GB+ recommended)
  • 8 GB disk (for persistent data partition)

Architecture

Boot Media (ISO or Disk Image)
  │
  ├── GRUB 2 bootloader (A/B slot selection, rollback counter)
  │
  └── Kernel + Initramfs (kubesolo-os.gz)
        │
        ├── switch_root → SquashFS root (read-only, in RAM)
        ├── Persistent data partition (ext4, bind-mounted)
        │     ├── /var/lib/kubesolo   (K8s state, certs, SQLite)
        │     ├── /var/lib/containerd  (container images)
        │     └── /etc/kubesolo        (node configuration)
        ├── Custom init (POSIX sh, staged boot 00→90)
        │     └── Stage 45: cloud-init (Go binary)
        ├── containerd (bundled with KubeSolo)
        └── KubeSolo (single-binary K8s)

Partition Layout (Disk Image)

GPT Disk (minimum 8 GB):
  Part 1: EFI/Boot   (256 MB, FAT32)  — GRUB + A/B boot logic
  Part 2: System A   (512 MB, ext4)   — vmlinuz + kubesolo-os.gz (active)
  Part 3: System B   (512 MB, ext4)   — vmlinuz + kubesolo-os.gz (passive)
  Part 4: Data       (remaining, ext4) — persistent K8s state

See docs/design/kubesolo-os-design.md for the full architecture document.

Custom Kernel

The stock Tiny Core 17.0 kernel lacks several configs required for containers. KubeSolo OS builds a custom kernel (6.18.2-tinycore64) that adds:

  • CONFIG_CGROUP_BPF — cgroup v2 device control via BPF
  • CONFIG_DEVTMPFS / CONFIG_DEVTMPFS_MOUNT — automatic /dev node creation
  • CONFIG_MEMCG — memory cgroup controller
  • CONFIG_CFS_BANDWIDTH — CPU bandwidth throttling

Unnecessary subsystems (sound, GPU, wireless, Bluetooth, etc.) are stripped to keep the kernel minimal. Build is cached in build/cache/custom-kernel/.

Cloud-Init

First-boot configuration via a simple YAML schema. All documented KubeSolo flags are supported:

hostname: edge-node-01
network:
  mode: static
  address: 192.168.1.100/24
  gateway: 192.168.1.1
  dns:
    - 8.8.8.8
kubesolo:
  local-storage: true
  local-storage-shared-path: "/mnt/shared"
  apiserver-extra-sans:
    - edge-node-01.local
  debug: false
  pprof-server: false
  portainer-edge-id: "your-edge-id"
  portainer-edge-key: "your-edge-key"
  portainer-edge-async: true

See docs/cloud-init.md and the examples.

Atomic Updates

A/B partition scheme with GRUB boot counter for automatic rollback:

  1. Update agent downloads new image to passive partition
  2. GRUB boots new partition with boot_counter=3
  3. Health check verifies containerd + K8s API + node Ready → sets boot_success=1
  4. On 3 consecutive boot failures, GRUB auto-rolls back to previous slot

Updates can be signed with Ed25519 for integrity verification. A K8s CronJob checks for updates every 6 hours.

See docs/update-flow.md.

Monitoring

The update agent exposes Prometheus metrics on port 9100:

kubesolo-update metrics --listen :9100

Metrics include: kubesolo_os_info, boot_success, boot_counter, uptime_seconds, update_available, memory_total_bytes, memory_available_bytes.

Project Structure

├── Makefile               # Build orchestration
├── build/                 # Build scripts, kernel config, rootfs overlays
│   └── scripts/
│       ├── build-kernel.sh        # Custom kernel compilation
│       ├── fetch-components.sh    # Download components
│       ├── create-iso.sh          # Bootable ISO
│       ├── create-disk-image.sh   # A/B partition disk image
│       └── create-oci-image.sh    # OCI container image
├── init/                  # Custom init system (POSIX sh)
│   ├── init.sh            # Main init + switch_root
│   └── lib/               # Staged boot scripts (00-90)
├── cloud-init/            # Go cloud-init parser
├── update/                # Go atomic update agent
├── test/                  # QEMU-based automated tests + benchmarks
├── hack/                  # Developer utilities (dev-vm, SSH, USB)
├── docs/                  # Documentation
│   ├── design/            # Architecture design document
│   ├── boot-flow.md       # Boot sequence reference
│   ├── update-flow.md     # A/B update reference
│   ├── cloud-init.md      # Cloud-init configuration reference
│   └── deployment-guide.md # Deployment and operations guide
└── .gitea/workflows/      # CI/CD (Gitea Actions)

Make Targets

Target Description
make fetch Download Tiny Core ISO + KubeSolo binary
make kernel Build custom kernel (cached)
make build-cloudinit Compile cloud-init Go binary
make build-update-agent Compile update agent Go binary
make rootfs Extract Tiny Core + inject KubeSolo
make initramfs Pack initramfs (kubesolo-os.gz)
make iso Create bootable ISO
make disk-image Create A/B partition disk image
make oci-image Package as OCI container
make build-cross Cross-compile for amd64 + arm64
make docker-build Build everything in Docker
make quick Fast rebuild (re-inject + repack + ISO)
make dev-vm Launch QEMU dev VM (Linux + macOS)
make test-all Run all tests

Documentation

Roadmap

Phase Scope Status
1 PoC: boot Tiny Core + KubeSolo, verify K8s Complete
2 Cloud-init Go parser, network, hostname Complete
3 A/B atomic updates, GRUB, rollback agent Complete
4 Ed25519 signing, Portainer Edge, SSH extension Complete
5 CI/CD, OCI distribution, Prometheus metrics, ARM64 Complete
6 Security hardening, AppArmor, ARM64 RPi support Complete
- Custom kernel build for container runtime fixes Complete

License

MIT License — see LICENSE for details.

Description
No description provided
Readme MIT 451 KiB
2026-02-13 02:27:54 +01:00
Languages
Shell 57.3%
Go 39.2%
Makefile 3.1%
Ruby 0.4%