CASCADE/common/k3s-cluster.nix

120 lines
3.9 KiB
Nix

{pkgs, config, ...}:
with pkgs.lib;
let
cfg = config.services.k3s-cluster;
agentTokenFilename = cfg.agentTokenFile;
agentTokenFileArg = ''--agent-token-file ${escapeShellArg agentTokenFilename}'';
serverTokenFilename = "/etc/k3s-server-token.txt";
serverTokenFileArg = "--token-file ${escapeShellArg serverTokenFilename}";
serverArg = if (cfg.leader != null) then "--server https://${escapeShellArg cfg.leader}:6443" else "";
in
{
options = with types; {
services.k3s-cluster.secretNamespace = mkOption {
type = nullOr str;
description = ''
namespace used with deterministic-passwords to isolate the
secrets for this cluster. this should be the same for all
members of the cluster, agent or server, and different for all
other clusters.
'';
default = null;
};
services.k3s-cluster.enabled = mkEnableOption "k3s cluster";
services.k3s-cluster.leader = mkOption {
default = null;
type = nullOr str;
description = ''
hostname or IP of cluster leader
This should be set to null (the default) for a cluster leader.
For a member server, this should be set to an address which may
be used to reach the cluster leader from this host.
After completion of cluster formation, this may be set to any
member server. This is a viable path forward when the original
leader dies.
This string will be wrapped in https://...:6443
'';
};
services.k3s-cluster.agentTokenFile = mkOption {
default = "/etc/k3s-agent-token.txt";
type = str;
description = "agent token file path for agents and servers";
};
services.k3s-cluster.serverTokenFile = mkOption {
default = "/etc/k3s-server-token.txt";
type = str;
description = "server token file path for servers";
};
services.k3s-cluster.role = mkOption {
default = "server";
type = str;
description = "server or agent, passed on to k3s";
};
};
config = { services.k3s = mkIf cfg.enabled (
if (cfg.role == "server") then {
extraFlags = mkForce "--cluster-init ${serverArg} ${agentTokenFileArg} ${serverTokenFileArg}";
enable = mkForce true;
role = mkForce "server";
} else {
extraFlags = mkForce "${agentTokenFileArg}";
role = "agent";
serverAddr = "https://${cfg.leader}:6443";
enable = mkForce true;
}
);
systemd = mkIf (cfg.enabled && cfg.leader == null && cfg.role == "server") {
sockets = {
tokenCAHash = {
listenStreams = [ "0.0.0.0:65479" ];
wantedBy = [ "multi-user.target" ];
socketConfig.Accept = "yes";
};
};
services = {
"tokenCAHash@" = {
script = ''
cat /var/lib/rancher/k3s/server/agent-token|cut -d: -f 1
'';
startLimitIntervalSec = 0;
serviceConfig.Type = "oneshot";
serviceConfig.StandardInput = "socket";
};
};
};
networking.firewall.allowedTCPPorts = mkIf cfg.enabled [ 6443 53 65479 ];
networking.firewall.allowedUDPPorts = mkIf cfg.enabled [ 53 ];
environment.deterministic-passwords.secrets = mkIf (cfg.enabled) {
"k3s-agent-token" = {
namespace = cfg.secretNamespace;
destination = agentTokenFilename;
before = ["k3s.service"];
writer = ''
echo "$(nc ${if cfg.leader == null then "localhost" else cfg.leader} 65479 < /dev/null)::server:$secret" > "$destination"
'';
};
"k3s-server-token" = mkIf (cfg.role == "server") {
namespace = cfg.secretNamespace;
destination = serverTokenFilename;
before = ["k3s.service"];
writer = ''
echo "$(nc ${if cfg.leader == null then "localhost" else cfg.leader} 65479 < /dev/null)::server:$secret" > "$destination"
'';
};
};};
}