Merge pull request 'Feature/deploy ha containers' (#10) from feature/deploy-HA-containers into main
Reviewed-on: #10
This commit was merged in pull request #10.
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
name: Deploy k8s Apps
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "04-k8s-apps/**"
|
||||
- ".gitea/workflows/**"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "04-k8s-apps/**"
|
||||
- ".gitea/workflows/**"
|
||||
|
||||
jobs:
|
||||
preview:
|
||||
name: Pulumi Preview
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
- name: Restore Stack Config
|
||||
run: echo "${{ secrets.K8S_APPS_PULUMI_DEV_YAML }}" | base64 -d > 04-k8s-apps/Pulumi.dev.yaml
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
working-directory: 04-k8s-apps
|
||||
|
||||
- name: Preview
|
||||
uses: pulumi/actions@v5
|
||||
with:
|
||||
command: preview
|
||||
stack-name: dev
|
||||
work-dir: 04-k8s-apps
|
||||
cloud-url: ${{ secrets.PULUMI_BACKEND_URL }}
|
||||
env:
|
||||
PULUMI_CONFIG_PASSPHRASE: ${{ secrets.PULUMI_CONFIG_PASSPHRASE }}
|
||||
|
||||
deploy:
|
||||
name: Pulumi Deploy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
- name: Restore Stack Config
|
||||
run: echo "${{ secrets.K8S_APPS_PULUMI_DEV_YAML }}" | base64 -d > 04-k8s-apps/Pulumi.dev.yaml
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
working-directory: 04-k8s-apps
|
||||
|
||||
- name: Refresh State
|
||||
uses: pulumi/actions@v5
|
||||
with:
|
||||
command: refresh
|
||||
stack-name: dev
|
||||
work-dir: 04-k8s-apps
|
||||
cloud-url: ${{ secrets.PULUMI_BACKEND_URL }}
|
||||
env:
|
||||
PULUMI_CONFIG_PASSPHRASE: ${{ secrets.PULUMI_CONFIG_PASSPHRASE }}
|
||||
|
||||
- name: Deploy
|
||||
uses: pulumi/actions@v5
|
||||
with:
|
||||
command: up
|
||||
stack-name: dev
|
||||
work-dir: 04-k8s-apps
|
||||
cloud-url: ${{ secrets.PULUMI_BACKEND_URL }}
|
||||
env:
|
||||
PULUMI_CONFIG_PASSPHRASE: ${{ secrets.PULUMI_CONFIG_PASSPHRASE }}
|
||||
@@ -254,11 +254,11 @@ const k3sVms = nodeConfigs.map(
|
||||
{
|
||||
interface: "scsi0",
|
||||
datastoreId: node.diskDatastore,
|
||||
size: node.role === "master" ? 10 : 20,
|
||||
size: 20,
|
||||
ssd: true,
|
||||
discard: "on",
|
||||
},
|
||||
...(node.longhornDiskSize
|
||||
...(node.longhornDiskSize == null
|
||||
? []
|
||||
: [
|
||||
{
|
||||
|
||||
+23
-4
@@ -3,7 +3,6 @@ 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`,
|
||||
);
|
||||
@@ -20,7 +19,7 @@ const opts = (extras?: pulumi.ResourceOptions): pulumi.ResourceOptions => ({
|
||||
...extras,
|
||||
});
|
||||
|
||||
// ── 1. NFS CSI Driver ────────────────────────────────────────────────────────
|
||||
// ── NFS CSI Driver ────────────────────────────────────────────────────────
|
||||
|
||||
const nfsCsiDriver = new k8s.helm.v3.Release(
|
||||
"nfs-csi-driver",
|
||||
@@ -57,7 +56,7 @@ new k8s.storage.v1.StorageClass(
|
||||
opts({ dependsOn: [nfsCsiDriver] }),
|
||||
);
|
||||
|
||||
// ── 2. cert-manager ──────────────────────────────────────────────────────────
|
||||
// ── cert-manager ──────────────────────────────────────────────────────────
|
||||
|
||||
const certManager = new k8s.helm.v3.Release(
|
||||
"cert-manager",
|
||||
@@ -75,7 +74,7 @@ const certManager = new k8s.helm.v3.Release(
|
||||
opts(),
|
||||
);
|
||||
|
||||
// ── 3. Cloudflare token secret + ClusterIssuer ───────────────────────────────
|
||||
// ── Cloudflare token secret + ClusterIssuer ───────────────────────────────
|
||||
|
||||
const cfSecret = new k8s.core.v1.Secret(
|
||||
"cloudflare-token",
|
||||
@@ -115,4 +114,24 @@ new k8s.apiextensions.CustomResource(
|
||||
opts({ dependsOn: [certManager, cfSecret] }),
|
||||
);
|
||||
|
||||
// ── Longhorn ──────────────────────────────────────────────────────────────
|
||||
|
||||
new k8s.helm.v3.Release(
|
||||
"longhorn",
|
||||
{
|
||||
name: "longhorn",
|
||||
chart: "longhorn",
|
||||
repositoryOpts: { repo: "https://charts.longhorn.io" },
|
||||
namespace: "longhorn-system",
|
||||
createNamespace: true,
|
||||
version: "1.12.0",
|
||||
values: {
|
||||
defaultSettings: {
|
||||
defaultReplicaCount: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
opts(),
|
||||
);
|
||||
|
||||
export const storageClass = "truenas-nfs";
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
name: k8s-apps
|
||||
description: Application workloads for the k3s homelab cluster
|
||||
runtime:
|
||||
name: nodejs
|
||||
options:
|
||||
packagemanager: npm
|
||||
@@ -0,0 +1,133 @@
|
||||
import * as pulumi from "@pulumi/pulumi";
|
||||
import * as k8s from "@pulumi/kubernetes";
|
||||
|
||||
const config = new pulumi.Config();
|
||||
|
||||
//fetch credentials from k8s-bootstrap
|
||||
const bootstrapRef = new pulumi.StackReference(
|
||||
`${pulumi.getOrganization()}/k8s-bootstrap/dev`,
|
||||
);
|
||||
|
||||
const kubeconfig = bootstrapRef.requireOutput("kubeconfig");
|
||||
const domain = config.requireSecret("domain");
|
||||
|
||||
const k8sProvider = new k8s.Provider("k3s", { kubeconfig });
|
||||
const opts = (extras?: pulumi.ResourceOptions): pulumi.ResourceOptions => ({
|
||||
provider: k8sProvider,
|
||||
...extras,
|
||||
});
|
||||
|
||||
const ns = new k8s.core.v1.Namespace(
|
||||
"heimdall",
|
||||
{ metadata: { name: "heimdall" } },
|
||||
opts(),
|
||||
);
|
||||
|
||||
const pvc = new k8s.core.v1.PersistentVolumeClaim(
|
||||
"heimdall-config",
|
||||
{
|
||||
metadata: { name: "heimdall-config", namespace: ns.metadata.name },
|
||||
spec: {
|
||||
accessModes: ["ReadWriteOnce"],
|
||||
storageClassName: "longhorn",
|
||||
resources: { requests: { storage: "50Mi" } },
|
||||
},
|
||||
},
|
||||
opts(),
|
||||
);
|
||||
|
||||
const labels = { app: "heimdall" };
|
||||
|
||||
new k8s.apps.v1.Deployment(
|
||||
"heimdall",
|
||||
{
|
||||
metadata: {
|
||||
name: "heimdall",
|
||||
namespace: ns.metadata.name,
|
||||
annotations: { "pulumi.com/patchForce": "true" },
|
||||
},
|
||||
spec: {
|
||||
replicas: 1,
|
||||
selector: { matchLabels: labels },
|
||||
template: {
|
||||
metadata: { labels },
|
||||
spec: {
|
||||
containers: [
|
||||
{
|
||||
name: "heimdall",
|
||||
image: "lscr.io/linuxserver/heimdall:latest",
|
||||
env: [
|
||||
{ name: "PUID", value: "1000" },
|
||||
{ name: "PGID", value: "1000" },
|
||||
],
|
||||
ports: [{ containerPort: 80 }],
|
||||
volumeMounts: [{ name: "config", mountPath: "/config" }],
|
||||
},
|
||||
],
|
||||
volumes: [
|
||||
{
|
||||
name: "config",
|
||||
persistentVolumeClaim: { claimName: pvc.metadata.name },
|
||||
},
|
||||
],
|
||||
terminationGracePeriodSeconds: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
opts(),
|
||||
);
|
||||
|
||||
const svc = new k8s.core.v1.Service(
|
||||
"heimdall",
|
||||
{
|
||||
metadata: { name: "heimdall", namespace: ns.metadata.name },
|
||||
spec: {
|
||||
selector: labels,
|
||||
ports: [{ port: 80, targetPort: 80 }],
|
||||
type: "ClusterIP",
|
||||
},
|
||||
},
|
||||
opts(),
|
||||
);
|
||||
|
||||
const host = pulumi.interpolate`heimdall.${domain}`;
|
||||
|
||||
new k8s.networking.v1.Ingress(
|
||||
"heimdall",
|
||||
{
|
||||
metadata: {
|
||||
name: "heimdall",
|
||||
namespace: ns.metadata.name,
|
||||
annotations: {
|
||||
"cert-manager.io/cluster-issuer": "letsencrypt-prod",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
ingressClassName: "traefik",
|
||||
tls: [{ hosts: [host], secretName: "heimdall-tls" }],
|
||||
rules: [
|
||||
{
|
||||
host,
|
||||
http: {
|
||||
paths: [
|
||||
{
|
||||
path: "/",
|
||||
pathType: "Prefix",
|
||||
backend: {
|
||||
service: {
|
||||
name: svc.metadata.name,
|
||||
port: { number: 80 },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
opts(),
|
||||
);
|
||||
|
||||
export const ingressHost = host;
|
||||
Generated
+2799
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "k8s-apps",
|
||||
"main": "index.ts",
|
||||
"devDependencies": {
|
||||
"@types/node": "^18",
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pulumi/kubernetes": "^4.0.0",
|
||||
"@pulumi/pulumi": "^3.113.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"outDir": "bin",
|
||||
"target": "es2020",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"pretty": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitReturns": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"files": [
|
||||
"index.ts"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user