1、存储卷的介绍
1.1 EmptyDir
EmptyDir是一种临时存储卷,其生命周期与Pod绑定。当Pod被调度到某个节点上时,Kubernetes会在该节点的文件系统中创建一个目录作为EmptyDir的存储位置,这个目录可以被Pod内的所有容器挂载使用。容器可以在这个目录中读写数据,但当Pod被删除时,EmptyDir中的数据也会被永久删除。EmptyDir的挂载非常简单,只需在Pod的配置文件中声明volume类型为EmptyDir,然后将其挂载到容器的指定路径即可,常用于容器间临时数据共享或缓存场景。
1.2 HostPath
HostPath挂载则允许将宿主机上的文件或目录挂载到Pod内的容器中。在配置时,需要在Pod的volume配置中指定HostPath类型,并设置path属性为宿主机上的绝对路径。容器可以像访问本地文件系统一样访问这个挂载点。需要注意的是,HostPath依赖于宿主机的文件系统结构,因此可能会影响容器的可移植性。此外,如果多个Pod被调度到不同的节点上,它们挂载的HostPath可能指向不同的物理位置。HostPath适用于需要容器访问宿主机特定文件(如配置文件、日志目录)或与宿主机进行数据交互的场景。
1.3 NFS
NFS(网络文件系统)挂载是一种基于网络的共享存储解决方案。在使用NFS挂载时,首先需要有一个可用的NFS服务器,该服务器上配置了共享目录。在Kubernetes中,需要在Pod的volume配置中指定NFS类型,并设置server属性为NFS服务器的IP地址或域名,path属性为NFS服务器上的共享目录路径。当Pod被调度到节点上时,Kubernetes会在节点上挂载NFS共享目录,然后将该挂载点映射到容器内。由于NFS是网络共享存储,多个Pod可以同时挂载同一个NFS卷,实现数据的共享访问。这种方式适用于需要跨节点共享数据的场景,如分布式应用中的共享配置、文件存储等。但NFS挂载的性能可能受到网络状况的影响,并且需要确保集群内的节点能够访问NFS服务器。
2、PV和PVC的介绍
2.1 PV和PVC之间的关系
在Kubernetes中,PV(PersistentVolume)和PVC(PersistentVolumeClaim)是用于管理持久化存储的重要概念。PV是集群中由管理员预先配置好的一段存储资源,它可以是各种不同类型的存储,如本地磁盘、网络存储等,PV有自己独立的生命周期,与使用它的Pod相互分离。管理员通过定义PV来描述存储的细节,包括存储的容量、访问模式(如只读、读写等)、存储类型等信息。而PVC则是用户对存储资源的一种请求声明,用户根据自己的应用需求来创建PVC,指定所需存储的容量、访问模式等要求。Kubernetes会根据PVC的要求去查找合适的PV来进行绑定。一旦PVC与PV成功绑定,PVC就可以像普通的存储卷一样被挂载到Pod中供容器使用,这样应用就能够在容器中对持久化存储进行读写操作,实现数据的持久化保存,而无需关心底层存储的具体实现细节。这种PV和PVC的架构设计,实现了存储资源的提供者(管理员)和使用者(用户)之间的解耦,使得存储资源的管理和分配更加灵活和高效,方便用户在不同的应用中便捷地使用各种类型的持久化存储资源,同时也便于管理员对集群中的存储资源进行统一的规划和管理。
2.2 静态PVC和动态PVC之间的区别
2.2.1静态PVC
静态PVC需要集群管理员预先创建PV(PersistentVolume),这些PV是具体存储资源的实体,如NFS共享目录、iSCSI卷或云存储卷,并定义其容量、访问模式和存储类等属性。当用户创建PVC请求存储时,系统会将PVC与已存在且匹配条件的PV进行绑定。这种方式的局限性在于,管理员需要提前预估存储需求并手动配置PV,可能导致资源分配不均或不足。例如,若管理员创建的PV容量过大,而用户的PVC请求容量较小,会造成存储资源浪费;反之,若PV容量过小,PVC可能无法找到合适的PV进行绑定。
2.2.2 动态PVC
动态PVC则通过StorageClass实现自动化的存储资源分配。管理员只需定义StorageClass,它描述了存储类型、供应商(如AWS EBS、GCE PD)以及如何创建PV的模板信息,而无需手动创建PV。当用户创建PVC并指定使用某个StorageClass时,Kubernetes会自动调用存储插件(如云提供商的存储接口)按需创建PV,并将其与PVC绑定。这种方式的优势在于按需分配,提高了资源利用率,减少了管理员的手动操作。例如,用户请求10GB的存储,系统会动态创建一个10GB的PV,避免了资源浪费。此外,动态PVC支持存储资源的自动扩展,当应用的存储需求增加时,可以通过修改PVC的请求容量来扩展存储,而静态PVC则需要管理员手动干预。动态PVC还简化了存储管理流程,降低了人为错误的风险,尤其适用于大规模集群和频繁变化的存储需求场景。
2.3 动态PVC的实现方法
storageclass+NFS
StorageClass结合NFS实现动态PV的核心原理是通过自动化机制按需创建NFS共享目录并映射为Kubernetes的PV资源。具体流程如下:管理员首先部署NFS客户端插件(Provisioner),该插件监听PVC创建事件;随后定义StorageClass指定NFS服务器地址和挂载路径等参数,并关联Provisioner;当用户创建PVC并引用该StorageClass时,Provisioner自动在NFS服务器上创建对应的目录,并生成匹配的PV对象完成绑定。这种方式无需手动预创建PV,实现了存储资源的按需分配,适合频繁变化的存储需求场景。
3、具体实现方法
3.1 配置nfs共享服务
先在nfs服务器上安装nfs服务 IP地址为192.168.107.178
在/etc/exports文件中声明共享的文件夹。注:此处应为opt目录下(少了一个t)
在集群内的其他机器上查看是否能看到共享的文件目录
3.1.1 测试nfs服务器是否正常
vim nfs.yaml
详情如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx1
#namespace:
spec:
replicas: 3
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
#定义容器和数据卷
containers:
- name: nginx1
image: nginx:1.22
volumeMounts:
- name: html
#设置挂载点,以及挂载点的名称,名称可以自定义
mountPath: /usr/share/nginx/html
- name: nginx2
image: nginx:1.22
volumeMounts:
- name: html
#容器内使用NFS挂载,挂载点的名称要一致
mountPath: /data
readOnly: false
command: ['/bin/bash', "-c", "while true;do echo $(date) >> /data/index.html;sleep 5;done"]
volumes:
- name: html
nfs:
path: /opt/k8s1
server: 192.168.107.178
#获取共享目录服务器的IP或者是主机名
声明共享目录
应用yaml文件,查看pod节点的状态
在nfs服务器上往挂载的文件中输入一串特殊的字符
在master节点上访问刚刚创建的测试nginx容器
3.2 动态PVC的配置示例图
这张图展示了 Kubernetes 中存储资源的关联关系。Pod 通过持久卷声明(PVC)来请求存储资源,PVC 可与多个持久卷(PV,如 PV1、PV2、PV3、PV4 )建立绑定关系。这些 PV 又分别连接到 NFS(网络文件系统)的挂载点,NFS 的挂载点最终与宿主机相连,体现了 Pod 如何通过 PVC 借助 PV 从 NFS 获取存储资源并挂载到宿主机的过程 。
3.3 配置nfs服务器的权限
我们先要为nfs服务器配置必要权限具体yaml文件如下
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"]
---
#集群角色绑定 kubectl explain ClusterRoleBinding 查看字段详情
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
这个 YAML 文件为 NFS 客户端存储供给器(NFS Client Provisioner)配置了必要的权限,使其能够在 Kubernetes 集群中动态创建 PV(PersistentVolume)。
3.4 部署和安装provisioner 的插件
3.4.1 屏蔽selflink字段
重新生成apiserver组件
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
不屏蔽selflink字段可能会报错
3.4.2 部署和安装provisioner 的插件
拖入相关的包
yaml文件具体如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs1
spec:
replicas: 1
selector:
matchLabels:
app: nfs1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs1
spec:
nodeName: node01
# 指定Service Account账户
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs1
image: quay.io/external_storage/nfs-client-provisioner:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
# 配置provisioner的Name,确保该名称与StorageClass资源中的provisioner名称保持一致
value: nfs-storage
- name: NFS_SERVER
# 配置绑定的nfs服务器
value: 192.168.107.178
- name: NFS_PATH
# 配置绑定的nfs服务器目录
value: /opt/k8s
volumes:
- name: nfs
nfs:
server: 192.168.107.178
path: /opt/k8s
应用yaml文件
3.5 实现自动的PV和PVC
vim nfs-client-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-client-storageclass
provisioner: nfs-storage
parameters:
archiveOnDelete: "false"
reclaimPolicy: Retain
allowVolumeExpansion: true
kubectl get storageclasses.storage.k8s.io 查看详细状态
4、创建pvc和pod测试
测试yaml文件如下
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-client-storageclass
resources:
requests:
storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-storageclass-deployment
labels:
app: nginx1
spec:
replicas: 3
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- name: nginx1
image: nginx:1.22
volumeMounts:
- name: nfs-pvc
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: nfs-pvc
测试成功