一、准备nfs服务器

1、安装nfs服务
yum install nfs-utils
2、启动nfs服务
systemctl start rpcbind && systemctl enable rpcbind
systemctl start nfs && systemctl enable nfs
3、创建nfs存储目录
mkdir -p /data/nfs/ && chmod 755 /data1/nfs/zhgd_web
4、修改nfs配置
echo "/data1/nfs/k8spv 192.168.231.0/24(rw,sync,no_root_squash,no_all_squash)" >>/etc/exports
5、重新加载nfs配置

      a、没有正在挂载使用nfs目录的情况

systemctl restart nfs

      b、正在挂载使用ngs目录的情况

exportfs -ra
6、开通防火墙规则

     如果有防火墙限制,需要申请其他与nfs服务器建立连接防火墙规则放行以下端口访问

#文件传输端口
 2049
#RPC端口映射服务
 111
#挂载验证端口
 20048
7、验证nfs可挂载性

     在所有要挂载nfs存储的服务器上执行测试

showmount -e 192.168.231.166


二、静态提供pv

1、创建 PV
cat > pv-nfs.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-smart-construction  # PV的名称,全局唯一
  namespace: uat 
  labels:
    type: nfs
spec:
  capacity:
    storage: 10Gi  # 定义存储容量,必须大于或等于PVC的请求
  accessModes:
    - ReadWriteMany  # NFS通常支持多节点读写,非常适合共享静态文件
  persistentVolumeReclaimPolicy: Retain  # 当PVC被删除时,PV保留(Retain)而不是删除(Delete)
  nfs:
    path: /data/nfs/k8spv  # NFS服务器上共享出来的实际路径
    server: 192.168.231.166  # NFS服务器的IP地址或主机名
EOF
kubectl apply -f pv-nfs.yaml
2、创建PVC
cat >pvc-smart-construction.yaml <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: smart-construction  # 这个名称必须和您部署文件中的claimName一致
  namespace: uat
spec:
  accessModes:
    - ReadWriteMany  # 这个模式必须和PV中定义的accessModes匹配
  resources:
    requests:
      storage: 10Gi  # 请求的存储大小,必须小于或等于PV的容量
  selector:
    matchLabels:
      type: nfs  # 可选:通过标签选择器,只绑定到带有`type: nfs`标签的PV
EOF
kubectl apply -f pvc-smart-construction.yaml
3、查看pv、pvc绑定关系
kubectl get pv -n uat |grep smart
4、如何使用挂载存储
volumeMounts:
      - name: static-files
        mountPath: /usr/share/nginx/html
volumes:
  - name: static-files
    persistentVolumeClaim:
      claimName: smart-construction

三、动态提供pv

1、创建sc
cat > storageclass.yml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs  # 名称需与 PV/PVC 中的 storageClassName 匹配
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  archiveOnDelete: "false"  # 删除 PV 时是否保留数据
  pathPattern: "${.PVC.namespace}/${.PVC.name}"  # 自动创建子目录
reclaimPolicy: Retain  # 推荐使用 Retain 避免数据误删
volumeBindingMode: Immediate
EOF
2、创建provisioner
cat >nfs_provisioner.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-provisioner
  namespace: uat
  labels:
    app: nfs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-provisioner
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccountName: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.2
          imagePullPolicy: IfNotPresent
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: 192.168.231.166  # 替换为您的 NFS 服务器 IP
            - name: NFS_PATH
              value: /data/nfs/k8spv  # 替换为您的 NFS 共享路径
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.231.166
            path: /data/nfs/k8spv
EOF
3、如何使用新创建的sc,将其设为默认sc (可选)

     如果一个集群有多个sc可以指定一个默认的。

kubectl patch storageclass nfs-client -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

    设置后,新创建的pvc如果不指定sc,就会自动使用默认的

4、创建pvc来测试动态供应
cat > test-pvc.yaml <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
  namespace: uat
spec:
  storageClassName: nfs # 指定使用我们刚创建的 StorageClass
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
EOF
kubectl apply -f test-pvc.yaml
kubectl get pvc -n uat  #会发现test-pvc的状态几乎是瞬间就变成了Bound
kubectl get pv -n  uat  #会发现系统自动创建了一个新的pv与这个pvc绑定

这个自动创建的pv对应的实际存储空间,就是NFS服务器上的一个自动创建的子目录

5、在部署中实际使用
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: smart-construction
spec:
  storageClassName: nfs # 指定StorageClass名称
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi # 按需修改大小
spec:
  serviceName: es-headless
  replicas: 3
  volumeClaimTemplates: # 关键:自动创建独立 PVC
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: nfs # 匹配 StorageClass 名称
      resources:
        requests:
          storage: 7Gi # 每个节点分配 7GB