From 5b34e711110b5d698b22c73b598d9dbf3d19ba7d Mon Sep 17 00:00:00 2001 From: Story Crater Bot <19826264+Riotpiaole@users.noreply.github.com> Date: Mon, 20 Jul 2026 08:22:53 -0700 Subject: [PATCH] =?UTF-8?q?feat(terraform):=20restructure=20control=20plan?= =?UTF-8?q?es=20into=20a=203-node=20map=20with=20LAN=20etcd=20advertise=20?= =?UTF-8?q?and=20live=20machine=20CA=20=E2=80=94=20enables=20talos-cp-1/2/?= =?UTF-8?q?3=20HA=20and=20drops=20worker=20configs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + k8s/argocd/apps/0-minio.yaml | 76 -------- k8s/argocd/apps/00-homelab-root.yaml | 22 --- k8s/argocd/apps/1-wave-1.yaml | 139 -------------- k8s/argocd/apps/2-wave-2.yaml | 115 ------------ k8s/argocd/apps/3-wave-3.yaml | 45 ----- k8s/argocd/apps/layer-1-infrastructure.yaml | 21 --- k8s/argocd/apps/layer-2-bootstrap.yaml | 21 --- k8s/argocd/apps/layer-3-platform.yaml | 21 --- k8s/argocd/apps/layer-4-security.yaml | 21 --- k8s/argocd/apps/layer-5-applications.yaml | 21 --- k8s/argocd/apps/layer-6-data.yaml | 21 --- k8s/argocd/apps/phase0-minio.yaml | 86 --------- k8s/argocd/apps/phase1-hookless-0.yaml | 172 ------------------ k8s/argocd/apps/phase1-hookless-1.yaml | 55 ------ .../apps/phase2-storage-observability-0.yaml | 61 ------- .../apps/phase2-storage-observability-1.yaml | 115 ------------ k8s/argocd/apps/phase3-iam-0.yaml | 32 ---- .../{apps => bootstrap}/cnpg-operator.yaml | 0 k8s/argocd/{apps => bootstrap}/forgejo.yaml | 0 terraform/main.tf | 92 +++------- terraform/templates/controlplane.tftpl | 25 ++- terraform/templates/worker.tftpl | 83 --------- terraform/variables.tf | 54 +++--- 24 files changed, 75 insertions(+), 1226 deletions(-) delete mode 100644 k8s/argocd/apps/0-minio.yaml delete mode 100644 k8s/argocd/apps/00-homelab-root.yaml delete mode 100644 k8s/argocd/apps/1-wave-1.yaml delete mode 100644 k8s/argocd/apps/2-wave-2.yaml delete mode 100644 k8s/argocd/apps/3-wave-3.yaml delete mode 100644 k8s/argocd/apps/layer-1-infrastructure.yaml delete mode 100644 k8s/argocd/apps/layer-2-bootstrap.yaml delete mode 100644 k8s/argocd/apps/layer-3-platform.yaml delete mode 100644 k8s/argocd/apps/layer-4-security.yaml delete mode 100644 k8s/argocd/apps/layer-5-applications.yaml delete mode 100644 k8s/argocd/apps/layer-6-data.yaml delete mode 100644 k8s/argocd/apps/phase0-minio.yaml delete mode 100644 k8s/argocd/apps/phase1-hookless-0.yaml delete mode 100644 k8s/argocd/apps/phase1-hookless-1.yaml delete mode 100644 k8s/argocd/apps/phase2-storage-observability-0.yaml delete mode 100644 k8s/argocd/apps/phase2-storage-observability-1.yaml delete mode 100644 k8s/argocd/apps/phase3-iam-0.yaml rename k8s/argocd/{apps => bootstrap}/cnpg-operator.yaml (100%) rename k8s/argocd/{apps => bootstrap}/forgejo.yaml (100%) delete mode 100644 terraform/templates/worker.tftpl diff --git a/.gitignore b/.gitignore index 6ed7055..a38c7cb 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ forge/pki/ # Talos machine configs — contain WireGuard private keys, bootstrap tokens, PKI cluster-config/controlplane.yaml cluster-config/worker*.yaml +cluster-config/talos-worker*.yaml +cluster-config/cp-*.yaml +cluster-config/talos-cp-*.yaml cluster-config/secrets.yaml cluster-config/talosconfig talos-forge-trust.yaml diff --git a/k8s/argocd/apps/0-minio.yaml b/k8s/argocd/apps/0-minio.yaml deleted file mode 100644 index 3aec051..0000000 --- a/k8s/argocd/apps/0-minio.yaml +++ /dev/null @@ -1,76 +0,0 @@ -# MinIO now managed by Terraform (terraform/minio.tf) via official minio/minio -# chart — removed from ArgoCD to avoid dual-controller conflict on storage NS. -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: strimzi-operator - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/sqs - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kmsvc-redis - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/sqs - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: prometheus - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/monitoring - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: monitoring - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/00-homelab-root.yaml b/k8s/argocd/apps/00-homelab-root.yaml deleted file mode 100644 index a4113c6..0000000 --- a/k8s/argocd/apps/00-homelab-root.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: homelab-root - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/argocd/root - destination: - server: https://kubernetes.default.svc - namespace: argocd - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/1-wave-1.yaml b/k8s/argocd/apps/1-wave-1.yaml deleted file mode 100644 index 4b0e197..0000000 --- a/k8s/argocd/apps/1-wave-1.yaml +++ /dev/null @@ -1,139 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: vault - namespace: argocd - labels: - test-gitops: "true" - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/talos-iam - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: iam - syncPolicy: - automated: - prune: true - selfHeal: true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: loki - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/logging - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: logging - syncPolicy: - automated: - prune: true - selfHeal: true -# cloudnative-pg: managed separately via k8s/argocd/apps/cnpg-operator.yaml -# (Helm-source Application, avoids the git chicken-egg for the operator itself) -# apiVersion: argoproj.io/v1alpha1 -# kind: Application -# metadata: -# name: cloudnative-pg -# namespace: argocd -# annotations: -# argocd.argoproj.io/sync-wave: "1" -# spec: -# project: homelab -# source: -# repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git -# targetRevision: main -# path: k8s/ddb -# directory: -# recurse: false -# destination: -# server: https://kubernetes.default.svc -# namespace: ddb -# syncPolicy: -# automated: -# prune: true -# selfHeal: true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: authentik - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/talos-iam - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: iam - syncPolicy: - syncOptions: - - CreateNamespace=true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: temporal - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/temporal - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: temporal - syncPolicy: - automated: - prune: true - selfHeal: true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kafka-cluster - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/sqs - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true diff --git a/k8s/argocd/apps/2-wave-2.yaml b/k8s/argocd/apps/2-wave-2.yaml deleted file mode 100644 index 7ce49bf..0000000 --- a/k8s/argocd/apps/2-wave-2.yaml +++ /dev/null @@ -1,115 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: queue-crd - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "2" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/sqs - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: management-service - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "2" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/sqs - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: grafana - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "2" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/logging - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: logging - syncPolicy: - automated: - prune: true - selfHeal: true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: promtail - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "2" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/logging - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: logging - syncPolicy: - automated: - prune: true - selfHeal: true -# forgejo: managed separately via k8s/argocd/apps/forgejo.yaml -# (Helm-source Application with inlined values, avoids the git chicken-egg) -# apiVersion: argoproj.io/v1alpha1 -# kind: Application -# metadata: -# name: forgejo -# namespace: argocd -# annotations: -# argocd.argoproj.io/sync-wave: "2" -# spec: -# project: homelab -# source: -# repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git -# targetRevision: main -# path: k8s/talos-ci-cd -# directory: -# recurse: false -# destination: -# server: https://kubernetes.default.svc -# namespace: cicd -# syncPolicy: -# automated: -# prune: true -# selfHeal: true diff --git a/k8s/argocd/apps/3-wave-3.yaml b/k8s/argocd/apps/3-wave-3.yaml deleted file mode 100644 index 98246e5..0000000 --- a/k8s/argocd/apps/3-wave-3.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: forgejo-runner - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "3" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/talos-ci-cd - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: cicd - syncPolicy: - automated: - prune: true - selfHeal: true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: portainer - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "3" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/portainer - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: dashboard - syncPolicy: - automated: - prune: true - selfHeal: true diff --git a/k8s/argocd/apps/layer-1-infrastructure.yaml b/k8s/argocd/apps/layer-1-infrastructure.yaml deleted file mode 100644 index c387b3c..0000000 --- a/k8s/argocd/apps/layer-1-infrastructure.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: layer-1-infrastructure - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/infrastructure - destination: - server: https://kubernetes.default.svc - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/layer-2-bootstrap.yaml b/k8s/argocd/apps/layer-2-bootstrap.yaml deleted file mode 100644 index a64779e..0000000 --- a/k8s/argocd/apps/layer-2-bootstrap.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: layer-2-bootstrap - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "2" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/bootstrap - destination: - server: https://kubernetes.default.svc - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/layer-3-platform.yaml b/k8s/argocd/apps/layer-3-platform.yaml deleted file mode 100644 index 8e6d5a8..0000000 --- a/k8s/argocd/apps/layer-3-platform.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: layer-3-platform - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "3" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/platform - destination: - server: https://kubernetes.default.svc - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/layer-4-security.yaml b/k8s/argocd/apps/layer-4-security.yaml deleted file mode 100644 index d24487c..0000000 --- a/k8s/argocd/apps/layer-4-security.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: layer-4-security - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "4" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/security - destination: - server: https://kubernetes.default.svc - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/layer-5-applications.yaml b/k8s/argocd/apps/layer-5-applications.yaml deleted file mode 100644 index 4c2503c..0000000 --- a/k8s/argocd/apps/layer-5-applications.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: layer-5-applications - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "5" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/applications - destination: - server: https://kubernetes.default.svc - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/layer-6-data.yaml b/k8s/argocd/apps/layer-6-data.yaml deleted file mode 100644 index 07d278a..0000000 --- a/k8s/argocd/apps/layer-6-data.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: layer-6-data - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "6" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/data - destination: - server: https://kubernetes.default.svc - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/phase0-minio.yaml b/k8s/argocd/apps/phase0-minio.yaml deleted file mode 100644 index 78d069b..0000000 --- a/k8s/argocd/apps/phase0-minio.yaml +++ /dev/null @@ -1,86 +0,0 @@ -# Phase 0 — MinIO (S3 backend for Terraform state) -# Deployed first, before all other applications -# Note: MinIO PVC managed separately (prevent_destroy in terraform/minio.tf) - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: minio - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - sources: - - repoURL: https://charts.min.io/ - chart: minio - targetRevision: 5.4.0 - helm: - values: | - mode: standalone - replicas: 1 - drivesPerNode: 1 - pools: 1 - - rootUser: minioadmin - rootPassword: nhKRAxwIjDBCzwFDvsAa7dNLouCXXh13LvMoxMVkUtY= - - persistence: - enabled: true - size: 100Gi - storageClass: longhorn-xfs - accessMode: ReadWriteOnce - - resources: - requests: - memory: 512Mi - - service: - type: ClusterIP - port: 9000 - consoleService: - type: ClusterIP - port: 9001 - - buckets: - - name: terraform-state - policy: none - purge: false - - name: vault - policy: none - purge: false - - name: riotpiao-models - policy: none - purge: false - - name: loki-chunks - policy: none - purge: false - - name: loki-ruler - policy: none - purge: false - - name: loki-admin - policy: none - purge: false - - name: loki-index - policy: none - purge: false - - environment: - MINIO_IDENTITY_OPENID_CONFIG_URL: https://authentik.riotpiao.com/application/o/minio/.well-known/openid-configuration - MINIO_IDENTITY_OPENID_CLIENT_ID: minio - MINIO_IDENTITY_OPENID_CLIENT_SECRET: 9d2867fe08c3bf7fedd7e32bbaf4456fce3b0aaf788966d7559e1955947b0219 - MINIO_IDENTITY_OPENID_CLAIM_NAME: policy - MINIO_IDENTITY_OPENID_SCOPES: openid,profile,email,minio - MINIO_IDENTITY_OPENID_REDIRECT_URI: https://minio.riotpiao.com/oauth_callback - MINIO_IDENTITY_OPENID_DISPLAY_NAME: Authentik - - destination: - server: https://kubernetes.default.svc - namespace: storage - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/phase1-hookless-0.yaml b/k8s/argocd/apps/phase1-hookless-0.yaml deleted file mode 100644 index 70bb80e..0000000 --- a/k8s/argocd/apps/phase1-hookless-0.yaml +++ /dev/null @@ -1,172 +0,0 @@ -# Phase 1 — Hookless releases: strimzi-operator, kafka-cluster, kmsvc-redis, queue-crd, management-service - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: strimzi-operator - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - source: - repoURL: https://strimzi.io/charts/ - chart: strimzi-kafka-operator - targetRevision: 0.46.0 - helm: - values: | - watchNamespaces: ["sqs"] - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kmsvc-redis - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - source: - repoURL: https://charts.bitnami.com/bitnami - chart: redis - targetRevision: 20.6.0 - helm: - values: | - architecture: standalone - global: - security: - allowInsecureImages: true - image: - repository: bitnamilegacy/redis - auth: - enabled: false - master: - persistence: - enabled: true - storageClass: longhorn - size: 2Gi - resources: - limits: - memory: 1Gi - requests: - memory: 1Gi - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kafka-cluster - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/sqs/charts/kafka-cluster - helm: - values: | - namespace: sqs - nodePool: - replicas: 3 - storage: - class: longhorn-kafka - sizeGi: 10 - resources: - memory: 5Gi - cpu: "2" - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: queue-crd - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/sqs/charts/queue-crd - helm: - values: | - namespace: sqs - kafkaBrokers: "kmsvc-kafka-bootstrap.sqs.svc.cluster.local:9092" - redisAddr: "kmsvc-redis-master.sqs.svc.cluster.local:6379" - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: management-service - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/sqs/charts/management-service - helm: - values: | - namespace: sqs - env: - kafkaBrokers: "kmsvc-kafka-bootstrap.sqs.svc.cluster.local:9092" - redisAddr: "kmsvc-redis-master.sqs.svc.cluster.local:6379" - authentikIssuerURL: "https://authentik.riotpiao.com/application/o/kafaka/" - authentikAudience: "QI0gPtR99ar8VvhK8Tqox4SDkTKzbNU7lbgwBNSc" - ingress: - enabled: true - host: kmsvc.riotpiao.com - clusterIssuer: homelab-ca - destination: - server: https://kubernetes.default.svc - namespace: sqs - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/phase1-hookless-1.yaml b/k8s/argocd/apps/phase1-hookless-1.yaml deleted file mode 100644 index 689d9b0..0000000 --- a/k8s/argocd/apps/phase1-hookless-1.yaml +++ /dev/null @@ -1,55 +0,0 @@ -# Phase 1 — Hookless releases continued: promtail, portainer - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: promtail - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://grafana.github.io/helm-charts - chart: promtail - targetRevision: latest - helm: - valueFiles: - - k8s/logging/promtail-values.yaml - destination: - server: https://kubernetes.default.svc - namespace: logging - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: portainer - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "3" -spec: - project: homelab - source: - repoURL: https://portainer.github.io/k8s/ - chart: portainer - targetRevision: latest - helm: - valueFiles: - - k8s/portainer/portainer-values.yaml - destination: - server: https://kubernetes.default.svc - namespace: dashboard - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/phase2-storage-observability-0.yaml b/k8s/argocd/apps/phase2-storage-observability-0.yaml deleted file mode 100644 index 8b0b889..0000000 --- a/k8s/argocd/apps/phase2-storage-observability-0.yaml +++ /dev/null @@ -1,61 +0,0 @@ -# Phase 2 — Storage/observability chain: prometheus, cloudnative-pg - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: prometheus - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - sources: - - repoURL: https://prometheus-community.github.io/helm-charts - chart: kube-prometheus-stack - targetRevision: latest - helm: - valueFiles: - - k8s/monitoring/prometheus-values.yaml - - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/hooks/phase2 - destination: - server: https://kubernetes.default.svc - namespace: monitoring - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: cloudnative-pg - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - sources: - - repoURL: https://cloudnative-pg.github.io/charts - chart: cloudnative-pg - targetRevision: "~0.20" - helm: - valueFiles: - - k8s/ddb/cnpg-values.yaml - - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/hooks/phase2 - destination: - server: https://kubernetes.default.svc - namespace: ddb - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/phase2-storage-observability-1.yaml b/k8s/argocd/apps/phase2-storage-observability-1.yaml deleted file mode 100644 index 8253b91..0000000 --- a/k8s/argocd/apps/phase2-storage-observability-1.yaml +++ /dev/null @@ -1,115 +0,0 @@ -# Phase 2 — Storage/observability chain continued: loki, grafana, forgejo, forgejo-runner - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: loki - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - source: - repoURL: https://grafana.github.io/helm-charts - chart: loki - targetRevision: latest - helm: - valueFiles: - - k8s/logging/loki-values.yaml - - k8s/logging/loki-secrets.enc.yaml - destination: - server: https://kubernetes.default.svc - namespace: logging - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: grafana - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "2" -spec: - project: homelab - source: - repoURL: https://grafana.github.io/helm-charts - chart: grafana - targetRevision: latest - helm: - valueFiles: - - k8s/logging/grafana-values.yaml - - k8s/logging/grafana-secrets.enc.yaml - destination: - server: https://kubernetes.default.svc - namespace: logging - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: forgejo - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "2" -spec: - project: homelab - source: - repoURL: https://dl.gitea.com/charts/ - chart: gitea - targetRevision: "~10" - helm: - valueFiles: - - k8s/talos-ci-cd/forgejo-values.yaml - - k8s/talos-ci-cd/forgejo-secrets.enc.yaml - destination: - server: https://kubernetes.default.svc - namespace: cicd - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: forgejo-runner - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "3" -spec: - project: homelab - sources: - - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/talos-ci-cd/charts/forgejo-runner - helm: - valueFiles: - - values.yaml - - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/hooks/phase2 - destination: - server: https://kubernetes.default.svc - namespace: cicd - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/phase3-iam-0.yaml b/k8s/argocd/apps/phase3-iam-0.yaml deleted file mode 100644 index 93fcba8..0000000 --- a/k8s/argocd/apps/phase3-iam-0.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# Phase 3 — IAM (Authentik) — identity-critical release - ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: authentik - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: homelab - sources: - - repoURL: https://charts.goauthentik.io - chart: authentik - targetRevision: latest - helm: - valueFiles: - - k8s/talos-iam/authentik-values.yaml - - k8s/talos-iam/authentik-secrets.enc.yaml - - repoURL: https://forgejo.riotpiao.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/hooks/phase3 - destination: - server: https://kubernetes.default.svc - namespace: iam - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true diff --git a/k8s/argocd/apps/cnpg-operator.yaml b/k8s/argocd/bootstrap/cnpg-operator.yaml similarity index 100% rename from k8s/argocd/apps/cnpg-operator.yaml rename to k8s/argocd/bootstrap/cnpg-operator.yaml diff --git a/k8s/argocd/apps/forgejo.yaml b/k8s/argocd/bootstrap/forgejo.yaml similarity index 100% rename from k8s/argocd/apps/forgejo.yaml rename to k8s/argocd/bootstrap/forgejo.yaml diff --git a/terraform/main.tf b/terraform/main.tf index 3188dfb..3670b89 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -14,38 +14,42 @@ locals { factory_image = "factory.talos.dev/installer/613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245:${var.talos_version}" } -# Control plane machine configuration -resource "local_file" "controlplane_config" { - filename = "${path.module}/../cluster-config/controlplane.yaml" +# Control plane machine configurations +resource "local_file" "controlplane_configs" { + for_each = var.controlplane_configs + + filename = "${path.module}/../cluster-config/${each.key}.yaml" content = templatefile("${path.module}/templates/controlplane.tftpl", { version = "v1alpha1" - hostname = var.controlplane_config.hostname + hostname = each.value.hostname token = var.machine_token ca_crt = var.machine_ca_crt ca_key = var.machine_ca_key - lan_ip = var.controlplane_config.lan_ip - lan_subnet = var.controlplane_config.lan_subnet - lan_gateway = var.controlplane_config.lan_gateway - wg0_ip = var.controlplane_config.wg0_ip - wg0_subnet = var.controlplane_config.wg0_subnet - wg0_port = var.controlplane_config.wg0_port - wg0_private_key = var.controlplane_config.wg0_private_key - wg0_peers = var.controlplane_config.wg0_peers - wg1_ip = var.controlplane_config.wg1_ip - wg1_subnet = var.controlplane_config.wg1_subnet - wg1_port = var.controlplane_config.wg1_port - wg1_private_key = var.controlplane_config.wg1_private_key - wg1_peers = var.controlplane_config.wg1_peers + lan_ip = each.value.lan_ip + lan_subnet = each.value.lan_subnet + lan_gateway = each.value.lan_gateway + wg0_ip = each.value.wg0_ip + wg0_subnet = each.value.wg0_subnet + wg0_port = each.value.wg0_port + wg0_private_key = each.value.wg0_private_key + wg0_peers = each.value.wg0_peers + wg1_ip = each.value.wg1_ip + wg1_subnet = each.value.wg1_subnet + wg1_port = each.value.wg1_port + wg1_private_key = each.value.wg1_private_key + wg1_peers = each.value.wg1_peers kubelet_image = local.kubelet_image cluster_dns_ip = local.cluster_dns_ip - install_disk = var.controlplane_config.install_disk + install_disk = each.value.install_disk factory_image = local.factory_image talos_version = var.talos_version - longhorn_disks = var.controlplane_config.longhorn_disks + longhorn_disks = each.value.longhorn_disks dns_servers = var.cluster_config.dns_servers forgejo_registry_ip = var.forgejo_registry_ip forgejo_hostname = var.forgejo_hostname + zone = each.value.zone + allow_scheduling = each.value.allow_scheduling # Cluster config cluster_id = var.cluster_id @@ -75,54 +79,10 @@ resource "local_file" "controlplane_config" { }) } -# Worker machine configurations -resource "local_file" "worker_configs" { - for_each = var.worker_configs - - filename = "${path.module}/../cluster-config/${each.key}.yaml" - - content = templatefile("${path.module}/templates/worker.tftpl", { - version = "v1alpha1" - hostname = each.value.hostname - token = var.machine_token - ca_crt = var.machine_ca_crt - lan_ip = each.value.lan_ip - lan_subnet = each.value.lan_subnet - lan_gateway = each.value.lan_gateway - kubelet_image = local.kubelet_image - cluster_dns_ip = local.cluster_dns_ip - install_disk = each.value.install_disk - factory_image = local.factory_image - talos_version = var.talos_version - node_labels = each.value.node_labels - - # Cluster config - cluster_id = var.cluster_id - cluster_secret = var.cluster_secret - controlplane_ip = local.controlplane_ip - cluster_name = var.cluster_name - pod_subnets = var.cluster_config.pod_subnets - service_subnets = var.cluster_config.service_subnets - dns_domain = var.cluster_config.dns_domain - bootstrap_token = var.bootstrap_token - - # Kubernetes certs - kubernetes_ca_crt = var.kubernetes_ca_crt - - # Component images - kube_proxy_img = local.kube_proxy_img - }) -} - # Output paths for reference -output "controlplane_config_path" { - value = local_file.controlplane_config.filename - description = "Path to generated controlplane config" -} - -output "worker_config_paths" { +output "controlplane_config_paths" { value = { - for k, v in local_file.worker_configs : k => v.filename + for k, v in local_file.controlplane_configs : k => v.filename } - description = "Paths to generated worker configs" + description = "Paths to generated controlplane configs" } diff --git a/terraform/templates/controlplane.tftpl b/terraform/templates/controlplane.tftpl index d5b628c..5dbcdaf 100644 --- a/terraform/templates/controlplane.tftpl +++ b/terraform/templates/controlplane.tftpl @@ -10,7 +10,9 @@ machine: key: ${ca_key} certSANs: - ${lan_ip} +%{ if wg0_ip != null ~} - ${wg0_ip} +%{ endif ~} network: hostname: ${hostname} interfaces: @@ -23,6 +25,7 @@ machine: dhcp: false dhcpOptions: ipv6: false +%{ if wg0_ip != null ~} - interface: wg0 addresses: - ${wg0_ip}/24 @@ -37,6 +40,8 @@ machine: - ${ip} %{ endfor ~} %{ endfor ~} +%{ endif ~} +%{ if wg1_ip != null ~} - interface: wg1 addresses: - ${wg1_ip}/24 @@ -52,6 +57,7 @@ machine: %{ endfor ~} persistentKeepaliveInterval: ${peer.persistent_keepalive_secs}s %{ endfor ~} +%{ endif ~} nameservers: %{ for ns in dns_servers ~} - ${ns} @@ -92,7 +98,14 @@ machine: nodeLabels: node.kubernetes.io/exclude-from-external-load-balancers: "" topology.kubernetes.io/region: homelab - topology.kubernetes.io/zone: az-a + topology.kubernetes.io/zone: ${zone} +%{ if !allow_scheduling ~} + # Dedicated control plane — re-apply the control-plane taint that + # allowSchedulingOnControlPlanes=true removed cluster-wide. Only nodes with + # allow_scheduling=true (talos-cp-1 / .213) stay schedulable. + nodeTaints: + node-role.kubernetes.io/control-plane: ":NoSchedule" +%{ endif ~} cluster: id: ${cluster_id} @@ -100,6 +113,8 @@ cluster: controlPlane: endpoint: https://${controlplane_ip}:6443 clusterName: ${cluster_name} + # true removes the default control-plane taint from ALL CP nodes; dedicated + # nodes (allow_scheduling=false) get it re-added via machine.nodeTaints above. allowSchedulingOnControlPlanes: true network: dnsDomain: ${dns_domain} @@ -126,7 +141,10 @@ cluster: apiServer: certSANs: - ${controlplane_ip} +%{ if wg0_ip != null ~} - ${wg0_ip} +%{ endif ~} + - ${lan_ip} image: ${kube_apiserver_img} admissionControl: - name: PodSecurity @@ -164,6 +182,11 @@ cluster: disabled: true service: {} etcd: + # Advertise/peer etcd on the LAN so all control planes can reach each other. + # Without this, Talos may pick the WireGuard IP (10.6.0.1), which the + # LAN-only control planes can't route to — new members get stuck as learners. + advertisedSubnets: + - 192.168.1.0/24 ca: crt: ${etcd_ca_crt} key: ${etcd_ca_key} diff --git a/terraform/templates/worker.tftpl b/terraform/templates/worker.tftpl deleted file mode 100644 index 38da50b..0000000 --- a/terraform/templates/worker.tftpl +++ /dev/null @@ -1,83 +0,0 @@ -version: ${version} -debug: false -persist: true - -machine: - type: worker - token: ${token} - ca: - crt: ${ca_crt} - key: "" - certSANs: [] - network: - hostname: ${hostname} - interfaces: - - interface: eno1 - addresses: - - ${lan_ip}/24 - routes: - - network: 0.0.0.0/0 - gateway: ${lan_gateway} - dhcp: false - nameservers: - - ${cluster_dns_ip} - - 8.8.8.8 - - 1.1.1.1 - kubelet: - image: ${kubelet_image} - defaultRuntimeSeccompProfileEnabled: true - disableManifestsDirectory: true - extraArgs: - rotate-server-certificates: true - install: - disk: ${install_disk} - image: factory.talos.dev/installer/613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245:${talos_version} - wipe: true - grubUseUKICmdline: true - registries: {} - features: - diskQuotaSupport: true - kubePrism: - enabled: true - port: 7445 - hostDNS: - enabled: true - forwardKubeDNSToHost: true - nodeLabels: -%{ for k, v in node_labels ~} - ${k}: ${v} -%{ endfor ~} - -cluster: - id: ${cluster_id} - secret: ${cluster_secret} - controlPlane: - endpoint: https://${controlplane_ip}:6443 - clusterName: ${cluster_name} - network: - dnsDomain: ${dns_domain} - podSubnets: -%{ for subnet in pod_subnets ~} - - ${subnet} -%{ endfor ~} - serviceSubnets: -%{ for subnet in service_subnets ~} - - ${subnet} -%{ endfor ~} - cni: - name: none - token: ${bootstrap_token} - ca: - crt: ${kubernetes_ca_crt} - key: "" - discovery: - enabled: true - registries: - kubernetes: - disabled: true - service: {} - proxy: - disabled: true - extraManifests: - - https://raw.githubusercontent.com/alex1989hu/kubelet-serving-cert-approver/main/deploy/standalone-install.yaml - - https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml diff --git a/terraform/variables.tf b/terraform/variables.tf index 804e0a8..1e18da5 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -100,48 +100,38 @@ variable "secretbox_encryption_secret" { description = "Secretbox encryption secret (base64 encoded)" } -variable "controlplane_config" { - type = object({ - hostname = string - lan_ip = string - lan_subnet = string - lan_gateway = string - wg0_ip = string - wg0_subnet = string - wg0_port = number - wg0_peers = list(object({ +variable "controlplane_configs" { + type = map(object({ + hostname = string + lan_ip = string + lan_subnet = string + lan_gateway = string + wg0_ip = optional(string) + wg0_subnet = optional(string) + wg0_port = optional(number) + wg0_private_key = optional(string) + wg0_peers = optional(list(object({ public_key = string allowed_ips = list(string) - })) - wg1_ip = string - wg1_subnet = string - wg1_port = number - wg1_peers = list(object({ + })), []) + wg1_ip = optional(string) + wg1_subnet = optional(string) + wg1_port = optional(number) + wg1_private_key = optional(string) + wg1_peers = optional(list(object({ public_key = string allowed_ips = list(string) persistent_keepalive_secs = number - })) - wg0_private_key = string - wg1_private_key = string - install_disk = string + })), []) + install_disk = string longhorn_disks = list(object({ device = string mountpoint = string })) - }) - description = "Control plane machine configuration" -} - -variable "worker_configs" { - type = map(object({ - hostname = string - lan_ip = string - lan_subnet = string - lan_gateway = string - install_disk = string - node_labels = map(string) + zone = string + allow_scheduling = bool })) - description = "Worker machine configurations" + description = "Control plane machine configurations, keyed by node" } variable "cluster_config" {