前提条件:

  • k8s集群(已搭建好)

  • nfs服务器(已搭建好)

  • nfs客户端(pod可调度节点作为客户端,已搭建好)

Kubernetes 推荐使用 PersistentVolume (PV)PersistentVolumeClaim (PVC) 来管理存储。

静态PV配置

该方法需要管理员手动配置PV

#测试pod使用nfs存储
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
  namespace: test-ng
spec:
  capacity:
    storage: 1Gi   # 你想要的存储大小
  accessModes:
    - ReadWriteMany  # 允许多个节点读写
  nfs:
    path: /data/k8s_nfs   # NFS 共享的路径
    server: x.x.x.x  # NFS 服务器地址
  persistentVolumeReclaimPolicy: Retain

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
  namespace: test-ng
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfsdemo-v1
  namespace: test-ng
  labels:
    app: nfsdemo
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfsdemo
      version: v1
  template:
    metadata:
      labels:
        app: nfsdemo
        version: v1
    spec:
      containers:
      - name: nfsdemo
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:stable-alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nfs-storage
          mountPath: "/usr/share/nginx/html"# 容器内的挂载路径
      volumes:
      - name: nfs-storage
        persistentVolumeClaim:
          claimName: nfs-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: nfsdemo-service
  namespace: test-ng
spec:
type: NodePort  # 设置为 NodePort 类型
  selector:
    app: nfsdemo  # 与 Deployment 中的 Pod 匹配的标签
  ports:
  - port: 80          # 服务的端口
    targetPort: 80    # Pod 中容器的端口

动态PV配置

该方法无需手动创建 PV,当用户创建 PVC 时,自动创建对应的 PV。

这需要部署一个 NFS Subdir External Provisioner(例如 nfs-subdir-external-provisioner Helm Chart)。这个 Provisioner 会监视 PVC 的创建,并自动在指定的 NFS 共享目录下创建以命名空间和 PVC 名称命名的子目录作为新的 PV。

使用helm配置

使用helm添加nfs-subdir-external-provisioner

$ helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
$ helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=x.x.x.x \
    --set nfs.path=/data/k8s_nfs

查看安装的chart的详细配置

[root@k8smaster ~]# helm show all nfs-subdir-external-provisioner/nfs-subdir-external-provisioner
apiVersion: v1
appVersion: 4.0.2
description: nfs-subdir-external-provisioner is an automatic provisioner that used
  your *already configured* NFS server, automatically creating Persistent Volumes.
home: https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
keywords:
- nfs
- storage
- provisioner
kubeVersion: '>=1.9.0-0'
name: nfs-subdir-external-provisioner
sources:
- https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
version: 4.0.18

---
replicaCount: 1
strategyType: Recreate

image:
  repository: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner
  tag: v4.0.2
  pullPolicy: IfNotPresent
imagePullSecrets: []

nfs:
  server:
  path: /nfs-storage
  mountOptions:
  volumeName: nfs-subdir-external-provisioner-root
  # Reclaim policy for the main nfs volume
  reclaimPolicy: Retain

# For creating the StorageClass automatically:
storageClass:
  create: true

  # Set a provisioner name. If unset, a name will be generated.
  # provisionerName:

  # Set StorageClass as the default StorageClass
  # Ignored if storageClass.create is false
  defaultClass: false

  # Set a StorageClass name
  # Ignored if storageClass.create is false
  name: nfs-client

  # Allow volume to be expanded dynamically
  allowVolumeExpansion: true

  # Method used to reclaim an obsoleted volume
  reclaimPolicy: Delete

  # When set to false your PVs will not be archived by the provisioner upon deletion of the PVC.
  archiveOnDelete: true

  # If it exists and has 'delete' value, delete the directory. If it exists and has 'retain' value, save the directory.
  # Overrides archiveOnDelete.
  # Ignored if value not set.
  onDelete:

  # Specifies a template for creating a directory path via PVC metadata's such as labels, annotations, name or namespace.
  # Ignored if value not set.
  pathPattern:

  # Set access mode - ReadWriteOnce, ReadOnlyMany or ReadWriteMany
  accessModes: ReadWriteOnce

  # Set volume bindinng mode - Immediate or WaitForFirstConsumer
  volumeBindingMode: Immediate

  # Storage class annotations
  annotations: {}

leaderElection:
  # When set to false leader election will be disabled
  enabled: true

## For RBAC support:
rbac:
  # Specifies whether RBAC resources should be created
  create: true

# If true, create & use Pod Security Policy resources
# https://kubernetes.io/docs/concepts/policy/pod-security-policy/
podSecurityPolicy:
  enabled: false

# Deployment pod annotations
podAnnotations: {}

## Set pod priorityClassName
# priorityClassName: ""

podSecurityContext: {}

securityContext: {}

serviceAccount:
  # Specifies whether a ServiceAccount should be created
  create: true

  # Annotations to add to the service account
  annotations: {}

  # The name of the ServiceAccount to use.
  # If not set and create is true, a name is generated using the fullname template
  name:

resources: {}
  # limits:
  #  cpu: 100m
  #  memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 128Mi

nodeSelector: {}

tolerations: []

affinity: {}

# Additional labels for any resource created
labels: {}

podDisruptionBudget:
  enabled: false
  maxUnavailable: 1

---
# NFS Subdirectory External Provisioner Helm Chart

The [NFS subdir external provisioner](https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner) is an automatic provisioner for Kubernetes that uses your *already configured* NFS server, automatically creating Persistent Volumes.

## TL;DR;

```console
$ helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
$ helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=x.x.x.x \
    --set nfs.path=/exported/path
```

## Introduction

This charts installs custom [storage class](https://kubernetes.io/docs/concepts/storage/storage-classes/) into a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. It also installs a [NFS client provisioner](https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner) into the cluster which dynamically creates persistent volumes from single NFS share.

## Prerequisites

- Kubernetes >=1.9
- Existing NFS Share

## Installing the Chart

To install the chart with the release name `my-release`:

```console
$ helm install my-release nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=x.x.x.x \
    --set nfs.path=/exported/path
```

The command deploys the given storage class in the default configuration. It can be used afterwards to provision persistent volumes. The [configuration](#configuration) section lists the parameters that can be configured during installation.

> **Tip**: List all releases using `helm list`

## Uninstalling the Chart

To uninstall/delete the `my-release` deployment:

```console
$ helm delete my-release
```

The command removes all the Kubernetes components associated with the chart and deletes the release.

## Configuration

The following tables lists the configurable parameters of this chart and their default values.

| Parameter                            | Description                                                                                           | Default                                                       |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `replicaCount`                       | Number of provisioner instances to deployed                                                           | `1`                                                           |
| `strategyType`                       | Specifies the strategy used to replace old Pods by new ones                                           | `Recreate`                                                    |
| `image.repository`                   | Provisioner image                                                                                     | `registry.k8s.io/sig-storage/nfs-subdir-external-provisioner` |
| `image.tag`                          | Version of provisioner image                                                                          | `v4.0.2`                                                      |
| `image.pullPolicy`                   | Image pull policy                                                                                     | `IfNotPresent`                                                |
| `imagePullSecrets`                   | Image pull secrets                                                                                    | `[]`                                                          |
| `storageClass.name`                  | Name of the storageClass                                                                              | `nfs-client`                                                  |
| `storageClass.defaultClass`          | Set as the default StorageClass                                                                       | `false`                                                       |
| `storageClass.allowVolumeExpansion`  | Allow expanding the volume                                                                            | `true`                                                        |
| `storageClass.reclaimPolicy`         | Method used to reclaim an obsoleted volume                                                            | `Delete`                                                      |
| `storageClass.provisionerName`       | Name of the provisionerName                                                                           | null                                                          |
| `storageClass.archiveOnDelete`       | Archive PVC when deleting                                                                             | `true`                                                        |
| `storageClass.onDelete`              | Strategy on PVC deletion. Overrides archiveOnDelete when set to lowercase values 'delete' or 'retain' | null                                                          |
| `storageClass.pathPattern`           | Specifies a template for the directory name                                                           | null                                                          |
| `storageClass.accessModes`           | Set access mode for PV                                                                                | `ReadWriteOnce`                                               |
| `storageClass.volumeBindingMode`     | Set volume binding mode for Storage Class                                                             | `Immediate`                                                   |
| `storageClass.annotations`           | Set additional annotations for the StorageClass                                                       | `{}`                                                          |
| `leaderElection.enabled`             | Enables or disables leader election                                                                   | `true`                                                        |
| `nfs.server`                         | Hostname of the NFS server (required)                                                                 | null (ip or hostname)                                         |
| `nfs.path`                           | Basepath of the mount point to be used                                                                | `/nfs-storage`                                                |
| `nfs.mountOptions`                   | Mount options (e.g. 'nfsvers=3')                                                                      | null                                                          |
| `nfs.volumeName`                     | Volume name used inside the pods                                                                      | `nfs-subdir-external-provisioner-root`                        |
| `nfs.reclaimPolicy`                  | Reclaim policy for the main nfs volume used for subdir provisioning                                   | `Retain`                                                      |
| `resources`                          | Resources required (e.g. CPU, memory)                                                                 | `{}`                                                          |
| `rbac.create`                        | Use Role-based Access Control                                                                         | `true`                                                        |
| `podSecurityPolicy.enabled`          | Create & use Pod Security Policy resources                                                            | `false`                                                       |
| `podAnnotations`                     | Additional annotations for the Pods                                                                   | `{}`                                                          |
| `priorityClassName`                  | Set pod priorityClassName                                                                             | null                                                          |
| `serviceAccount.create`              | Should we create a ServiceAccount                                                                     | `true`                                                        |
| `serviceAccount.name`                | Name of the ServiceAccount to use                                                                     | null                                                          |
| `serviceAccount.annotations`         | Additional annotations for the ServiceAccount                                                         | `{}`                                                          |
| `nodeSelector`                       | Node labels for pod assignment                                                                        | `{}`                                                          |
| `affinity`                           | Affinity settings                                                                                     | `{}`                                                          |
| `tolerations`                        | List of node taints to tolerate                                                                       | `[]`                                                          |
| `labels`                             | Additional labels for any resource created                                                            | `{}`                                                          |
| `podDisruptionBudget.enabled`        | Create and use Pod Disruption Budget                                                                  | `false`                                                       |
| `podDisruptionBudget.maxUnavailable` | Set maximum unavailable pods in the Pod Disruption Budget                                             | `1`                                                           |

## Install Multiple Provisioners

It is possible to install more than one provisioner in your cluster to have access to multiple nfs servers and/or multiple exports from a single nfs server. Each provisioner must have a different `storageClass.provisionerName` and a different `storageClass.name`. For example:

```console
helm install second-nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=y.y.y.y \
    --set nfs.path=/other/exported/path \
    --set storageClass.name=second-nfs-client \
    --set storageClass.provisionerName=k8s-sigs.io/second-nfs-subdir-external-provisioner
```

卸载 nfs-subdir-external-provisioner

helm uninstall nfs-subdir-external-provisioner

动态PV测试

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-claim
spec:
  storageClassName: "nfs-sc"
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:stable-alpine
    volumeMounts:
    - name: nfs-pvc
      mountPath: "/usr/share/nginx/html"
  volumes:
  - name: nfs-pvc
    persistentVolumeClaim:
      claimName: test-claim

手动配置资源

确保能够连接到nfs server

获取 NFS Subdir External Provisioner 文件,编辑它们以添加您的 NFS 服务器的连接信息,然后使用 kubectl / oc 命令应用每个文件

配置nfs-rbac, kubectl apply -f rbac.yaml

配置 NFS subdir 外部提供程序, kubectl apply -f deployment.yaml

部署存储类 kubectl apply -f class.yaml

完成测试 kubectl apply -f test-claim.yaml kubectl apply -f test-pod.yaml

参考链接
https://blog.csdn.net/qq_49288154/article/details/143956580
https://www.cnblogs.com/nb-blog/p/17970547
https://blog.csdn.net/ltgsoldier1/article/details/142534752
https://mp.weixin.qq.com/s/0EDSZYN_uePKr7mP43gCAw