k8s 存储卷详解与动静部署详解

目录

[Volume 卷](#Volume 卷)

卷类型

[emptyDir :](#emptyDir :)

hostPath:

[persistentVolumeClaim (PVC):](#persistentVolumeClaim (PVC):)

[configMap 和 secret:](#configMap 和 secret:)

emptyDir存储卷

特点

用途:

示例

hostPath存储卷

特点

用途

示例

nfs共享存储卷

特点

用途

示例

PV和PVC

PV和PVC之间的相互作用的生命周期

pv的状态

pv从创建到销毁的过程

回收策略

pv操作

简单举例

结合举例

查看pv的定义方式

查看pv定义的规格

查看PVC的定义方式

查看pvc定义规格

NFS使用PV和PVC(静态)

NFS主机上配置nfs存储

master上定义pv

master上定义pvc

测试访问

[搭建StorageClass + NFS(NFS 的动态 PV 创建)](#搭建StorageClass + NFS(NFS 的动态 PV 创建))

stor01节点上安装nfs,并配置nfs服务

[master创建 Service Account,设置 nfs-client 对 PV,PVC,StorageClass 等的规则](#master创建 Service Account,设置 nfs-client 对 PV,PVC,StorageClass 等的规则)

[使用 Deployment 来创建 NFS Provisioner](#使用 Deployment 来创建 NFS Provisioner)

[创建 StorageClass](#创建 StorageClass)

[创建 PVC](#创建 PVC)

[查看 NFS 服务器上是否生成对应的目录](#查看 NFS 服务器上是否生成对应的目录)


Volume 卷

容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失------容器以干净的状态(镜像最初的状态)重新启动。其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件。

Kubernetes 中的 Volume 抽象确实解决了容器中文件生命周期短暂的问题。通过 Volume,可以将持久化存储挂载到 Pod 中的容器,使得即使容器重新启动或者崩溃,文件依然可用。而共享文件的需求则可以通过将 Volume 挂载到 Pod 中的多个容器来实现,在这种情况下,这些容器可以共享相同的文件系统。

卷类型

emptyDir

  • emptyDir 是一种临时性卷,在同一个 Pod 中的容器之间共享文件。

  • 它在 Pod 创建时被创建,并且对于同一个 Pod 中的所有容器都可见。

  • 当 Pod 被删除时,emptyDir 中的数据也会被清除。

  • 适用于临时数据交换或共享,例如缓存空间或某些计算任务的检查点。

hostPath

  • hostPath 允许将宿主机文件系统路径挂载到 Pod 中,容器可以直接读写宿主机上的文件。

  • 它可以用于需要对宿主机文件系统进行直接操作的场景,但可能会引入安全风险和依赖于特定节点的问题。

persistentVolumeClaim (PVC)

  • persistentVolumeClaim (PVC) 用于请求持久化存储资源,可以在多个 Pod 之间共享。

  • PVC 是一种抽象,用于请求集群中的持久化存储资源,例如 NFS、AWS EBS、Azure Disk 等。

  • PVC 可以独立于 Pod 存在,并且可以通过标签选择器与 Pod 动态绑定,从而实现存储资源的动态分配和回收。

configMap 和 secret

  • configMap 和 secret 允许将配置文件或机密信息挂载到容器中。

  • configMap 用于存储配置数据,例如环境变量、配置文件等。

  • secret 用于存储敏感信息,例如密码、证书等。

  • 这些信息可以作为卷挂载到 Pod 中,或者以环境变量的形式注入到容器中。

通过使用这些不同类型的卷,Kubernetes 用户可以灵活地管理和利用存储资源,满足不同应用场景的需求。

emptyDir存储卷

emptyDir 存储卷是 Kubernetes 中的一种卷类型,用于在同一个 Pod 中的容器之间共享文件。

emptyDir 卷在 Pod 被分配给节点时被创建,并且只要 Pod 在该节点上运行,该卷就会一直存在。它最初是空的,因此其名称为 emptyDir。Pod 中的所有容器可以读取和写入 emptyDir 卷中的相同文件,尽管可以将该卷挂载到每个容器中的相同或不同路径上。但需要注意的是,当出于任何原因从节点中删除 Pod 时,emptyDir 中的数据将被永久删除,因为它是临时性存储,其生命周期与 Pod 相关联。

特点

  • 临时性存储

  • emptyDir 提供的存储是临时的,其生命周期与所属的 Pod 相关。

  • 当 Pod 被删除时,emptyDir 中的数据也会被清除,因此不适合用于持久化存储。

  • Pod 内容器之间的共享

  • emptyDir 在同一个 Pod 中的所有容器之间共享,容器可以读写其中的数据。

  • 创建时机

  • emptyDir 在 Pod 创建时被创建,当容器启动时,可以访问其中的空目录。

用途

  • 适用于需要在同一个 Pod 中的多个容器之间进行临时数据交换或共享的场景。

  • 例如,可以用于容器间的缓存共享、临时文件存储等用途。

示例

mkdir /opt/volumes
cd /opt/volumes

vim pod-emptydir.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-emptydir
  namespace: default
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    #定义容器挂载内容
    volumeMounts:
    #使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷
    - name: html
      #挂载至容器中哪个目录
      mountPath: /usr/share/nginx/html/
  - name: busybox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: html
      #在容器内定义挂载存储名称和挂载路径
      mountPath: /data/
    command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
  #定义存储卷
  volumes:
  #定义存储卷名称  
  - name: html
    #定义存储卷类型
    emptyDir: {}
  • 这个YAML文件描述了一个名为pod-emptydir的Pod,其中包含两个容器:myappbusyboxmyapp容器使用名为html的空目录卷挂载到/usr/share/nginx/html/目录,而busybox容器也使用相同的卷挂载到/data/目录,并在容器内运行一个循环,每两秒将当前日期追加到/data/index.html文件中。最后,通过emptyDir类型定义了一个名为html的存储卷,这样做是为了验证两个容器之间挂载的emptyDir实现共享。

  • 这配置的目的是验证两个容器之间通过emptyDir实现的存储卷共享。

    kubectl apply -f pod-emptydir.yaml #启动Pod
    [root@master01 volumes]# kubectl get pods -o wide

    NAME READY STATUS RESTARTS AGE IP NODE
    pod-emptydir 2/2 Running 0 70s 10.244.2.4 node02 <none> <none>

  • 可见pod-emptydir Pod 正常运行且两个容器都处于Ready状态。

    [root@master01 volumes]# curl 10.244.2.4

这表示成功地从Pod pod-emptydir中获取到了日期信息。这表明配置正确,busybox容器将日期写入到了/data/index.html文件中,而myapp容器通过共享的存储卷可以访问到这个文件。因此,存储卷之间的共享通过emptyDir实现成功。

hostPath存储卷

HostPath存储卷是Kubernetes中的一种卷类型,允许将节点上的文件系统路径挂载到Pod中。这意味着Pod可以访问主机节点上的文件或目录,并与主机共享存储空间。

hostPath卷将 node 节点的文件系统中的文件或目录挂载到集群中。 hostPath可以实现持久存储,但是在node节点故障时,也会导致数据的丢失。

特点

  • 直接访问主机文件系统: HostPath存储卷允许Pod直接访问主机节点上的文件系统,提供了对主机存储的直接访问权限。

  • 读写权限: Pod可以对HostPath上的文件进行读写操作,这为一些需要在容器内进行文件操作的应用提供了便利。

  • 节点依赖性: Pod使用HostPath时,会依赖节点上的具体路径,这可能导致在不同节点上部署相同Pod时出现问题,因为节点之间的文件系统路径可能不同。

  • **共享资源:**多个Pod可以共享同一个HostPath,但要小心避免数据冲突或竞争条件。

用途

  • 主机文件操作: 适用于需要在Pod内进行主机文件系统操作的场景,例如读取或写入主机上的特定文件。

  • 数据共享: 多个Pod可以共享同一个HostPath,这在一些需要多个Pod之间共享数据的情况下可能很有用。

  • 特殊需求: 用于满足一些特殊需求,例如某些应用需要在容器内直接操作主机上的某些文件。

需要注意的是,由于HostPath存储卷的使用可能涉及到权限和安全性的考虑,一般情况下建议慎重使用,并确保在生产环境中采取适当的安全措施。

示例

在 node01 节点上创建挂载目录

mkdir -p /data/pod/volume1
echo 'node01.test.com' > /data/pod/volume1/index.html

在 node02 节点上创建挂载目录

mkdir -p /data/pod/volume1
echo 'node02.test.com' > /data/pod/volume1/index.html

在master01上创建 Pod 资源

vim pod-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-hostpath
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    #定义容器挂载内容
    volumeMounts:
    #使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷
    - name: html
      #挂载至容器中哪个目录
      mountPath: /usr/share/nginx/html
      #读写挂载方式,默认为读写模式false
      readOnly: false
  #volumes字段定义了paues容器关联的宿主机或分布式文件系统存储卷
  volumes:
    #存储卷名称
    - name: html
      #路径,为宿主机存储路径
      hostPath:
        #在宿主机上目录的路径
        path: /data/pod/volume1
        #定义类型,这表示如果宿主机没有此目录则会自动创建
        type: DirectoryOrCreate
  • 此YAML配置描述了在默认命名空间中命名为"pod-hostpath"的Kubernetes Pod。它将主机路径卷挂载到容器中,使主机目录的内容在容器内的指定路径可用。如果主机上的目录不存在,由于"类型: 目录或创建"属性,它将被自动创建。

    kubectl apply -f pod-hostpath.yaml

  • 该命令 "kubectl apply -f pod-hostpath.yaml" 用于将 "pod-hostpath.yaml" 文件中指定的配置应用到 Kubernetes 集群中。它根据提供的配置创建或更新 YAML 文件中定义的资源,例如 Pod。

访问测试

[root@master01 volumes]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE    pod-hostpath             1/1     Running   0          28s   10.244.1.5   node01   <none>           <none>
[root@master01 volumes]# curl 10.244.1.5
node02.test.com

删除pod,再重建,验证是否依旧可以访问原来的内容

[root@master01 volumes]# kubectl delete -f pod-hostpath.yaml
pod "pod-hostpath" deleted
[root@master01 volumes]# kubectl apply -f pod-hostpath.yaml
pod/pod-hostpath created
[root@master01 volumes]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE   
pod-hostpath             1/1     Running   0          14s   10.244.1.6   node01   <none>           <none>
[root@master01 volumes]# curl 10.244.1.6
node02.test.com
  • 可见数据访问实现了持久存储

nfs共享存储卷

在Kubernetes中,NFS共享存储卷是一种常见的持久化存储解决方案,它允许多个Pod在集群中共享同一个NFS服务器上的存储空间。

  • NFS介绍: NFS(Network File System)是一种基于网络的文件系统协议,允许在网络上共享文件系统资源。它使得不同的计算机之间可以像访问本地文件一样访问远程文件。

  • Kubernetes中的NFS存储卷: Kubernetes提供了多种方式来使用NFS作为持久化存储卷。其中一种常见的方法是使用NFS卷插件,例如NFS CSI Driver,它能够与Kubernetes集成并提供对NFS存储的访问。

  • 配置NFS存储卷: 要在Kubernetes中配置NFS存储卷,首先需要在NFS服务器上设置共享目录,并确保NFS服务器可以通过网络访问。然后,可以通过Kubernetes的PersistentVolume(PV)和PersistentVolumeClaim(PVC)对象来声明和使用NFS存储卷。

特点

  • 共享性: NFS存储卷允许多个Pod在集群中共享同一个NFS服务器上的存储空间。这使得多个应用程序可以访问和操作相同的数据,促进了数据共享和协作。

  • 持久性: NFS存储卷提供了持久化的存储解决方案,数据存储在NFS服务器上并且在Pod重新启动或迁移时仍然可用。这对于需要长期保存数据的应用程序和服务非常有用。

  • 可扩展性: NFS存储卷可以轻松地扩展以满足应用程序的需求。通过在NFS服务器上添加更多的存储空间或者增加NFS服务器的数量,可以扩展存储容量和性能。

  • 灵活性: 使用NFS存储卷可以将存储与Pod分离,从而使得Pod可以在不同的节点上迁移而不会丢失数据。这种灵活性使得在Kubernetes集群中部署和管理应用程序变得更加容易。

用途

  • 简化管理: NFS存储卷可以通过Kubernetes的PV和PVC对象进行声明和管理,而无需手动管理存储配置。这简化了存储管理的流程,并提高了部署和维护的效率。

  • 适用范围广泛: NFS存储卷适用于许多不同类型的应用程序和场景,包括数据库、文件共享、日志存储等。它提供了一种通用的存储解决方案,适用于各种不同的业务需求。

示例

stor01节点上安装nfs,并配置nfs服务

[root@35 ~]# hostnamectl set-hostname stor01
[root@35 ~]# su
[root@stor01 ~]#

mkdir /data/volumes -p
chmod 777 /data/volumes

vim /etc/exports
/data/volumes 192.168.41.0/24(rw,no_root_squash)

systemctl start rpcbind
systemctl start nfs

showmount -e

这一系列命令用于配置 NFS(Network File System)共享。

  • 创建一个名为 /data/volumes 的目录,并使用 -p 参数确保创建路径中不存在的目录。

  • 使用 chmod 777 /data/volumes 命令将 /data/volumes 目录的权限设置为 777,以确保所有用户都有完全的读写权限。

  • 使用 vim /etc/exports 命令编辑 NFS 服务器的导出文件,添加一行配置 /data/volumes 192.168.41.0/24(rw,no_root_squash),这表示将 /data/volumes 目录导出给位于子网 192.168.41.0/24 的主机,允许读写访问,并且禁用了 no_root_squash

  • 使用 systemctl start rpcbindsystemctl start nfs 命令启动 RPC 绑定和 NFS 服务。

  • 使用 showmount -e 命令检查 NFS 导出列表,确认 /data/volumes 目录已经成功导出给了 192.168.41.0/24 子网的主机。

这些步骤使得在网络上可以访问并且共享 /data/volumes 目录。

在master节点上

vim pod-nfs-vol.yaml

kind: Pod                  # 指定资源类型为 Pod
apiVersion: v1             # 使用 API 版本 v1
metadata:
  name: pod-vol-nfs        # Pod 的名称为 pod-vol-nfs
  namespace: default       # Pod 将被创建在 default 命名空间中
spec:                      # 描述 Pod 的规格(specification)
  containers:
  - name: myapp            # 容器的名称为 myapp
    image: ikubernetes/myapp:v1  # 容器使用的镜像为 ikubernetes/myapp:v1
    volumeMounts:              # 容器内的卷挂载设置
    - name: html                # 卷的名称为 html
      mountPath: /usr/share/nginx/html  # 容器内挂载卷的路径
  volumes:                  # Pod 级别的卷定义
    - name: html            # 定义一个名为 html 的卷
      nfs:                  # 指定卷类型为 NFS
        path: /data/volumes # NFS 服务器上共享的路径
        server: stor01      # NFS 服务器的主机名或 IP 地址
  • 此配置文件通过 NFS 卷将外部存储挂载到 Pod 中的容器上,使得容器可以访问 NFS 上的数据。

    kubectl apply -f pod-nfs-vol.yaml #创建pod
    kubectl get pods -o wide #配置

  • 用来创建并查看 Kubernetes Pod 和将 pod-nfs-vol.yaml 文件中定义的 Pod 配置应用到 Kubernetes 集群中,从而创建名为 pod-vol-nfs 的 Pod,其中包含一个名为 myapp 的容器,并挂载了一个 NFS 类型的卷。

  • 用于获取当前 Kubernetes 集群中的 Pod 列表

如果在yaml文件中server指定的是主机名而不是ip,需要在pod所在主机上添加主机名映射

vim  /etc/hosts
192.168.41.35   stor01

在nfs服务器上创建index.html

cd /data/volumes
echo "<h1> nfs stor01</h1>" > index.html

在master节点测试

curl 10.244.1.7
<h1> nfs stor01</h1>

kubectl delete -f pod-nfs-vol.yaml   #删除nfs相关pod,再重新创建,可以得到数据的持久化存储

kubectl apply -f pod-nfs-vol.yaml

#再次测试

PV和PVC

  • PV(Persistent Volume)是描述或定义存储卷的工具,通常由运维工程师创建。

  • PVC(Persistent Volume Claim)是对PV的请求,用于描述所需的存储条件。

  • PVC的逻辑是在Pod中定义一个存储卷(类型为PVC),指定大小并与相应的PV建立关系。PVC 必须与对应的 PV 建立关系,PVC 会根据配置的定义去 PV 申请,而 PPV由存储空间创建,二者是Kubernetes抽象的存储资源。

  • 在Kubernetes中,PV(持久卷)有两种供给方式,静态和动态。静态PV是由集群管理员手动创建的,携带着真实存储信息,但存在缺陷,因为需要手动为多个用户配置存储,可能显得繁琐。而动态PV则是当静态PV无法匹配用户的PVC(持久卷声明)时,集群会尝试动态地供给volume给PVC,更灵活地满足用户需求。

  • 为了避免手动创建PV的繁琐,Kubernetes引入了StorageClass,用于自动创建PV模板。创建StorageClass需定义PV属性和存储插件,如Ceph。Kubernetes可根据用户PVC请求,使用对应的StorageClass调用StorageClass 声明的存储插件自动创建需要的PV并进行绑定。

PV是集群中的资源。 PVC是对这些资源的请求,也是对资源的索引检查。

PV和PVC之间的相互作用的生命周期

  • Provisioning(配置): PV的创建阶段,可通过静态方式直接创建PV,或使用StorageClass进行动态创建。

  • Binding(绑定): 将PV分配给对应的PVC。

  • Using(使用): Pod通过PVC使用Volume,通过准入控制StorageProtection(1.9及以前版本为PVCProtection)可以阻止删除正在使用的PVC。

  • Releasing(释放): Pod释放Volume并删除PVC。

  • Recycling(回收): 回收PV,可保留PV以备下次使用,或直接从云存储中删除。

pv的状态

  • Available(可用):PV已经被创建,但尚未被绑定到任何PVC上,因此可以被任何PVC请求使用。

  • Bound(已绑定):PV已经被绑定到一个PVC上,可以被挂载到一个Pod中使用。

  • Released(已释放):PVC与PV之间的绑定关系已经被删除,但是PV上的数据还未被清除。此时PV处于Released状态,可以被重新绑定到另一个PVC上使用。

  • Failed(失败):PV与底层存储后端的连接出现问题,或者存储后端出现了错误,导致PV无法使用。此时PV处于Failed状态。

pv从创建到销毁的过程

PV(Persistent Volume)从创建到销毁的过程通常包括以下几个步骤:

  • 创建 (Provisioning):PV可以通过两种方式创建,一种是静态创建,另一种是动态创建。静态创建是指管理员手动创建PV对象并指定其属性,如存储类型、大小等。动态创建则是通过StorageClass进行配置,当PVC请求存储资源时,根据StorageClass的定义动态创建PV。无论是静态还是动态创建,都会生成一个PV对象。状态会变成Available,等待被PVC绑定

  • 绑定 (Binding):PV需要与PVC进行绑定才能被使用。管理员或Kubernetes系统会将某个PV绑定到一个特定的PVC上,使其成为PVC的存储资源,状态会变成Bound,就可以被定义了相应PVC的Pod使用。

  • 使用(Using):一旦PV被绑定到PVC上,Pod可以通过PVC来使用PV提供的存储资源。Pod会挂载PVC,从而访问PV中的数据,。

  • 释放 (Releasing):当PVC不再需要PV提供的存储资源时,管理员或Kubernetes系统会将PV与PVC之间的绑定解除,释放PV,PV的状态变成Released。这并不会立即删除PV中的数据,而是将PV标记为已释放状态。

  • 回收 (Recycling):在PV被释放后,根据管理员或系统配置的策略,可以选择回收PV。回收的方式可能包括保留PV以备下次使用,或者直接删除PV以释放资源。有三种回收策略,Retain、Delete和Recycle。Retain就是保留现场,K8S集群什么也不做,等待用户手动去处理PV里的数据,处理完后,再手动删除PV。Delete策略,K8S会自动删除该PV及里面的数据。Recycle方式,K8S会将PV里的数据删除,然后把PV的状态变成Available,又可以被新的PVC绑定使用。

回收策略

在Kubernetes中,PV(Persistent Volume)的回收策略定义了在释放PV时如何处理其底层存储资源。常见的PV回收策略包括以下几种:

  • Retain(保留):当PV被释放后,底层存储资源不会被删除,而是保留在系统中。这意味着PV的数据仍然可用,但需要手动处理以释放存储资源。

  • Recycle(回收):在这种策略下,PV被释放后,底层存储资源会被清空,以便下次使用。然而,这种方式存在安全性和隐私问题,因此已经不推荐使用。

  • Delete(删除):PV被释放后,底层存储资源会被直接删除。这是一种自动化的清理方式,适用于不再需要PV数据的情况。

pv操作

在 Kubernetes 中,PV(PersistentVolume)是集群中的一种资源,用于提供持久化存储。PV 的操作包括以下几个方面:

  • 创建 PV:可以通过定义 PV 对象的 YAML 文件来创建 PV。在 YAML 文件中指定 PV 的属性,如容量、访问模式、存储类型等。

  • 删除 PV:当 PV 不再需要时,可以通过删除相应的 PV 对象来释放资源。删除 PV 时需要确保相关的 PVC(PersistentVolumeClaim)已经被释放,否则删除操作可能会失败。

  • 管理 PV 的状态:可以通过修改 PV 对象的属性来管理 PV 的状态,如修改容量、访问模式等。需要注意的是,某些属性(如容量)可能无法在运行时修改,需要在创建 PV 时就确定好。

  • 挂载 PV 到 Pod:创建 PV 后,需要将 PV 挂载到 Pod 中以供应用程序使用。可以通过 PVC(PersistentVolumeClaim)来实现 PV 和 Pod 之间的绑定关系。

  • 监控 PV 的使用情况:可以通过 Kubernetes 的监控系统或者第三方工具来监控 PV 的使用情况,包括存储容量、使用率等指标。

这些是在 Kubernetes 中对 PV 进行常见操作的一些例子。 PV 的操作可以通过命令行工具(如 kubectl)、Kubernetes API 或者管理平台(如 Kubernetes Dashboard)来进行。

简单举例

创建 PV 时,通过以下 YAML 示例可以指定 PV 的基本属性:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: standard
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /export/data
    server: nfs-server.example.com
  • capacity 定义了 PV 的存储容量。

  • volumeMode 指定了 PV 的工作模式,可以是 FilesystemBlock

  • accessModes 定义了 PV 的访问模式,包括 ReadWriteOnceReadOnlyManyReadWriteMany

  • persistentVolumeReclaimPolicy 定义了当 PV 释放时的回收策略,可以是 RetainRecycleDelete

  • storageClassName 指定了 PV 所属的存储类。

  • mountOptions 包含了挂载 PV 时使用的挂载选项。

  • nfs 描述了 NFS 类型的 PV 的具体配置,包括 NFS 服务器地址和路径。

删除 PV 时,可以使用以下命令:

kubectl delete pv example-pv

管理 PV 状态时,可以通过修改 PV 对象的 YAML 文件中的字段值来实现。例如,修改 PV 的容量:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 10Gi  # 修改容量为10Gi
  ...

挂载 PV 到 Pod 时,需要创建一个 PVC,并在 Pod 的 YAML 文件中引用该 PVC。例如:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
    - name: my-container
      image: nginx
      volumeMounts:
        - name: my-volume
          mountPath: /mnt/data
  volumes:
    - name: my-volume
      persistentVolumeClaim:
        claimName: example-pvc  # 引用 PVC 的名称

结合举例

在 Kubernetes 中,PV 的动态配置是一项重要的功能,它允许集群动态地创建和管理 PV 资源。以下是 PV 的动态配置的一般流程:

  • 定义存储类(StorageClass):首先,需要定义一个存储类,它描述了动态创建 PV 所需的存储属性。以下是一个存储类的示例:

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
    name: standard
    provisioner: example.com/nfs

其中,provisioner 指定了用于动态创建 PV 的存储插件。

  • 创建 PVC:接下来,创建一个 PVC,请求所需的存储资源。PVC 将使用存储类来确定如何动态地创建 PV。以下是 PVC 的示例:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    name: my-pvc
    spec:
    accessModes:
    - ReadWriteOnce
    storageClassName: standard
    resources:
    requests:
    storage: 5Gi

在这个示例中,storageClassName 指定了使用的存储类,而 resources 字段指定了 PVC 请求的存储容量。

  • 动态创建 PV:当 PVC 被创建时,存储类会使用定义的插件动态创建 PV,并将其与 PVC 绑定。

  • 挂载 PV 到 Pod:最后,创建 Pod,并通过 PVC 引用 PV,将其挂载到 Pod 中。以下是一个 Pod 的示例:

    apiVersion: v1
    kind: Pod
    metadata:
    name: my-pod
    spec:
    containers:
    - name: my-container
    image: nginx
    volumeMounts:
    - mountPath: "/mnt/data"
    name: my-volume
    volumes:
    - name: my-volume
    persistentVolumeClaim:
    claimName: my-pvc

在这个示例中,persistentVolumeClaim 字段引用了前面创建的 PVC。

这样,通过存储类和 PVC 的组合,Kubernetes 可以实现 PV 的动态创建和管理,使存储资源更加灵活和自动化。

查看pv的定义方式

kubectl explain pv    #查看pv的定义方式

kubectl explain 命令可以用来查看 Kubernetes 资源的定义方式和字段说明。对于 PV(PersistentVolume),以下是其定义方式和字段说明:

  • apiVersion:表示 Kubernetes API 的版本。对于 PV,它的 API 版本通常为 v1

  • kind:表示 Kubernetes 资源的类型。对于 PV,它的类型是 PersistentVolume

  • metadata:包含有关 PV 的元数据信息,如名称、标签等。由于 PV 是集群级别的资源,因此 PV 的 metadata 中不需要配置命名空间(namespace)。

  • spec:PV 的规格(specification),定义了 PV 的属性和配置。PV 的规格包括以下属性:

  • capacity:定义了 PV 的存储容量。

  • volumeMode:指定了 PV 的工作模式,可以是 FilesystemBlock

  • accessModes:定义了 PV 的访问模式,包括 ReadWriteOnceReadOnlyManyReadWriteMany

  • persistentVolumeReclaimPolicy:定义了当 PV 释放时的回收策略,可以是 RetainRecycleDelete

  • storageClassName:指定了 PV 所属的存储类。

  • mountOptions:包含了挂载 PV 时使用的挂载选项。

  • nfsiscsiawsElasticBlockStore 等:描述了不同类型 PV 的具体配置。

查看pv定义的规格

kubectl explain pv.spec

kubectl explain pv.spec 命令用于查看 PV 规格中的 spec 字段的详细说明。以下是 pv.spec 的说明:

  • spec.nfs:用于定义 NFS 类型的存储。

  • path:指定了挂载卷的路径。

  • server:指定了 NFS 服务器的名称。

  • spec.accessModes:定义了 PV 的访问模式,可以有以下三种模式,以列表的方式存在,允许定义多个访问模式:

  • ReadWriteOnce(RWO):存储可读可写,但只支持被单个 Pod 挂载。

  • ReadOnlyMany(ROX):存储可以以只读的方式被多个 Pod 挂载。

  • ReadWriteMany(RWX):存储可以以读写的方式被多个 Pod 共享。

这些规格说明了 PV 中存储类型的配置以及访问模式的定义方式。PV 的 spec 字段允许定义不同类型的存储,并配置适当的访问模式以满足应用程序对持久化存储的需求。

  • nfs 支持全部三种;iSCSI 不支持 ReadWriteMany(iSCSI 就是在 IP 网络上运行 SCSI 协议的一种网络存储技术);HostPath 不支持 ReadOnlyMany 和 ReadWriteMany。

  • capacity:用于定义 PV 的存储容量。在配置中,storage 字段用于指定存储的大小,以 GiB 或者其他存储单位为单位。

  • storageClassName:用于指定 PV 所属的存储类。存储类是用来定义存储资源的配置和策略,以便于 PV 和 PVC 的匹配。通过指定相同的存储类,可以确保 PVC 和 PV 之间的匹配。

  • persistentVolumeReclaimPolicy:定义了 PV 释放后的回收策略,有以下几种选项:

  • Retain(保留):当 PV 被释放时,将 PV 标记为 "released" 状态,数据依然保存在 PV 上,但 PV 不可用,需要手动处理数据并删除 PV。

  • Delete(删除):当 PV 被释放时,将删除与 PV 相关联的后端存储资源。需要注意的是,只有某些后端存储资源(如 AWS EBS、GCE PD、Azure Disk 和 Cinder)支持此选项。

  • Recycle(回收):当 PV 被释放时,将删除 PV 上的数据,相当于执行 rm -rf /thevolume/*。需要注意的是,只有某些后端存储资源(如 NFS 和 HostPath)支持此选项。

查看PVC的定义方式

kubectl explain pvc   #查看PVC的定义方式

kubectl explain pvc 命令用于查看 PVC(PersistentVolumeClaim)的定义方式和字段说明。以下是 PVC 的基本字段说明:

  • apiVersion:指示 Kubernetes API 的版本。对于 PVC,通常是 v1

  • kind:指明资源类型,在这个情况下是 PersistentVolumeClaim

  • metadata:包含关于 PVC 的元数据信息,如名称、命名空间、标签等。

  • spec:定义了 PVC 的规格,包括请求的存储容量、访问模式等。PVC 的 spec 字段主要包含以下属性:

  • accessModes:一个 PVC 请求的访问模式列表,包括 ReadWriteOnceReadOnlyManyReadWriteMany

  • resources:请求的资源,通常是存储资源。在 resources 下的 requests 字段中可以指定所需的存储容量。

  • storageClassName:指定 PVC 要使用的 StorageClass 的名称。StorageClass 用于动态配备 PV。

  • volumeName:如果要将 PVC 绑定到特定的 PV,则可以指定 PV 的名称。通常,这个字段由 Kubernetes 系统自动填充,当动态配备或者预先存在的 PV 与 PVC 匹配时。

  • selector:允许指定一个标签选择器来进一步约束应该绑定到 PVC 的 PV。这可以用于选择一组特定的 PV。

PVC 是 Kubernetes 中的一种资源,它允许用户声明他们所需要的存储资源。PVC 与 PV 之间的绑定可以是动态的,也可以是静态的,取决于是否使用 StorageClass 以及如何配置 PVC 和 PV。- volumeMode:指定所请求的卷是应被格式化为文件系统还是作为原始块设备提供。可能的值包括 FilesystemBlock

  • dataSource:指定从现有的 PVC 或快照创建新 PVC 的数据源。这允许用户克隆现有的 PVC 或从快照创建 PVC,实现数据的复制和恢复。

PVC 的定义方式为用户与存储资源之间提供了一个抽象层,使得用户无需关心底层存储的具体实现细节,只需根据需求声明所需的存储容量和访问模式。Kubernetes 系统将负责满足这些请求,无论是通过动态地创建新的 PV 来配合 PVC,还是通过匹配现有的、未被其他 PVC 使用的 PV。

PV和PVC中的spec关键字段要匹配,比如存储(storage)大小、访问模式(accessModes)、存储类名称(storageClassName)

查看pvc定义规格

kubectl explain pvc.spec
  • spec.accessModes:定义了 PVC 请求的访问模式,必须是 PV 的访问模式的子集。可以指定一个或多个访问模式,以满足应用程序的需求。支持的访问模式包括:

  • ReadWriteOnce(RWO):存储可读可写,但只支持被单个 Pod 挂载。

  • ReadOnlyMany(ROX):存储可以以只读的方式被多个 Pod 挂载。

  • ReadWriteMany(RWX):存储可以以读写的方式被多个 Pod 共享。

  • spec.resources.requests.storage:用于定义 PVC 请求的存储容量。在 requests 字段下的 storage 字段中指定所需的存储容量,以 GiB 或其他存储单位为单位。Kubernetes 将尝试为 PVC 分配至少指定大小的 PV。

  • spec.storageClassName:指定 PVC 要使用的存储类的名称。存储类定义了 PV 的属性和配置,以便与 PVC 匹配。当 PVC 没有明确指定存储类时,将使用默认的存储类。指定存储类的好处在于可以根据应用程序的需求定义不同的存储策略,例如性能、可靠性和成本等方面。

这些规格允许用户定义 PVC 所需的存储容量、访问模式和存储类,从而满足应用程序对持久化存储的需求。PV 将根据这些规格来为 PVC 提供相应的存储资源,并与 PVC 进行绑定以供应用程序使用

NFS使用PV和PVC(静态)

官方文档:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-persistentvolume

NFS主机上配置nfs存储

mkdir -p /data/volumes/v{1..5}

vim /etc/exports
/data/volumes/v1 192.168.41.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.41.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.41.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.41.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.41.0/24(rw,no_root_squash)

exportfs -arv

showmount -e

这段解析是关于配置NFS(Network File System)存储的过程,其中使用了PV(PersistentVolume)和PVC(PersistentVolumeClaim)这两个 Kubernetes 中的概念。

  • 创建了五个目录 v1v5 作为存储目录。

  • /etc/exports 文件中配置了这些目录的导出选项,允许 192.168.41.0/24 网段的主机以读写方式挂载这些目录,并且禁止了 root 用户权限限制。

  • 通过 exportfs -arv 命令重新加载并应用了导出的设置。

  • 使用 showmount -e 命令显示了可导出的目录列表。

这个配置使得其他主机可以通过 NFS 挂载这些目录并进行读写操作。

master上定义pv

定义5个PV,并且定义挂载的路径以及访问模式,还有PV划分的大小

vim pv-demo.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    name: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 1Gi

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: stor01
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 2Gi

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
  labels:
    name: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 4Gi

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 5Gi

这是一个 Kubernetes 中用于定义 PersistentVolume(持久卷)的 YAML 文件示例。每个 PersistentVolume 配置都描述了一个持久存储卷,这些卷可以在 Kubernetes 集群中供应用程序使用。

逐段解析这个文件:

  • apiVersion : 指定了 Kubernetes API 的版本,这里使用的是 v1 版本。

  • kind : 指定了 Kubernetes 资源的类型,这里是 PersistentVolume,表示持久卷。

  • metadata: 元数据部分,包含了持久卷的名称和标签信息。

  • spec: 规范部分,定义了持久卷的详细配置。

  • nfs: 指定了该持久卷使用 NFS 存储,包括 NFS 服务器地址和路径。

  • accessModes : 指定了持久卷的访问模式,可以是 ReadWriteOnce(单个节点读写)、ReadOnlyMany(多个节点只读)或 ReadWriteMany(多个节点读写)。

  • capacity: 指定了持久卷的容量大小。

这个文件中包含了五个不同的持久卷配置,每个持久卷都有唯一的名称和配置。这些持久卷可以被 Kubernetes 应用程序通过 PersistentVolumeClaim(持久卷声明)来请求和使用。

kubectl apply -f pv-demo.yaml
kubectl get pv

执行 kubectl apply -f pv-demo.yaml 命令将会根据 pv-demo.yaml 文件中的配置创建 PersistentVolume(持久卷)。然后,kubectl get pv 命令将会列出所有已经存在的 PersistentVolume,以便确认这些持久卷是否已经成功创建并且处于可用状态。

master上定义pvc

这里定义了pvc的访问模式为多路读写,该访问模式必须在前面pv定义的访问模式之中。定义PVC申请的大小为2Gi,此时PVC会自动去匹配多路读写且大小为2Gi的PV,匹配成功获取PVC的状态即为Bound

vim pod-vol-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
  namespace: default
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 2Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-pvc
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
    - name: html
      persistentVolumeClaim:
        claimName: mypvc

这个 YAML 文件定义了两个 Kubernetes 资源:一个 PersistentVolumeClaim (PVC) 和一个 Pod,它们都配置在默认的命名空间中。

PersistentVolumeClaim (PVC)

  • apiVersion : 指定了 Kubernetes API 的版本,这里是 v1

  • kind : 资源类型,这里是 PersistentVolumeClaim,表示一个存储卷声明。

  • metadata : 包含资源的元数据,这里定义了 PVC 的名称为 mypvc

  • spec: 规格定义部分。

  • accessModes : 定义了 PVC 的访问模式,这里是 ReadWriteMany,意味着存储卷可以被多个节点同时以读写方式挂载。

  • resources: 定义了资源请求。

    • requests : 指定了存储资源的请求量,这里是 2Gi

Pod

  • apiVersion : 指定 Kubernetes API 的版本,这里也是 v1

  • kind : 资源类型,这里是 Pod

  • metadata : 包含资源的元数据,这里定义了 Pod 的名称为 pod-vol-pvc

  • spec: 规格定义部分,描述了 Pod 的具体配置。

  • containers: 容器数组,每个对象定义了一个容器的配置。

    • name : 容器的名称,这里是 myapp

    • image : 容器的镜像,这里使用的是 ikubernetes/myapp:v1

    • volumeMounts: 定义了容器内的挂载点。

    • name : 卷的引用名称,这里是 html

    • mountPath : 容器内的挂载路径,这里是 /usr/share/nginx/html

  • volumes: 定义了 Pod 级别的存储卷。

    • name : 卷的名称,与 volumeMounts 中的引用名称相匹配,这里是 html

    • persistentVolumeClaim: 指定了卷的来源是一个 PVC。

    • claimName : 引用 PVC 的名称,这里是 mypvc

这个配置允许 Pod pod-vol-pvc 通过 PVC mypvc 挂载一个持久卷到容器的 /usr/share/nginx/html 路径。

kubectl apply -f pod-vol-pvc.yaml
kubectl get pv
kubectl get pvc

测试访问

在nfs存储服务器上创建index.html,并写入数据,通过访问Pod进行查看,可以获取到相应的页面。

cd /data/volumes/v3/
echo "welcome to use pv3" > index.html

master上测试

kubectl get pods -o wide
curl 

搭建StorageClass + NFS(NFS 的动态 PV 创建)

搭建 StorageClass + NFS 实现 NFS 的动态 PV 创建需要使用外部存储卷插件,称为 Provisioner(存储分配器)。在此过程中,NFS 使用的是 nfs-client,作为外部 PV。

Provisioner:用于指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/aws-ebs)和外部插件(如 exte卷插件会使用已经配置好的 NFS 服务器自动创建 rnal-storage 提供的 ceph.com/cephfs)。

  • 内置插件:kubernetes.io/aws-ebs 是用于 AWS Elastic Block Store(EBS)的内置插件。它能够动态地创建和管理 AWS EBS 存储。

  • 外部插件 : ceph.com/cephfs,这是 Ceph 文件系统的外部插件。此外,nfs-client 也是一个外部插件,用于与 NFS 服务器集成,实现动态创建 PV。

在使用外部插件时,通常需要确保已经正确配置并运行相应的存储系统,以便 Kubernetes 能够利用它们进行动态 PV 的创建和管理。

步骤如下:

  • 配置 NFS 服务器,确保 NFS 服务已正确配置和运行。

  • 创建 StorageClass,并将 Provisioner 设置为 nfs-client,同时指定 NFS 服务器的地址和共享路径。

  • 创建 PVC,使用上述创建的 StorageClass。

  • 检查 PV 是否已自动创建,系统会自动创建 PV 并与 PVC 绑定,实现动态的 NFS PV 创建。

参考链接:Kubernetes 存储类概念

stor01节点上安装nfs,并配置nfs服务

mkdir /opt/k8s
chmod 777 /opt/k8s/

vim /etc/exports
/opt/k8s 192.168.41.0/24(rw,no_root_squash,sync)

systemctl restart nfs
  • 创建一个名为/opt/k8s的目录:mkdir /opt/k8s

  • /opt/k8s目录的权限设置为777:chmod 777 /opt/k8s/

  • 使用vim编辑/etc/exports文件,添加如下行,允许192.168.41.0/24网段的主机以读写模式挂载/opt/k8s目录,并且不进行root权限转换(norootsquash),并同步写入(sync):

  • 重启NFS服务:systemctl restart nfs

master创建 Service Account,设置 nfs-client 对 PV,PVC,StorageClass 等的规则

在Kubernetes(k8s)集群中,创建Service Account是为了管理NFS Provisioner在集群中运行时的权限。NFS Provisioner是用于动态创建Persistent Volumes(PV)和Persistent Volume Claims(PVC)的工具,通常与StorageClass一起使用。

设置nfs-client对PV、PVC和StorageClass的规则是确保NFS Provisioner在使用NFS共享存储时遵循一定的访问和权限规则。这可以包括定义NFS服务器地址、共享路径、访问权限等配置,以便Kubernetes中的应用程序能够正确地使用NFS存储。通过Service Account的设置,可以为NFS Provisioner分配适当的权限,确保其能够成功管理和提供NFS存储服务。

vim nfs-client-rbac.yaml

# 创建 Service Account 账户,用来管理 NFS Provisioner 在 k8s 集群中运行的权限
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner  # Service Account 的名称

# 创建集群角色
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:
- kind: ServiceAccount
  name: nfs-client-provisioner  # 绑定的 Service Account 的名称
  namespace: default  # 所在的命名空间
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-clusterrole  # 所绑定的集群角色名称
  apiGroup: rbac.authorization.k8s.io

这段YAML文件定义了在Kubernetes中创建一个Service Account以及相关的ClusterRole和ClusterRoleBinding来管理NFS Provisioner的权限。

  • ServiceAccount部分定义了一个名为nfs-client-provisioner的Service Account,用于代表NFS Provisioner在集群中运行时的身份。

  • ClusterRole部分定义了一个名为nfs-client-provisioner-clusterrole的ClusterRole,包含了对于Persistent Volumes(PV)、Persistent Volume Claims(PVC)、StorageClasses等资源的访问权限规则。这些规则包括获取、列出、监视、创建和删除PV、PVC,以及获取、列出、监视StorageClasses等操作。

  • ClusterRoleBinding部分定义了一个名为nfs-client-provisioner-clusterrolebinding的ClusterRoleBinding,将前面定义的ClusterRole绑定到先前定义的Service Account上,以确保该Service Account拥有相应的权限。

通过这些定义,可以确保NFS Provisioner在Kubernetes集群中具有适当的权限,以管理PV、PVC和StorageClasses等资源。

kubectl apply -f nfs-client-rbac.yaml

使用 Deployment 来创建 NFS Provisioner

使用Kubernetes的Deployment来部署NFS Provisioner(即nfs-client)。NFS Provisioner在Kubernetes中的作用是两个方面:一是在NFS共享目录下创建挂载点(volume),二是将Persistent Volumes(PV)与NFS的挂载点建立关联,使得Kubernetes中的应用程序能够使用NFS存储。

通过Deployment创建NFS Provisioner的实例,可以确保其在集群中始终处于运行状态,并且可以根据需要进行水平扩展。这样,Kubernetes集群中的应用程序可以方便地访问和使用NFS存储,而无需手动管理PV和NFS之间的关联关系。

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

# 修改kube-apiserver.yaml文件,设置kube-apiserver的参数
vim /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=RemoveSelfLink=false  # 添加这一行,开启RemoveSelfLink特性
    - --advertise-address=192.168.41.31      # 设置kube-apiserver的广告地址
......

# 应用kube-apiserver.yaml文件的更改
kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml

# 删除kube-apiserver的Pod以便更改生效
kubectl delete pods kube-apiserver -n kube-system 

# 检查kube-apiserver的Pod是否重新启动
kubectl get pods -n kube-system | grep apiserver

这段脚本是修改 kube-apiserver.yaml 文件的步骤,其中设置了 kube-apiserver 的参数,添加了 --feature-gates=RemoveSelfLink=false 开启了 RemoveSelfLink 特性,以及设置了 --advertise-address=192.168.41.31 作为 kube-apiserver 的广告地址。然后通过 kubectl apply 应用修改,通过 kubectl delete pods 删除 kube-apiserver 的 Pod 以便更改生效,最后通过 kubectl get pods 检查 kube-apiserver 的 Pod 是否重新启动。

创建 NFS Provisioner

# 编辑nfs-client-provisioner.yaml文件,定义NFS Provisioner的Deployment
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   # 指定ServiceAccount
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest  # 使用的NFS Provisioner镜像
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes   # 挂载路径
          env:
            - name: PROVISIONER_NAME
              value: nfs-storage   # Provisioner的名称
            - name: NFS_SERVER
              value: stor01   # NFS服务器地址
            - name: NFS_PATH
              value: /opt/k8s   # NFS共享路径
      volumes:
        - name: nfs-client-root
          nfs:
            server: stor01   # NFS服务器地址
            path: /opt/k8s   # NFS共享路径

这段 YAML 文件定义了 NFS Provisioner 的 Deployment。其中包括了指定的 Replicas 数量、选择器、部署策略等。在 Pod 模板中,指定了使用的 ServiceAccount,镜像来源,以及挂载的路径等信息。此外,还定义了 NFS 服务器地址和共享路径。

kubectl apply -f nfs-client-provisioner.yaml 
kubectl get pod

创建 StorageClass

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

创建 StorageClass 是为了定义存储的类型以及如何提供存储服务。当用户创建 PVC(PersistentVolumeClaim)时,StorageClass 可以指导 Kubernetes 如何动态地提供 PV(PersistentVolume)。关联 PV 与 PVC 是将 PVC 绑定到满足其需求的 PV 上,从而实现 PVC 对存储资源的预定工作。这通常是通过 StorageClass 中定义的配置信息来实现的,例如指定的 Provisioner、参数等。因此,当 PVC 被创建时,Kubernetes 将使用 StorageClass 中定义的规则来选择并创建 PV,并将它们关联起来,以满足 PVC 的要求。

vim nfs-client-storageclass.yaml

# 定义一个名为 nfs-client-storageclass 的 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-storageclass  # StorageClass 的名称
provisioner: nfs-storage         # 使用的 Provisioner 名称,需与配置文件中的 PROVISIONER_NAME 一致
parameters:
  archiveOnDelete: "false"       # 在删除 PVC 时是否对数据进行存档,false 表示直接删除数据

这个 YAML 文件定义了一个名为 nfs-client-storageclass 的 StorageClass。它指定了 NFS Provisioner 的名称为 nfs-storage,这与 Provisioner 配置文件中的环境变量 PROVISIONER_NAME 要保持一致。另外,设置了参数 archiveOnDelete: "false",表示在删除 PersistentVolumeClaim (PVC) 时不会对数据进行存档,即直接删除数据。

kubectl apply -f nfs-client-storageclass.yaml
kubectl get storageclass
  • kubectl apply -f nfs-client-storageclass.yaml: 通过 Kubernetes 的命令行工具 kubectl 应用(或创建)nfs-client-storageclass.yaml 文件中定义的资源,这里是一个 StorageClass。

  • kubectl get storageclass: 通过 kubectl 获取当前 Kubernetes 集群中所有的 StorageClass 列表。这可以用于确认上一步的 StorageClass 是否成功创建。

创建 PVC

vim test-pvc-pod.yaml

# 定义持久卷声明(PersistentVolumeClaim),用于请求持久卷
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-nfs-pvc  # 持久卷声明的名称
spec:
  accessModes:
    - ReadWriteMany  # 访问模式设置为读写多个节点
  storageClassName: nfs-client-storageclass  # 关联的存储类对象
  resources:
    requests:
      storage: 1Gi  # 请求的存储容量为1Gi

---
# 定义Pod,用于使用持久卷
apiVersion: v1
kind: Pod
metadata:
  name: test-storageclass-pod  # Pod 的名称
spec:
  containers:
  - name: busybox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command:
    - "/bin/sh"
    - "-c"
    args:
    - "sleep 3600"  # 命令参数,让容器保持运行状态
    volumeMounts:
    - name: nfs-pvc  # 指定挂载的持久卷名称
      mountPath: /mnt  # 挂载路径
  restartPolicy: Never  # Pod 的重启策略
  volumes:
  - name: nfs-pvc  # 定义一个名为nfs-pvc的卷
    persistentVolumeClaim:
      claimName: test-nfs-pvc  # 引用之前定义的持久卷声明的名称
  • 这个 YAML 文件定义了一个 Kubernetes Pod 和一个 PersistentVolumeClaim(持久卷声明)。Pod 使用了名为 test-nfs-pvc 的持久卷声明,请求了 1Gi 的存储空间,并使用了 nfs-client-storageclass 存储类。Pod 中的容器使用了 BusyBox 镜像,并将持久卷挂载到 /mnt 路径下。 Pod 的重启策略设置为 Never,这意味着当 Pod 退出时,不会自动重启。

    kubectl apply -f test-pvc-pod.yaml
    kubectl get pods
    kubectl get pvc

  • PVC 通过 StorageClass 自动申请到空间

查看 NFS 服务器上是否生成对应的目录

自动创建的 PV 会以 {namespace}-{pvcName}-${pvName} 的目录格式放到 NFS 服务器上

ls /opt/k8s/

master进入 Pod 在挂载目录 /mnt 下写一个文件,然后查看 NFS 服务器上是否存在该文件

kubectl exec -it test-storageclass-pod sh
#回车
/ # cd /mnt/
#回车
/mnt # echo 'this is test file' > test.txt
#exit 退出

stor01上发现 NFS 服务器上存在,说明验证成功

cat /opt/k8s/default-test-nfs-pvc-pvc-5550e3f1-3221-42d0-adfd-97bd46eec2f5/test.txt
相关推荐
iangyu34 分钟前
docker常用命令
运维·docker·容器
winkee1 小时前
在 git commit 中使用 gpg key 进行签名
架构·前端框架·代码规范
小小不董1 小时前
图文深入理解Oracle DB Scheduler
linux·运维·服务器·数据库·oracle
Dylanioucn1 小时前
【分布式微服务云原生】掌握 Redis Cluster架构解析、动态扩展原理以及哈希槽分片算法
算法·云原生·架构
南瓜小米粥、2 小时前
通过fdisk初始化Linux数据盘
linux·运维·服务器
黄俊懿3 小时前
【深入理解SpringCloud微服务】手写实现各种限流算法——固定时间窗、滑动时间窗、令牌桶算法、漏桶算法
java·后端·算法·spring cloud·微服务·架构
飞酱不会电脑4 小时前
云计算第四阶段 CLOUD2周目 01-03
云原生·容器·kubernetes
LYK_HAHA4 小时前
centos常用知识和命令
linux·运维·centos
PythonFun4 小时前
自建RustDesk服务器:详细步骤与操作指南
运维·服务器
可涵不会debug4 小时前
【Linux】信号知识三把斧——信号的产生、保存和处理
linux·运维·信号