|
16 | 16 | pkgs.kubernetes # kubectl, kubeadm, kubelet |
17 | 17 | pkgs.cri-tools # crictl |
18 | 18 | pkgs.helix # editor |
| 19 | + pkgs.k9s |
| 20 | + pkgs.fish |
| 21 | + pkgs.stern |
19 | 22 | ]; |
20 | 23 |
|
21 | 24 | environment.variables.EDITOR = "hx"; |
|
47 | 50 | }; |
48 | 51 | }; |
49 | 52 |
|
50 | | - # -- CNI bridge config -- |
51 | | - # Simple bridge CNI — no cluster-level setup needed, just this config file. |
52 | | - environment.etc."cni/net.d/10-bridge.conflist".text = builtins.toJSON { |
| 53 | + # -- CNI ptp config -- |
| 54 | + # PTP (point-to-point) CNI: each pod gets a veth pair, no shared bridge. |
| 55 | + # Traffic between pods is routed at L3 on the host, which lets kube-proxy |
| 56 | + # iptables/ipvs rules see and rewrite service traffic correctly. |
| 57 | + environment.etc."cni/net.d/10-ptp.conflist".text = builtins.toJSON { |
53 | 58 | cniVersion = "1.0.0"; |
54 | | - name = "bridge"; |
| 59 | + name = "ptp"; |
55 | 60 | plugins = [ |
56 | 61 | { |
57 | | - type = "bridge"; |
58 | | - bridge = "cni0"; |
59 | | - isGateway = true; |
| 62 | + type = "ptp"; |
60 | 63 | ipMasq = true; |
61 | 64 | ipam = { |
62 | 65 | type = "host-local"; |
63 | | - ranges = [ [ { subnet = "10.244.0.0/16"; } ] ]; |
| 66 | + subnet = "10.113.37.0/24"; |
| 67 | + # Explicit gateway ensures the host-side veth always gets this IP, |
| 68 | + # which nixkube pods use to reach nix-serve on the VM. |
| 69 | + gateway = "10.113.37.1"; |
64 | 70 | routes = [ { dst = "0.0.0.0/0"; } ]; |
65 | 71 | }; |
66 | 72 | } |
|
135 | 141 | # -- VM sizing for kubeadm cluster -- |
136 | 142 | virtualisation = { |
137 | 143 | memorySize = 4096; |
138 | | - diskSize = 10240; |
| 144 | + diskSize = 30720; # 30GB: 20GB system + 8GB swap + headroom |
139 | 145 | cores = 4; |
140 | 146 | }; |
141 | 147 |
|
| 148 | + # Increase 9p max packet size for Nix store mounts (default 16 KB is slow). |
| 149 | + virtualisation.msize = 131072; |
| 150 | + |
| 151 | + |
| 152 | + # Swap so the 10GB tmpfs below can exceed physical RAM without OOM. |
| 153 | + swapDevices = [ |
| 154 | + { |
| 155 | + device = "/swapfile"; |
| 156 | + size = 8192; # 8GB in MiB |
| 157 | + } |
| 158 | + ]; |
| 159 | + |
| 160 | + # nixkube's initContainer copies the full node-env closure here — potentially |
| 161 | + # several GB. Keeping it on tmpfs avoids thrashing the qcow2 disk image. |
| 162 | + fileSystems."/var/lib/nix-csi" = { |
| 163 | + device = "tmpfs"; |
| 164 | + fsType = "tmpfs"; |
| 165 | + options = [ "size=10g" "mode=755" ]; |
| 166 | + }; |
| 167 | + |
142 | 168 | # -- Interactive debug user -- |
143 | 169 | users.users.nixkube = { |
144 | 170 | isNormalUser = true; |
|
160 | 186 | "d /var/run/nri 0755 root root -" |
161 | 187 | ]; |
162 | 188 |
|
| 189 | + # Serve the VM's /nix/store as an unsigned binary cache on port 5000. |
| 190 | + # nixkube pods use this as a trusted substituter so test workload paths can be |
| 191 | + # fetched without going to the internet (paths pre-populated via additionalPaths). |
| 192 | + services.nix-serve = { |
| 193 | + enable = true; |
| 194 | + package = pkgs.nix-serve-ng; |
| 195 | + bindAddress = "0.0.0.0"; |
| 196 | + port = 5000; |
| 197 | + }; |
| 198 | + |
163 | 199 | # Enable external networking for image pulls and nix binary cache access |
164 | 200 | # SLiRP provides DHCP + DNS automatically |
165 | 201 | networking.firewall.enable = false; |
|
0 commit comments