K8s存储emptyDir/hostPath/pv与pvc

K8s存储emptyDir、hostPath、pv和pvc
pod容器组在宕机或者删除以后,数据会随着pod的销毁而消失,所以需要使用一些存储方案来做数据的持久化,目前有很多存储方案,主要有emptyDir、hostPath、NFS、云存储
我们下面就通过例子来看看上述几种存储方式的区别
1.emptyDir
emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配一个目录,因此无需指定宿主机node上对应的目录文件。这个目录的初始内容为空,当Pod从node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录
例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-emptydir
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeName: k8s-node1  # 指定部署节点
      containers:
        - name: nginx
          image: nginx
          volumeMounts:  # 挂载容器内部目录
            - mountPath: /data/empty
              name: emptydir #存储卷名称
      volumes:
        - name: emptydir
          emptyDir: {}

2.hostpath
HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用HostPath卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载
例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-hostpath
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeName: k8s-node1  # 指定部署节点
      containers:
        - name: nginx
          image: nginx
          volumeMounts:  # 挂载容器内部目录
            - mountPath: /data/share
              name: localpath #存储卷名称
      volumes:
        - name: localpath
          hostPath:
            path: /opt/hostpath # 这里会在node节点创建目录并对应容器内部的mountPath
            type:  DirectoryOrCreate # 类型:没有就创建,有就不创建

用户可以选择性地为 hostPath 卷指定 type
支持的 type 值如下:

DirectoryOrCreate  宿主机上不存在创建此目录  
Directory 必须存在挂载目录  
FileOrCreate 宿主机上不存在挂载文件就创建  
File 必须存在文件

当使用这种类型的卷时要小心,因为:
HostPath 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字), 可用于容器逃逸或攻击集群的其他部分。
具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同 而在不同节点上有不同的行为。
下层主机上创建的文件或目录只能由 root 用户写入。你需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath卷

3.pv/pvc
PersistentVolume(PV)是群集中的一块存储(类似一块磁盘),由管理员配置或使用存储类动态配置。 它是集群中的资源,就像节点是集群资源一样。 PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。 此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统
PersistentVolumeClaim(PVC)是一个持久化存储卷,我们在创建pod时可以定义这个类型的存储卷。 它类似于一个pod。 Pod消耗节点资源,PVC消耗PV资源。 Pod可以请求特定级别的资源(CPU和内存)。 pvc在申请pv的时候也可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)
PV的访问模式

ReadWriteOnce(RWO)     可读可写,但只支持被单个节点挂载。
ReadOnlyMany(ROX)     只读,可以被多个节点挂载。
ReadWriteMany(RWX)     多路可读可写。这种存储可以以读写的方式被多个节点共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。

PV的回收策略

Retain     不清理, 保留 Volume(需要手动清理)
Recycle     删除数据,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持)
Delete     删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)

PVC状态

Available(可用)——一块空闲资源还没有被任何声明绑定
Bound(已绑定)——卷已经被声明绑定
Released(已释放)——声明被删除,但是资源还未被集群重新声明
Failed(失败)——该卷的自动回收失败

下面来一组例子:

pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-1
  labels:
    app: pv-nfs-1
spec:
  volumeMode: Filesystem
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /data/nas1
    server: 192.168.137.10
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-2
  labels:
    app: pv-nfs-2
spec:
  volumeMode: Filesystem
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 3Gi
  volumeMode: Filesystem
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /data/nas2
    server: 192.168.137.10
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-3
  labels:
    app: pv-nfs-3
spec:
  volumeMode: Filesystem
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 4Gi # 申请多大的PV,PVC会申请一个匹配或者稍大于的PV资源
  volumeMode: Filesystem
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /data/nas3
    server: 192.168.137.10
---
#pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 1Gi
  selector:
    matchLabels:
      app: pv-nfs-2

我们可以用过命令查看卷状态

kubectl get pv/pvc

图片.png

可以看到pvc和pv-nfs-2是bound状态
最后我们再重新编辑下deploy,挂载下这个pvc看看效果

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-pvc
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      #nodeName: k8s-node1  # 指定部署节点
      containers:
        - name: nginx
          image: nginx
          volumeMounts:  # 挂载容器内部目录
            - mountPath: /data/nfs
              name: nginx-nfs #存储卷名称
      volumes:                              
        - name: nginx-nfs
          persistentVolumeClaim:
            claimName: pvc-nfs

注意:
我们每次创建pvc的时候,需要事先有划分好的pv,这样可能不方便,那么可以在创建pvc的时候直接动态创建一个pv这个存储类,pv事先是不存在的
pvc和pv绑定,如果使用默认的回收策略retain,那么删除pvc之后,pv会处于released状态,我们想要继续使用这个pv,需要手动删除pv,kubectl delete pv pv_name,删除pv,不会删除pv里的数据,当我们重新创建pvc时还会和这个最匹配的pv绑定,数据还是原来数据,不会丢失
删除流程:POD->PVC->PV


内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://sulao.cn/post/824.html