From 481e4fa46e033c59862d178130861f28de3ebc94 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Sun, 1 Mar 2026 23:38:58 +0000 Subject: [PATCH] [ci skip] add NFS CSI driver + nfs_volume shared module - Deploy csi-driver-nfs Helm chart as platform module (nfs-csi) - Create nfs-truenas StorageClass with soft,timeo=30,retrans=3 mount options - Add shared nfs_volume module for PV/PVC boilerplate (modules/kubernetes/nfs_volume/) --- modules/kubernetes/nfs_volume/main.tf | 80 +++++++++++++++++++++++++ stacks/platform/main.tf | 9 +++ stacks/platform/modules/nfs-csi/main.tf | 62 +++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 modules/kubernetes/nfs_volume/main.tf create mode 100644 stacks/platform/modules/nfs-csi/main.tf diff --git a/modules/kubernetes/nfs_volume/main.tf b/modules/kubernetes/nfs_volume/main.tf new file mode 100644 index 00000000..c6427a10 --- /dev/null +++ b/modules/kubernetes/nfs_volume/main.tf @@ -0,0 +1,80 @@ +variable "name" { + description = "Unique name for PV and PVC (convention: -)" + type = string +} + +variable "namespace" { + description = "Kubernetes namespace for the PVC" + type = string +} + +variable "nfs_server" { + description = "NFS server address" + type = string +} + +variable "nfs_path" { + description = "NFS export path (e.g. /mnt/main/myservice)" + type = string +} + +variable "storage" { + description = "Storage capacity (informational for NFS)" + type = string + default = "10Gi" +} + +variable "access_modes" { + description = "PV/PVC access modes" + type = list(string) + default = ["ReadWriteMany"] +} + +resource "kubernetes_persistent_volume" "this" { + metadata { + name = var.name + } + spec { + capacity = { + storage = var.storage + } + access_modes = var.access_modes + persistent_volume_reclaim_policy = "Retain" + storage_class_name = "nfs-truenas" + volume_mode = "Filesystem" + + persistent_volume_source { + csi { + driver = "nfs.csi.k8s.io" + volume_handle = var.name + volume_attributes = { + server = var.nfs_server + share = var.nfs_path + } + } + } + } +} + +resource "kubernetes_persistent_volume_claim" "this" { + metadata { + name = var.name + namespace = var.namespace + } + spec { + access_modes = var.access_modes + storage_class_name = "nfs-truenas" + volume_name = kubernetes_persistent_volume.this.metadata[0].name + + resources { + requests = { + storage = var.storage + } + } + } +} + +output "claim_name" { + description = "PVC name to use in pod spec persistent_volume_claim blocks" + value = kubernetes_persistent_volume_claim.this.metadata[0].name +} diff --git a/stacks/platform/main.tf b/stacks/platform/main.tf index 4c68fb7f..98100aed 100644 --- a/stacks/platform/main.tf +++ b/stacks/platform/main.tf @@ -309,6 +309,15 @@ module "vpa" { tier = local.tiers.cluster } +# ----------------------------------------------------------------------------- +# NFS CSI — CSI driver for NFS with soft mount options (no stale mount hangs) +# ----------------------------------------------------------------------------- +module "nfs-csi" { + source = "./modules/nfs-csi" + tier = local.tiers.cluster + nfs_server = var.nfs_server +} + # ----------------------------------------------------------------------------- # CNPG — CloudNativePG Operator + local-path-provisioner for database storage # ----------------------------------------------------------------------------- diff --git a/stacks/platform/modules/nfs-csi/main.tf b/stacks/platform/modules/nfs-csi/main.tf new file mode 100644 index 00000000..2c1aa2f6 --- /dev/null +++ b/stacks/platform/modules/nfs-csi/main.tf @@ -0,0 +1,62 @@ +variable "tier" { type = string } +variable "nfs_server" { type = string } + +resource "kubernetes_namespace" "nfs_csi" { + metadata { + name = "nfs-csi" + labels = { + tier = var.tier + } + } +} + +resource "helm_release" "nfs_csi_driver" { + namespace = kubernetes_namespace.nfs_csi.metadata[0].name + create_namespace = false + name = "csi-driver-nfs" + atomic = true + timeout = 300 + + repository = "https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts" + chart = "csi-driver-nfs" + + values = [yamlencode({ + controller = { + replicas = 1 + resources = { + requests = { cpu = "10m", memory = "32Mi" } + limits = { cpu = "100m", memory = "128Mi" } + } + } + node = { + resources = { + requests = { cpu = "10m", memory = "32Mi" } + limits = { cpu = "100m", memory = "128Mi" } + } + } + storageClass = { + create = false + } + })] +} + +resource "kubernetes_storage_class" "nfs_truenas" { + metadata { + name = "nfs-truenas" + } + storage_provisioner = "nfs.csi.k8s.io" + reclaim_policy = "Retain" + volume_binding_mode = "Immediate" + + mount_options = [ + "soft", + "timeo=30", + "retrans=3", + "actimeo=5", + ] + + parameters = { + server = var.nfs_server + share = "/mnt/main" + } +}