文章目录

kubernetes(k8s)数据持久化Volume

一、数据持久化

Pod是由容器组成的,而容器宕机或停止之后,数据就随之丢了,那么这也就意味着我们在做Kubernetes集群的时候就不得不考虑存储的问题,而存储卷就是为了Pod保存数据而生的

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

1、Vlolume概述

Volume 提供了对各种 backend 的抽象,容器在使用 Volume 读写数据的时候不需要关心数据到底是存放在本地节点的文件系统中呢还是云硬盘上。对它来说,所有类型的 Volume 都只是一个目录
 
Kubernetes中的Volume提供了在容器中挂载外部存储的能力
Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可以使用相应的Volume

2、数据卷的分类

本地(hostPath,emptyDir等)
网络(NFS,Ceph,GlusterFS等)
公有云(AWS EBS等)
K8S资源(configmap,secret等)

3、常用的四种数据卷

emptyDir
hostPath
NFS
云存储(ceph, glasterfs...)

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_emptydir

4、Pod使用Volume步骤:

1、在Pod上定义存储卷,并关联至目标存储服务上;

2、在需要用到存储卷的容器上,挂载其所属Pod的存储卷

5、 volume基本资源清单

spec:
volumes:
- name <string> #存储卷名称标识,仅可使用DNS标签格式的字符,在当前Pod中必须唯一
VOL_TYPE <Object> #存储卷插件及具体的目标存储供给方的相关配置
containers:
- name: ...
image: ...
volumeMounts:
- name <string> #要挂载的存储卷的名称,必须匹配存储卷列表中的某项定义
mountPatch <string> #容器文件系统上的挂载点路径
readOnly <boolean> #是否挂载为只读模式,默认为"否"
subPath <string> #挂载存储卷上的一个子目录至指定的挂载点
subPathExpr <string> #挂载由指定的模式匹配到的存储卷的文件或目录至挂载点
mountPropagation <string> #挂载卷的传播模式

二、emptyDir(临时存储卷)

1、emptyDir的简述

1》emptyDir存储卷是Pod对象生命周期中的一个临时目录,类似于Docker上的docker挂载卷,在Pod对象启动时即被创建,而在Pod对象被移除时会被一并删除
2》不具有持久能力的emptyDir存储卷只能用于某些特殊场景中
3》emptyDir只是一个临时挂载的文件,pod删除后,该目录也会在node节点上被删除;但是容器崩溃时,该文件还存在



#例如:

2、emptyDir的使用方法

1》暂存空间,例如用于基于磁盘的合并排序

2》用作长时间计算崩溃恢复时的检查点

3》Web服务器容器提供数据时,保存内容管理器容器提取的文件

4、emptyDir的使用

案列一

#编写资源清单:
[root@m01 /hzl]# cat emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: emptydir #注意大小写
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent #镜像拉取策略
volumeMounts:
- mountPath: /hzl/ #添加容器内部的挂载点
name: emptydir-name


volumes:
- name: emptydir-name
emptyDir: {} #创建一个空目录
sizeLimit: 1G #目录容量大小为1G





#创建pod
[root@m01 /hzl]# kubectl apply -f emptydir.yaml
pod/emptydir created





#查看Pod
[root@ubuntu-200 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
emptydir-pod 1/1 Running 0 17s 10.244.2.62 ubuntu-210 <none> <none>




#进入容器并在容器中创建文件测试
[root@ubuntu-200 ~]# kubectl exec -it emptydir-pod -- bash
root@emptydir-pod:/# ls -l /cache/
total 0
root@emptydir-pod:/cache# touch /cache/nginx-emptydir.log
root@emptydir-pod:/cache# echo nginx-emptydir > /cache/nginx-emptydir.log
root@emptydir-pod:/cache# cat /cache/nginx-emptydir.log
nginx-emptydir





#在node节点上查找临时存储的文件位置
[root@ubuntu-210 ~]# find / -name nginx-emptydir.log
/var/lib/kubelet/pods/95dcb0a8-61f7-42e3-aa35-e7f1a1872b20/volumes/kubernetes.io~empty-dir/cache-volume/nginx-emptydir.log





#查看文件内容
[root@ubuntu-210 ~]# cat /var/lib/kubelet/pods/95dcb0a8-61f7-42e3-aa35-e7f1a1872b20/volumes/kubernetes.io~empty-dir/cache-volume/nginx-emptydir.log
nginx-emptydir





#在master节点上删除pod
[root@ubuntu-200 ~]# kubectl delete -f volume-emptyDir.yaml
pod "emptydir-pod" deleted





#在node节点上查看临时存储是否还存在
[root@ubuntu-210 ~]# cat /var/lib/kubelet/pods/95dcb0a8-61f7-42e3-aa35-e7f1a1872b20/volumes/kubernetes.io~empty-dir/cache-volume/nginx-emptydir.log
cat: /var/lib/kubelet/pods/95dcb0a8-61f7-42e3-aa35-e7f1a1872b20/volumes/kubernetes.io~empty-dir/cache-volume/nginx-emptydir.log: No such file or directory
[root@ubuntu-210 ~]# ll /var/lib/kubelet/pods/95dcb0a8-61f7-42e3-aa35-e7f1a1872b20/volumes/kubernetes.io~empty-dir/cache-volume/
ls: cannot access '/var/lib/kubelet/pods/95dcb0a8-61f7-42e3-aa35-e7f1a1872b20/volumes/kubernetes.io~empty-dir/cache-volume/': No such file

案列二

#编写资源清单
kind: Deployment
apiVersion: apps/v1
metadata:
name: emptydir
spec:
selector:
matchLabels:
app: emptydir
template:
metadata:
labels:
app: emptydir
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /data/
name: emptydir-name
- name: php
image: registry.cn-hangzhou.aliyuncs.com/k8sos/web:discuz-php-v1
volumeMounts:
- mountPath: /opt/
name: emptydir-name
volumes:
- name: emptydir-name
emptyDir: {}


#创建pod
[root@m01 /hzl]# kubectl apply -f emptydir.yaml
deployment.apps/emptydir unchanged



#查看pod状态
[root@m01 /hzl]# kubectl get pod -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
emptydir-7d5cdb7b48-qzqqg 2/2 Running 0 107s 10.244.2.2 nod02 <none> <none>





#################################### 测试 ########################################

#进入容器nginx(进入到挂载目录)
[root@m01 /hzl]# kubectl exec -it emptydir-7d5cdb7b48-qzqqg -c nginx -- bash
root@emptydir-7d5cdb7b48-qzqqg:/# cd /data/
root@emptydir-7d5cdb7b48-qzqqg:/data# touch hzl.txt
root@emptydir-7d5cdb7b48-qzqqg:/data# tail -f hzl.txt #使用tail进行监控




#进入容器php(进入到挂载目录)
[root@m01 /hzl]# kubectl exec -it emptydir-7d5cdb7b48-qzqqg -c php -- bash
[root@emptydir-7d5cdb7b48-qzqqg html]# cd /opt/
[root@emptydir-7d5cdb7b48-qzqqg html]# ls
[root@emptydir-7d5cdb7b48-qzqqg html]# hzl.txt #文件在也在php容器中,实现了容器内部数据共享
[root@emptydir-7d5cdb7b48-qzqqg html]# echo ‘666’ > hzl.txt





#查看文件容器nginx状态
[root@emptydir-7d5cdb7b48-qzqqg:/data# tail -f hzl.txt
666
#在nginx容器删除文件hzl.txt
[root@emptydir-7d5cdb7b48-qzqqg:/data# rm -rf hzl.txt



#查看容器php的状态
[root@emptydir-7d5cdb7b48-qzqqg html]# ll #查看文件已经不存在了





#总结 :

三、hostPath(节点存储卷)

hostPath类型则是映射node文件系统中的文件或者目录到pod里。在使用hostPath类型的存储卷时,也可以设置type字段,支持的类型有文件、目录、File、Socket、CharDevice和BlockDevice

1、hostpath的概述:

hostPath是挂载node 主机上的(当pod运行在那台主机上,hostPtah就相当于docker挂载到当前系统)

hostPath类型的存储卷是指将工作节点上某个文件系统的目录或文件挂载于Pod中的一种存储卷,它独立于Pod资源的生命周期,因而具有持久性。但它是工作节点本地的存储空间,仅适用于特定情况下的存储卷使用要求,例如,将工作节点上的文件系统关联为Pod的存储卷,从而使得容器访问节点文件系统上的数据。这一点在运行有管理任务的系统级Pod资源需要访问节点上的文件时尤为有用

2、hostpath支持数据类型

DirectoryCreate:如果在给定的路径上没有任何东⻄存在,那么将根据需要在那⾥创建⼀个空⽬录,权限设置为 0755,与 Kubelet 具有相同的组和所有权;

Directory: 给定的路径下必须存在⽬录;

FileOrCreate: 如果在给定的路径上没有任何东⻄存在,那么会根据需要创建⼀个空⽂件,权限设置为0644,与 Kubelet 具有相同的组和所有权;

File: 给定的路径下必须存在⽂件;

Socket: 给定的路径下必须存在 UNIX 套接字;

CharDevice: 给定的路径下必须存在字符设备;

BlockDevice: 给定的路径下必须存在块设备;

“” : 空字符串,默认配置,在关联hostPath存储卷之前不进行任何检查

3、hostpath的使用

案列二

#查看文档:https://kubernetes.io/docs/concepts/storage/volumes#hostpath
[root@m01 /hzl]# kubectl explain pod.spec.volumes.hostPath
KIND: Pod
VERSION: v1

RESOURCE: hostPath <Object>
.......
.....




#创建资源配置清单
[root@m01 /hzl]# cat hostpath.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: hostpath
spec:
selector:
matchLabels:
app: hostpath
template:
metadata:
labels:
app: hostpath
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /opt/
name: hostpath-name
volumes:
- name: hostpath-name
hostPath:
path: /opt/hzl/hhh
type: DirectoryCreate



#创建pod
[root@m01 /hzl]# kubectl apply -f hostpath.yaml
deployment.apps/hostpath created





#查看pod状态
[root@m01 /hzl]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hostpath-6b8bd7459d-bpfhb 1/1 Running 0 25s
[root@m01 /hzl]# kubectl get pods -o wide #查看部署到node位置
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hostpath-6b8bd7459d-bpfhb 1/1 Running 0 3m11s 10.244.1.4 nod01 <none> <none>





#在node01上查看(给定挂载的位置没有东西,就会自己创建并授权755)
[root@nod01 /opt]# ll
总用量 1
drwxr-xr-x 3 root root 17 89 21:46 hzl
[root@nod01 /hzl]# cd /opt/hzl/hhh/
[root@nod01 /opt/hzl/hhh]# pwd
/opt/hzl/hhh



ps : 使用DirectoryCreate类型,挂载目录点,不管存不存在,都不影响正常挂载。即,如果挂载点存存在,则直接挂载,如果不存在,则自动创建目录并挂载

#################################### 测试 ####################################
#更改资源清单
[root@m01 /hzl]# vim hostpath.yaml
.......
....
volumes:
- name: hostpath-name
hostPath:
path: /opt/hzl/hhh
type: Directory #更改数据类型




#创建pod
[root@m01 /hzl]# kubectl apply -f hostpath.yaml
deployment.apps/hostpath configured



#查看pod(节点为node02)
[root@m01 /hzl]# kubectl get pod
NAME READY STATUS RESTARTS AGE
hostpath-6b8bd7459d-bpfhb 1/1 Running 0 13m
hostpath-b5fb78645-9fd4r 0/1 ContainerCreating 0 33s #查看发现一直在创建中
[root@m01 /hzl]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hostpath-6b8bd7459d-bpfhb 1/1 Running 0 17m 10.244.1.4 nod01 <none> <none>
hostpath-b5fb78645-9fd4r 0/1 ContainerCreating 0 4m46s <none> nod02 <none> <none>








#查看详情
[root@m01 /hzl]# kubectl describe pods hostpath-b5fb78645-9fd4r
.......
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 107s default-scheduler Successfully assigned default/hostpath-b5fb78645-9fd4r to nod02
Warning FailedMount 43s (x8 over 107s) kubelet MountVolume.SetUp failed for volume "hostpath-name" : hostPath type check failed: /opt/hzl/ is not a directory #查看原因为挂载时找不到目录而一直等待






#手动创建目录(nod02)
[root@nod02 ~]# cd /opt/
[root@nod02 /opt]# mkdir hzl
[root@nod02 /opt]# ll
总用量 1
drwxr-xr-x 2 root root 6 89 22:04 hzl
[root@nod02 /opt]#



#查看pod状态(m01)
[root@m01 /hzl]# kubectl get pod
NAME READY STATUS RESTARTS AGE
hostpath-b5fb78645-9fd4r 1/1 Running 0 6m38s #查看pod已经正常创建运行


ps

案列二

#编写资源清单
[root@m01 /hzl]# cat volume-hostPath-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: hostpath-test-pod
spec:
containers:
- name: nginx-hostpath
image: nginx
volumeMounts:
- mountPath: /var/logs/
name: data-log
#定义hostPath卷名,和宿主机共享的路径
volumes:
- name: data-log
hostPath:
path: /data/logs


#创建pod
[root@m01 /hzl]# kubectl apply -f volume-hostPath-test.yaml
[root@m01 /hzl]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hostpath-test-pod 1/1 Running 0 66m 10.244.2.65 ubuntu-210 <none> <none>



#在node节点上的共享目录上创建文件
[root@m01 /hzl]# echo 111 > /data/logs/1.txt
[root@m01 /hzl]# cat /data/logs/1.txt
111




#在master节点上进入pod,查看挂载卷的文件内容
[root@m01 /hzl]# kubectl exec -it hostpath-test-pod -- bash
root@hostpath-test-pod:/# cat /var/logs/1.txt
111



#在pod内查看和创建创建文件
root@hostpath-test-pod:/# ls /var/logs/
1.txt
root@hostpath-test-pod:/# echo ’666‘ > /var/logs/2.txt
root@hostpath-test-pod:/# cat /var/logs/2.txt
666
root@hostpath-test-pod:/# ls /var/logs/
1.txt 2.txt

#在Node节点上查看pod内部创建的文件
[root@m01 /hzl]# cat /data/logs/2.txt
666




#删除Pod
[root@m01 /hzl]# kubectl delete -f volume-hostPath-test.yaml
pod "hostpath-test-pod" deleted




#Node节点上查看文件是否存在
[root@m01 /hzl]# ll /data/logs/
total 16
drwxr-xr-x 2 root root 4096 Dec 8 08:46 ./
drwxr-xr-x 4 root root 4096 Dec 8 07:34 ../
-rw-r--r-- 1 root root 4 Dec 8 08:43 1.txt
-rw-r--r-- 1 root root 4 Dec 8 08:46 2.txt #可看到在Pod内部创建的文件依然存在,没有随pod的删除而删除,已初步实现了持久化.
[root@m01 /hzl]# cat /data/logs/2.txt
666

四、nfs存储卷(pv、pvc)

nfs卷能将NFS(网络文件系统)挂载到你的pod中。不像emptyDir,当删除Pod时,nfs卷的内容被保留,卷仅仅是被卸载。另外,NFS是文件系统级共享服务,它支持同时存在的多路挂载请求

1、nfs存储卷的概述

nfs使得我们可以挂载已经存在的共享到我们的Pod中,和emptyDir不同的是,当Pod被删除时,emptyDir也会被删除。但是nfs不会被删除,仅仅是解除挂在状态而已,这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递,并且nfs可以同时被多个pod挂在并进行读写



ps

2、pv、pvc的介绍

PersistentVolume(PV)是集群中已由管理员配置的一段网络存储。 集群中的资源就像一个节点是一个集群资源。 PV是诸如卷之类的卷插件,但是具有独立于使用PV的任何单个pod的生命周期。 该API对象捕获存储的实现细节,即NFS,iSCSI或云提供商特定的存储系统

PersistentVolumeClaim(PVC)是用户存储的请求。PVC的使用逻辑:在pod中定义一个存储卷(该存储卷类型为PVC),定义的时候直接指定大小,pvc必须与对应的pv建立关系,pvc会根据定义去pv申请,而pv是由存储空间创建出来的。pv和pvc是kubernetes抽象出来的一种存储资源

3、PV和PVC的生命周期

将PV看作可用的存储资源,PVC则是对存储资源的需求

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_volume_02

(1)#资源供应

k8s支持两种资源的供应模式:静态模式(Static)和动态模式(Dynamic)。资源供应的结果就是创建好的PV

1>静态模式:集群管理员手工创建许多PV,在定义PV时需要将后端存储的特性进行设置。

2>动态模式:集群管理员无需手工创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种类型。此时要求PVC对存储的类型进行声明,系统将自动完成PV的创建及与PVC的绑定。PVC可以声明Class为"",说明该PVC禁止使用动态模式。




(2)#资源绑定
在定义好PVC之后,系统将根据PVC对存储资源的要求(存储空间和访问模式)在已存在的PV中选择一个满足PVC要求的PV,一旦找到,就将该PV与定义的PVC进行绑定,应用就可以使用这个PVC了。
如果系统中没有这个PV,则PVC则会一直处理Pending状态,直到系统中有符合条件的PV。PV一旦绑定到PVC上,就会被PVC独占,不能再与其他PVC进行绑定。
当PVC申请的存储空间比PV的少时,整个PV的空间就都能够为PVC所用,可能会造成资源的浪费。
如果资源供应使用的是动态模式,则系统在为PVC找到合适的StorageClass后,将自动创建一个PV并完成与PVC的绑定。





(3)#资源使用
Pod使用Volume定义,将PVC挂载到容器内的某个路径进行使用。
Volume的类型为Persistent VolumeClaim,在容器挂载了一个PVC后,就能被持续独占使用。多个Pod可以挂载到同一个PVC上。

volumes:
- name: pv
persistentVolumeClaim:
claimName: pvc




(4)#资源释放
当存储资源使用完毕后,可以删除PVC,与该PVC绑定的PV会被标记为“已释放”,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还被保留在存储设备上,只有在清除之后该PV才能被再次使用。




(5)#资源回收

4、存储管理机制

静态资源供应模式下,通过PV和PVC完成绑定,并供Pod使用的存储管理机制:

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_pv_03

动态资源供应模式下,通过StorageClass和PVC完成资源动态绑定(系统自动生成PV),并供Pod使用的存储管理机制

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_pv_04

5、简述pv过载过程

1>用户提交一个包含PVC的POD

2>调度器把根据各种调度算法把该POD分配到某个节点,比如node01

3>Node01上的kubelet等待Volume Manager准备存储设备

4>PV控制器调用存储插件创建PV并与PVC进行绑定

5>Attach/Detach Controller或Volume Manager通过存储插件实现设备的attach。(这一步是针对块设备存储)

6>Volume Manager等待存储设备变为可用后,挂载该设备到/var/lib/kubelet/pods/<Pod 的 ID>/volumes/kubernetes.io~<Volume 类型 >/<Volume 名字 >目录上

7>Kubelet被告知卷已经准备好,开始启动POD,通过映射方式挂载到容器中

【pv、pvc的使用(全部节点必须安装nfs)】

1、安装nfs

[root@m01 /hzl]# yum install nfs-utils rpcbind  -y
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* elrepo: mirrors.tuna.tsinghua.edu.cn
* epel: mirror.sjtu.edu.cn
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
.......
...



#配置文件添加
[root@m01 /hzl]# mkdir -p /nfs/v{1..3}
[root@m01 /hzl]# cat > /etc/exports <<EOF
> /nfs/v1 192.168.15.0/24(rw,no_root_squash)
> /nfs/v2 192.168.15.0/24(rw,no_root_squash)
> /nfs/v3 192.168.15.0/24(rw,no_root_squash)
> EOF




#启动 nfs rpcbind
[root@m01 /hzl]# systemctl enable --now rpcbind nfs-server.service
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.




#查看配置状态
[root@m01 /hzl]# exportfs -arv
exporting 192.168.15.0/24:/nfs/v3
exporting 192.168.15.0/24:/nfs/v2
exporting 192.168.15.0/24:/nfs/v1





#查看挂载点
[root@m01 /hzl]# showmount -e
Export list for m01:
/nfs/v3 192.168.15.0/24
/nfs/v2 192.168.15.0/24
/nfs/v1 192.168.15.0/24

2、nfs存储卷(创建pv、pvc)

#编写资源清单 :pv
[root@m01 /hzl]# cat pv1.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv1
labels:
app: pv1
spec:
nfs:
path: /nfs/v1
server: 192.168.15.55
accessModes:
- "ReadWriteMany"
capacity:
storage: 2Gi



[root@m01 /hzl]# cat pv2.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv2
labels:
app: pv2
spec:
nfs:
path: /nfs/v2
server: 192.168.15.55
accessModes:
- "ReadWriteMany"
capacity:
storage: 10Gi



[root@m01 /hzl]# cat pv3.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv3
labels:
app: pv3
spec:
persistentVolumeReclaimPolicy: Recycle
nfs:
path: /nfs/v3
server: 192.168.15.55
accessModes:
- "ReadWriteMany"
capacity:
storage: 10Gi




#创建所有:pv
[root@m01 /hzl]# kubectl apply -f pv1.yaml
persistentvolume/pv1 created
[root@m01 /hzl]# kubectl apply -f pv2.yaml
persistentvolume/pv2 created
[root@m01 /hzl]# kubectl apply -f pv3.yaml
persistentvolume/pv3 created




#查看所有:pv
[root@m01 /hzl]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv1 2Gi RWX Retain Available 12m
pv2 10Gi RWX Retain Available 2s
pv3 10Gi RWX Recycle Available 98s







#######################################################################


#创建资源清单 :pvc
[root@m01 /hzl]# cat pvc1.yaml
piVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
accessModes:
- "ReadWriteMany"
resources:
requests:
storage: "6Gi"





[root@m01 /hzl]# cat pvc2.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc3
spec:
accessModes:
- "ReadWriteMany"
resources:
requests:
storage: "6Gi"







#创建:pvc
[root@m01 /hzl]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/pvc1 created
[root@m01 /hzl]# kubectl apply -f pvc2.yaml
persistentvolumeclaim/pvc2 created







#查看pv,pvc(根据设定pvc的大小自动关联所合适的pv)
[root@m01 /hzl]# kubectl get pv,pvc

3、nfs存储卷的挂载使用(单节点挂载)

#编写资源清单
[root@m01 /hzl]# cat deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: test-rwo
spec:
selector:
matchLabels:
app: rwo
template:
metadata:
labels:
app: rwo
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /data/ #容器内的挂载点
name: rwo
volumes:
- name: rwo
persistentVolumeClaim:
claimName: pvc1



#创建pod
[root@m01 /hzl]# kubectl apply -f deployment.yaml
deployment.apps/test-rwo unchanged





#查看pod(已经正常运行)
[root@m01 /hzl]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-rwo-6dcb5687f-sxlmq 1/1 Running 0 2m27s

#查看详情(nginx已经正常运行到node02上)
[root@m01 /hzl]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-rwo-6dcb5687f-sxlmq 1/1 Running 0 7m1s 10.244.2.5 nod02 <none> <none>




#查看pvc绑定状态(绑定成功状态)

[root@m01 /hzl]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv1 2Gi RWX Retain Available 86m
persistentvolume/pv2 10Gi RWX Retain Bound default/pvc3 18s
persistentvolume/pv3 10Gi RWX Recycle Bound default/pvc1 75m

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc1 Bound pv3 10Gi RWX 68m
persistentvolumeclaim/pvc3 Bound pv2 10Gi RWX 3s


################################### 测试 #####################################

#进入容器测试
[root@m01 /hzl]# kubectl exec -it test-rwo-6dcb5687f-sxlmq -- bash
root@test-rwo-6dcb5687f-sxlmq:/# cd /data/
root@test-rwo-6dcb5687f-sxlmq:/data# ls
root@test-rwo-6dcb5687f-sxlmq:/data# touch hzl.txt
root@test-rwo-6dcb5687f-sxlmq:/data# ls
hzl.txt




#查看挂载目录测试状态(文件已创建)
[root@m01 /nfs/v3]# cd /nfs/v3/
[root@m01 /nfs/v3]# pwd
/nfs/v3
[root@m01 /nfs/v3]# ls
hzl.txt




#删除pv、pvc
[root@m01 /hzl]# kubectl delete pv pvc3
persistentvolume "pvc3" deleted
[root@m01 /hzl]# kubectl delete pv pv2
persistentvolume "pv2" deleted



#查看挂载点状态
[root@m01 /nfs/v3]# ll
总用量 0
-rw-r--r-- 1 root root 0 810 00:56 hzl.txt



ps :

4、nfs存储卷(多点挂载使用)

#更改pv、pvc策略
[root@m01 /hzl]# cat pv2.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv2
labels:
app: pv2
spec:
nfs:
path: /nfs/v2
server: 192.168.15.55
accessModes:
- "ReadOnlyMany" #更改模式
capacity:
storage: 10Gi


[root@m01 /hzl]# cat pvc3.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc3
spec:
accessModes:
- "ReadOnlyMany" #更改模式
resources:
requests:
storage: "6Gi"


#编写资源清单
[root@m01 /hzl]# cat deployment1.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: test-rwo-2
spec:
selector:
matchLabels:
app: test-rwo-2
template:
metadata:
labels:
app: test-rwo-2
spec:
containers:
- name: nginx1
image: nginx
volumeMounts:
- mountPath: /data/
name: test-rwo

volumes:
- name: test-rwo
persistentVolumeClaim:
claimName: pvc3



#创建pv,pvc
[root@m01 /hzl]# kubectl apply -f pv2.yaml
persistentvolumeclaim/pv2 unchanged
[root@m01 /hzl]# kubectl apply -f pvc3.yaml
persistentvolumeclaim/pvc3 unchanged
#创建pod
[root@m01 /hzl]# kubectl apply -f deployment1.yaml
deployment.apps/test-rwo-2 unchanged



#查看pc,pvc(pvc3已经绑定pv2上)
[root@m01 /hzl]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv1 2Gi RWX Retain Available 155m
persistentvolume/pv2 10Gi ROX Retain Bound default/pvc3 18s
persistentvolume/pv3 10Gi RWX Recycle Bound default/pvc1 144m

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc1 Bound pv3 10Gi RWX 137m
persistentvolumeclaim/pvc3 Bound pv2 10Gi ROX 10s




#查看pod
[root@m01 /hzl]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-rwo-2-66ddb84cf7-tw4mx 1/1 Running 0 31m
test-rwo-6dcb5687f-s496r 1/1 Running 0 13s




[root@m01 /hzl]# kubectl exec -it test-rwo-2-66ddb84cf7-tw4mx -- bash
Defaulted container "nginx1" out of: nginx1, nginx2
root@test-rwo-2-66ddb84cf7-tw4mx:/# cd /data/
root@test-rwo-2-66ddb84cf7-tw4mx:/data# touch 123.txt
root@test-rwo-2-66ddb84cf7-tw4mx:/data# ls
123.txt



[root@m01 /hzl]# kubectl exec -it test-rwo-6dcb5687f-s496r -- bash
root@test-rwo-2-66ddb84cf7-tw4mx:/# cd /data/
root@test-rwo-2-66ddb84cf7-tw4mx:/data# ls
123.txt

5、案列(数据持久化)

#先配置nfs服务器
[root@C8_58 test]# yum -y install nfs-utils
[root@C8_58 test]# cat /etc/exports
/data/test *(rw)
[root@C8_58 test]# mkdir -p /data/test
[root@C8_58 test]# echo nginx web > /data/test/index.html
[root@C8_58 test]# systemctl restart nfs-server

#测试能否正常挂载
[root@ubuntu-220 ~]# apt -y install nfs-server
[root@ubuntu-220 ~]# showmount -e 10.0.0.58
Export list for 10.0.0.58:
/data/test *
[root@ubuntu-220 ~]# mount -t nfs 10.0.0.58:/data/test /mnt/
[root@ubuntu-220 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
udev 955M 0 955M 0% /dev
tmpfs 198M 13M 185M 7% /run
/dev/sda2 98G 5.4G 88G 6% /
tmpfs 986M 0 986M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 986M 0 986M 0% /sys/fs/cgroup
/dev/loop1 97M 97M 0 100% /snap/core/9665
/dev/loop0 98M 98M 0 100% /snap/core/10444
/dev/sda3 976M 146M 764M 16% /boot
/dev/sda5 95G 61M 91G 1% /data
tmpfs 198M 0 198M 0% /run/user/0
10.0.0.58:/data/test 50G 390M 50G 1% /mnt

#编写资源清单
[root@ubuntu-200 ~]# cat volume-nfs.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-nfs
labels:
app: nginx-nfs
spec:
containers:
- name: nginx-nfs
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: my-nfs-volume
volumes:
- name: my-nfs-volume
nfs:
server: 10.0.0.58
path: /data/test

---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ports:
- name: http
port: 81
targetPort: 80
nodePort: 30016
protocol: TCP
type: NodePort
selector:
app: nginx-nfs

#创建Pod及service
[root@ubuntu-200 ~]# kubectl apply -f volume-nfs.yaml
[root@ubuntu-200 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-nfs 1/1 Running 0 24m 10.244.2.67 ubuntu-210 <none> <none>
[root@ubuntu-200 ~]# kubectl get service nginx-service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-service NodePort 10.104.177.209 <none> 81:30016/TCP 25m app=nginx-nfs

#进入Pod查看是否挂载成功
[root@ubuntu-200 ~]# kubectl exec -it nginx-nfs -- bash
root@nginx-nfs:/# cat /usr/share/nginx/html/index.html
nginx web




##########################################################################



#编辑资源清单
[root@ubuntu-200 ~]# cat volume-nfs-redis.yaml
apiVersion: v1
kind: Pod
metadata:
name: volume-nfs-redis
labels:
app: redis
spec:
containers:
- name: redis
image: redis:alpine
securityContext: #配置了这项,需要在nfs服务器让id为999的账户对共享的命令有读写写权限
runAsUser: 999
ports:
- containerPort: 6379
name: redisport
volumeMounts:
- mountPath: /data
name: redisdata
volumes:
- name: redisdata
nfs:
server: 10.0.0.58
path: /data/redis
readOnly: false

#创建pod
[root@ubuntu-200 ~]# kubectl apply -f volume-nfs-redis.yaml

#进入Pod
[root@ubuntu-200 ~]# kubectl exec -it volume-nfs-redis -- /bin/sh
#登录redis并创建
/data $ redis-cli
127.0.0.1:6379> set name yang
OK
127.0.0.1:6379> get name
"yang"
127.0.0.1:6379> bgsave
#查看创建的redis文件
/data $ ls -l
total 4
-rw-r--r-- 1 1099 nobody 120 Dec 9 13:19 dump.rdb

#在nfs服务器主机上也能看到
[root@C8_58 ~]# ll /data/redis/
total 4
-rw-r--r-- 1 redis nobody 120 Dec 9 21:19 dump.rdb

#删除镜像,重新创建一次
[root@ubuntu-200 ~]# kubectl delete -f volume-nfs-redis.yaml
pod "volume-nfs-redis" deleted
[root@ubuntu-200 ~]# kubectl apply -f volume-nfs-redis.yaml
pod/volume-nfs-redis created
[root@ubuntu-200 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
volume-nfs-redis 1/1 Running 0 8s 10.244.2.71 ubuntu-210 <none> <none>

#再次进入pod,可看到数据仍然存在,已实现持久化.
[root@ubuntu-200 ~]# kubectl exec -it volume-nfs-redis -- /bin/sh
/data $ ls
dump.rdb
/data $ redis-cli
127.0.0.1:6379> get name
"yang"

【 使用存储卷搭建lnmp】

1、创建资源清单(数据库)

#资源清单编写:(数据库)
[root@m01 /hzl]# cat mysql.yaml
kind: Namespace
apiVersion: v1
metadata:
name: mysql
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: mysql
namespace: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
- name: MYSQL_DATABASE
value: discuz
livenessProbe:
exec:
command:
- "/bin/sh"
- "-c"
- "cat /etc/mysql/my.cnf"
initialDelaySeconds: 0
periodSeconds: 3
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
readinessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 30
periodSeconds: 1
timeoutSeconds: 1
successThreshold: 3
failureThreshold: 1
---
kind: Service
apiVersion: v1
metadata:
name: mysql
namespace: mysql
spec:
ports:
- port: 3306
targetPort: 3306
protocol: TCP
name: mysql
selector:
app: mysql




#创建pod
[root@m01 /hzl]# kubectl apply -f mysql.yaml
namespace/mysql unchanged
deployment.apps/mysql configured
service/mysql unchanged



#查看pod
[root@m01 /hzl]# kubectl get -n mysql pods
NAME READY STATUS RESTARTS AGE
mysql-7795495b8b-b2lwq 1/1 Running 0 28m



#查看svc
[root@m01 /hzl]# kubectl get svc -n mysql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql ClusterIP 10.102.58.127 <none> 3306/TCP 36m

2、创建资源清单(web+php)

#资源清单编写:
[root@m01 /hzl]# cat descuz.yaml
kind: Namespace
apiVersion: v1
metadata:
name: web
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: discuz
labels:
app: discuz
spec:
persistentVolumeReclaimPolicy: Retain
nfs:
path: /nfs/discuz
server: 192.168.15.55
accessModes:
- "ReadWriteMany"
capacity:
storage: 10Gi
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: discuz
namespace: web
spec:
accessModes:
- "ReadWriteMany"
resources:
requests:
storage: "6Gi"
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: discuz
namespace: web
spec:
replicas: 5
selector:
matchLabels:
app: discuz
template:
metadata:
labels:
app: discuz
spec:
containers:
- name: php
image: registry.cn-hangzhou.aliyuncs.com/k8sos/web:discuz-php-v1
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/share/nginx/html/
name: discuz
- name: nginx
image: registry.cn-hangzhou.aliyuncs.com/k8sos/web:discuz-v1
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/share/nginx/html/
name: discuz
volumes:
- name: discuz
persistentVolumeClaim:
claimName: discuz
---
kind: Service
apiVersion: v1
metadata:
name: discuz
namespace: web
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
nodePort: 30080
type: NodePort
selector:
app: discuz




#创建pod
[root@m01 /hzl]# kubectl apply -f discuz.yaml
namespace/discuz unchanged
deployment.apps/discuz configured
service/discuz unchanged




#查看pod
[root@m01 /hzl]# kubectl get -n web pods
NAME READY STATUS RESTARTS AGE
discuz-587854655b-5h4q8 2/2 Running 0 15m
discuz-587854655b-97wr2 2/2 Running 0 15m
discuz-587854655b-9ktlb 2/2 Running 0 15m
discuz-587854655b-lzqf2 2/2 Running 0 15m
discuz-587854655b-vjqm9 2/2 Running 0 15m




#查看pv,pvc状态
[root@m01 /hzl]# kubectl get svc -n web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
discuz NodePort 10.102.201.10 <none> 80:30080/TCP 17m
[root@m01 /hzl]# kubectl get pv,pvc

3、测试部署(lnmp)

#查看svc
[root@m01 /hzl]# kubectl get svc -n web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
discuz NodePort 10.102.201.10 <none> 80:30080/TCP 17m




#给配置文件添加权限(用户www)
[root@m01 /nfs]# useradd www
[root@m01 /nfs]# chown +777 -R /nfs/discuz/ #授最高权限
[root@m01 /nfs]# chown www.www -R /nfs/discuz/
[root@m01 /nfs]# ll
总用量 4
drwxrwxrwx 14 www www 4096 810 04:01 discuz


#使用浏览器测试:ok

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_k8s_05

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_pv_06


@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_k8s_07

五、StorageClass(存储类别)

PV是需要运维人员手动创建的,开发操作PVC,可是大规模集群中可能会有很多PV,如果这些PV都需要运维手动来处理这也是一件很繁琐的事情,所以就有了动态供给概念,也就是Dynamic Provisioning。而我们上面的创建的PV都是静态供给方式,也就是Static Provisioning。而动态供给的关键就是StorageClass,它的作用就是创建PV模板

每一个存储类都包含provisioner、parameters和reclaimPolicy这三个参数域,当一个属于某个类的PersistentVolume需要被动态提供时,将会使用上述的参数域

1、简述StorageClass

1>StorageClass作为对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端存储的细节,一方面减少了用户对存储资源细节的关注,另一方面减少了管理员手工管理PV的工作,由系统自动完成PV的创建和绑定,实现了动态的资源供应

2>StorageClass的定义主要包括名称、后端存储的提供者(privisioner)和后端存储的相关参数配置

3>StorageClass一旦被创建,就无法修改,如需修改,只能删除重建

基本框架:

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_emptydir_08

2、StorageClass的使用

​【helm官方网站】​

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_hostpath_09

1# 下载helm
[root@m01 /hzl]# wget https://get.helm.sh/helm-v3.3.4-linux-amd64.tar.gz
--2021-08-10 10:35:32-- https://get.helm.sh/helm-v3.3.4-linux-amd64.tar.gz
正在解析主机 get.helm.sh (get.helm.sh)... 152.199.39.108, 2606:2800:247:1cb7:261b:1f9c:2074:3c
# 解压
[root@m01 /hzl]# tar xf helm-v3.3.4-linux-amd64.tar.gz





2# 安装工作目录
[root@m01 /hzl]# mv linux-amd64/helm /usr/local/bin/





3# 验证安装
[root@m01 /hzl]# helm version
version.BuildInfo{Version:"v3.3.4", GitCommit:"a61ce5633af99708171414353ed49547cf05013d", GitTreeState:"clean", GoVersion:"go1.14.9"}





4#添加仓库
# 阿里云镜像仓库(推荐使用)
[root@m01 /hzl]# helm repo add ali-stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
"ali-stable" has been added to your repositories
# 官方仓库
[root@m01 /hzl]# helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories





5# 查看仓库列表
[root@m01 /hzl]# helm repo list
NAME URL
ali-stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
bitnami https://charts.bitnami.com/bitnami






6#创建helm使用目录(缓存、配置文件、数据存放目录)
[root@m01 ~]# mkdir -p $HOME/.cache/helm
[root@m01 ~]# mkdir -p $HOME/.config/helm
[root@m01 ~]# mkdir -p $HOME/.local/share/helm





7#查找搜索安装包
[root@m01 /hzl]# helm search repo nginx
NAME CHART VERSION APP VERSION DESCRIPTION
ali-stable/nginx-ingress 0.9.5 0.10.2 An nginx Ingress controller that uses ConfigMap...
ali-stable/nginx-lego 0.3.1 Chart for nginx-ingress-controller and kube-lego
bitnami/nginx 9.4.2 1.21.1 Chart for the nginx server
bitnami/nginx-ingress-controller 7.6.18 0.48.1 Chart for the nginx Ingress controller
bitnami/kong 3.8.1 2.5.0 Kong is a scalable, open source API layer (aka ...
ali-stable/gcloud-endpoints 0.1.0 Develop, deploy, protect and monitor your APIs ...







8# 使用helm下载mysql测试
[root@m01 /hzl]# helm search repo mysql #搜索mysql
NAME CHART VERSION APP VERSION DESCRIPTION
ali-stable/mysql 0.3.5 Fast, reliable, scalable, and easy to use open-...
bitnami/mysql 8.8.3 8.0.26 Chart to create a Highly available MySQL cluster
ali-stable/percona 0.3.0 free, fully compatible, enhanced, open source d...
ali-stable/percona-xtradb-cluster 0.0.2 5.7.19 free, fully compatible, enhanced, open source d...
bitnami/phpmyadmin 8.2.11 5.1.1 phpMyAdmin is an mysql administration frontend
ali-stable/gcloud-sqlproxy 0.2.3 Google Cloud SQL Proxy
ali-stable/mariadb 2.1.6 10.1.31 Fast, reliable, scalable, and easy to use open-...
bitnami/mariadb 9.4.2 10.5.12 Fast, reliable, scalable, and easy to use open-...
bitnami/mariadb-cluster 1.0.2 10.2.14 DEPRECATED Chart to create a Highly available M...
bitnami/mariadb-galera 5.11.2 10.5.11 MariaDB Galera is a multi-master database clust...
[root@m01 /hzl]# helm pull bitnami/mysql
[root@m01 /hzl]# ll |grep mysql
-rw-r--r-- 1 root root 38954 810 11:05 mysql-8.8.3.tgz

【helm安装nfs(storageclass)】

1#使用helm安装
[root@m01 ~]# helm repo add ckotzbauer https://ckotzbauer.github.io/helm-charts
"ckotzbauer" has been added to your repositories #添加仓库
[root@m01 ~]# helm search repo nfs-client #搜索nfs-client
NAME CHART VERSION APP VERSION DESCRIPTION
ckotzbauer/nfs-client-provisioner 1.0.2 3.1.0 nfs-client is an automatic provisioner that use...
[root@m01 ~]# helm pull ckotzbauer/nfs-client-provisioner #使用helm进行拉取
[root@m01 ~]# ll |grep nfs-client-provisioner
-rw-r--r-- 1 root root 4802 810 2021 nfs-client-provisioner-1.0.2.tgz
[root@m01 ~]# tar xf nfs-client-provisioner-1.0.2.tgz






2#跟改文件使用参(下图所示)
[root@m01 ~/nfs-client-provisioner]# vim values.yaml






3#安装nfs
[root@m01 ~/nfs-client-provisioner]# helm install nfs ./
NAME: nfs
LAST DEPLOYED: Tue Aug 10 11:50:50 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
#卸载
[root@m01 ~/nfs-client-provisioner]# helm uninstall nfs





4#查看pod
[root@m01 ~/nfs-client-provisioner]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-nfs-client-provisioner-5c854cb79b-pph46 1/1 Running 0 2m17s





5#查看创建的nfs集群(默认命名空间为default)
[root@m01 ~/nfs-client-provisioner]# kubectl get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-storagclass (default) cluster.local/nfs-nfs-client-provisioner Delete Immediate true 4m4s







------------------------------------------------------------------------------------------------------------------------------------------------------
(问题1)
#添加配置文件(如果有报错,使用此参数)
[root@m01 /hzl]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
......
....
- --feature-gates=RemoveSelfLink=false #自动链接
......
....
[root@m01 /hzl]# kubectl delete -n kube-system pod kube-apiserver
[root@m01 /hzl]# kubectl apply -f kube-apiserver.yaml

(问题2)
#创建使用目录
[root@m01 /hzl]# mkdir /nfs/v1 -p
[root@m01 /hzl]# chown +777 -R /nfs/v1`


1、使用storageclasses

#资源清单编写
[root@m01 /hzl]# cat sc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
namespace: default
name: test-nfs
labels:
app: test-nfs
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-storagclass #名称与创建时nfs时一致
resources:
requests:
storage: 8Gi

---
kind: Deployment
apiVersion: apps/v1
metadata:
name: test-nfs-storageclass
namespace: default
labels:
app: test-nfs
spec:
selector:
matchLabels:
app: test-nfs
template:
metadata:
labels:
app: test-nfs
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-nfs
volumes:
- name: test-nfs
persistentVolumeClaim:
claimName: test-nfs





#创建pod
[root@m01 /hzl]# kubectl apply -f sc.yaml
persistentvolumeclaim/test-nfs unchanged
deployment.apps/test-nfs-storageclass unchanged






#查看已挂载(正常绑定)
[root@m01 /hzl]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Bound pv3 10Gi RWX 13h
test-nfs Bound pvc-693904ab-62f6-45b1-8539-bb6d0f8c4053 8Gi RWX nfs-storagclass 15m



ps

【CSI存储机制】

Container Storage Interface(CSI)机制,用于在kubenetes和外部存储系统之间建立一套标准的存储管理接口,通过该接口为容器提供存储服务

1、CSI部署架构

@kubernetes(k8s)数据持久化Volume存储卷(emptyDir、hostPath、NFS、StorageClass)_k8s_10

2、CSI主要包括两个组件:

CSI Controller
CSI Node

【CSI Controller】

提供存储服务视角对存储资源和存储进行管理和操作,在k8s中建议部署为单实例Pod,可以使用StatefulSet和Deployment控制器进行部署,设置副本数为1,保证为一种存储插件只运行一个控制器实例。

#在Pod内部署两个容器:
【CSI Node】

对主机(Node)上的Volume进行管理和操作,建议使用DaemonSet,每个Node上都运行一个Pod

#在此Pod上部署如下两个容器:

(1)与kubelet通信的辅助sidecar容器node-driver-register,主要功能是将存储驱动注册到kubelet中


(2)CSI Driver存储驱动容器,由第三方存储提供商提供,主要功能是接收kubelet的调用,需要实现一系列与Node相关的CSI接口,例如NodePublishVolume接口(用于将Volume挂载到容器内的目标路径)、NodeUnpublishVolume接口(用于从容器中卸载Volume),等等。






ps :