Kubernetes 中的Volume

目录

前言

一 emptyDir存储卷

1.emptyDir存储卷概述

2.示例

二 hostPath存储卷

1.hostPath存储卷概述

2.示例

三 nfs共享存储卷

1.nfs共享存储卷概述

2.示例 

四 PVC 和 PV

1.什么是PV和PVC

2.PVC使用的逻辑

3.StorageClasss

4.PV和PVC相互作用

5.PV的生命周期中,一般有几种状态?

6.一个PV从创建到销毁的过程

7.PV、PVC的定义和回收策略

7.1 PV的定义

7.2 PVC的定义

7.3 回收策略

8.示例

8.1 NFS使用PV和PVC  

故障1:"clnt_create: RPC: Program not registered"表示客户端无法注册 RPC 程序,因此无法执行 showmount 命令。 

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


前言

容器磁盘上的文件生命周期短暂是在容器化环境中常见的情况。当容器崩溃时,kubelet 会重新启动它,但是容器中的文件将丢失,容器会以干净的状态(即镜像最初的状态)重新启动。这对于需要持久化数据或者需要多个容器之间共享文件的应用来说确实会造成问题。

Kubernetes 中的Volume抽象解决了这些问题,通过Volume可以将持久化存储挂载到Pod中的一个或多个容器,使得它们可以共享文件并且在容器重新启动时不会丢失数据。而通过Pause容器来实现共享Volume的方式也很巧妙,其他容器通过与Pause容器共享Volume来实现文件共享的功能。

使用Volume可以实现数据持久化和共享,为容器化应用提供了更多灵活性和可靠性,特别是对于运行重要应用的场景。合理利用Volume可以确保应用数据的安全性和可靠性,同时也满足了多个容器共享文件的需求。这些方面都使得Kubernetes 中的Volume抽象成为容器编排和管理中非常重要的一部分。


一 emptyDir存储卷

1.emptyDir存储卷概述

emptyDir 卷是 Kubernetes 中一种临时性存储卷,它会在 Pod 被分配给节点时创建,并且只要该 Pod 在该节点上运行,该卷就会一直存在。emptyDir 卷最初是空的,可以被 Pod 中的容器读取和写入。这种卷可以被挂载到每个容器中的相同或不同路径上,使得容器之间可以共享数据。

注意:当从节点中删除 Pod 时,emptyDir 中的数据将被永久删除。因为 emptyDir 是临时性存储,其生命周期与 Pod 的生命周期绑定,一旦 Pod 被删除,emptyDir 中的数据也会被清除。因此,不适合将重要或持久数据存储在 emptyDir 中,适合用于临时性数据的存储或者容器之间共享一些临时性文件。

2.示例

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: {}
	
	
kubectl apply -f pod-emptydir.yaml

kubectl get pods -o wide

#在上面定义了2个容器,其中一个容器是输入日期到index.html中,然后验证访问nginx的html是否可以获取日期。以验证两个容器之间挂载的emptyDir实现共享。

 curl 10.244.2.5


二 hostPath存储卷

1.hostPath存储卷概述

hostPath 存储卷是 Kubernetes 中一种用于将宿主机上的文件或目录挂载到 Pod 内的存储卷类型。通过 hostPath 存储卷,可以将宿主机上的文件系统路径挂载到 Pod 中的一个或多个容器中,实现容器与宿主机文件系统之间的数据共享。

hostPath 存储卷可以将宿主机上的文件或目录挂载到 Pod 中,实现容器与宿主机文件系统之间的数据共享。因为 hostPath 卷是直接使用节点的文件系统路径来进行挂载的,所以它的生命周期与节点的生命周期绑定,当节点失效或重建时,hostPath 挂载的数据也会丢失。

尽管 hostPath 存储卷可以实现持久化存储,但是并不适合用于持久化数据的场景,因为节点的故障可能会导致数据的丢失。对于需要持久化存储的应用,建议使用 Kubernetes 中的其他持久化存储方案,例如本地存储卷 Local Persistent Volume、动态存储卷 Dynamic Provisioning 等,这些方案可以通过备份和恢复策略来保证数据的可靠性。

2.示例

#在 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

#创建 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

kubectl apply -f pod-hostpath.yaml

#访问测试

kubectl get pods -o wide

curl 10.244.1.5

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

kubectl delete -f pod-hostpath.yaml  
kubectl apply -f pod-hostpath.yaml 

kubectl get pods -o wide

curl  10.244.1.6 


三 nfs共享存储卷

1.nfs共享存储卷概述

NFS 共享存储卷是 Kubernetes 中一种用于将网络文件系统(NFS)挂载到 Pod 内的存储卷类型。通过 NFS 共享存储卷,可以将远程服务器上的文件系统挂载到 Pod 中的一个或多个容器中,实现容器与远程服务器之间的数据共享。

使用 NFS 共享存储卷时需要注意以下几点:

  • 配置 NFS 服务器:需要在 NFS 服务器上安装和配置 NFS 服务,并创建共享目录并设置相应的权限,以便 Kubernetes 可以访问共享目录。
  • 安全性:由于 NFS 共享存储卷需要访问远程服务器上的文件系统,因此需要确保 NFS 服务器和网络的安全性,以避免数据泄露和攻击。
  • 可靠性:使用 NFS 共享存储卷需要确保远程服务器可靠、稳定,并且具有足够的带宽和容量来支持容器内的访问和使用。

2.示例 

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

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

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

systemctl start rpcbind
systemctl start nfs

showmount -e

#master节点操作

vim pod-nfs-vol.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-nfs
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
    - name: html
      nfs:
        path: /data/volumes
        server: stor01


kubectl apply -f pod-nfs-vol.yaml

kubectl get pods -o wide

#在nfs服务器上创建index.html

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

#master节点操作

curl 10.244.2.2

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

kubectl apply -f pod-nfs-vol.yaml


nas gfs  ceph san

四 PVC 和 PV

1.什么是PV和PVC

PV(PersistentVolume)和 PVC(PersistentVolumeClaim)是 Kubernetes 中用于持久存储的重要概念。

  • PV(PersistentVolume):PV代表集群中的持久存储卷,可以是实际的存储资源,如网络存储、云存储,也可以是集群中的本地存储,由集群管理员手动创建。PV是全局可见的,独立于Pod存在。

  • PVC(PersistentVolumeClaim):PVC是Pod对PV的申请,用于请求访问PV提供的存储资源,使开发人员可以在不关心实际存储细节的情况下获取所需的持久存储资源。PVC是对PV存储的请求,描述希望使用什么样的存储或满足什么条件。

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

通常,PV由运维工程师定义,而PVC由开发人员定义。总结来说,PV用于描述或定义一个存储卷,而PVC用于描述希望使用或满足什么条件的PV存储,并通过声明PVC来请求持久存储资源。

2.PVC使用的逻辑

  • 开发人员首先需要在Pod的配置文件中定义一个存储卷,并指定该存储卷的类型为PVC(PersistentVolumeClaim),同时设置所需的存储容量。

  • 管理员会事先创建PV(PersistentVolume)资源,定义实际的存储资源,例如网络存储、云存储或本地存储,并为其分配一定的存储容量。

  • 在创建PVC时,开发人员需要指定与之关联的PV,可以通过PV的名称或者标签选择器来匹配。

  • 当Pod被调度并启动时,Kubernetes会自动将PVC与对应的PV进行绑定,将PV的存储资源分配给PVC。

  • Pod中的容器可以通过挂载PVC来访问PV提供的持久化存储资源,从而实现数据的持久化和共享。

总结来说,PVC的使用逻辑是在Pod中定义一个存储卷类型为PVC,并指定所需的存储容量。PVC会与预先创建的PV建立关联,并将PV的存储资源分配给PVC。然后,Pod中的容器可以通过挂载PVC来访问PV提供的持久化存储资源。这种方式使得开发人员可以方便地使用存储资源,而无需关心底层的存储类型和实现细节。

3.StorageClasss

当需要在Kubernetes集群中动态创建和管理大量的持久化卷(Persistent Volume)时,手动为每个持久化卷创建一个持久化卷对象(Persistent Volume Object,PV)将会非常繁琐且易错。为了简化这个过程并降低维护成本,Kubernetes引入了StorageClass。

StorageClass是一个用于定义持久化卷的模板的对象。通过创建StorageClass,管理员可以指定持久化卷的属性,如存储类型、容量大小等,并选择所需的存储插件,如Ceph、AWS EBS等。这样,开发人员在创建持久化卷声明(Persistent Volume Claim,PVC)时,只需指定使用的StorageClass,而不需要关心具体的持久化卷配置。

当创建PVC并指定对应的StorageClass后,Kubernetes就会自动根据StorageClass的定义,调用相应的存储插件创建符合要求的持久化卷,并将其绑定到相应的PVC上。这种自动创建和绑定的机制极大地减轻了运维人员的负担,特别是在面对大量PVC请求时,无需手动创建和管理PV,降低了维护成本。

通过StorageClass,Kubernetes实现了动态供应和管理持久化卷的能力,极大地简化了存储资源的管理和分配。同时,StorageClass也提供了灵活性,允许管理员根据需求定义多个不同的StorageClass,以满足不同类型和要求的应用程序的存储需求。

综上所述,StorageClass是Kubernetes中用于自动创建和管理PV的模板机制,它简化了PV的创建和绑定过程,降低了维护成本,并提供了灵活性和可扩展性。

4.PV和PVC相互作用

PV和PVC之间的相互作用遵循配置、绑定、使用、释放和回收的生命周期。具体来说:

  • Provisioning(配置):PV可以通过静态方式直接创建,也可以使用StorageClass动态创建。

  • Binding(绑定):PV被分配给PVC。

  • Using(使用):Pod通过PVC使用该Volume,并可以通过准入控制StorageProtection阻止删除正在使用的PVC。

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

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

5.PV的生命周期中,一般有几种状态?

  • Available(可用):PV处于可用状态,还未被任何PVC绑定。

  • Bound(已绑定):PV已经绑定到PVC。

  • Released(已释放):PVC被删除,但是资源尚未被集群回收。

  • Failed(失败):表示该PV的自动回收失败。

6.一个PV从创建到销毁的过程

  • 创建PV资源后,其状态会变为Available,等待被PVC绑定。

  • PV资源被PVC绑定后,其状态会变为Bound,并且可以被定义了相应PVC的Pod使用。

  • Pod使用PV资源完成后,PV的状态会变为Released。

  • 根据定义的回收策略,PV资源会进行相应的资源回收工作:

    • Retain策略:Kubernetes集群不会自动删除PV资源,需要手动处理PV里的数据,处理完后再手动删除PV资源。

    • Delete策略:Kubernetes会自动删除该PV及其中的数据,释放存储资源。

    • Recycle策略:Kubernetes会将PV中的数据删除,然后将PV的状态设为Available,可以被新的PVC绑定使用。

7.PV、PVC的定义和回收策略

7.1 PV的定义

#查看PV的定义方式

kubectl explain pv

FIELDS:
	apiVersion: v1
	kind: PersistentVolume
	metadata:    #由于 PV 是集群级别的资源,即 PV 可以跨 namespace 使用,所以 PV 的 metadata 中不用配置namespace
	  name: 
	spec

#查看PV定义的规格

kubectl explain pv.spec

spce:
  nfs:(定义存储类型)
    path:(定义挂载卷路径)
    server:(定义服(定义访问模型,务器名称)
  accessModes:(定义访问模式,可以是 ReadWriteOnce、ReadOnlyMany、ReadWriteMany 中的一个或多个)
  capacity:(定义存储能力,一般用于设置存储空间)
    storage: 2Gi (指定大小)
  storageClassName: (自定义存储类名称,此配置用于绑定具有相同类别的PVC和PV)
  persistentVolumeReclaimPolicy: Retain 

accessModes 是用于定义存储卷的访问模式的选项。在 Kubernetes 中,有以下三种访问模式:

  • ReadWriteOnce (RWO): 存储可以被单个 Pod 以读写方式挂载。这意味着只能将存储卷挂载到一个 Pod 上,并且该 Pod 可以读取和写入存储卷的数据。其他 Pod 无法挂载或访问该存储卷。

  • ReadOnlyMany (ROX): 存储可以以只读的方式被多个 Pod 挂载。这意味着多个 Pod 可以共享访问该存储卷,但只能以只读方式进行访问。这对于需要在多个 Pod 之间共享只读数据的场景非常有用。

  • ReadWriteMany (RWX): 存储可以以读写的方式被多个 Pod 共享。这意味着多个 Pod 可以同时挂载该存储卷,并进行读取和写入操作。这对于需要多个 Pod 之间共享可写数据的场景非常有用。

不同的存储后端对这些访问模式的支持可能有所不同。例如,NFS 支持全部三种访问模式,而 iSCSI 不支持 ReadWriteMany,而 HostPath 不支持 ReadOnlyMany 和 ReadWriteMany。

7.2 PVC的定义

#查看PVC的定义方式

kubectl explain pvc

KIND:     PersistentVolumeClaim
VERSION:  v1
FIELDS:
   apiVersion	<string>
   kind	<string>  
   metadata	<Object>
   spec	<Object>

#查看PV定义的规格

kubectl explain pvc.spec

spec:
  accessModes: (定义访问模式,必须是PV的访问模式的子集)
  resources:
    requests:
      storage: (定义申请资源的大小)
  storageClassName: (定义存储类名称,此配置用于绑定具有相同类别的PVC和PV)

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

7.3 回收策略

回收策略是用于定义在删除 PersistentVolumeClaim (PVC) 后如何处理与之绑定的 PersistentVolume (PV) 的选项。在 Kubernetes 中,有以下三种回收策略:

  • Retain(保留): 当 PVC 被删除后,PV 会被保留,并标记为已释放(released)。这意味着 PV 中保存的数据仍然可用,但 PV 不再与任何 PVC 相关联。管理员需要手动将 PV 与新的 PVC 关联,或者手动清除 PV 中的数据以进行回收。

  • Delete(删除): 当 PVC 被删除时,PV 中的数据也会被删除。如果 PV 是动态创建的,则后端存储资源(如 AWS EBS、GCE PD、Azure Disk 和 Cinder)中的数据也会被自动删除。

  • Recycle(回收): 当 PVC 被删除时,PV 中的数据会被清空,相当于执行了 "rm -rf /thevolume/*" 命令。该回收策略只适用于 NFS 和 HostPath 存储类型。

需要注意的是,对于动态创建的 PV,其回收策略必须由存储类 (StorageClass) 定义。存储类指定了动态 Provisioning 时创建的 PV 的默认参数,包括回收策略、访问模式和存储容量等。如果没有指定回收策略,则使用默认值 Delete。

在选择回收策略时,需要考虑与 PV 相关联的存储类型和后端存储资源的要求。例如,如果使用的是 NFS 存储,则建议使用 Recycle 回收策略,因为 NFS 不支持删除后端存储资源。

8.示例

8.1 NFS使用PV和PVC  

#配置nfs存储

mkdir v{1,2,3,4,5}

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

exportfs -arv

showmount -e
故障1:"clnt_create: RPC: Program not registered"表示客户端无法注册 RPC 程序,因此无法执行 showmount 命令。 

排错思路:①NFS服务未启动;②NFS配置文件配置错误;③防火墙或者网络问题。

解决:使用“systemctl status nfs”发现是NFS服务未启动,启动NFS服务即可。

#定义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
kubectl apply -f pv-demo.yaml

kubectl get pv

#定义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
kubectl apply -f pod-vol-pvc.yaml

kubectl get pv

kubectl get pvc

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

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

kubectl get pods -o wide

 curl  10.244.2.11
welcome to use pv3

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

Kubernetes 本身支持的动态 PV 创建不包括 NFS,所以需要使用外部存储卷插件分配PV。详见:https://kubernetes.io/zh/docs/concepts/storage/storage-classes/

卷插件称为 Provisioner(存储分配器),NFS 使用的是 nfs-client,这个外部PV。
Provisioner:用于指定 Volume 插件的类型,包括内置插件(如 kubernetes.io/aws-ebs)和外部插件(如 exte卷插件会使用已经配置好的 NFS 服务器自动创建 rnal-storage 提供的 ceph.com/cephfs)。
#在stor01节点上安装nfs,并配置nfs服务

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

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

systemctl restart nfs

#创建 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:
- 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

#

使用 Deployment 来创建 NFS Provisioner
NFS Provisione(即 nfs-client),有两个功能:一个是在 NFS 共享目录下创建挂载点(volume),另一个则是将 PV 与 NFS 的挂载点建立关联。

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

vim /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=RemoveSelfLink=false       #添加这一行
    - --advertise-address=192.168.80.20
......

kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml
kubectl delete pods kube-apiserver -n kube-system 
kubectl get pods -n kube-system | grep apiserver

#创建 NFS Provisioner

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: PROVISIONER_NAME
              value: nfs-storage       #配置provisioner的Name,确保该名称与StorageClass资源中的provisioner名称保持一致
            - name: NFS_SERVER
              value: stor01           #配置绑定的nfs服务器
            - name: NFS_PATH
              value: /opt/k8s          #配置绑定的nfs服务器目录
      volumes:              #申明nfs数据卷
        - name: nfs-client-root
          nfs:
            server: stor01
            path: /opt/k8s
	
	
kubectl apply -f nfs-client-provisioner.yaml 

kubectl get pod

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

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 storageclass

#创建 PVC 和 Pod 测试

vim test-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-nfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs-client-PROVISIONER    #关联StorageClass对象
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: test-storageclass-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
  volumes:
  - name: nfs-pvc
    persistentVolumeClaim:
      claimName: test-nfs-pvc      #与PVC名称保持一致
	  
	  
kubectl apply -f test-pvc-pod.yaml

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

kubectl get pvc

#查看 NFS 服务器上是否生成对应的目录,自动创建的 PV 会以 ${namespace}-${pvcName}-${pvName} 的目录格式放到 NFS 服务器上

ls /opt/k8s/
default-test-nfs-pvc-pvc-11670f39-782d-41b8-a842-eabe1859a456

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

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

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

cat /opt/k8s/test.txt

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值