Volume

Volume(存储卷)是Pod中能够被多个容器访问的共享目录。Kubernetes的Volume概念、用途和目的与Docker的Volume比较类似,但两者不能等价。首先,Kubernetes中的Volume被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下;其次,Kubernetes中的Volume与Pod的生命周期相同,但与容器的生命周期不相关,当容器终止或者重启时,Volume中的数据也不会丢失。最后,Kubernetes支持多种类型的Volume,例如GlusterFS、Ceph等先进的分布式文件系统。

emptyDir

emptyDir Volume是在Pod分配到node时创建的,正如卷的名字,它的初始内容为空,并且无需指定宿主机上对应的目录文件,因为这是kubernetes自动分配的一个目录,当Pod从node上移除时,emptyDir中的数据也会被永久删除。

拓扑图:

emptyDir的用途有:

  • 临时空间,例如用于某些应用程序运行时所需的临时目录,且无需永久保留
  • 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
  • 一个容器需要从另一个容器中获取数据库的目录(多容器共享目录)

Volume的使用也比较简单,在大多数情况下,我们先在Pod上声明一个Volume,然后在容器里引用该Volume并挂载(Mount)到容器里的某个目录上。

举例来说,为我们先创建一个pod,里面定义两个容器,一个nginx,一个busybox,然后指定nginx挂载路径/user/share/nginx/html/,指定busybox的挂载路径为/test。

[root@master ~]# cat volume_test.yaml
apiVersion: v1
kind: Service
metadata:
name: service-nginx
namespace: default
spec:
type: NodePort
selector:
app: nginx
ports:
- name: nginx
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mydeploy
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
name: web
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.4
ports:
- name: nginx
containerPort: 80
volumeMounts:
- name: html
mountPath: /user/share/nginx/html/
- name: busybox
image: busybox
command:
- "/bin/sh"
- "-c"
- "sleep 6000"
volumeMounts:
- mountPath: /test/
name: html
volumes:
- name: html
emptyDir: {}

创建pod并查看

[root@master ~]# kubectl apply -f volume_test.yaml
service/service-nginx created
deployment.apps/mydeploy created
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mydeploy-786cbf6968-tndxp 2/2 Running 0 81s
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 38m
service-nginx NodePort 10.100.6.107 <none> 80:32649/TCP 87s

进入pod查看busybox这个容器

[root@master ~]# kubectl exec mydeploy-786cbf6968-tndxp -c busybox -it -- sh
/ # ls
bin dev etc home proc root sys test tmp usr var
/ # cd /test/ #进入挂载目录
/test # ls
/test # date > index.html #创建一个index.html,并写入当前时间
/test # ls
index.html
/test # cat index.html
Mon Aug 1 06:46:29 UTC 2022
/test #

再进入当前pod的nginx容器中

[root@master ~]# kubectl exec mydeploy-786cbf6968-tndxp -c nginx -it -- /bin/bash
root@mydeploy-786cbf6968-tndxp:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp user usr var
root@mydeploy-786cbf6968-tndxp:/# cd /user/share/nginx/html/
root@mydeploy-786cbf6968-tndxp:/user/share/nginx/html# ls
index.html
root@mydeploy-786cbf6968-tndxp:/user/share/nginx/html# cat index.html
Mon Aug 1 06:46:29 UTC 2022
root@mydeploy-786cbf6968-tndxp:/user/share/nginx/html#

此时我们发现当busybox这个容器中的挂载点文件和nginx容器中的挂载点文件一样,并且当busybox的文件发生改变时,nginx容器的文件也发生变化。说明两个容器公用一个volume。

hostPath

hostPath为在Pod上挂载宿主机上的文件或目录,它通常可以用于以下几方面:

  • 容器应用程序生成的日志文件需要永久保存时,可以使用宿主机的告诉文件系统进行存储
  • 需要访问宿主机上Docker引擎内部数据结构的容器应用时,可以通过定义hostPath为宿主机/var/lib/docker目录,使容器内部应用可以直接访问Docker的文件系统

在使用这种类型的volume时,需要注意以下几点:

  • 在不同的node上具有相同配置的Pod时,可能会因为宿主机上的目录和文件不同而导致对volume上的目录和文件访问结果不一致
  • 如果使用了资源配置,则kubernetes无法将hostPath在宿主机上使用的资源纳入管理
  • 宿主机创建的文件或目录只能由 root 用户写入。你需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入hostPath 卷。

当我们配置hostPath时需要指定他的type,参数如下:

取值 行为
  空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory 在给定路径上必须存在的目录。
FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File 在给定路径上必须存在的文件。
Socket 在给定路径上必须存在的 UNIX 套接字。
CharDevice 在给定路径上必须存在的字符设备。
BlockDevice

在给定路径上必须存在的块设备。

下面举例说明:

创建一个pod,里面部署nginx容器,并指定挂载方式时hostPath,类型为DirectoryOrCreate。

[root@master ~]# cat volume_test2.yaml
apiVersion: v1
kind: Service
metadata:
name: service-nginx
namespace: default
spec:
type: NodePort
selector:
app: nginx
ports:
- name: nginx
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mydeploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
name: web
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.4
ports:
- name: nginx
containerPort: 80
volumeMounts:
- name: nginx-volume
mountPath: /usr/share/nginx/html/
volumes:
- name: nginx-volume
hostPath:
path: /test-volume # 宿主上目录位置
type: DirectoryOrCreate #类型可选

创建pod并查看pod、svc

[root@master ~]# kubectl get svc -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17h <none>
service-nginx NodePort 10.111.102.100 <none> 80:32457/TCP 14h app=nginx
[root@master ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mydeploy-695f458b88-66s8n 1/1 Running 0 14h 10.101.11.54 node2 <none> <none>
mydeploy-695f458b88-tnn59 1/1 Running 0 14h 10.101.149.28 node1 <none> <none>

此时我们看到pod被创建在node1和node2上,我们查看node1和node2的/目录下是否有test-volume创建

往test-volume目录下创建一个index.html文件,并添加内容。

[root@node1 ~]# echo node1 >/test-volume/index.html
[root@node1 ~]# cat /test-volume/index.html
node1 [root@node2 ~]# echo node2 >/test-volume/index.html
[root@node2 ~]# cat /test-volume/index.html
node2

最后验证一下,在master节点curl  主机IP:32457

[root@master ~]# curl 192.168.248.129:32457
node1
[root@master ~]# curl 192.168.248.129:32457
node2
[root@master ~]# curl 192.168.248.129:32457
node2
[root@master ~]# curl 192.168.248.129:32457
node1

此时发现master节点负载均衡到每个node节点,每个节点对应的时宿主机的文件。

NFS

nfs卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir那样会在删除 Pod 的同时也会被删除,nfs卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着nfs卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

开启集群以外的另一台虚拟机,安装nfs-utils安装包

note:这里要注意的是需要在集群每个节点都安装nfs-utils安装包,并且nfs-server主机要关闭防火墙,不然挂载会失败!

[root@bogon ~]# yum install nfs-utils -y

创建一个/data/nfs的目录

[root@bogon ~]# mkdir -p /data/nfs

开启nfs服务并修改配置文件/etc/exports,将挂载点写入配置文件中

[root@bogon ~]# vim /etc/exports
/data/nfs/ 192.168.228.0/24(insecure,rw,no_root_squash)

重启nfs服务

[root@bogon ~]#  systemctl restart nfs

在/data/nfs/目录下创建一个index.html的文件,并写入数据

[root@bogon ~]# cd /data/nfs
[root@bogon nfs]# echo test > index.html
[root@bogon nfs]# cat index.html
test

检查nfs是否能被检测到

[root@master ~]# showmount -e 192.168.248.131
Export list for 192.168.248.131:
/date/nfs 192.168.248.0/24

创建一个yaml文件并写入nfs挂载

[root@master ~]# cat nfs_test.yaml 

apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: nginx-svc
namespace: default
spec:
ports:
- name: http
port: 80 # service暴露的端口
protocol: TCP
targetPort: 80 #后端容器的端口
selector: #标签选择器与deployment一致
app: web
type: NodePort
--- apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: deployment-nginx
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: nginx:1.21.4
name: nginx
ports:
- name: http
containerPort: 80 #容器端口
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nfs
volumes:
- name: nfs
nfs:
server: 192.168.248.131 #nfs服务器地址
path: /date/nfs/       #nfs服务器共享目录

执行yaml并验证

[root@master ~]# kubectl apply  -f nfs_service.yaml
service/nginx-svc created
deployment.apps/deployment-nginx created
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-nginx-68cbc68d45-gnpdx 1/1 Running 0 44s 10.244.104.2 node2 <none> <none>
deployment-nginx-68cbc68d45-tlqxv 1/1 Running 0 44s 10.244.166.131 node1 <none> <none>
[root@master ~]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h24m <none>
nginx-svc NodePort 10.108.207.154 <none> 80:32435/TCP 53s app=web

此时我们可以看到nfs服务器上/date/nfs/index.html被挂载到容器的内部,我们修改nfs服务器上/date/nfs/index.html

[root@localhost ~]# cd /date/nfs/
[root@localhost nfs]# ls
index.html
[root@localhost nfs]# ls
index.html
[root@localhost nfs]# echo 123 > index.html
[root@localhost nfs]# cat index.html
123

再次刷新网页发现被同步

PV、PVC

之前提到的Volume是被定义在Pod上的,属于计算资源的一部分,而实际上,网络存储是相对独立于计算资源而存在的一种实体资源。比如在使用虚拟机的情况下,我们通常会先定义一个网络存储,然后从中划出一个“网盘”并挂接到虚拟机上。Persistent Volume(PV)和与之相关联的Persistent Volume Claim(PVC)也起到了类似的作用。

Persistent Volume(PV)

是由管理员设置的存储,他是集群的一部分,就像node也是集群的一部分一样,pv也是集群资源,是volume之类的卷插件,具有独立的pod之外的生命周期,当pv挂载到某个pod上时,pv不会因为pod删除而删除。

pv可以理解成为kubernetes集群中的某个网络存储对应的一块存储,它与Volume类似,但有以下区别:

  • pv只能是网络存储,不属于任何Node,但可以在每个Node上访问
  • pv并不是被定义在Pod上的,而是独立于Pod之外定义的
PV的关键配置参数

1、存储能力(Capacity)

描述存储设备具备的能力,目前仅支持对存储空间的设置(storage=xx)

2、存储卷模式(Volume Mode)

存储卷类型的设置(volumeMode=xxx),可选项包括Filesystem(文件系统)和Block(块设备),默认值为Filesystem。

3、访问模式(Access Modes)

对PV进行访问模式的设置,用于描述用户的应用对存储资源的访问权限。访问模式如下。

  • ReadWriteOnce(RWO):读写权限,并且只能被单个Node挂载。
  • ReadOnlyMany(ROX):只读权限,允许被多个Node挂载。
  • ReadWriteMany(RWX):读写权限,允许被多个Node挂载。

某些PV可能支持多种访问模式,但PV在挂载时只能使用一种访问模式,多种访问模式不能同时生效,具体请百度。

4.存储类别(Class)

PV可以设定其存储的类别,通过storageClassName参数指定一个StorageClass资源对象的名称。具有特定类别的PV只能与请求了该类别的PVC进行绑定。未设定类别的PV则只能与不请求任何类别的PVC进行绑定。

5.回收策略(Reclaim Policy)

通过PV定义中的persistentVolumeReclaimPolicy字段进行设置,当pod生命周期结束后对PV中的数据处理,可选项如下:

  • retain(保留):保留数据,需手动回收
  • Recycle(擦除):简单清除文件的操作(rm -rf )
  • delete(删除):与PV相连的后端存储完成Volume的删除操作(如AWS EBS、GCE PD、Azure Disk、OpenStack Cinder等设备的内部Volume清理)。

Persistent Volume Claim(PVC)

PVC作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别等信息的设置。

PVC的关键配置参数

资源请求(Resources):描述对存储资源的请求,目前仅支持request.storage的设置,即存储空间大小。

访问模式(Access Modes):PVC也可以设置访问模式,用于描述用户应用对存储资源的访问权限。其三种访问模式的设置与PV的设置相同。

存储卷模式(Volume Modes):PVC也可以设置存储卷模式,用于描述希望使用的PV存储卷模式,包括文件系统和块设备。

PV选择条件(Selector):通过对Label Selector的设置,可使PVC对于系统中已存在的各种PV进行筛选。系统将根据标签选出合适的PV与该PVC进行绑定。选择条件可以使用matchLabels和matchExpressions进行设置,如果两个字段都设置了,则Selector的逻辑将是两组条件同时满足才能完成匹配。

存储类别(Class):PVC 在定义时可以设定需要的后端存储的类别(通过storageClassName字段指定),以减少对后端存储特性的详细信息的依赖。只有设置了该Class的PV才能被系统选出,并与该PVC进行绑定。

PVC也可以不设置Class需求。如果storageClassName字段的值被设置为空(storageClassName=""),则表示该PVC不要求特定的Class,系统将只选择未设定Class的PV与之匹配和绑定。

持久化演示

在nfs服务器上创建nfs的卷并重启

[root@bogon date]# cat /etc/exports
/date/nfs/ 192.168.248.0/24(insecure,rw,no_root_squash)
/date/nfs1/ 192.168.248.0/24(insecure,rw,no_root_squash)
/date/nfs2/ 192.168.248.0/24(insecure,rw,no_root_squash)
/date/nfs3/ 192.168.248.0/24(insecure,rw,no_root_squash)
/date/nfs4/ 192.168.248.0/24(insecure,rw,no_root_squash) [root@bogon date]# systemctl restart nfs

在nfs服务器上创建对应的目录

[root@bogon date]# mkdir nfs{1..4}
[root@bogon date]# ls
nfs nfs1 nfs2 nfs3 nfs4

创建PV,创建5个pv对应上面的nfs挂载目录

[root@master ~]# cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01
spec:
capacity: #存储容量            
storage: 10Gi #pv存储卷为10G
accessModes: #访问模式:
- ReadWriteMany #读写权限,允许被多个Node挂载。
- ReadWriteOnce #读写权限,并且只能被单个Node挂载
persistentVolumeReclaimPolicy: Retain #回收策略:保留
storageClassName: nfs #存储类别
nfs: #存储类型
path: /date/nfs/ #要挂在的nfs服务器的目录位置
server: 192.168.248.131 #nfs server地址,也可以是域名,前提是能被解析
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv02
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /date/nfs1/
server: 192.168.248.131
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03
spec:
capacity:
storage: 30Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /date/nfs2/
server: 192.168.248.131
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv04
spec:
capacity:
storage: 40Gi
accessModes:
- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /date/nfs3/
server: 192.168.248.131
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv05
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /date/nfs4/
server: 192.168.248.131

执行yaml文件创建pv并查看

[root@master ~]# kubectl apply -f pv.yaml
persistentvolume/pv01 unchanged
persistentvolume/pv02 configured
persistentvolume/pv03 configured
persistentvolume/pv04 configured
persistentvolume/pv05 configured
[root@master ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 10Gi RWO,RWX Retain Available nfs 6m24s
pv02 20Gi RWX Retain Available nfs 5m28s
pv03 30Gi RWX Retain Available nfs 108s
pv04 40Gi ROX Retain Available nfs 108s
pv05 50Gi RWO Retain Available nfs 108s

解释:
ACCESS MODES: 访问模式
  RWO:ReadWriteOnly 读写权限,并且只能被单个Node挂载。
  RWX:ReadWriteMany 只读权限,允许被多个Node挂载。
  ROX:ReadOnlyMany 读写权限,允许被多个Node挂载。
RECLAIM POLICY: 回收策略
  Retain:保护pvc释放的pv及其上的数据,将不会被其他pvc绑定
  recycle:保留pv但清空数据
  delete:删除pvc释放的pv及后端存储volume
STATUS:
  Available:空闲状态
  Bound:已经绑定到某个pvc上
  Released:对应的pvc已经被删除,但是资源没有被集群回收
  Failed:pv自动回收失败
CLAIM:
  被绑定到了那个pvc上面格式为:NAMESPACE/PVC_NAME

STORAGECLASS:对应存储类别storageClassName

创建pvc

[root@master ~]# cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 10Gi
storageClassName: nfs

查看pvc、pv

[root@master ~]# kubectl get pv,pvc -owide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/pv01 10Gi RWO,RWX Retain Available nfs 75s Filesystem
persistentvolume/pv02 20Gi RWX Retain Available nfs 75s Filesystem
persistentvolume/pv03 30Gi RWX Retain Available nfs 75s Filesystem
persistentvolume/pv04 40Gi ROX Retain Bound default/mypvc nfs 75s Filesystem
persistentvolume/pv05 50Gi RWO Retain Available nfs 75s Filesystem NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/mypvc Bound pv04 40Gi ROX nfs 28s Filesystem

此时mypvc根据匹配已经绑定到pv04上面了,pv、pvc已经创建好,我们在创建一个pod将pvc关联到容器中

[root@master ~]# cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 10Gi
storageClassName: nfs
[root@master ~]# vim pvc_pod.yaml
[root@master ~]# cat pvc_pod.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-deploy
namespace: default
spec:
selector:
app: mynginx
type: NodePort
ports:
- name: nginx
port: 80
targetPort: 80
nodePort: 30001 ---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mydeploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: mynginx
template:
metadata:
name: web
labels:
app: mynginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: html
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc

执行yaml

[root@master ~]# kubectl apply -f  pvc_pod.yaml
service/nginx-deploy created
deployment.apps/mydeploy created

pv04对应的是nfs服务器中的/data/nfs3/目录,我们在目录下创建index.html并写入test-pvc

[root@bogon date]# cd nfs3/
[root@bogon nfs3]# echo test-pvc > index.html
[root@bogon nfs3]# cat index.html
test-pvc

验证

[root@master ~]# kubectl exec -it  mydeploy-6fff8986f7-7qdrn -- /bin/bash
root@mydeploy-6fff8986f7-7qdrn:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 27G 3.2G 24G 12% /
tmpfs 64M 0 64M 0% /dev
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/mapper/centos-root 27G 3.2G 24G 12% /etc/hosts
shm 64M 0 64M 0% /dev/shm
192.168.248.131:/date/nfs3 8.0G 1.4G 6.6G 18% /usr/share/nginx/html
tmpfs 910M 12K 910M 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 910M 0 910M 0% /proc/acpi
tmpfs 910M 0 910M 0% /proc/scsi
tmpfs 910M 0 910M 0% /sys/firmware
root@mydeploy-6fff8986f7-7qdrn:/# cd /usr/share/nginx/html
root@mydeploy-6fff8986f7-7qdrn:/usr/share/nginx/html# ls
index.html
root@mydeploy-6fff8986f7-7qdrn:/usr/share/nginx/html# cat index.html
test-pvc
root@mydeploy-6fff8986f7-7qdrn:/usr/share/nginx/html#

当我们删除pod是看回收机制是不是生效。

[root@master ~]# kubectl delete -f pod_pvc.yaml
service "nginx-deploy" deleted
deployment.apps "mydeploy" deleted
[root@master ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound pv04 40Gi ROX nfs 35m
[root@master ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 10Gi RWO,RWX Retain Available nfs 36m
pv02 20Gi RWX Retain Available nfs 36m
pv03 30Gi RWX Retain Available nfs 36m
pv04 40Gi ROX Retain Bound default/mypvc nfs 36m
pv05 50Gi RWO Retain Available nfs 36m

当pod删除时pvc和pv还是绑定状态,查看nfs挂载目录的文件还在

[root@localhost nfs3]# ls
index.html
[root@localhost nfs3]# cat index.html
test-pvc
[root@localhost nfs3]#

当pvc被删掉时,查看pv状态

[root@master ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound pv04 40Gi ROX nfs 42m
[root@master ~]# kubectl delete pvc mypvc
persistentvolumeclaim "mypvc" deleted
[root@master ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 10Gi RWO,RWX Retain Available nfs 43m
pv02 20Gi RWX Retain Available nfs 43m
pv03 30Gi RWX Retain Available nfs 43m
pv04 40Gi ROX Retain Released default/mypvc nfs 43m
pv05 50Gi RWO Retain Available nfs 43m

当pvc被删除后需要我们手动释放pv和pvc的绑定

[root@master ~]# kubectl edit pv pv04
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"PersistentVolume","metadata":{"annotations":{},"name":"pv04"},"spec":{"accessModes":["ReadOnlyMany"],"capacity":{"storage":"40Gi"},"nfs":{"path":"/date/nfs3/","server":"192.168.248.131"},"persistentVolumeReclaimPolicy":"Retain","storageClassName":"nfs"}}
pv.kubernetes.io/bound-by-controller: "yes"
creationTimestamp: "2022-08-04T14:20:20Z"
finalizers:
- kubernetes.io/pv-protection
name: pv04
resourceVersion: "20526"
uid: 4e0d6db7-c0c3-41c5-9912-a26da20e72c5
spec:
accessModes:
- ReadOnlyMany
capacity:
storage: 40Gi
claimRef: #需要将这块手动删掉
apiVersion: v1
kind: PersistentVolumeClaim
name: mypvc
namespace: default
resourceVersion: "16788"
uid: 558a73ae-21b4-496e-abb5-4224884392e3
nfs:
path: /date/nfs3/
server: 192.168.248.131
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
volumeMode: Filesystem
status:
phase: Released

然后再查看pv,发现pv和pvc接触绑定

[root@master ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 10Gi RWO,RWX Retain Available nfs 47m
pv02 20Gi RWX Retain Available nfs 47m
pv03 30Gi RWX Retain Available nfs 47m
pv04 40Gi ROX Retain Available nfs 47m
pv05 50Gi RWO Retain Available nfs 47m

StorageClass(SC)动态存储

StorageClass作为对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端存储的细节,一方面减少了用户对于存储资源细节的关注,另一方面减轻了管理员手工管理PV的工作,由系统自动完成PV的创建和绑定,实现了动态的资源供应。基于StorageClass的动态资源供应模式将逐步成为云平台的标准存储配置模式。

StorageClass的定义主要包括名称、后端存储的提供者(provisioner)和后端存储的相关参数配置。StorageClass一旦被创建出来,则将无法修改。如需更改,则只能删除原StorageClass的定义重建。

要使用StorageClass,需要安装对应的自动配置程序,比如我们后端使用的是NFS,那么我们就要使用nfs-client的自动配置程序,也叫Provisioner(供应者),这个程序使用我们已经配置好的nfs服务器,来自动创建持久卷,也就是自动帮我们创建pv,自动创建的pv以${namespace}-${pvcname}-${pvname}这样的命名格式存在我们的NFS服务器上。当pv被回收以后则以archieved-${namespace}-${pvcname}-${pvname}这样的命名方式存在NFS服务器上。

安装nfs-client

nfs-client官方文档:https://github.com/kubernetes-retired/external-storage/tree/master/nfs-client

首先创建一个nfs-client的deployment.yaml

[root@master ~]# cat deployment.yaml
piVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
#replace with namespace where provisioner is deployed
namespace: default
spec:
replicas: 1
strategy: #更新策略
type: Recreate #重建更新
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner #SA名称
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER #NFS服务器地址
value: 192.168.248.131
- name: NFS_PATH #数据共享目录
value: /data/nfs
volumes:
- name: nfs-client-root
nfs:
server: 192.168.248.131
path: /data/nfs/

然后再创建一个名为nfs-client-provisioner的serviceAccount(SA)

[root@master ~]# kubectl create sa nfs-client-provisioner -n default
serviceaccount/nfs-client-provisioner created

创建一个clustrrole和clusterrolebinding为SA赋予权限

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
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: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io

再创建一个storageclass的yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: fuseim.pri/ifs # 必须与上面deployment的env下的PROVISIONER_NAME下的值一致
parameters:
archiveOnDelete: "false"

K8s存储之Volume、PV、PVC、SC的更多相关文章

  1. Kubernetes 存储系统 Storage 介绍:PV,PVC,SC

    要求:先了解数据docker容器中数据卷的挂载等知识 参考网址: https://www.cnblogs.com/sanduzxcvbnm/p/13176938.html https://www.cn ...

  2. 6.k8s.存储Volume.PV.PVC

    #Volume Volume 解决数据持久化和容器间共享数据 Kubernetes支持几十种类型的后端存储卷 #hostPath挂载实例,挂载Node节点/tmp/test-volume目录到容器/t ...

  3. 4.k8s存储之Volume、PV、PVC和StatefulSet

    3.Volume 容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题.首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失--容器以干净的状态(镜像最初的 ...

  4. Kubernetes 存储卷管理 PV&PVC(十)

    目录 一.emptyDir 二.hostPath 三.PV & PVC 1.NFS PersistentVolume 2.创建 PVC 3.创建 Pod 进行挂载 为了持久化保存容器的数据,可 ...

  5. K8s存储卷、pv和pvc的使用

    emptyDIR 临时目录 hostPath :使用主机的路径 网络存储: 传统的设备存储:NAS,SAN 分布式存储:glusterfs,rbd,cephfs 云存储:EBS,Azure,阿里云的 ...

  6. k8-s存储

    原文 https://mp.weixin.qq.com/s/6yg_bt5mYKWdXS0CidY6Rg 从用户角度看,存储就是一块盘或者一个目录,用户不关心盘或者目录如何实现,用户要求非常" ...

  7. k8s的持久化存储PV&&PVC

    1.PV和PVC的引入 Volume 提供了非常好的数据持久化方案,不过在可管理性上还有不足. 拿前面 AWS EBS 的例子来说,要使用 Volume,Pod 必须事先知道如下信息: 当前 Volu ...

  8. K8S系列第九篇(持久化存储,emptyDir、hostPath、PV/PVC)

    更多k8s内容,请关注威信公众好:新猿技术生态圈 一.数据持久化 Pod是由容器组成的,而容器宕机或停止之后,数据就随之丢了,那么这也就意味着我们在做Kubernetes集群的时候就不得不考虑存储的问 ...

  9. k8s存储 pv pvc ,storageclass

    1.  pv  pvc 现在测试 glusterfs  nfs  可读可写, 多个pod绑定到同一个pvc上,可读可写. 2. storageclass  分成两种 (1)  建立pvc, 相当于多个 ...

  10. kubernetes存储类与PV与PVC关系及实践

    StorageClass & PV & PVC关系图 Volumes是最基础的存储抽象,其支持多种类型,包括本地存储.NFS.FC以及众多的云存储,我们也可以编写自己的存储插件来支持特 ...

随机推荐

  1. Python函数用法和底层分析

    目录 Python函数用法和底层分析 函数的基本概念 Python 函数的分类 核心要点 形参和实参 文档字符串(函数的注释) 返回值 函数也是对象,内存底层分析 变量的作用域(全局变量和局部变量) ...

  2. Linux命令篇 - nc(ncat) 命令

    nc (ncat) Ncat is a feature-packed networking utility which reads and writes data across networks fr ...

  3. 07.synchronized都问啥?

    大家好,我是王有志.关注王有志,一起聊技术,聊游戏,从北漂生活谈到国际风云.最近搞了个抽奖送书的活动,欢迎点击链接参与. 如果Java面试有什么是必问的,synchronized必定占据一席之地.初出 ...

  4. vue 中安装并使用echart

    本文为博主原创,转载请注明出处: 1.安装echart 依赖: 安装命令: npm install echarts --save 在vscode 的终端窗口进行执行,如图所示: 执行完之后,查看 项目 ...

  5. K8s 为什么会抛弃 docker

    为什么 K8s 会抛弃 docker 前言 CRI containerd 参考 为什么 K8s 会抛弃 docker 前言 在这之前先来了解下,k8s 是如何和 docker 进行交互的. CRI k ...

  6. python3连接postgresql/greenpulm

    python3安装:pip install psycopg2github地址:https://github.com/psycopg/psycopg2文档地址:http://initd.org/psyc ...

  7. GIT安装步骤记录以及Git 常用命令,忽略文件,推送本地代码到仓库示例以及报错解决

    下载 下载地址 git-scm.com 或 gitforwindows.org 安装(凡是下面没有给出图片的,都按默认选项就行) 选择安装组件 调整你的 path 环境变量 第一种是仅从 Git Ba ...

  8. ng-alain组件st表格,实现点击表格行变色,或者渲染变色

    实现点击表格行变色 html文件 <st #st [data]="data" (change)="changeClick($event)" [column ...

  9. Odoo View 常用技巧

    隐藏Field <field name="currency_id" invisible="True"/> <field name=" ...

  10. spring.jackson.default-property-inclusion 不生效问题分析

    背景 项目里每个返回体里都有@JsonInclude(JsonInclude.Include.NON_NULL) 这个注解,也就是不返回null字段 想有没有办法全局配置一下,这样就不用每个类都加这个 ...