5de2a16b9b
Deploy Proxmox Infra / Pulumi Preview (push) Has been skipped
Deploy Proxmox Infra / Pulumi Deploy (push) Failing after 50s
Deploy k8s Bootstrap / Pulumi Preview (push) Has been skipped
Deploy k8s Bootstrap / Bootstrap k3s Cluster (push) Failing after 7s
Deploy k8s Infra / Pulumi Preview (push) Has been skipped
Deploy k8s Infra / Pulumi Deploy (push) Failing after 7s
119 lines
3.3 KiB
TypeScript
119 lines
3.3 KiB
TypeScript
import * as pulumi from "@pulumi/pulumi";
|
|
import * as k8s from "@pulumi/kubernetes";
|
|
|
|
const config = new pulumi.Config();
|
|
|
|
//fetch credentials from k8s-bootstrap
|
|
const infraRef = new pulumi.StackReference(
|
|
`${pulumi.getOrganization()}/k8s-bootstrap/dev`,
|
|
);
|
|
|
|
const kubeconfig = infraRef.requireOutput("kubeconfig");
|
|
const truenasHost = config.requireSecret("truenasHost");
|
|
const truenasNfsPath = config.requireSecret("truenasNfsPath");
|
|
const cloudflareToken = config.requireSecret("cloudflareApiToken");
|
|
const letsencryptEmail = config.requireSecret("letsencryptEmail");
|
|
|
|
const k8sProvider = new k8s.Provider("k3s", { kubeconfig });
|
|
const opts = (extras?: pulumi.ResourceOptions): pulumi.ResourceOptions => ({
|
|
provider: k8sProvider,
|
|
...extras,
|
|
});
|
|
|
|
// ── 1. NFS CSI Driver ────────────────────────────────────────────────────────
|
|
|
|
const nfsCsiDriver = new k8s.helm.v3.Release(
|
|
"nfs-csi-driver",
|
|
{
|
|
name: "csi-driver-nfs",
|
|
chart: "csi-driver-nfs",
|
|
repositoryOpts: {
|
|
repo: "https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts",
|
|
},
|
|
namespace: "kube-system",
|
|
version: "4.12.0",
|
|
values: {
|
|
kubeletDir: "/var/lib/kubelet",
|
|
},
|
|
},
|
|
opts(),
|
|
);
|
|
|
|
new k8s.storage.v1.StorageClass(
|
|
"truenas-nfs",
|
|
{
|
|
metadata: { name: "truenas-nfs" },
|
|
provisioner: "nfs.csi.k8s.io",
|
|
parameters: {
|
|
server: truenasHost,
|
|
share: truenasNfsPath,
|
|
mountPermissions: "0",
|
|
},
|
|
reclaimPolicy: "Retain",
|
|
volumeBindingMode: "Immediate",
|
|
allowVolumeExpansion: true,
|
|
mountOptions: ["nfsvers=4.1"],
|
|
},
|
|
opts({ dependsOn: [nfsCsiDriver] }),
|
|
);
|
|
|
|
// ── 2. cert-manager ──────────────────────────────────────────────────────────
|
|
|
|
const certManager = new k8s.helm.v3.Release(
|
|
"cert-manager",
|
|
{
|
|
name: "cert-manager",
|
|
chart: "cert-manager",
|
|
repositoryOpts: { repo: "https://charts.jetstack.io" },
|
|
namespace: "cert-manager",
|
|
createNamespace: true,
|
|
timeout: 600,
|
|
values: {
|
|
crds: { enabled: true },
|
|
},
|
|
},
|
|
opts(),
|
|
);
|
|
|
|
// ── 3. Cloudflare token secret + ClusterIssuer ───────────────────────────────
|
|
|
|
const cfSecret = new k8s.core.v1.Secret(
|
|
"cloudflare-token",
|
|
{
|
|
metadata: { name: "cloudflare-api-token", namespace: "cert-manager" },
|
|
stringData: { "api-token": cloudflareToken },
|
|
},
|
|
opts({ dependsOn: [certManager] }),
|
|
);
|
|
|
|
new k8s.apiextensions.CustomResource(
|
|
"letsencrypt-prod",
|
|
{
|
|
apiVersion: "cert-manager.io/v1",
|
|
kind: "ClusterIssuer",
|
|
metadata: { name: "letsencrypt-prod" },
|
|
spec: {
|
|
acme: {
|
|
server: "https://acme-v02.api.letsencrypt.org/directory",
|
|
email: letsencryptEmail,
|
|
privateKeySecretRef: { name: "letsencrypt-prod-account-key" },
|
|
solvers: [
|
|
{
|
|
dns01: {
|
|
cloudflare: {
|
|
apiTokenSecretRef: {
|
|
name: cfSecret.metadata.name,
|
|
key: "api-token",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
opts({ dependsOn: [certManager, cfSecret] }),
|
|
);
|
|
|
|
export const storageClass = "truenas-nfs";
|