feat(terraform): restructure control planes into a 3-node map with LAN etcd advertise and live machine CA — enables talos-cp-1/2/3 HA and drops worker configs

This commit is contained in:
Story Crater Bot
2026-07-20 08:22:53 -07:00
parent f7a8df0514
commit 15b1ec6ad4
24 changed files with 75 additions and 1226 deletions
+3
View File
@@ -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
-76
View File
@@ -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
-22
View File
@@ -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
-139
View File
@@ -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
-115
View File
@@ -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
-45
View File
@@ -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
@@ -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
-21
View File
@@ -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
-21
View File
@@ -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
-21
View File
@@ -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
-21
View File
@@ -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
-21
View File
@@ -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
-86
View File
@@ -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
-172
View File
@@ -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
-55
View File
@@ -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
@@ -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
@@ -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
-32
View File
@@ -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
+26 -66
View File
@@ -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"
}
+24 -1
View File
@@ -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}
-83
View File
@@ -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
+25 -35
View File
@@ -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({
public_key = string
allowed_ips = list(string)
}))
wg1_ip = string
wg1_subnet = string
wg1_port = number
wg1_peers = list(object({
public_key = string
allowed_ips = list(string)
persistent_keepalive_secs = number
}))
wg0_private_key = string
wg1_private_key = string
install_disk = string
longhorn_disks = list(object({
device = string
mountpoint = string
}))
})
description = "Control plane machine configuration"
}
variable "worker_configs" {
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 = 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
})), [])
install_disk = string
node_labels = map(string)
longhorn_disks = list(object({
device = string
mountpoint = string
}))
description = "Worker machine configurations"
zone = string
allow_scheduling = bool
}))
description = "Control plane machine configurations, keyed by node"
}
variable "cluster_config" {