talos-platform/main.tf
bast ad6f917606
Some checks failed
Talos Platform Deploy / deploy (push) Failing after 6s
main.tf aktualisiert
2026-11-08 02:08:54 +00:00

157 lines
4 KiB
HCL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# talos-platform – gemeinsame Cluster-Dienste für Produktion (Talos)
# Hier liegt alles, was ALLE Apps brauchen. Apps (boday_tf, ...) bringen nur ihr eigenes Chart mit.
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.26"
}
helm = {
source = "hashicorp/helm"
version = "~> 2.12"
}
}
backend "consul" {
address = "consul:8500"
path = "terraform/states/talos_platform"
}
}
variable "kubeconfig_path" {
type = string
default = "./talos_kubeconfig"
}
# Version des Traefik-Helm-Charts (traefik/traefik). Bewusst pinnen, damit Updates geplant passieren.
variable "traefik_chart_version" {
type = string
}
provider "kubernetes" {
config_path = var.kubeconfig_path
}
provider "helm" {
kubernetes {
config_path = var.kubeconfig_path
}
}
# Feste IP für Traefik aus dem MetalLB-Pool. Auf diese IP zeigt das OPNsense-Portforwarding (80/443).
variable "traefik_lb_ip" {
type = string
}
# Hostname des Longhorn-Dashboards (internes DNS, z.B. Unbound-Override in OPNsense)
variable "longhorn_host" {
type = string
default = "longhorn.boday.lan"
}
# BasicAuth für Longhorn als htpasswd-Zeile, z.B.: htpasswd -nbB admin 'geheim'
variable "longhorn_basic_auth" {
type = string
sensitive = true
}
# Kein hostPort mehr -> der Talos-Standard (PSA "baseline") reicht
resource "kubernetes_namespace" "traefik" {
metadata {
name = "traefik"
}
}
# Traefik hinter einem MetalLB-LoadBalancer: VIP wandert bei Node-Ausfall auf den anderen Node
resource "helm_release" "traefik" {
name = "traefik"
repository = "https://traefik.github.io/charts"
chart = "traefik"
version = var.traefik_chart_version
namespace = kubernetes_namespace.traefik.metadata[0].name
values = [yamlencode({
deployment = { replicas = 2 }
# Je ein Pod pro Node
topologySpreadConstraints = [{
maxSkew = 1
topologyKey = "kubernetes.io/hostname"
whenUnsatisfiable = "DoNotSchedule"
labelSelector = {
matchLabels = {
"app.kubernetes.io/name" = "traefik"
"app.kubernetes.io/instance" = "traefik-traefik"
}
}
}]
service = {
type = "LoadBalancer"
annotations = {
"metallb.io/loadBalancerIPs" = var.traefik_lb_ip
}
spec = {
# Echte Client-IP bleibt erhalten (Django-Logs, CrowdSec)
externalTrafficPolicy = "Local"
}
}
ingressClass = {
enabled = true
isDefaultClass = true
name = "traefik"
}
providers = {
kubernetesIngress = { enabled = true }
kubernetesCRD = { enabled = true }
}
# Gemeinsame Routen der Plattform: Longhorn-Dashboard mit Login hinter Traefik
extraObjects = [
{
apiVersion = "v1"
kind = "Secret"
metadata = { name = "longhorn-basic-auth", namespace = "longhorn-system" }
type = "Opaque"
stringData = { users = var.longhorn_basic_auth }
},
{
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = { name = "longhorn-auth", namespace = "longhorn-system" }
spec = { basicAuth = { secret = "longhorn-basic-auth" } }
},
{
apiVersion = "networking.k8s.io/v1"
kind = "Ingress"
metadata = {
name = "longhorn"
namespace = "longhorn-system"
annotations = {
"traefik.ingress.kubernetes.io/router.middlewares" = "longhorn-system-longhorn-auth@kubernetescrd"
}
}
spec = {
ingressClassName = "traefik"
rules = [{
host = var.longhorn_host
http = {
paths = [{
path = "/"
pathType = "Prefix"
backend = { service = { name = "longhorn-frontend", port = { number = 80 } } }
}]
}
}]
}
},
]
})]
}
output "traefik_lb_ip" {
value = var.traefik_lb_ip
}