K8s集群之 存储卷 PV PVC
目录
默写
1 如何将pod创建在指定的Node节点上
2 污点的种类(在node上设置)
一 挂载存储
1 emptyDir存储卷
2 hostPath存储卷
①在 node01 节点上创建挂载目录
② 在 node02 节点上创建挂载目录
③ 创建 Pod 资源
④ 在master上检测一下:curl
特点
作用
3 nfs共享存储卷
① 在stor01节点上安装nfs,并配置nfs服务
② master节点操作
③ 在nfs服务器上创建index.html
④ master节点操作
编辑 ⑤ 删除nfs相关pod,再重新创建,可以得到数据的持久化存储
4 挂载存储总结
二 PVC 和 PV
1 PVC 的使用逻辑:
2 创建 StorageClass
3 PV和PVC之间的相互作用遵循这个生命周期:
4 根据这 5 个阶段,PV 的状态有以下 4 种:
5 一个PV从创建到销毁的具体流程:
6 回收策略,Retain、Delete和Recycle。
三 回收策略
nfs 支持全部三种
PV和PVC中的spec关键字段要匹配
四 NFS使用PV和PVC---静态
1 配置nfs存储
2 定义PV
3 定义PVC
4 测试访问
五 搭建 StorageClass + NFS,实现 NFS 的动态 PV 创建
1 在stor01节点上安装nfs,并配置nfs服务
2 创建 Service Account
3 使用 Deployment 来创建 NFS Provisioner
4 创建 NFS Provisioner
5 创建 StorageClass,负责建立 PVC 并调用 NFS provisioner 进行预定的工作,并让 PV 与 PVC 建立关联
6 创建 PVC 和 Pod 测试
7 PVC 通过 StorageClass 自动申请到空间
8 发现 NFS 服务器上存在,说明验证成功
默写
1 如何将pod创建在指定的Node节点上
node亲和、pod亲和、pod反亲和:
调度策略 匹配标签 操作符
nodeAffinity 主机 In,NotIn,Exists,DoesNotExist,Gt,Lt
podAffinity pod In,NotIn,Exists,DoesNotExist,
podAntiAffinity pod In,NotIn,Exists,DoesNotExist,
调度目标指定主机Pod与指定Pod同一拓扑域Pod与指定Pod不在同一拓扑域
2 污点的种类(在node上设置)
当前 taint effect 支持如下三个选项:
Noschedule:表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上
PreferNoschedule:表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node 上
NoExecute:表示 k8s 将不会将 pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 pod 驱逐出去
一 挂载存储
容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。
首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。
其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件。
Kubernetes 中的Volume抽象就很好的解决了这些问题。Pod中的容器通过Pause容器共享 Volume。
总结:(用本地磁盘进行挂载,把本地数据挂载虚拟机中做持久化)
查看支持存储卷类型:
kubectl explain pod.spec.volumes
1 emptyDir存储卷
当Pod被分配给节点时,首先创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。
Pod 中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 Pod 时,emptyDir中的数据将被永久删除。
总结:依赖于某一个容器,从一个容器挂载到另一个容器
临时性存储:
emptyDir 提供的存储是临时的,其生命周期与所属的 Pod 相关。
当 Pod 被删除时,emptyDir 中的数据也会被清除,因此不适合用于持久化存储。
Pod 内容器之间的共享:
emptyDir 在同一个 Pod 中的所有容器之间共享,容器可以读写其中的数据。
创建时机:
emptyDir 在 Pod 创建时被创建,当容器启动时,可以访问其中的空目录。
用途
适用于需要在同一个 Pod 中的多个容器之间进行临时数据交换或共享的场景。
例如,可以用于容器间的缓存共享、临时文件存储等用途。
理论版
vim pod-emptydir.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-emptydirnamespace: defaultlabels: #加两个标签app: myapptier: frontend
spec:containers:- name: myappimage: ikubernetes/myapp:v1 #定义镜像imagePullPolicy: IfNotPresent #拉取策略ports:- name: httpcontainerPort: 80#定义容器挂载内容volumeMounts:#使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷- name: html#挂载至容器中哪个目录mountPath: /usr/share/nginx/html/- name: busyboximage: busybox:latestimagePullPolicy: IfNotPresentvolumeMounts:- name: html#在容器内定义挂载存储名称和挂载路径mountPath: /data/command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done'] #等待2s就结束
#定义存储卷volumes:#定义存储卷名称 - name: html#定义存储卷类型emptyDir: {}
实践版 搭建
apiVersion: v1
kind: Pod
metadata:name: pod-emptydirnamespace: defaultlabels:app: myapp
spec:containers:- name: myappimage: soscscs/myapp:v1imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80volumeMounts:- name: ky35mountPath: /usr/share/nginx/html/- name: busyboximage: busybox:latestimagePullPolicy: IfNotPresentvolumeMounts:- name: ky35mountPath: /data/command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']volumes:- name: ky35emptyDir: {}
kubectl apply -f pod-emptydir.yamlkubectl get pods -o wide
kubectl exec -it pod-emptydir -c busybox sh #进入容器
概括:定义了2个容器,其中一个容器是输入日期到index.html中,然后验证访问nginx的html是否可以获取日期。以验证两个容器之间挂载的emptyDir实现共享。
总结:
emptypir: 可以实现pod中的容器之间共享数据,但是存储卷不能持久化数据,且会随着pod 生命周结束而一起删除
hostpath: 可以实现持久化存储,使用node节点的目录或文件挂载到容器,但是存储空间会受到弄得节点单机限制,node节点故障数据会丢失,pod跨节点不能共享数据
失败总结------强制删除
kubectl delete pod pod-emptydir --force --grace-period=0
2 hostPath存储卷
hostPath卷将 node 节点的文件系统中的文件或目录挂载到集群中。
hostPath可以实现持久存储,但是在node节点故障时,也会导致数据的丢失。
apiVersion: v1
kind: Pod
metadata:name: pod-hostpathnamespace: default
spec:containers:- name: myappimage: soscscs/myapp:v1#定义容器挂载内容volumeMounts:#使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷- name: html#挂载至容器中哪个目录mountPath: /usr/share/nginx/html#读写挂载方式,默认为读写模式falsereadOnly: false#volumes字段定义了paues容器关联的宿主机或分布式文件系统存储卷volumes:#存储卷名称- name: html#路径,为宿主机存储路径hostPath:#在宿主机上目录的路径path: /data/pod/volume1#定义类型,这表示如果宿主机没有此目录则会自动创建type: DirectoryOrCreate
①在 node01 节点上创建挂载目录
mkdir -p /data/pod/volume1
echo 'node01.kgc.com' > /data/pod/volume1/index.html
② 在 node02 节点上创建挂载目录
mkdir -p /data/pod/volume1
echo 'node02.kgc.com' > /data/pod/volume1/index.html
③ 创建 Pod 资源
vim pod-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-hostpathnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1#定义容器挂载内容volumeMounts:#使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷- name: html#挂载至容器中哪个目录mountPath: /usr/share/nginx/html#读写挂载方式,默认为读写模式falsereadOnly: false #代表了可读可查都可以进行#volumes字段定义了paues容器关联的宿主机或分布式文件系统存储卷volumes:#存储卷名称- name: html#路径,为宿主机存储路径hostPath:#在宿主机上目录的路径path: /data/pod/volume1#定义类型,这表示如果宿主机没有此目录则会自动创建type: DirectoryOrCreate
④ 在master上检测一下:curl
kubectl apply -f pod-hostpath.yaml
访问测试
kubectl get pods -o wide
注意:若启动不run 就重启一下
特点
直接访问主机文件系统: HostPath存储卷允许Pod直接访问主机节点上的文件系统,提供了对主机存储的直接访问权限。
读写权限: Pod可以对HostPath上的文件进行读写操作,这为一些需要在容器内进行文件操作的应用提供了便利。
节点依赖性: Pod使用HostPath时,会依赖节点上的具体路径,这可能导致在不同节点上部署相同Pod时出现问题,因为节点之间的文件系统路径可能不同。
共享资源:多个Pod可以共享同一个HostPath,但要小心避免数据冲突或竞争条件
作用
主机文件操作: 适用于需要在Pod内进行主机文件系统操作的场景,例如读取或写入主机上的特 定文件。
数据共享: 多个Pod可以共享同一个HostPath,这在一些需要多个Pod之间共享数据的情况下可 能很有用。
特殊需求: 用于满足一些特殊需求,例如某些应用需要在容器内直接操作主机上的某些文件。
需要注意的是,由于HostPath存储卷的使用可能涉及到权限和安全性的考虑,一般情况下建议慎重使用,并确保在生产环境中采取适当的安全措施
3 nfs共享存储卷
注意:只是共享存储,没有存储能力,pod可以跨node节点共享数据
NAS存储设备 + NFS 才能共享出去
GFS--自动搭 ceph---第三方 NAS---第三方
云端存储:oss s3 SLB LB CDN AWS
① 在stor01节点上安装nfs,并配置nfs服务
在stor01节点上安装nfs,并配置nfs服务
mkdir /data/volumes -p
chmod 777 /data/volumes
vim /etc/exports
/data/volumes 192.168.10.0/24(rw,no_root_squash)systemctl start rpcbind
systemctl start nfsshowmount -e
Export list for stor01:
/data/volumes 192.168.10.0/24
做映射
② master节点操作
kind: Pod
vim pod-nfs-vol.yaml
apiVersion: v1
metadata:name: pod-vol-nfsnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlnfs:path: /data/volumesserver: stor01
apiVersion: v1
kind: Pod
metadata:name: pod-nfsnamespace: default
spec:containers:- name: myappimage: soscscs/myapp:v1volumeMounts:- name: ky35mountPath: /usr/share/nginx/htmlvolumes:- name: ky35nfs:path: /data/volumesserver: 192.168.11.14
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节点操作
⑤ 删除nfs相关pod,再重新创建,可以得到数据的持久化存储
kubectl delete -f demo03.yaml
kubectl delete -f pod-nfs-vol.yaml
失败总结
特点
共享性: NFS存储卷允许多个Pod在集群中共享同一个NFS服务器上的存储空间。这使得多个应 用程序可以访问和操作相同的数据,促进了数据共享和协作。
持久性: NFS存储卷提供了持久化的存储解决方案,数据存储在NFS服务器上并且在Pod重新启 动或迁移时仍然可用。这对于需要长期保存数据的应用程序和服务非常有用。
可扩展性: NFS存储卷可以轻松地扩展以满足应用程序的需求。通过在NFS服务器上添加更多的 存储空间或者增加NFS服务器的数量,可以扩展存储容量和性能。
灵活性: 使用NFS存储卷可以将存储与Pod分离,从而使得Pod可以在不同的节点上迁移而不会丢 失数据。这种灵活性使得在Kubernetes集群中部署和管理应用程序变得更加容易。
用途
简化管理: NFS存储卷可以通过Kubernetes的PV和PVC对象进行声明和管理,而无需手动管理存 储配置。这简化了存储管理的流程,并提高了部署和维护的效率。
适用范围广泛: NFS存储卷适用于许多不同类型的应用程序和场景,包括数据库、文件共享、日 志存储等。它提供了一种通用的存储解决方案,适用于各种不同的业务需求。
4 挂载存储总结
emptypir :可以实现Pod中的容器之间共享数据,但是存储卷不能持久化数据,且会随着pod 生命周结束而一起删除
hostpath:可以实现持久化存储,使用node节点的目录或文件挂载到容器,但是存储空间会受到弄得节点单机限制,node节点故障数据会丢失,poa跨节点不能共享数据
nfs:可以实现持久化存储,使用nfs将存储设别空间挂载到容器中,pod可以跨node节点共享数据
二 PVC 和 PV
PV 全称叫做 Persistent Volume,持久化存储卷。它是用来描述或者说用来定义一个存储卷的,这个通常都是由运维工程师来定义。
PVC 的全称是 Persistent Volume Claim,是持久化存储的请求。它是用来描述希望使用什么样的或者说是满足什么条件的 PV 存储。
1 PVC 的使用逻辑:
在 Pod 中定义一个存储卷(该存储卷类型为 PVC),定义的时候直接指定大小,PVC 必须与对应的 PV 建立关系,PVC 会根据配置的定义去 PV 申请,而 PV 是由存储空间创建出来的。PV 和 PVC 是 Kubernetes 抽象出来的一种存储资源。
上面介绍的PV和PVC模式是需要运维人员先创建好PV,然后开发人员定义好PVC进行一对一的Bond,但是如果PVC请求成千上万,那么就需要创建成千上万的PV,对于运维人员来说维护成本很高,Kubernetes提供一种自动创建PV的机制,叫StorageClass,它的作用就是创建PV的模板。
2 创建 StorageClass
需要定义 PV 的属性,比如存储类型、大小等;另外创建这种 PV 需要用到的存储插件,比如 Ceph 等。 有了这两部分信息,Kubernetes 就能够根据用户提交的 PVC,找到对应的 StorageClass,然后 Kubernetes 就会调用 StorageClass 声明的存储插件,自动创建需要的 PV 并进行绑定。
- 存储: 存储工程师运维
- PV: k8s 管理员运维
- PVC: 用户维护
PV是集群中的资源, PVC是对这些资源的请求,也是对资源的索引检查。
3 PV和PVC之间的相互作用遵循这个生命周期:
Provisioning(配置)---> Binding(绑定)---> Using(使用)---> Releasing(释放) ---> Recycling(回收)
Provisioning:即 PV 的创建,可以直接创建 PV(静态方式),也可以使用 StorageClass 动态 创建
Binding:将 PV 分配给 PVC
Using:Pod 通过 PVC 使用该 Volume,并可以通过准入控制StorageProtection(1.9及以前版本 为PVCProtection) 阻止删除正在使用的 PVC
Releasing:Pod 释放 Volume 并删除 PVC
Reclaiming:回收 PV,可以保留 PV 以便下次使用,也可以直接从云存储中删除
4 根据这 5 个阶段,PV 的状态有以下 4 种:
- Available(可用):表示可用状态,还未被任何 PVC 绑定
- Bound(已绑定):表示 PV 已经绑定到 PVC
- Released(已释放):表示 PVC 被删掉,但是资源尚未被集群回收
- Failed(失败):表示该 PV 的自动回收失败
5 一个PV从创建到销毁的具体流程:
1 一个PV创建完后状态会变成Available,等待被PVC绑定。
2 一旦被PVC邦定,PV的状态会变成Bound,就可以被定义了相应PVC的Pod使用。
3 Pod使用完后会释放PV,PV的状态变成Released。
4 变成Released的PV会根据定义的回收策略做相应的回收工作。
6 回收策略,Retain、Delete和Recycle。
Retain就是保留现场,K8S集群什么也不做,等待用户手动去处理PV里的数据,处理完后,再手 动删除PV。
Delete策略,K8S会自动删除该PV及里面的数据。
Recycle方式,K8S会将PV里的数据删除,然后把PV的状态变成Available,又可以被新的PVC绑 定使用。
三 回收策略
kubectl explain pv.spec #查看pv定义的规格
kubectl explain pv #查看pv的定义方式
FIELDS:apiVersion: v1kind: PersistentVolumemetadata: #由于 PV 是集群级别的资源,即 PV 可以跨 namespace 使用,所以 PV 的 metadata 中不用配置 namespacename: speckubectl explain pv.spec #查看pv定义的规格
spce:nfs:(定义存储类型)path:(定义挂载卷路径)server:(定义服(定义访问模型,务器名称)accessModes:有以下三种访问模型,以列表的方式存在,也就是说可以定义多个访问模式) * * *- ReadWriteOnce #(RWO)存储可读可写,但只支持被单个 Pod 挂载- ReadOnlyMany #(ROX)存储可以以只读的方式被多个 Pod 挂载- ReadWriteMany #(RWX)存储可以以读写的方式被多个 Pod 共享 注:官网
#nfs 支持全部三种;iSCSI 不支持 ReadWriteMany(iSCSI 就是在 IP 网络上运行 SCSI 协议的一种网络存储技术);HostPath 不支持 ReadOnlyMany 和 ReadWriteMany。capacity:(定义存储能力,一般用于设置存储空间)storage: 2Gi (指定大小)storageClassName: (自定义存储类名称,此配置用于绑定具有相同类别的PVC和PV)persistentVolumeReclaimPolicy: Retain #回收策略(Retain/Delete/Recycle) * * *
#Retain(保留):当删除与之绑定的PVC时候,这个PV被标记为released(PVC与PV解绑但还没有执行回收策略)且之前的数据依然保存在该PV上,但是该PV不可用,需要手动来处理这些数据并删除该PV。
#Delete(删除):删除与PV相连的后端存储资源(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)
#Recycle(回收):删除数据,效果相当于执行了 rm -rf /thevolume/* (只有 NFS 和 HostPath 支持)kubectl explain pvc #查看PVC的定义方式
KIND: PersistentVolumeClaim
VERSION: v1
FIELDS:apiVersion <string>kind <string> metadata <Object>spec <Object>
nfs 支持全部三种
iSCSI 不支持 ReadWriteMany(iSCSI 就是在 IP 网络上运行 SCSI 协议的一种网络存储技术);HostPath 不支持 ReadOnlyMany 和 ReadWriteMany。
- capacity: (定义存储能力,一般用于设置存储空间)
- storage: 2Gi (指定大小)
- storageClassName: (自定义存储类名称,此配置用于绑定具有相同类别的PVC和PV)
persistentVolumeReclaimPolicy: Retain #回收策略(Retain/Delete/Recycle)
Retain(保留):当删除与之绑定的PVC时候,这个PV被标记为released(PVC与PV解绑但还没有执行回收策略)且之前的数据依然保存在该PV上,但是该PV不可用,需要手动来处理这些数据并删除该PV。Delete(删除):删除与PV相连的后端存储资源(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)Recycle(回收):删除数据,效果相当于执行了 rm -rf /thevolume/* (只有 NFS 和 HostPath 支持)
kubectl explain pv.spec #查看pv定义的规格
PV和PVC中的spec关键字段要匹配
比如存储(storage)大小、访问模式(accessModes)、存储类名称(storageClassName)
kubectl explain pvc.spec
spec:accessModes: (定义访问模式,必须是PV的访问模式的子集)resources:requests:storage: (定义申请资源的大小)storageClassName: (定义存储类名称,此配置用于绑定具有相同类别的PVC和PV)
四 NFS使用PV和PVC---静态
结论:只能创建一些简单的,
官方文档:
https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-persistentvolume
1 配置nfs存储
mkdir v{1,2,3,4,5}
vim /etc/exports
/data/volumes/v1 192.168.10.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.10.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.10.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.10.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.10.0/24(rw,no_root_squash)exportfs -arv
showmount -e
2 定义PV
这里定义5个PV,并且定义挂载的路径以及访问模式,还有PV划分的大小。
vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: pv001labels:name: pv001
spec:nfs:path: /data/volumes/v1server:stor01 accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv002labels:name: pv002
spec:nfs:path: /data/volumes/v2server: stor01accessModes: ["ReadWriteOnce"]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv003labels:name: pv003
spec:nfs:path: /data/volumes/v3server: stor01accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv004labels:name: pv004
spec:nfs:path: /data/volumes/v4server: stor01accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv005labels:name: pv005
spec:nfs:path: /data/volumes/v5server: stor01accessModes: ["ReadWriteMany","ReadWriteOnce"]capacity:storage: 5Gi
术语解析
配置文件解析PersistentVolumeClaim (PVC)apiVersion: 指定了 Kubernetes API 的版本,这里是 v1。
kind: 资源类型,这里是 PersistentVolumeClaim,表示一个存储卷声明。
metadata: 包含资源的元数据,这里定义了 PVC 的名称为 mypvc。
spec: 规格定义部分。
accessModes: 定义了 PVC 的访问模式,这里是 ReadWriteMany,意味着存储卷可以被多个节点同时以读写方式挂载。
resources: 定义了资源请求。
requests: 指定了存储资源的请求量,这里是 2Gi。
PodapiVersion: 指定 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。
3 定义PVC
这里定义了pvc的访问模式为多路读写,该访问模式必须在前面pv定义的访问模式之中。定义PVC申请的大小为2Gi,此时PVC会自动去匹配多路读写且大小为2Gi的PV,匹配成功获取PVC的状态即为Bound
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mypvcnamespace: default
spec:accessModes: ["ReadWriteMany"]resources:requests:storage: 2Gi
apiVersion: v1
kind: Pod
metadata:name: pod-vol-pvcnamespace: default
spec:containers:- name: myappimage: ikubernetes/myapp:v1volumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlvolumes:- name: htmlpersistentVolumeClaim:claimName: mypvc
4 测试访问
在存储服务器上创建index.html,并写入数据,通过访问Pod进行查看,可以获取到相应的页面。
cd /data/volumes/v3/
echo "welcome to use pv3" > index.html
术语解析
PersistentVolumeClaim (PVC)apiVersion: 指定了 Kubernetes API 的版本,这里是 v1。
kind: 资源类型,这里是 PersistentVolumeClaim,表示一个存储卷声明。
metadata: 包含资源的元数据,这里定义了 PVC 的名称为 mypvc。
spec: 规格定义部分。
accessModes: 定义了 PVC 的访问模式,这里是 ReadWriteMany,意味着存储卷可以被多个节点同时以读写方式挂载。
resources: 定义了资源请求。
requests: 指定了存储资源的请求量,这里是 2Gi。
PodapiVersion: 指定 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。
步骤
静态创建PV的步骤:准备好存储设备和共享目录
准备创建PV资源的配置文件,定义访问模式(ReadWriteOnce、ReadOnlyMany、ReadWriteMany、ReadWriteMany)、存储空间大小、回收策略(Retain、Recycle、Delete)、存储设备类型、storageClassName等
准备创建PVC资源的配置文件,定义访问模式(必要条件,必须是PV支持的访问模式)、存储空间大小(默认就近选择大于等于指定大小的PV)、storageClassName等来绑定PV
创建Pod资源挂载PVC存储卷,定义卷类型为persistentVolumeClaim,并在容器配置中定义存储卷挂载点路径
五 搭建 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)。
内置插件:kubernetes.io/aws-ebs 是用于 AWS Elastic Block Store(EBS)的内置插件。它能够动态地创建和管理 AWS EBS 存储。外部插件 : ceph.com/cephfs,这是 Ceph 文件系统的外部插件。此外,nfs-client 也是一个外部插件,用于与 NFS 服务器集成,实现动态创建 PV。
1 在stor01节点上安装nfs,并配置nfs服务
mkdir /opt/k8s
chmod 777 /opt/k8s/vim /etc/exports
/opt/k8s 192.168.10.0/24(rw,no_root_squash,sync)systemctl restart nfs
2 创建 Service Account,
用来管理 NFS Provisioner 在 k8s 集群中运行的权限,设置 nfs-client 对 PV,PVC,StorageClass 等的规则
vim nfs-client-rbac.yaml
创建 Service Account 账户,用来管理 NFS Provisioner 在 k8s 集群中运行的权限
apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisioner
---
#创建集群角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: nfs-client-provisioner-clusterrole
rules:- apiGroups: [""]resources: ["persistentvolumes"]verbs: ["get", "list", "watch", "create", "delete"]- apiGroups: [""]resources: ["persistentvolumeclaims"]verbs: ["get", "list", "watch", "update"]- apiGroups: ["storage.k8s.io"]resources: ["storageclasses"]verbs: ["get", "list", "watch"]- apiGroups: [""]resources: ["events"]verbs: ["list", "watch", "create", "update", "patch"]- apiGroups: [""]resources: ["endpoints"]verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
---
#集群角色绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: nfs-client-provisioner-clusterrolebinding
subjects:
- kind: ServiceAccountname: nfs-client-provisionernamespace: default
roleRef:kind: ClusterRolename: nfs-client-provisioner-clusterroleapiGroup: rbac.authorization.k8s.io
3 使用 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.10.19
......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
4 创建 NFS Provisioner
注意:需要在两个节点加载镜像才行
vim nfs-client-provisioner.yaml
kind: Deployment
apiVersion: apps/v1
metadata:name: nfs-client-provisioner
spec:replicas: 1selector:matchLabels:app: nfs-client-provisionerstrategy:type: Recreatetemplate:metadata:labels:app: nfs-client-provisionerspec:serviceAccountName: nfs-client-provisioner #指定Service Account账户containers:- name: nfs-client-provisionerimage: quay.io/external_storage/nfs-client-provisioner:latestimagePullPolicy: IfNotPresentvolumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAMEvalue: nfs-storage #配置provisioner的Name,确保该名称与StorageClass资源中的provisioner名称保持一致- name: NFS_SERVERvalue: stor01 #配置绑定的nfs服务器- name: NFS_PATHvalue: /opt/k8s #配置绑定的nfs服务器目录volumes: #申明nfs数据卷- name: nfs-client-rootnfs:server: stor01path: /opt/k8s
注意:一直在创建中 是因为另外两个节点要加载镜像
5 创建 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: 通过 Kubernetes 的命令行工具 kubectl 应用(或创建)nfs-client-storageclass.yaml 文件中定义的资源,这里是一个 StorageClass。
kubectl get storageclass: 通过 kubectl 获取当前 Kubernetes 集群中所有的 StorageClass 列表。这可以用于确认上一步的 StorageClass 是否成功创建。
6 创建 PVC 和 Pod 测试
vim test-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: test-nfs-pvc
spec:accessModes:- ReadWriteManystorageClassName: nfs-client-provisioner #关联StorageClass对象resources:requests:storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:name: test-storageclass-pod
spec:containers:- name: busyboximage: busybox:latestimagePullPolicy: IfNotPresentcommand:- "/bin/sh"- "-c"args:- "sleep 3600"volumeMounts:- name: nfs-pvcmountPath: /mntrestartPolicy: Nevervolumes:- name: nfs-pvcpersistentVolumeClaim:claimName: test-nfs-pvc #与PVC名称保持一致
7 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
8 发现 NFS 服务器上存在,说明验证成功
相关文章:

K8s集群之 存储卷 PV PVC
目录 默写 1 如何将pod创建在指定的Node节点上 2 污点的种类(在node上设置) 一 挂载存储 1 emptyDir存储卷 2 hostPath存储卷 ①在 node01 节点上创建挂载目录 ② 在 node02 节点上创建挂载目录 ③ 创建 Pod 资源 ④ 在master上检测一下:…...

“腾讯云 AI 代码助手”体验
一、“腾讯云 AI 代码助手”体验 1、注册账号并进行实名认证 2、进入开发环境 3、体验javascript简单函数 代码如下: //请写一个两个日期计算的函数 function dateDiff(date1, date2) {return date2.getTime() - date1.getTime(); } var date1 new Date("2…...

Django入门全攻略:从零搭建你的第一个Web项目
系列文章目录 努力ing Django入门全攻略:从零搭建你的第一个Web项目努力ing… 文章目录 系列文章目录前言一、Django1.0 框架介绍1.1 Django安装1.2 Django项目创建1.3 目录介绍 二、子应用2.1 子应用创建2.2 目录结构2.3 子应用注册2.4 子应用视图逻辑2.4.1 编写视…...

AI大模型日报#0529:杨红霞创业入局“端侧模型”、Ilya左膀右臂被Claude团队挖走
导读:AI大模型日报,爬虫LLM自动生成,一文览尽每日AI大模型要点资讯!目前采用“文心一言”(ERNIE 4.0)、“零一万物”(Yi-34B)生成了今日要点以及每条资讯的摘要。欢迎阅读࿰…...

达梦数据库
达梦数据库 达梦Docker部署 达梦Docker部署 1、下载链接 https://pan.baidu.com/s/1RI3Lg0ppRhCgUsThjWV6zQ?pwdjc62 2、docker启动命令 docker run -d -p 5236:5236 \ --restartalways \ --name dm8 \ -e LD_LIBRARY_PATH/app/dm8/bin \ -e LENGTH_IN_CHAR1 \ -e CASE_SENS…...

什么是Axios
2024年5月23日,周四上午 Axios 是一个基于Promise的HTTP客户端,用于浏览器和node.js环境。它提供了一个简单易用的API来发送HTTP请求,并支持Promise API,这使得异步请求变得容易处理。 Axios的一些主要特点包括: Pro…...

React 其他 Hooks
其他 Hooks useRef 可用于获取 DOM 元素 const ScrollRef useRef(null)ScrollRef.current useContext (先回顾一下之前的 Context 知识,借用之前 ppt 和源码) Hooks 中使用 useContext 来获取 context 的值 // 父组件创建 contextexpor…...

echarts配置记录,一些已经废弃的写法
1、normal,4.0以后无需将样式写在normal中了 改前: 改后: DEPRECATED: normal hierarchy in labelLine has been removed since 4.0. All style properties are configured in labelLine directly now. 2、axisLabel中的文字样式无需使用te…...

电量计量芯片HLW8110的前端电路设计与误差分析校正.pdf 下载
电量计量芯片HLW8110的前端电路设计与误差分析校正.pdf 下载地址: 链接:https://pan.baidu.com/s/1vlCtC3LGFMzYpSUUDY-tEg 提取码:8110...

Redis实践记录与总结
最近生产环境缓存数据库数据过大(如何搭建单服务redis缓存数据库?以及可视化工具Another Redis Desktop Manager使用),导致在对数据库做rdb快照备份时消耗内存过大,缓存数据库宕机一小时。基础运维通过增加虚拟机内存暂…...

持续总结中!2024年面试必问 20 道 Rocket MQ面试题(三)
上一篇地址:持续总结中!2024年面试必问 20 道 Rocket MQ面试题(二)-CSDN博客 五、什么是生产者(Producer)和消费者(Consumer)在RocketMQ中? RocketMQ是一个高性能、高吞…...

Android 自定义Adapter关键函数getView性能最优使用
文章目录 1、自定义Adapter关键函数getView()标准写法2、布局文件list_item_user.xml3、解释3、示例使用4、结果5、进一步优化和扩展5.1. **优化性能:ViewHolder模式**5.2. **处理多种类型的视图**5.3. **使用RecyclerView.Adapter** 6、RecyclerView使用示例7、结果…...

Linux服务上MySQL的启动、重启和关闭
Linux服务上MySQL的启动、重启和关闭 MySQL是一种广泛使用的开源关系型数据库管理系统,常用于各种规模的应用程序中。在Linux服务器上管理MySQL服务是一个基本的运维任务。本文将详细介绍如何在Linux系统上启动、重启和关闭MySQL服务,涵盖不同Linux发行…...

ctfshow web入门 嵌入式 bash cpp pwn
kali转bash shell方法 方便我们本地 bash脚本教程 下面这个代码是bash脚本 #!/bin/bashOIFS"$IFS"IFS"," //表示逗号为字段分隔符set $QUERY_STRING //将参数传入数组Args($QUERY_STRING)IFS"$OIFS" //恢复原始IFS值if [ "$…...

【ONE·Git || 基本用法入门】
总言 主要内容:主要介绍Git中常用的指令。 PS:多人协作与企业开发模型使用,此部分内容不作博文总结。 文章目录 总言1、初识Git1.1、版本控制器1.2、git安装 2、基本操作2.1、Git本地仓库2.1.1、创建Git本地仓库&…...

【运维项目经历|021】Spark大数据分析平台建设项目
目录 项目名称 项目背景 项目目标 项目成果 我的角色与职责 我主要完成的工作内容 本次项目涉及的技术 本次项目遇到的问题与解决方法 本次项目中可能被面试官问到的问题 问题1:项目周期多久? 问题2:服务器部署架构方式及数量和配置…...

装机数台,依旧还会心念i5-12600KF的性能和性价比优势:
近几个月的时间中, 装机差不多4台电脑,由于工作需要,计划年中再增添一台。 目前市场上英特尔CPU促销非常火爆,第12代、第13代以及第14代的产品在年中有适当的优惠。 年中也是装机的旺季,各种相关配件也相对便宜一些。…...

Docker-----emqx部署
emqx通过Docker容器化部署流程 1.创建持久化挂载目录 mkdir -p /home/emqx/etc ------挂载emqx的配置文件目录 mkdir -p /home/emqx/data ------挂载emqx的存储目录 mkdir -p /home/emqx/log ------挂载emqx的日志目录 [root home]# mkdir -p /home/emqx/etc [root home]# mkd…...

三数之和-力扣
这道题在使用哈希表来做时,做的很吃力,对重复的去除很费劲。 首先是对i的去重,不能使用nums[i] nums[i] 这样的条件去判断,这会遗漏掉类似[-1, -1 , 2]这样的解其次是对j的去重, 对j的去重是为了防止类似[-4, 2, 2, …...

2024 五月份国内外CTF 散装re 部分wp
cr3CTF warmup 附件拖入ida main函数无法反汇编,仔细看,有花指令,jnz实际上必定跳转。有非常多处,可以写脚本patch程序去掉花指令,只要匹配指令,再获取跳转地址,nop掉中间的代码就行。但…...

[猫头虎分享21天微信小程序基础入门教程]第21天:小程序的社交分享与消息推送
[猫头虎分享21天微信小程序基础入门教程]第21天:小程序的社交分享与消息推送 第21天:小程序的社交分享与消息推送 📲 自我介绍 大家好,我是猫头虎,一名全栈软件工程师。今天我们继续微信小程序的学习,重…...

aop整理
一、aop基础知识 Spring AOP 详细深入讲解代码示例 二、spring/spring boot/spring cloud中出现的注解/类与概念的对应 Aspect: 标注当前MyAspect是一个切面类,–》对应切面的概念,在切面类中有用Before等注解修饰的方法作为advice,也有用…...

Sublime Text 基础教程(个人总结)
Sublime Text 是一款广受欢迎的代码编辑器,以其简洁的界面和强大的功能而著称。它支持多种编程语言,具有高效的代码编辑和管理功能。本教程将详细介绍如何使用 Sublime Text,从安装到高级使用技巧,帮助你充分利用这款工具。 目录…...

线程安全 - 笔记
1 程序a调用c.so,程序b也调用c.so c.so加载两次吗? 在这种情况下,通常 c.so 不会被加载两次。 当一个程序调用一个共享对象文件(.so)时,操作系统的动态链接器将该共享对象映射到进程的虚拟内存空间中。后续由不同程序或者同一个程序调用相同的共享对象,都不会导致共享…...

分支机构多,如何确保文件跨域传输安全可控?
随着企业全球化发展,分支机构的分布越来越广泛,跨域文件传输需求也随之增加。然而,跨域文件传输面临的数据安全和传输效率问题,使得构建一个安全、可控的文件交换系统成为迫切需求。FileLink跨网文件交换系统通过综合的技术手段和…...

长安链使用Golang编写智能合约教程(二)
长安链2.3.0的go合约虚拟机和2.3.0以下的不兼容,编译的方式也有差异,所以在ide上做了区分。 教程三会写一些,其他比较常用SDK方法的解释和使用方法 教程一:(长安链2.1.的版本的智能合约) 教程三ÿ…...

jpom linux发布前端 ruoyi
前置条件 辅助安装 安装jdk curl -fsSL https://jpom.top/docs/install.sh | bash -s Server jdkonly-moduledefault 一键安装maven 后端必备 curl -fsSL https://jpom.top/docs/install.sh | bash -s Server mvnonly-moduledefault 一键安装node 前端必备 curl -fsSL http…...

K8S认证|CKA题库+答案| 15. 备份还原Etcd
目录 15、 备份还原Etcd CKA v1.29.0模拟系统 下载试用 题目: 开始操作: 1)、切换集群 2)、登录master并提权 3)、备份Etcd现有数据 4)、验证备份数据快照 5)、查看节点和Pod状态 6࿰…...

软件架构设计属性之一:功能性属性浅析
文章目录 引言一、定义二、关键要素1. 需求满足2. 操作性3. 数据处理4. 业务流程支持5. 合规性 三、 设计原则1. 用户中心设计2. 模块化3. 抽象化4. 可扩展性5. 可维护性6. 设计原则的实施策略7. 设计原则的评估 四、实现策略1. 需求分析2. 功能分解3. 接口设计4. 技术选型5. 迭…...

学习Java的日子 Day48 函数,DOM
Day48 1.流程控制语句 if else for for-in(遍历数组时,跟Java是否一样) While do while break 语句用于跳出循环 continue 用于跳过循环中的一个迭代 2.函数 2.1 JavaScript 函数语法 函数就是包裹在花括号中的代码块,前面使用了关键词 function funct…...