photoncloud-monorepo/nix/nodes/vm-cluster/lib.nix
2026-04-04 16:33:03 +09:00

240 lines
6 KiB
Nix

{ lib }:
let
inherit (lib) concatStringsSep genAttrs mkIf;
clusterName = "ultracloud-vm-cluster";
clusterId = clusterName;
environment = "dev";
bgpAsn = 64512;
bootstrapToken = "vm-cluster-bootstrap-token";
adminToken = "vm-cluster-admin-token";
chainfireApiPort = 2379;
chainfireRaftPort = 2380;
flaredbApiPort = 2479;
flaredbRaftPort = 2480;
iamPort = 50080;
controlPlaneLabels = {
tier = "control-plane";
platform = "vm-cluster";
};
controlPlaneNodes = {
node01 = {
ip = "192.168.100.11";
failureDomain = "rack-a";
};
node02 = {
ip = "192.168.100.12";
failureDomain = "rack-b";
};
node03 = {
ip = "192.168.100.13";
failureDomain = "rack-c";
};
};
controlPlaneNodeNames = builtins.attrNames controlPlaneNodes;
bootstrapNodeName = builtins.head controlPlaneNodeNames;
mkEndpoint = nodeName: port:
let
node = controlPlaneNodes.${nodeName};
in
"${node.ip}:${toString port}";
chainfireInitialPeers =
map (nodeName: "${nodeName}=${mkEndpoint nodeName chainfireRaftPort}") controlPlaneNodeNames;
flaredbInitialPeers =
map (nodeName: "${nodeName}=${mkEndpoint nodeName flaredbRaftPort}") controlPlaneNodeNames;
chainfireControlPlaneAddrs =
concatStringsSep "," (map (nodeName: mkEndpoint nodeName chainfireApiPort) controlPlaneNodeNames);
flaredbControlPlaneAddrs =
concatStringsSep "," (map (nodeName: mkEndpoint nodeName flaredbApiPort) controlPlaneNodeNames);
sharedDesiredSystem = {
healthCheckCommand = [ "systemctl" "is-system-running" "--wait" ];
rollbackOnFailure = true;
};
mkInstallPlan = nodeName: {
nixosConfiguration = nodeName;
diskoConfigPath = "nix/nodes/vm-cluster/${nodeName}/disko.nix";
targetDisk = "/dev/vda";
};
mkClusterNode = nodeName:
let
node = controlPlaneNodes.${nodeName};
in
{
role = "control-plane";
ip = node.ip;
services = [ "chainfire" "flaredb" "iam" ];
labels = controlPlaneLabels;
pool = "control";
nodeClass = "control-plane";
failureDomain = node.failureDomain;
nixProfile = "profiles/control-plane";
installPlan = mkInstallPlan nodeName;
desiredSystem = sharedDesiredSystem;
raftPort = chainfireRaftPort;
apiPort = chainfireApiPort;
};
clusterNodes = genAttrs controlPlaneNodeNames mkClusterNode;
nodeConfigurationPaths = {
node01 = ./node01/configuration.nix;
node02 = ./node02/configuration.nix;
node03 = ./node03/configuration.nix;
};
nodeDiskoPaths = {
node01 = ./node01/disko.nix;
node02 = ./node02/disko.nix;
node03 = ./node03/disko.nix;
};
in
{
inherit
adminToken
bgpAsn
bootstrapNodeName
bootstrapToken
chainfireApiPort
chainfireControlPlaneAddrs
chainfireInitialPeers
chainfireRaftPort
clusterId
clusterName
clusterNodes
controlPlaneLabels
controlPlaneNodeNames
controlPlaneNodes
environment
flaredbApiPort
flaredbControlPlaneAddrs
flaredbInitialPeers
flaredbRaftPort
iamPort
nodeConfigurationPaths
nodeDiskoPaths
sharedDesiredSystem
;
controlPlaneNodeClass = {
description = "Control-plane VM cluster nodes";
nixProfile = "profiles/control-plane";
roles = [ "control-plane" ];
labels = controlPlaneLabels;
};
controlPlanePool = {
description = "VM cluster control-plane pool";
nodeClass = "control-plane";
labels = {
plane = "control";
cluster = "vm-cluster";
};
};
hostDeployments = {
control-plane-canary = {
selector.nodeIds = [ bootstrapNodeName ];
nixosConfiguration = bootstrapNodeName;
flakeRef = "github:centra/cloud";
batchSize = 1;
maxUnavailable = 1;
healthCheckCommand = sharedDesiredSystem.healthCheckCommand;
switchAction = "switch";
rollbackOnFailure = sharedDesiredSystem.rollbackOnFailure;
};
};
mkControlPlaneNodeModule = nodeName:
{ lib, ... }:
{
imports = [
./cluster.nix
nodeDiskoPaths.${nodeName}
];
networking.hostName = nodeName;
networking.useDHCP = lib.mkDefault true;
boot.loader.grub = {
enable = true;
devices = [ "/dev/vda" ];
efiSupport = true;
efiInstallAsRemovable = true;
};
services.chainfire = {
enable = true;
nodeId = nodeName;
apiAddr = mkEndpoint nodeName chainfireApiPort;
raftAddr = mkEndpoint nodeName chainfireRaftPort;
initialPeers = chainfireInitialPeers;
};
services.flaredb = {
enable = true;
nodeId = nodeName;
apiAddr = mkEndpoint nodeName flaredbApiPort;
raftAddr = mkEndpoint nodeName flaredbRaftPort;
initialPeers = flaredbInitialPeers;
};
services.iam = {
enable = true;
port = iamPort;
chainfireAddr = chainfireControlPlaneAddrs;
flaredbAddr = flaredbControlPlaneAddrs;
};
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keys = [ ];
system.stateVersion = "24.05";
};
mkBootstrapServicesModule =
{ self
, nodeName
, enableDeployer ? false
,
}:
{ pkgs, lib, ... }:
{
services.nix-agent = {
enable = true;
chainfireEndpoint = "http://${mkEndpoint bootstrapNodeName chainfireApiPort}";
clusterId = clusterId;
nodeId = nodeName;
flakeRoot = self.outPath;
intervalSecs = 30;
apply = true;
};
services.deployer = mkIf enableDeployer {
enable = true;
bindAddr = "0.0.0.0:8088";
chainfireEndpoints = [ "http://${mkEndpoint bootstrapNodeName chainfireApiPort}" ];
clusterId = clusterId;
requireChainfire = true;
allowUnknownNodes = false;
allowUnauthenticated = false;
bootstrapToken = bootstrapToken;
adminToken = adminToken;
bootstrapFlakeBundle = pkgs.ultracloudFlakeBundle;
seedClusterState = true;
};
};
}