diff --git a/01-proxmox-infra/index.ts b/01-proxmox-infra/index.ts index d346fd8..9a63deb 100644 --- a/01-proxmox-infra/index.ts +++ b/01-proxmox-infra/index.ts @@ -6,9 +6,12 @@ import * as pfsense from "@pulumi/pfsense"; const config = new pulumi.Config(); const pve1Endpoint = config.requireSecret("pve1Endpoint"); -const pve1ApiToken = config.requireSecret("pve1ApiToken"); const pve2Endpoint = config.requireSecret("pve2Endpoint"); +const pve3Endpoint = config.requireSecret("pve3Endpoint"); + +const pve1ApiToken = config.requireSecret("pve1ApiToken"); const pve2ApiToken = config.requireSecret("pve2ApiToken"); +const pve3ApiToken = config.requireSecret("pve3ApiToken"); const pfSenseUrl = config.requireSecret("pfSenseUrl"); const pfSenseUser = config.requireSecret("pfSenseUser"); @@ -16,9 +19,11 @@ const pfSensePassword = config.requireSecret("pfSensePassword"); const master1Ip = config.requireSecret("master1Ip"); const master2Ip = config.requireSecret("master2Ip"); -const worker1Ip = config.requireSecret("worker1Ip"); const master3Ip = config.requireSecret("master3Ip"); + +const worker1Ip = config.requireSecret("worker1Ip"); const worker2Ip = config.requireSecret("worker2Ip"); +const worker3Ip = config.requireSecret("worker3Ip"); // --------------------------------------------------------------------------- // Providers — one per standalone Proxmox machine @@ -36,6 +41,18 @@ const pveBckpProvider = new proxmox.Provider("pve-bckp", { insecure: true, }); +const pveEsprimoProvider = new proxmox.Provider("pve-esprimo", { + endpoint: pve3Endpoint, + apiToken: pve3ApiToken, + insecure: true, +}); + +const pveNodes = { + "pve-b550": { nodeName: "pve", isoStore: "pve-local-ext1", dataStore: "local-lvm" }, + "pve-optiplex": { nodeName: "pve-bckp", isoStore: "local", dataStore: "local" }, + "pve-esprimo": { nodeName: "pve", isoStore: "local", dataStore: "local-lvm" }, +} as const; + // --------------------------------------------------------------------------- // Providers — PfSense // --------------------------------------------------------------------------- @@ -66,8 +83,8 @@ const ubuntuNobleUrl = const ubuntuImagePve = new proxmox.download.File( "ubuntu-noble-pve", { - nodeName: "pve", - datastoreId: "pve-local-ext1", + nodeName: pveNodes["pve-b550"].nodeName, + datastoreId: pveNodes["pve-b550"].isoStore, contentType: "import", fileName: "noble-server-cloudimg-amd64.qcow2", url: ubuntuNobleUrl, @@ -80,8 +97,8 @@ const ubuntuImagePve = new proxmox.download.File( const ubuntuImagePveBckp = new proxmox.download.File( "ubuntu-noble-pve-bckp", { - nodeName: "pve-bckp", - datastoreId: "local", + nodeName: pveNodes["pve-optiplex"].nodeName, + datastoreId: pveNodes["pve-optiplex"].isoStore, contentType: "import", fileName: "noble-server-cloudimg-amd64.qcow2", url: ubuntuNobleUrl, @@ -91,6 +108,20 @@ const ubuntuImagePveBckp = new proxmox.download.File( { provider: pveBckpProvider }, ); +const ubuntuImagePveEsprimo = new proxmox.download.File( + "ubuntu-noble-pve-esprimo", + { + nodeName: pveNodes["pve-esprimo"].nodeName, + datastoreId: pveNodes["pve-esprimo"].isoStore, + contentType: "import", + fileName: "noble-server-cloudimg-amd64.qcow2", + url: ubuntuNobleUrl, + overwrite: false, + overwriteUnmanaged: true, + }, + { provider: pveEsprimoProvider }, +); + // --------------------------------------------------------------------------- // VM templates — one per node, cloned from the downloaded cloud image. // Templates are not started and have no cloud-init config; that is applied @@ -127,7 +158,7 @@ const pveTemplate = new proxmox.VmLegacy( disks: [ { interface: "scsi0", - datastoreId: "local-lvm", + datastoreId: pveNodes["pve-b550"].dataStore, importFrom: pulumi.interpolate`${ubuntuImagePve.datastoreId}:import/${ubuntuImagePve.fileName}`, size: 10, ssd: true, @@ -147,7 +178,7 @@ const pveBckpTemplate = new proxmox.VmLegacy( disks: [ { interface: "scsi0", - datastoreId: "local", + datastoreId: pveNodes["pve-optiplex"].dataStore, importFrom: pulumi.interpolate`${ubuntuImagePveBckp.datastoreId}:import/${ubuntuImagePveBckp.fileName}`, size: 10, ssd: true, @@ -158,6 +189,26 @@ const pveBckpTemplate = new proxmox.VmLegacy( { provider: pveBckpProvider, ignoreChanges: ["disks"] }, ); +const pveEsprimoTemplate = new proxmox.VmLegacy( + "k3s-template-pve-esprimo", + { + ...templateSettings, + nodeName: "pve", + name: "k3s-ubuntu-noble-template", + disks: [ + { + interface: "scsi0", + datastoreId: pveNodes["pve-esprimo"].dataStore, + importFrom: pulumi.interpolate`${ubuntuImagePveEsprimo.datastoreId}:import/${ubuntuImagePveEsprimo.fileName}`, + size: 10, + ssd: true, + discard: "on", + }, + ], + }, + { provider: pveEsprimoProvider, ignoreChanges: ["disks"] }, +); + // --------------------------------------------------------------------------- // k3s nodes — full clones of their respective templates // --------------------------------------------------------------------------- @@ -180,50 +231,60 @@ const nodeConfigs: NodeConfig[] = [ { name: "k3s-master-1", role: "master", - nodeName: "pve", + nodeName: pveNodes["pve-b550"].nodeName, provider: pveProvider, template: pveTemplate, - diskDatastore: "local-lvm", + diskDatastore: pveNodes["pve-b550"].dataStore, ip: master1Ip, }, { name: "k3s-master-2", role: "master", - nodeName: "pve", - provider: pveProvider, + nodeName: pveNodes["pve-esprimo"].nodeName, + provider: pveEsprimoProvider, template: pveTemplate, - diskDatastore: "local-lvm", + diskDatastore: pveNodes["pve-esprimo"].dataStore, ip: master2Ip, }, { name: "k3s-worker-1", role: "worker", - nodeName: "pve", + nodeName: pveNodes["pve-b550"].nodeName, provider: pveProvider, template: pveTemplate, - diskDatastore: "local-lvm", + diskDatastore: pveNodes["pve-b550"].dataStore, ip: worker1Ip, longhornDiskSize: 50, }, { name: "k3s-master-3", role: "master", - nodeName: "pve-bckp", + nodeName: pveNodes["pve-optiplex"].nodeName, provider: pveBckpProvider, template: pveBckpTemplate, - diskDatastore: "local", + diskDatastore: pveNodes["pve-optiplex"].dataStore, ip: master3Ip, }, { name: "k3s-worker-2", role: "worker", - nodeName: "pve-bckp", + nodeName: pveNodes["pve-optiplex"].nodeName, provider: pveBckpProvider, template: pveBckpTemplate, - diskDatastore: "local", + diskDatastore: pveNodes["pve-optiplex"].dataStore, ip: worker2Ip, longhornDiskSize: 50, }, + { + name: "k3s-worker-3", + role: "worker", + nodeName: pveNodes["pve-esprimo"].nodeName, + provider: pveEsprimoProvider, + template: pveEsprimoTemplate, + diskDatastore: pveNodes["pve-esprimo"].dataStore, + ip: worker3Ip, + longhornDiskSize: 50, + }, ]; const k3sVms = nodeConfigs.map( @@ -321,11 +382,19 @@ export const vmIds = { worker1: k3sVms[2].vmId, master3: k3sVms[3].vmId, worker2: k3sVms[4].vmId, + worker3: k3sVms[5].vmId, }; // CI runner SSH private key — consumed by k8s-bootstrap via StackReference. export const ciRunnerPrivateKey = pulumi.secret(ciRunnerKey.privateKeyOpenssh); -export { pve1Endpoint, pve1ApiToken, pve2Endpoint, pve2ApiToken }; +export { + pve1Endpoint, + pve1ApiToken, + pve2Endpoint, + pve2ApiToken, + pve3Endpoint, + pve3ApiToken, +}; -export { master1Ip, master2Ip, worker1Ip, master3Ip, worker2Ip }; +export { master1Ip, master2Ip, worker1Ip, master3Ip, worker2Ip, worker3Ip };