An open API service indexing awesome lists of open source software.

https://github.com/saiyam1814/kiac

Local Kubernetes on Apple's container framework - every node is its own lightweight VM. Metrics, storage, and LoadBalancer included.
https://github.com/saiyam1814/kiac

apple-silicon containers kubernetes macos

Last synced: 2 days ago
JSON representation

Local Kubernetes on Apple's container framework - every node is its own lightweight VM. Metrics, storage, and LoadBalancer included.

Awesome Lists containing this project

README

          


kiac - Kubernetes in Apple Containers


Local Kubernetes clusters where every node is its own lightweight VM.

Native on Apple silicon, powered by apple/container. No Docker Desktop. No Lima. No QEMU.


release
MIT
Apple silicon
Kubernetes 1.32-1.36
website


kiac creating a 3-node cluster

```bash
brew install saiyam1814/tap/kiac
kiac create cluster --workers 2
```

---

## Why this matters

Running a local Kubernetes cluster on a Mac has always meant a quiet compromise. Your "nodes" were containers sharing one kernel inside one hidden Linux VM, all pretending to be separate machines. It worked until you tried to test a node failure, or `kubectl top`, or a `type: LoadBalancer` service, and the illusion cracked.

A Kubernetes node wants to *be* a machine: its own kernel, its own kubelet, its own cgroups, its own IP that can come and go on its own. **kiac gives every node exactly that** by booting each one as its own lightweight virtual machine on Apple's native runtime. The result is a local cluster that behaves like a real one, created with a single command in a couple of minutes.

## Why Apple containers

When Apple shipped `container` 1.0, most people read it as "Docker, but from Apple." It is something more interesting underneath: **every container is its own lightweight virtual machine.**


How one Apple container works

The [Containerization](https://github.com/apple/containerization) framework boots a separate, minimal Linux VM for each container on Apple's `Virtualization.framework`:

- **The image becomes a disk.** The OCI image is turned into an EXT4 filesystem and handed to the VM as its root block device. No overlay mount layered on a shared host kernel.
- **A dedicated kernel boots.** Each container gets its own minimal, optimized Linux kernel. It is not shared with the host or any other container.
- **`vminitd` is PID 1.** A tiny Swift init system comes up first, then launches and supervises your process. The host drives it through a gRPC API over `vsock`.
- **virtio devices, direct networking.** No BIOS, no legacy device emulation, so the VM boots in about a second and gets its own IP you can reach from your Mac.

You get the developer experience of containers with the isolation boundary of a virtual machine. That combination is exactly what a Kubernetes node wants.

## Why Kubernetes on Apple containers: real isolation

When local Kubernetes tools run "nodes" as Docker containers, those nodes are processes sharing one Linux kernel, separated only by namespaces. Namespaces are a software boundary *inside* a single shared kernel. With kiac, the boundary between nodes is the **hypervisor** itself.


Where the isolation boundary sits

That difference is not academic. It changes what the cluster can actually do:

- **Blast radius.** A container escape that reaches the shared kernel reaches every node on it. With a VM per node, an escape is contained to one VM.
- **Failure domains.** A shared kernel is a shared fate: one panic or runaway sysctl takes everything down together. With kiac, a kernel problem stays inside the VM that caused it.
- **Real node failure.** Stop one node VM and it behaves like an actual node going offline: NotReady detection, eviction, rescheduling. You cannot meaningfully test that when "stopping a node" means killing one of several processes that share a kernel.
- **Per-node kernel reality.** Each node has its own `/proc`, `/sys`, modules, and sysctls. Node-level behavior is real, not simulated.

Containers are great for packaging software, and kiac depends on them. The point is narrower: when the workload you are isolating is itself a machine, a machine-grade boundary is the right tool.

## Features

- ๐Ÿ”’ **Hardware-grade isolation** โ€” each node is one lightweight VM with its own kernel and cgroups, not namespaces sharing a daemon.
- ๐Ÿ“Š **Metrics out of the box** โ€” `kubectl top nodes` works the moment the cluster is up. metrics-server ships preconfigured.
- ๐Ÿ’พ **PVCs that just bind** โ€” a default StorageClass (local-path-provisioner) is installed on create, so StatefulSets and `volumeClaimTemplates` work immediately.
- โš–๏ธ **`type: LoadBalancer` works** โ€” MetalLB ships by default, pooled on node IPs, so Services get a real EXTERNAL-IP you can curl from your Mac. No ``, no tunnels.
- ๐ŸŒ **Direct networking** โ€” every node gets a routable IP on macOS 26+. Hit NodePorts directly, no port-mapping flags.
- ๐Ÿงฑ **Multi-node, day one** โ€” `--workers N` gives a real topology: scheduling, cross-node pod networking, node failures you can practice on.
- ๐Ÿ–ฅ๏ธ **A console when you want one** โ€” `kiac ui` opens a local web console to create, watch, and delete clusters, same engine as the CLI.
- ๐ŸŽ **Native stack** โ€” one Swift runtime from Apple, one Go binary from us. Coexists with Docker Desktop, kind, and k3d; never touches the Docker socket.

## Quickstart

### Requirements

- An Apple silicon Mac
- macOS 26+ for multi-node clusters (single-node works on macOS 15, with limitations)
- [apple/container](https://github.com/apple/container/releases) 1.0.0+
- `kubectl`

### Install

```bash
brew install saiyam1814/tap/kiac
```

Other install methods

```bash
# With Go
go install github.com/saiyam1814/kiac@latest

# From source
git clone https://github.com/saiyam1814/kiac && cd kiac && make build
```

### Create your first cluster

```bash
kiac doctor # check your setup
kiac create cluster --name dev --workers 2 # 1 control plane + 2 workers
```

```text
โฌข kiac v0.1.0 ยท Kubernetes in Apple Containers
โœ“ Preflight checks (0.3s)
โœ“ Pulling node image kindest/node:v1.36.1 (8.4s)
โœ“ Booting 3 node VM(s) (9.8s)
โœ“ Initializing Kubernetes control plane (49.6s)
โœ“ Joining 2 worker(s) (13.5s)
โœ“ Installing CNI (kindnet) (0.4s)
โœ“ Installing storage (local-path-provisioner) (0.5s)
โœ“ Installing metrics-server (0.4s)
โœ“ Installing LoadBalancer (MetalLB) (0.6s)
โœ“ Waiting for nodes to be Ready (10.7s)
โœ“ Configuring LoadBalancer IP pool (3.2s)
โœ“ Writing kubeconfig (0.2s)

Cluster "dev" is ready in 2m26s. Every node is its own lightweight VM.
```

The kubeconfig is merged into `~/.kube/config` as context `kiac-dev` (your existing config is backed up to `~/.kube/config.kiac.bak` the first time).

### See the isolation pay off

```bash
$ kubectl get nodes -o wide
NAME STATUS ROLES VERSION INTERNAL-IP KERNEL-VERSION CONTAINER-RUNTIME
kiac-dev-control-plane Ready control-plane v1.36.1 192.168.64.2 6.12.28 (arm64) containerd://2.3.1
kiac-dev-worker-1 Ready v1.36.1 192.168.64.3 6.12.28 (arm64) containerd://2.3.1
kiac-dev-worker-2 Ready v1.36.1 192.168.64.4 6.12.28 (arm64) containerd://2.3.1

$ kubectl top nodes
NAME CPU(cores) CPU(%) MEMORY(bytes) MEMORY(%)
kiac-dev-control-plane 269m 5% 828Mi 20%
kiac-dev-worker-1 35m 0% 288Mi 7%
kiac-dev-worker-2 52m 1% 359Mi 9%

$ kubectl expose deploy web --port=80 --type=LoadBalancer
$ kubectl get svc web
NAME TYPE EXTERNAL-IP PORT(S) AGE
web LoadBalancer 192.168.64.3 80:30495/TCP 15s
$ curl http://192.168.64.3 # HTTP 200, straight from your Mac
```

## Usage

```bash
kiac doctor # check your setup
kiac create cluster # single node, everything included
kiac create cluster --name dev --workers 2 # 1 control plane + 2 workers
kiac create cluster --k8s-version 1.34 # pick your Kubernetes (1.32-1.36 pinned)
kiac ui # local web console to create/manage clusters
kiac get clusters
kiac get nodes --name dev
container build -t myapp:dev . # build with apple/container
kiac load image myapp:dev --name dev # push it into every node
kiac delete cluster --name dev
```

### Flags for `create cluster`

| Flag | Default | Description |
|---|---|---|
| `--name` | `dev` | cluster name |
| `--workers` | `0` | worker count; control plane is untainted when 0 |
| `--k8s-version` | `1.36` | Kubernetes minor, pinned digests for 1.32-1.36 |
| `--image` | resolved from `--k8s-version` | explicit node image override |
| `--cni` | `kindnet` | pod network: `kindnet` or `none` (Flannel/Calico/Cilium need kernel features missing from Apple's stock node kernel; custom kernels are on the roadmap) |
| `--cpus` | `4` | vCPUs per node VM |
| `--memory` | `4G` | memory per node VM |
| `--no-metrics` | `false` | skip metrics-server |
| `--no-storage` | `false` | skip the local-path default StorageClass |
| `--no-lb` | `false` | skip MetalLB (`type: LoadBalancer` support) |
| `--wait` | `5m` | node readiness timeout |

## How it works


How kiac builds a cluster

kiac drives the `apple/container` CLI to boot one lightweight VM per node from the standard `kindest/node` image (systemd, containerd, kubeadm preinstalled), initializes the control plane with `kubeadm`, joins the workers over the `vmnet` network, applies the kindnet CNI, and installs metrics-server, local-path storage, and MetalLB by default. It talks only to the `apple/container` runtime and never touches the Docker socket, so it coexists with Docker Desktop, Rancher Desktop, kind, and k3d.

## Roadmap

- **Node chaos** โ€” `kiac stop|start node` to test real NotReady detection, eviction, and rescheduling
- **Custom node kernels** (`--kernel`) to unlock Flannel, Calico, Cilium, and eBPF
- **Persistent clusters** backed by `container machine` (WWDC26 persistent Linux environments), so a cluster survives a reboot
- **Built-in LoadBalancer controller** to replace MetalLB (node-IP allocation needs no ARP speaker)
- **HA control planes** and an ingress helper

## Contributing

Issues and PRs are welcome. New here? Look for issues labeled [`good first issue`](https://github.com/saiyam1814/kiac/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) โ€” they are scoped with context and acceptance criteria to be a clean first contribution.

## Credits

kiac stands on other people's work: the [`apple/container`](https://github.com/apple/container) and [Containerization](https://github.com/apple/containerization) teams at Apple built the runtime; Akihiro Suda's [`kina`](https://github.com/AkihiroSuda/kina) proved Kubernetes on `apple/container` was viable; and the node experience reuses the [`kindest/node`](https://github.com/kubernetes-sigs/kind) image from the kind project.

## License

[MIT](LICENSE)