homelab/k3s/storage/nas-pv.yaml
2026-04-18 18:28:55 -04:00

153 lines
4 KiB
YAML

# NAS storage — Synology 425+
# Share: 192.168.40.96:/volume1/samantha-private (the only NAS share k3s uses)
#
# Uses kubernetes-sigs/nfs-subdir-external-provisioner:
# any PVC that asks for storageClassName: nas-nfs automatically gets a subdir
# carved out of the share. Subdir name = ${namespace}-${pvc}-${pv} by default,
# or see pathPattern annotation on a PVC to override.
#
# Prerequisites (one-time):
# - apt install nfs-common on every k3s node (handled via
# k3s/scripts/install-nfs-common.sh + on-all-nodes.sh)
#
# Deploy (cluster-scoped):
# kubectl apply -f nas-pv.yaml
#
# Usage in a service manifest (note: storageClassName: nas-nfs):
# apiVersion: v1
# kind: PersistentVolumeClaim
# metadata:
# name: foo-data
# annotations:
# nfs.io/storage-path: "foo" # subdir literal name (optional)
# spec:
# storageClassName: nas-nfs
# accessModes: [ReadWriteMany]
# resources:
# requests:
# storage: 10Gi
---
apiVersion: v1
kind: Namespace
metadata:
name: nfs-provisioner
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-subdir-external-provisioner
namespace: nfs-provisioner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-subdir-external-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: run-nfs-subdir-external-provisioner
subjects:
- kind: ServiceAccount
name: nfs-subdir-external-provisioner
namespace: nfs-provisioner
roleRef:
kind: ClusterRole
name: nfs-subdir-external-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: leader-locking-nfs-subdir-external-provisioner
namespace: nfs-provisioner
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: leader-locking-nfs-subdir-external-provisioner
namespace: nfs-provisioner
subjects:
- kind: ServiceAccount
name: nfs-subdir-external-provisioner
namespace: nfs-provisioner
roleRef:
kind: Role
name: leader-locking-nfs-subdir-external-provisioner
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-subdir-external-provisioner
namespace: nfs-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-subdir-external-provisioner
template:
metadata:
labels:
app: nfs-subdir-external-provisioner
spec:
serviceAccountName: nfs-subdir-external-provisioner
containers:
- name: nfs-subdir-external-provisioner
image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: homelab.nas/nfs-subdir
- name: NFS_SERVER
value: 192.168.40.96
- name: NFS_PATH
value: /volume1/samantha-private
volumes:
- name: nfs-client-root
nfs:
server: 192.168.40.96
path: /volume1/samantha-private
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nas-nfs
provisioner: homelab.nas/nfs-subdir
parameters:
archiveOnDelete: "true"
pathPattern: "${.PVC.annotations.nfs.io/storage-path}"
reclaimPolicy: Retain
volumeBindingMode: Immediate