[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-85182":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":21,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":27,"readmeContent":28,"aiSummary":10,"trendingCount":16,"starSnapshotCount":16,"syncStatus":13,"lastSyncTime":29,"discoverSource":30},85182,"kiac","saiyam1814\u002Fkiac","saiyam1814","Local Kubernetes on Apple's container framework - every node is its own lightweight VM. Metrics, storage, and LoadBalancer included.","https:\u002F\u002Fsaiyam1814.github.io\u002Fkiac\u002F",null,"Go",54,2,1,5,0,37.43,"MIT License",false,"main",true,[23,24,25,26],"apple-silicon","containers","kubernetes","macos","2026-06-15 10:05:21","\u003Cp align=\"center\">\n  \u003Cimg src=\"assets\u002Fbanner.png\" alt=\"kiac - Kubernetes in Apple Containers\" width=\"100%\">\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cb>Local Kubernetes clusters where every node is its own lightweight VM.\u003C\u002Fb>\u003Cbr>\n  Native on Apple silicon, powered by \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fapple\u002Fcontainer\">apple\u002Fcontainer\u003C\u002Fa>. No Docker Desktop. No Lima. No QEMU.\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fsaiyam1814\u002Fkiac\u002Freleases\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002Fsaiyam1814\u002Fkiac?color=326CE5&label=release\" alt=\"release\">\u003C\u002Fa>\n  \u003Ca href=\"LICENSE\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-MIT-326CE5\" alt=\"MIT\">\u003C\u002Fa>\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplatform-Apple%20silicon-555\" alt=\"Apple silicon\">\n  \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FKubernetes-1.32–1.36-326CE5\" alt=\"Kubernetes 1.32-1.36\">\n  \u003Ca href=\"https:\u002F\u002Fsaiyam1814.github.io\u002Fkiac\u002F\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fwebsite-kiac-326CE5\" alt=\"website\">\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"assets\u002Fkiac-demo.gif\" alt=\"kiac creating a 3-node cluster\" width=\"80%\">\n\u003C\u002Fp>\n\n```bash\nbrew install saiyam1814\u002Ftap\u002Fkiac\nkiac create cluster --workers 2\n```\n\n---\n\n## Why this matters\n\nRunning 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.\n\nA 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.\n\n## Why Apple containers\n\nWhen 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.**\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"assets\u002Fapple-container-anatomy.png\" alt=\"How one Apple container works\" width=\"92%\">\n\u003C\u002Fp>\n\nThe [Containerization](https:\u002F\u002Fgithub.com\u002Fapple\u002Fcontainerization) framework boots a separate, minimal Linux VM for each container on Apple's `Virtualization.framework`:\n\n- **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.\n- **A dedicated kernel boots.** Each container gets its own minimal, optimized Linux kernel. It is not shared with the host or any other container.\n- **`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`.\n- **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.\n\nYou get the developer experience of containers with the isolation boundary of a virtual machine. That combination is exactly what a Kubernetes node wants.\n\n## Why Kubernetes on Apple containers: real isolation\n\nWhen 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.\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"assets\u002Fisolation.png\" alt=\"Where the isolation boundary sits\" width=\"100%\">\n\u003C\u002Fp>\n\nThat difference is not academic. It changes what the cluster can actually do:\n\n- **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.\n- **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.\n- **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.\n- **Per-node kernel reality.** Each node has its own `\u002Fproc`, `\u002Fsys`, modules, and sysctls. Node-level behavior is real, not simulated.\n\nContainers 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.\n\n## Features\n\n- 🔒 **Hardware-grade isolation** — each node is one lightweight VM with its own kernel and cgroups, not namespaces sharing a daemon.\n- 📊 **Metrics out of the box** — `kubectl top nodes` works the moment the cluster is up. metrics-server ships preconfigured.\n- 💾 **PVCs that just bind** — a default StorageClass (local-path-provisioner) is installed on create, so StatefulSets and `volumeClaimTemplates` work immediately.\n- ⚖️ **`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 `\u003Cpending>`, no tunnels.\n- 🌐 **Direct networking** — every node gets a routable IP on macOS 26+. Hit NodePorts directly, no port-mapping flags.\n- 🧱 **Multi-node, day one** — `--workers N` gives a real topology: scheduling, cross-node pod networking, node failures you can practice on.\n- 🖥️ **A console when you want one** — `kiac ui` opens a local web console to create, watch, and delete clusters, same engine as the CLI.\n- 🍎 **Native stack** — one Swift runtime from Apple, one Go binary from us. Coexists with Docker Desktop, kind, and k3d; never touches the Docker socket.\n\n## Quickstart\n\n### Requirements\n\n- An Apple silicon Mac\n- macOS 26+ for multi-node clusters (single-node works on macOS 15, with limitations)\n- [apple\u002Fcontainer](https:\u002F\u002Fgithub.com\u002Fapple\u002Fcontainer\u002Freleases) 1.0.0+\n- `kubectl`\n\n### Install\n\n```bash\nbrew install saiyam1814\u002Ftap\u002Fkiac\n```\n\n\u003Cdetails>\n\u003Csummary>Other install methods\u003C\u002Fsummary>\n\n```bash\n# With Go\ngo install github.com\u002Fsaiyam1814\u002Fkiac@latest\n\n# From source\ngit clone https:\u002F\u002Fgithub.com\u002Fsaiyam1814\u002Fkiac && cd kiac && make build\n```\n\u003C\u002Fdetails>\n\n### Create your first cluster\n\n```bash\nkiac doctor                                  # check your setup\nkiac create cluster --name dev --workers 2   # 1 control plane + 2 workers\n```\n\n```text\n⬢ kiac v0.1.0 · Kubernetes in Apple Containers\n ✓ Preflight checks (0.3s)\n ✓ Pulling node image kindest\u002Fnode:v1.36.1 (8.4s)\n ✓ Booting 3 node VM(s) (9.8s)\n ✓ Initializing Kubernetes control plane (49.6s)\n ✓ Joining 2 worker(s) (13.5s)\n ✓ Installing CNI (kindnet) (0.4s)\n ✓ Installing storage (local-path-provisioner) (0.5s)\n ✓ Installing metrics-server (0.4s)\n ✓ Installing LoadBalancer (MetalLB) (0.6s)\n ✓ Waiting for nodes to be Ready (10.7s)\n ✓ Configuring LoadBalancer IP pool (3.2s)\n ✓ Writing kubeconfig (0.2s)\n\nCluster \"dev\" is ready in 2m26s. Every node is its own lightweight VM.\n```\n\nThe kubeconfig is merged into `~\u002F.kube\u002Fconfig` as context `kiac-dev` (your existing config is backed up to `~\u002F.kube\u002Fconfig.kiac.bak` the first time).\n\n### See the isolation pay off\n\n```bash\n$ kubectl get nodes -o wide\nNAME                     STATUS   ROLES           VERSION   INTERNAL-IP    KERNEL-VERSION    CONTAINER-RUNTIME\nkiac-dev-control-plane   Ready    control-plane   v1.36.1   192.168.64.2   6.12.28 (arm64)   containerd:\u002F\u002F2.3.1\nkiac-dev-worker-1        Ready    \u003Cnone>          v1.36.1   192.168.64.3   6.12.28 (arm64)   containerd:\u002F\u002F2.3.1\nkiac-dev-worker-2        Ready    \u003Cnone>          v1.36.1   192.168.64.4   6.12.28 (arm64)   containerd:\u002F\u002F2.3.1\n\n$ kubectl top nodes\nNAME                     CPU(cores)   CPU(%)   MEMORY(bytes)   MEMORY(%)\nkiac-dev-control-plane   269m         5%       828Mi           20%\nkiac-dev-worker-1        35m          0%       288Mi           7%\nkiac-dev-worker-2        52m          1%       359Mi           9%\n\n$ kubectl expose deploy web --port=80 --type=LoadBalancer\n$ kubectl get svc web\nNAME   TYPE           EXTERNAL-IP    PORT(S)        AGE\nweb    LoadBalancer   192.168.64.3   80:30495\u002FTCP   15s\n$ curl http:\u002F\u002F192.168.64.3       # HTTP 200, straight from your Mac\n```\n\n## Usage\n\n```bash\nkiac doctor                                  # check your setup\nkiac create cluster                          # single node, everything included\nkiac create cluster --name dev --workers 2   # 1 control plane + 2 workers\nkiac create cluster --k8s-version 1.34       # pick your Kubernetes (1.32-1.36 pinned)\nkiac ui                                      # local web console to create\u002Fmanage clusters\nkiac get clusters\nkiac get nodes --name dev\ncontainer build -t myapp:dev .               # build with apple\u002Fcontainer\nkiac load image myapp:dev --name dev         # push it into every node\nkiac delete cluster --name dev\n```\n\n### Flags for `create cluster`\n\n| Flag | Default | Description |\n|---|---|---|\n| `--name` | `kiac` | cluster name |\n| `--workers` | `0` | worker count; control plane is untainted when 0 |\n| `--k8s-version` | `1.36` | Kubernetes minor, pinned digests for 1.32-1.36 |\n| `--image` | resolved from `--k8s-version` | explicit node image override |\n| `--cni` | `kindnet` | pod network: `kindnet` or `none` (Flannel\u002FCalico\u002FCilium need kernel features missing from Apple's stock node kernel; custom kernels are on the roadmap) |\n| `--cpus` | `4` | vCPUs per node VM |\n| `--memory` | `4G` | memory per node VM |\n| `--no-metrics` | `false` | skip metrics-server |\n| `--no-storage` | `false` | skip the local-path default StorageClass |\n| `--no-lb` | `false` | skip MetalLB (`type: LoadBalancer` support) |\n| `--wait` | `5m` | node readiness timeout |\n\n## How it works\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"assets\u002Farchitecture.png\" alt=\"How kiac builds a cluster\" width=\"100%\">\n\u003C\u002Fp>\n\nkiac drives the `apple\u002Fcontainer` CLI to boot one lightweight VM per node from the standard `kindest\u002Fnode` 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\u002Fcontainer` runtime and never touches the Docker socket, so it coexists with Docker Desktop, Rancher Desktop, kind, and k3d.\n\n## Roadmap\n\n- **Node chaos** — `kiac stop|start node` to test real NotReady detection, eviction, and rescheduling\n- **Custom node kernels** (`--kernel`) to unlock Flannel, Calico, Cilium, and eBPF\n- **Persistent clusters** backed by `container machine` (WWDC26 persistent Linux environments), so a cluster survives a reboot\n- **Built-in LoadBalancer controller** to replace MetalLB (node-IP allocation needs no ARP speaker)\n- **HA control planes** and an ingress helper\n\n## Contributing\n\nIssues and PRs are welcome. New here? Look for issues labeled [`good first issue`](https:\u002F\u002Fgithub.com\u002Fsaiyam1814\u002Fkiac\u002Fissues?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.\n\n## Credits\n\nkiac stands on other people's work: the [`apple\u002Fcontainer`](https:\u002F\u002Fgithub.com\u002Fapple\u002Fcontainer) and [Containerization](https:\u002F\u002Fgithub.com\u002Fapple\u002Fcontainerization) teams at Apple built the runtime; Akihiro Suda's [`kina`](https:\u002F\u002Fgithub.com\u002FAkihiroSuda\u002Fkina) proved Kubernetes on `apple\u002Fcontainer` was viable; and the node experience reuses the [`kindest\u002Fnode`](https:\u002F\u002Fgithub.com\u002Fkubernetes-sigs\u002Fkind) image from the kind project.\n\n## License\n\n[MIT](LICENSE)\n","2026-06-15 02:30:16","CREATED_QUERY"]