搭建 StorageClass + NFS,实现 NFS 的动态 PV 创建

K8S   2025-01-12 15:20   291   0  

一、StorageClass 存储类

StorageClass 存储类用于描述集群中可以提供的存储的类型。不同的存储类可能对应着不同的:

  • 服务等级(quality-of-service level)

  • 备份策略

  • 集群管理员自定义的策略

Kubernetes 自身对存储类所代表的含义并无感知,由集群管理员自行约定。

二、StorageClass 资源

每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段, 这些字段会在 StorageClass 需要动态分配 PersistentVolume 时会使用到。
StorageClass 对象的命名很重要,用户使用这个命名来请求生成一个特定的类。 当创建 StorageClass 对象时,管理员设置 StorageClass 对象的命名和其他参数,一旦创建了对象就不能再对其更新。

三、实现NFS的动态pv创建

Kubernetes 本身支持的动态 PV 创建不包括 NFS,所以需要使用外部存储卷插件分配PV。
卷插件称为 Provisioner(存储分配器),NFS 使用的是 nfs-client,这个外部卷插件会使用已经配置好的 NFS 服务器自动创建 PV。 Provisioner:用于指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/aws-ebs)和外部插件(如 external-storage 提供的 ceph.com/cephfs)。

1、在master节点上安装nfs,并配置nfs服务

这里新建一个/data/nfs/的文件夹,并挂载。

2、创建 Service Account,用来管理 NFS Provisioner 在 k8s 集群中运行的权限,设置 nfs-client 对 PV,PVC,StorageClass 等的规则

vim nfs-client-rbac.yaml
#创建 Service Account 账户,用来管理 NFS Provisioner 在 k8s 集群中运行的权限
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
---
#创建集群角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-client-provisioner-clusterrole
rules:
# 角色中可以访问的权限
  - 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: ["list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]

---
#集群角色绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: nfs-client-provisioner-clusterrolebinding
subjects:
  # 绑定角色 ServiceAccount
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-clusterrole
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f nfs-client-rbac.yaml

image.png

kubectl get serviceaccount -A|grep nfs
kubectl get clusterrole -A|grep nfs
kubectl get clusterrolebinding -A|grep nfs

image.png

3、使用 Deployment 来创建 NFS Provisioner NFS Provisione(即 nfs-client)

由于 1.20 版本启用了 selfLink,所以 k8s 1.20+ 版本通过 nfs provisioner 动态生成pv会报错,解决方法如下

vim /etc/kubernetes/manifests/kube-apiserver.yaml

- --feature-gates=RemoveSelfLink=false       #添加这一行

image.png

# 重启apiserver,删除apiserver的pod,让他自动重建
kubectl delete pod kube-apiserver-master01 -n kube-system
kubectl get pod --all-namespaces

image.png

有两个功能:一个是在 NFS 共享目录下创建挂载点(volume),另一个则是将 PV 与 NFS 的挂载点建立关联。

vim nfs-client-provisioner.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner          #指定Service Account账户
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: TZ
              value: Asia/Shanghai    #容器时区
            - name: PROVISIONER_NAME
              value: nfs-storage       #配置provisioner的Name,确保该名称与StorageClass资源中的provisioner名称保持一致
            - name: NFS_SERVER
              value: 192.168.102.130           #配置绑定的nfs服务器
            - name: NFS_PATH
              value: /data/nfs          #配置绑定的nfs服务器目录,挂载路径
      volumes:              #申明nfs数据卷
        - name: nfs-client-root
          nfs:
            server: 192.168.102.130  #配置绑定的nfs服务器
            path: /data/nfs
kubectl apply -f nfs-client-provisioner.yaml
kubectl get pod --all-namespaces

image.png

4、创建 StorageClass,负责建立 PVC 并调用 NFS provisioner 进行预定的工作,并让 PV 与 PVC 建立关联

查看 apiVersion 版本

kubectl api-resources

image.png

vim nfs-client-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-storageclass
provisioner: nfs-storage     #这里的名称要和provisioner配置文件中的环境变量PROVISIONER_NAME保持一致
parameters:
  archiveOnDelete: "false"   #false表示在删除PVC时不会对数据进行存档,即删除数据
kubectl apply -f nfs-client-storageclass.yaml
kubectl get storageclasses

image.png
image.png

5、创建 PVC 和 Pod 测试

vim test-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-nfs-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: nfs-client-storageclass    #关联StorageClass对象
  resources:
    requests:
      storage: 2Gi
kubectl apply -f test-pvc-pod.yaml
kubectl get pvc
kubectl get pv

自动绑定
image.png
image.png
nfs服务器查看

cd /data/nfs
ls -l

image.png

创建一个pod

vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: test-nfs-pvc
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      env:
        - name: TZ
          value: Asia/Shanghai    #容器时区
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage    #与PVC名称保持一致
kubectl apply -f pod.yaml
kubectl get pod --all-namespaces

image.png
image.png
在 NFS 服务器中,添加一条数据。因为我们把 pod 的 /usr/share/nginx/html 目录挂载到了 pvc,所以在 /data/nfs 目录下面新增文件就相当于在 /usr/share/nginx/html 目录下新增文件。

cd /data/nfs/default-test-nfs-pvc-pvc-f83594bf-cd41-4056-9065-bd19a3871c43/
vim index.html
cat index.html

image.png
访问

kubectl get pods -o wide
curl 10.122.241.118

image.png


博客评论
还没有人评论,赶紧抢个沙发~
发表评论
说明:请文明发言,共建和谐网络,您的个人信息不会被公开显示。