赞
踩
容器中的文件在磁盘上是临时存放的,当容器崩溃或停止时容器上面的数据未保存, 因此在容器生命周期内创建或修改的所有文件都将丢失。 在崩溃期间,kubelet 会以干净的状态重新启动容器。 当多个容器在一个 Pod 中运行并且需要共享文件时,会出现另一个问题,跨所有容器设置和访问共享文件系统具有一定的挑战性。K8S 卷(Volume) 这一抽象概念能够解决这两个问题。
警告:
HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。HostPath 仅适用于单个节点上的存储,不支持跨节点访问(如果Pod偏移到其他宿主机节点上面可能会出问题)。
type值 | 说明 |
---|---|
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查 | |
DirectoryOrCreate | 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet相同的组和属主信息 |
Directory | 在给定路径上必须存在的目录 |
FileOrCreate | 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权 |
File | 在给定路径上必须存在的文件 |
Socket | 在给定路径上必须存在的 UNIX 套接字 |
CharDevice | 在给定路径上必须存在的字符设备 |
BlockDevice | 在给定路径上必须存在的块设备 |
如有多个节点,在使用 hostPath 存储需要指定pod部署在那个节点上面,例如在Pod上面添加nodeSelector字段指定到某一个节点(需要提前给节点打标签)
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: # nodeSelector: # 指定部署到特定节点上面 # disktype: ssd # 标签 - image: nginx name: test-container volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: path: /data # 宿主机上目录位置,注意权限 type: Directory # 此字段为可选,详细解释在上面
定义了 emptyDir 卷的 Pod,在 Pod 被指派到某节点时此卷会被创建。emptyDir 卷最初是空的。Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,但这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会被永久删除。主要作用是为了共享数据用。
emptyDir 卷存储可以使用任何磁盘、SSD 或网络存储,这取决于你的环境。 你可以将 emptyDir.medium 字段设置为 “Memory”, 以告诉 Kubernetes 为你挂载 tmpfs(基于 RAM 的文件系统)。虽然 tmpfs 速度非常快,但是要注意它与磁盘不同, 并且你所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束
说明:
容器崩溃并不会导致 Pod 被从节点上移除,因此容器崩溃期间 emptyDir 卷中的数据是安全的。
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 500Mi # 写入磁盘的大小限制,如果没限制直接删除这行 在emptyDir: []即可
nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。
说明:
在使用 NFS 卷之前,你必须部署自己的 NFS 服务器才可以使用,这里不再叙述。
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: registry.k8s.io/test-webserver name: test-container volumeMounts: - mountPath: /my-nfs-data name: test-volume volumes: - name: test-volume nfs: server: my-nfs-server.example.com # nfs服务的地址 path: /my-nfs-volume # nfs 服务共享的路径 readOnly: true
在 Kubernetes 中,PV(PersistentVolume)和 PVC(PersistentVolumeClaim)是用于持久化存储的核心概念,其本身并没有存储的相关功能所以需要准备后端存储的环境。
PersistentVolume(PV):PV 是集群中的一块持久化存储,它是集群管理员预先配置好的存储资源。PV 可以是网络存储(如 NFS、GlusterFS、Ceph)、云存储(如 AWS EBS、Azure Disk)、本地存储(HostPath)等。PV 与存储后端进行绑定,表示集群中的可用存储资源,支持的后端存储类型详情请查看K8S官方文档
PersistentVolumeClaim(PVC):PVC 是 Pod 对 PV 的申请。PVC 定义了对存储资源的需求,包括存储容量、访问模式和其他属性。Pod 中的容器可以通过 PVC 来申请并使用 PV 提供的持久化存储。Kubernetes 会根据 PVC 的需求匹配可用的 PV,并将其动态绑定到 Pod 中。
下面是 hostPath PersistentVolume 的配置文件:
apiVersion: v1 kind: PersistentVolume metadata: labels: type: local name: task-pv-volume spec: accessModes: - ReadWriteOnce capacity: storage: 10Gi hostPath: path: /mnt type: "" persistentVolumeReclaimPolicy: Recycle storageClassName: manual volumeMode: Filesystem
Kubernetes 支持两种卷模式(volumeModes):
kubectl create -f pv0003.yaml
创建好以后查看
kubectl get pv
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
pv0003 5Gi RWO Recycle Available manual 4s
PV状态说明:
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
每个持久卷会处于以下阶段(Phase)之一:
使用 kubectl describe persistentvolume 查看已绑定到 PV 的 PVC 的名称。
创建一个PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
这里面的字段意思基本和PV里面的一样,访问模式和卷模式也是一样的,就不再解释了。
匹配步骤:
创建PV和PVC
apiVersion: v1 kind: PersistentVolume metadata: name: task1 labels: type: local1 spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: task-pv-claim spec: accessModes: - ReadWriteOnce resources: requests: storage: 9Gi
查看PV和PVC状态
[root@master01 pv]# kubectl get pvc,pv
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/task-pv-claim Bound task1 10Gi RWO 26s
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/task1 10Gi RWO Retain Bound default/task-pv-claim 10m
都是已经绑状态
创建PV和PVC
apiVersion: v1 kind: PersistentVolume metadata: name: my-pv labels: desk: "test1" # 设置标签 spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: /mnt --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi selector: matchLabels: desk: "test1" # 匹配PV的标签
查看PV和PVC状态
可以看到 my-pvc 已经绑定到 my-pv 上面了,如果没有标签自动绑定的话 则会绑定到 task2 的PV上面
[root@master01 pv]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
my-pv 10Gi RWO Retain Bound default/my-pvc 3s
task1 10Gi RWO Retain Available 46s
task2 5Gi RWO Retain Available 46s
[root@master01 pv]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
my-pvc Bound my-pv 10Gi RWO 12s
apiVersion: v1 kind: PersistentVolume metadata: name: my-pv spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce hostPath: path: /mnt/data --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteOnce volumeName: my-pv # 指定要绑定的 PV 的名称 resources: requests: storage: 5Gi
查看PV和PVC绑定情况
[root@master01 pv]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/my-pv 20Gi RWO Retain Bound default/my-pvc 5s
persistentvolume/task1 10Gi RWO Retain Available 158m
persistentvolume/task2 5Gi RWO Retain Available 158m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/my-pvc Pending my-pv 0 5s
PV 和 PVC 之间的绑定是一对一的关系。一个 PVC 只能绑定到一个 PV 上,而一个 PV 可以同时被多个 PVC 绑定。如果没有足够的 PV 来满足 PVC 的需求,或者没有满足 PVC 的要求的可用 PV,则 PVC 将处于 Pending(挂起)状态,直到满足条件为止。
创建PV和PVC:
apiVersion: v1 kind: PersistentVolume metadata: name: task-pv-volume labels: type: local spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: task-pv-claim spec: accessModes: - ReadWriteOnce resources: requests: storage: 3Gi
创建一个Pod使用上面这个PVC
apiVersion: v1 kind: Pod metadata: name: task-pv-pod spec: containers: - name: task-pv-container image: nginx ports: - containerPort: 80 name: "http-server" volumeMounts: - mountPath: "/usr/share/nginx/html" name: task-pv-storage volumes: - name: task-pv-storage persistentVolumeClaim: # 指定使用PVC存储 claimName: task-pv-claim # PVC存储的名字
在Pod里面多次挂在PVC
apiVersion: v1 kind: Pod metadata: name: test spec: containers: - name: test image: nginx volumeMounts: # 网站数据挂载 - name: config mountPath: /usr/share/nginx/html subPath: html # Nginx 配置挂载 - name: config mountPath: /etc/nginx/nginx.conf subPath: nginx.conf volumes: - name: config persistentVolumeClaim: claimName: test-nfs-claim
创建PVC后,一直绑定不上PV(Pending):
Pod挂在PVC后,一直处于Pending状态:
删除PVC后k8s会创建一个用于回收的Pod,根据PV的回收策略进行pv的回收,回收完以后PV的状态就会变成可被绑定的状态也就是空闲状态,其他的Pending状态的PVC如果匹配到了这个PV,他就能和这个PV进行绑定。
主要功能:
在开始之前请安装后端存储,我这里使用的是CEPH存储并且安装到K8S集群里,下面是安装方法。(所有环境中如果有用到的安装包或者容器镜像什么的都可以私信我)
安装方法:点击跳转
注意: 本次演示默认已经安装好ceph存储。
## sc 是 StorageClass 简写
[root@master01 ~]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
rook-ceph-rbd rook-ceph.rbd.csi.ceph.com Retain Immediate true 228d
rook-cephfs rook-ceph.cephfs.csi.ceph.com Retain Immediate true 228d
适用场景:
查看命令
kubectl get sc rook-ceph-rbd -oyaml
allowVolumeExpansion: true apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rook-ceph-rbd parameters: clusterID: rook-ceph csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph csi.storage.k8s.io/fstype: ext4 csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph imageFeatures: layering imageFormat: "2" pool: replicapool provisioner: rook-ceph.rbd.csi.ceph.com reclaimPolicy: Retain volumeBindingMode: Immediate
部署成功以后 StorageClass 会根据PVC申请的去自动创建PV并绑定好
apiVersion: apps/v1 kind: StatefulSet metadata: name: my-statefulset spec: serviceName: "my-statefulset" replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: nginx:latest ports: - containerPort: 80 volumeMounts: - name: my-persistent-storage mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: my-persistent-storage spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "rook-ceph-rbd" # 指定刚刚查出来的 StorageClass 名字 resources: requests: storage: 5Gi
创建PVC成功以后会自动创建PV并绑定好,后面Pod使用方式和上面手动创建PV和PVC的方式一样。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: rook-ceph-rbd # 指定要使用的 StorageClass 的名称
resources:
requests:
storage: 1Gi # 请求 1GB 的存储容量
直接修改 “storage: 1Gi ” 修改为2G即可,但是生效还需要等几分钟。
kubectl edit pvc my-pvc
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。