diff --git a/k8s/argocd/apps/0-minio.yaml b/k8s/argocd/apps/0-minio.yaml index eb1cb23..3bd650c 100644 --- a/k8s/argocd/apps/0-minio.yaml +++ b/k8s/argocd/apps/0-minio.yaml @@ -1,85 +1,5 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: minio-operator - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - source: - repoURL: https://operator.min.io - targetRevision: v5.0.0 - chart: operator - helm: - releaseName: minio-operator - values: | - operator: - image: - repository: minio/operator - tag: "v5.0.0" - pullPolicy: IfNotPresent - replicaCount: 1 - resources: - requests: - cpu: 100m - memory: 256Mi - limits: - cpu: 500m - memory: 512Mi - metrics: - enabled: true - port: 8080 - rbac: - create: true - console: - enabled: true - replicaCount: 1 - image: - repository: minio/console - tag: "v0.30.0" - resources: - requests: - cpu: 50m - memory: 128Mi - limits: - cpu: 200m - memory: 256Mi - destination: - server: https://kubernetes.default.svc - namespace: minio-operator - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: minio - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: homelab - source: - repoURL: https://forgejo.riotpiao.homelab.com/riotpiao.com/homelab.git - targetRevision: main - path: k8s/storage - directory: - recurse: false - destination: - server: https://kubernetes.default.svc - namespace: storage - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true ---- +# 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: diff --git a/terraform/argocd-bootstrap.tf b/terraform/argocd-bootstrap.tf index c45304a..b899175 100644 --- a/terraform/argocd-bootstrap.tf +++ b/terraform/argocd-bootstrap.tf @@ -8,6 +8,22 @@ resource "kubernetes_namespace" "argocd" { } } +# Copy homelab-ca-secret from cert-manager to argocd namespace +# (Required for repo-server pod to verify self-signed forgejo TLS) +resource "null_resource" "copy_ca_secret_to_argocd" { + provisioner "local-exec" { + command = <<-EOT + kubectl get secret homelab-ca-secret -n cert-manager -o yaml | \ + sed 's/namespace: cert-manager/namespace: argocd/' | \ + kubectl apply -f - + EOT + } + + depends_on = [ + kubernetes_namespace.argocd + ] +} + resource "helm_release" "argocd" { name = "argocd" repository = local.helm_repos["argo"] @@ -27,13 +43,6 @@ resource "helm_release" "argocd" { rbac = { "policy.default" = "role:readonly" } - repositories = { - "minio-operator" = { - url = "https://operator.min.io" - name = "minio-operator" - type = "helm" - } - } } server = { extraArgs = [ @@ -44,6 +53,14 @@ resource "helm_release" "argocd" { hosts = [ "argocd.${var.cluster_domain}" ] + annotations = { + "nginx.ingress.kubernetes.io/backend-protocol" = "HTTPS" + } + ingressClassName = "nginx" + } + service = { + type = "ClusterIP" + port = 80 } } repoServer = { @@ -80,7 +97,8 @@ resource "helm_release" "argocd" { ] depends_on = [ - kubernetes_namespace.argocd + kubernetes_namespace.argocd, + null_resource.copy_ca_secret_to_argocd ] # Note: lifecycle.ignore_changes removed to allow CA cert update @@ -97,8 +115,7 @@ resource "kubernetes_manifest" "argocd_project" { } spec = { sourceRepos = [ - "https://forgejo.riotpiao.homelab.com/riotpiao.com/*", - "https://operator.min.io" + "https://forgejo.riotpiao.homelab.com/riotpiao.com/*" ] destinations = [ { diff --git a/terraform/minio-operator.tf b/terraform/minio-operator.tf deleted file mode 100644 index e26c7fc..0000000 --- a/terraform/minio-operator.tf +++ /dev/null @@ -1,78 +0,0 @@ -# MinIO Operator - v4.5.8 (compatible with installed CRD) -# v5.0.0 has credential validation bug that breaks tenants -# Downgrading to stable v4.5.8 until upstream fixes validation logic - -resource "kubernetes_namespace" "minio_operator" { - metadata { - name = "minio-operator" - labels = { - "pod-security.kubernetes.io/enforce" = "baseline" - "pod-security.kubernetes.io/enforce-version" = "latest" - } - } -} - -resource "helm_release" "minio_operator" { - name = "minio-operator" - repository = "https://operator.min.io" - chart = "operator" - version = "4.5.8" - namespace = kubernetes_namespace.minio_operator.metadata[0].name - - values = [ - yamlencode({ - operator = { - image = { - repository = "minio/operator" - tag = "v4.5.8" - } - replicaCount = 1 - } - console = { - enabled = true - } - }) - ] - - depends_on = [ - kubernetes_namespace.minio_operator - ] -} - -# MinIO credentials secret - v4.5.8 format (credsSecret with individual keys) -resource "kubernetes_secret" "minio_creds" { - metadata { - name = "minio-creds" - namespace = "storage" - } - type = "Opaque" - - data = { - accesskey = base64encode("minioadmin") - secretkey = base64encode(var.minio_root_password) - } - - depends_on = [ - kubernetes_namespace.storage - ] -} - -# Placeholder: kubernetes_namespace.storage should exist from bootstrap -# If not, create: -resource "kubernetes_namespace" "storage" { - count = var.create_storage_namespace ? 1 : 0 - - metadata { - name = "storage" - labels = { - "pod-security.kubernetes.io/enforce" = "baseline" - "pod-security.kubernetes.io/enforce-version" = "latest" - } - } -} - -variable "create_storage_namespace" { - description = "Create storage namespace if it doesn't exist" - type = bool - default = false -} diff --git a/terraform/minio.tf b/terraform/minio.tf new file mode 100644 index 0000000..e16046e --- /dev/null +++ b/terraform/minio.tf @@ -0,0 +1,90 @@ +# MinIO - Official minio/minio chart, direct Helm deployment (no operator) +# All-in-one: single helm_release + dedicated xfs StorageClass. +# Why xfs: default `longhorn` SC uses ext4 whose mkfs on 100Gi (~4.5min) +# exceeds kubelet mount timeout. xfs mkfs is near-instant. min.io chart has +# no persistence.fsType, so fsType must be set on the StorageClass. + +resource "kubernetes_storage_class" "longhorn_xfs" { + metadata { + name = "longhorn-xfs" + } + storage_provisioner = "driver.longhorn.io" + reclaim_policy = "Delete" + allow_volume_expansion = true + volume_binding_mode = "Immediate" + + parameters = { + numberOfReplicas = "2" + staleReplicaTimeout = "60" + fsType = "xfs" + dataLocality = "disabled" + } +} + +resource "helm_release" "minio" { + name = "minio" + repository = "https://charts.min.io/" + chart = "minio" + version = "5.4.0" + namespace = "storage" + upgrade_install = true + force_update = true + wait = true + timeout = 600 + + values = [ + yamlencode({ + mode = "standalone" + replicas = 1 + drivesPerNode = 1 + pools = 1 + + rootUser = "minioadmin" + rootPassword = var.minio_root_password + + persistence = { + enabled = true + size = "100Gi" + storageClass = kubernetes_storage_class.longhorn_xfs.metadata[0].name + accessMode = "ReadWriteOnce" + } + + resources = { + requests = { + memory = "512Mi" + } + } + + service = { + type = "ClusterIP" + port = "9000" + } + consoleService = { + type = "ClusterIP" + port = "9001" + } + + # Buckets auto-created on install (all-in-one, no post-hook needed) + buckets = [ + { name = "vault", policy = "none", purge = false }, + { name = "riotpiao-models", policy = "none", purge = false }, + ] + + environment = { + MINIO_IDENTITY_OPENID_CONFIG_URL = "https://authentik.riotpiao.homelab.com/application/o/minio/.well-known/openid-configuration" + MINIO_IDENTITY_OPENID_CLIENT_ID = "minio" + MINIO_IDENTITY_OPENID_CLIENT_SECRET = var.minio_oidc_client_secret + MINIO_IDENTITY_OPENID_CLAIM_NAME = "policy" + MINIO_IDENTITY_OPENID_SCOPES = "openid,profile,email,minio" + MINIO_IDENTITY_OPENID_REDIRECT_URI = "https://minio.riotpiao.homelab.com/oauth_callback" + MINIO_IDENTITY_OPENID_DISPLAY_NAME = "Authentik" + } + }) + ] +} + +variable "create_storage_namespace" { + description = "Create storage namespace if it doesn't exist" + type = bool + default = false +}