1 # A test that runs a multi-node k3s cluster and verify pod networking works across nodes
2 import ../make-test-python.nix (
10 imageEnv = pkgs.buildEnv {
11 name = "k3s-pause-image-env";
19 pauseImage = pkgs.dockerTools.streamLayeredImage {
20 name = "test.local/pause";
30 # A daemonset that responds 'server' on port 8000
31 networkTestDaemonset = pkgs.writeText "test.yml" ''
49 image: test.local/pause:local
50 imagePullPolicy: Never
54 command: ["socat", "TCP4-LISTEN:8000,fork", "EXEC:echo server"]
56 tokenFile = pkgs.writeText "token" "p@s$w0rd";
59 name = "${k3s.name}-multi-node";
65 environment.systemPackages = with pkgs; [
69 # k3s uses enough resources the default vm fails.
70 virtualisation.memorySize = 1536;
71 virtualisation.diskSize = 4096;
81 "--disable local-storage"
82 "--disable metrics-server"
85 "--node-ip 192.168.1.1"
86 "--pause-image test.local/pause:local"
89 networking.firewall.allowedTCPPorts = [
94 networking.firewall.allowedUDPPorts = [ 8472 ];
95 networking.firewall.trustedInterfaces = [ "flannel.1" ];
96 networking.useDHCP = false;
97 networking.defaultGateway = "192.168.1.1";
98 networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
100 address = "192.168.1.1";
109 environment.systemPackages = with pkgs; [
113 virtualisation.memorySize = 1536;
114 virtualisation.diskSize = 4096;
119 serverAddr = "https://192.168.1.1:6443";
121 extraFlags = builtins.toString [
135 "test.local/pause:local"
138 networking.firewall.allowedTCPPorts = [
143 networking.firewall.allowedUDPPorts = [ 8472 ];
144 networking.firewall.trustedInterfaces = [ "flannel.1" ];
145 networking.useDHCP = false;
146 networking.defaultGateway = "192.168.1.3";
147 networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
149 address = "192.168.1.3";
158 virtualisation.memorySize = 1024;
159 virtualisation.diskSize = 2048;
164 serverAddr = "https://192.168.1.3:6443";
165 extraFlags = lib.concatStringsSep " " [
167 "test.local/pause:local"
172 networking.firewall.allowedTCPPorts = [ 6443 ];
173 networking.firewall.allowedUDPPorts = [ 8472 ];
174 networking.firewall.trustedInterfaces = [ "flannel.1" ];
175 networking.useDHCP = false;
176 networking.defaultGateway = "192.168.1.2";
177 networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkForce [
179 address = "192.168.1.2";
187 machines = [server, server2, agent]
190 m.wait_for_unit("k3s")
192 is_aarch64 = "${toString pkgs.stdenv.hostPlatform.isAarch64}" == "1"
194 # wait for the agent to show up
195 server.wait_until_succeeds("k3s kubectl get node agent")
198 m.succeed("k3s check-config")
200 "${pauseImage} | k3s ctr image import -"
203 server.succeed("k3s kubectl cluster-info")
204 # Also wait for our service account to show up; it takes a sec
205 server.wait_until_succeeds("k3s kubectl get serviceaccount default")
207 # Now create a pod on each node via a daemonset and verify they can talk to each other.
208 server.succeed("k3s kubectl apply -f ${networkTestDaemonset}")
209 server.wait_until_succeeds(f'[ "$(k3s kubectl get ds test -o json | jq .status.numberReady)" -eq {len(machines)} ]')
212 pods = server.succeed("k3s kubectl get po -o json | jq '.items[].metadata.name' -r").splitlines()
213 pod_ips = [server.succeed(f"k3s kubectl get po {name} -o json | jq '.status.podIP' -cr").strip() for name in pods]
215 # Verify each server can ping each pod ip
216 for pod_ip in pod_ips:
217 server.succeed(f"ping -c 1 {pod_ip}")
218 agent.succeed(f"ping -c 1 {pod_ip}")
220 # Verify the pods can talk to each other
221 resp = server.wait_until_succeeds(f"k3s kubectl exec {pods[0]} -- socat TCP:{pod_ips[1]}:8000 -")
222 assert resp.strip() == "server"
223 resp = server.wait_until_succeeds(f"k3s kubectl exec {pods[1]} -- socat TCP:{pod_ips[0]}:8000 -")
224 assert resp.strip() == "server"
227 server.succeed("k3s kubectl delete -f ${networkTestDaemonset}")
233 meta.maintainers = lib.teams.k3s.members;