Kubernetes之数据存储

一、Volume

默认情况下容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问题,第一:当容器挂掉kubelet将重启启动它时,文件将会丢失;第二:当 Pod 中同时运行多个容器,容器之间需要共享文件时。Kubernetes的Volume解决了这两个问题。

Kubernetes 支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。 临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁 持久卷。对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。

Kubernetes支持Volume类型有:

  • emptyDir、hostPath、local、gcePersistentDisk
  • awsElasticBlockStore、azureFileVolume、azureDisk
  • nfs、iscsi、fc、secret、downwardAPI
  • flocker、glusterfs、rbd、cephfs、gitRepo
  • projected、vsphereVolume、persistentVolumeClaim
  • Quobyte、PortworxVolume、ScaleIO、StorageOS

1.1 emptyDir

当 Pod 分派到某个 Node 上时,emptyDir 卷会被创建,并且在 Pod 在该节点上运行期间,卷一直存在。 就像其名称表示的那样,卷最初是空的。当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会被永久删除。目的是同一 Pod 内的不同容器之间可以共享工作过程中产生的文件。

emptyDir 的用途:

  • 缓存空间,例如基于磁盘的归并排序。
  • 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
  • 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
# cat emptydirdemo.yml
apiVersion: v1
kind: Pod
metadata: 
  name: volume-emptydir
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:       # 将logs-volume挂载到nginx容器中,对应的目录为 /var/log/nginx
    - name: logs-volume
      mountPath: /var/log/nginx
  - name: busybox
    image: busybox
    command: ["/bin/sh","-c","tail -f /logs/access.log"] # 初始命令,动态读取指定文件中内容
    volumeMounts: # 将logs-volume挂载到busybox容器中,对应的目录为 /logs
    - name: logs-volume
      mountPath: /logs
  volumes:        # 声明volume,name为logs-volume,类型为emptyDir
  - name: logs-volume
    emptyDir: {}

1.2 hostPath

由于EmptyDir中数据不会被持久化,它会随着Pod的结束而销毁,如果想简单地将数据持久化到主机中,可以选择HostPath。hostPath允许挂载Node上的文件系统到Pod里面去,如果Pod需要使用Node上的文件,可以使用hostPath。

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

hostPath 的用法:

  • 运行一个需要访问 Docker 内部机制的容器;可使用 hostPath 挂载 /var/lib/docker 路径。
  • 在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys。
  • 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。
# cat hostPathdemo.yml
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /var/www/html
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # 宿主上目录位置
      path: /data
      # 此字段为可选
      type: Directory

1.3 local

Local 是Kubernetes集群中每个节点的本地存储(如磁盘,分区或目录),Local 卷只能用作静态创建的持久卷。尚不支持动态配置。

与 hostPath 卷相比,Local 卷能够以持久和可移植的方式使用,Kubernets 可自动对 Pod 进行调度,而无需手动将 Pod 调度到节点。

使用 Local 卷时,你需要设置 PersistentVolume 对象的 nodeAffinity 字段。 Kubernetes 调度器使用 PersistentVolume 的 nodeAffinity 信息来将使用 local 卷的 Pod 调度到正确的节点。


# cat local-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 100Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - example-node

1.4 nfs

hostPath可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到了别的节点,又会出现问题了,此时需要准备单独的网络存储系统,比较常用的有NFS、ISCSI。

NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样的话,无论Pod在任何节点上,只要与NFS可通就没问题。


# cat volume-nfs.yml
apiVersion: v1
kind: Pod
metadata: 
  name: volume-nfs
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: logs-volume
      mountPath: /var/log/nginx
  volumes:
  - name: logs-volume
    nfs:
      server: 10.10.10.1
      path: /root/data/nfs

二、Persistent Volumes

Pod 虽然可以直接挂载存储,但是管理不方便,特别是 Pod 的数量越来越多。K8S引入了一组叫作Persistent Volume Claim(PVC)和Persistent Volume(PV)的API对象,大大降低了用户声明和使用持久化Volume的门槛。

  • PersistentVolume(PV)
    PV是集群中的的一部分,像Node一样是集群中的一种资源,用于描述一个具体的 Volume 属性,比如 Volume 的类型、挂载目录、远程存储服务器地址等。可以由管理员事先供应,或者使用​存储类(Storage Class)​来动态供应。就像节点是集群中的资源一样,PV 也是集群中的资源。PV 是 Volume 之类的卷插件,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。此 API 对象中记录了存储的实现细节,即 NFS、iSCSI 或特定于云供应商的存储系统。

  • PersistentVolumeClaim(PVC)
    PVC是用户对存储的请求,用于描述 Pod 想要使用的持久化属性,比如存储大小、读写权限等。它与 Pod 相似。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。同样PVC也可以请求特定的大小和访问模式(例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载。

  • StorageClass(SC)
    尽管 PVC 允许用户消耗抽象的存储资源,常见的情况是针对不同的 问题用户需要的是具有不同属性(如性能)的 PV 卷。 集群管理员需要能够提供不同性质的 PV,并且这些 PV 卷之间的差别不 仅限于卷大小和访问模式,同时又不能将卷是如何实现的这些细节暴露给用户。 为了满足这类需求,就有了 存储类(StorageClass) 资源。相当于充当 PV 的模板,自动为 PVC 创建 PV。

2.1 基本概念

2.1.1 生命周期

PV 卷是集群中的资源。PVC 是对这些资源的请求,也被用来执行对资源的申领检查。 PV 卷和 PVC 交互存在如下生命周期:

  • 供应 (Provisioning):pv的创建
  • 绑定 (Binding): pvc 绑定pv
  • 使用 (Using): pod通过pvc使用vloume
  • 释放 (Releasing): pod释放volume并删除pvc
  • 回收 (Reclaiming): 回收pv

根据上述的5个阶段,存储卷的存在下面的4种状态:

  • Available: 可用状态,表面此PV可被PVC绑定
  • Bound: 绑定状态,表明PV已被分配给了PVC。
  • Released: 释放状态,表明PVC解绑PV,但还未执行回收策略。
  • Failed: 错误状态,表明PV发生错误。
2.1.2 供应

PV 卷的供应有两种方式:静态供应或动态供应。

  • 静态供应

集群管理员创建若干 PV 卷。这些卷对象带有真实存储的细节信息,并且对集群用户可见。PV 卷对象存在于 Kubernetes API 中,可供用户消费。管理员创建PVC和Pod,Pod通过PVC使用PV提供的存储。在这里插入图片描述

  • 动态供应

动态供应就是在创建PVC之后,自动创建出PV。当管理员所创建的所有静态 PV 卷都无法与用户的 PersistentVolumeClaim 匹配, 集群可以尝试为该 PVC 动态供应一个存储卷。 这一供应操作是基于 StorageClass 来实现的:PVC 必须请求某个 StorageClass,同时集群管理员必须 已经创建并配置了该类,这样动态供应卷的动作才会发生。 如果 PVC 指定存储类为"",则相当于为自身禁止使用动态供应的卷。在这里插入图片描述

2.1.3 绑定

在Kubernetes中,会动态的将PVC与可用的PV的进行绑定。Master节点中的控制回路会监测新的 PVC 对象,寻找与之匹配的 PV 卷(如果有), 并将二者绑定到一起。 如果新的 PVC 动态供应了 PV 卷,则控制回路总是将该 PV 卷绑定到这一 PVC 请求。 否则,用户总是能够获得他们所请求的资源,只是所获得的 PV 卷可能会超出所请求的配置。 一旦绑定关系建立,则 PVC 绑定就是排他性的,无论该 PVC 如何与 PV 卷建立绑定关系。 PVC 与 PV 卷之间的绑定是一种一对一的映射,实现上使用 ClaimRef 来描述 PV 卷 与 PVC 间的双向绑定关系。

如果找不到匹配的 PV 卷,PVC 会无限期地处于未绑定状态。 当与之匹配的 PV 卷可用时,PVC 会被绑定。 例如,即使某集群上供应了很多 50 G大小的 PV 卷,也无法与请求 100 G大小存储的 PVC 匹配。当新的 100 G PV 卷被加入到集群时,该 PVC 才有可能被绑定。

2.1.4 使用

Pod 将 PVC 作为卷来使用,Kubernetes集群会检查 PVC 查找绑定的PV,并将其挂接至Pod。对于支持多种访问方式的卷,用户在使用 PVC 作为卷时,可以指定期望的访问方式。一旦用户拥有了一个已经绑定的PVC,被绑定的PV就归该用户所有。用户能够通过在Pod的存储卷中包含的PVC,从而访问所占有的PV。

2.1.5 释放

当用户对存储资源使用哪个完毕后,用户可以删除 PVC,与该 PVC 绑定的 PV 将会被标记为已释放,但还不能立刻与其他 PVC 进行绑定。通过之前 PVC 写入的数据可能还留在存储设备上,只有在清除之后该 PV 才能继续使用。

2.1.6 回收

当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除,从而允许该资源被回收再利用。PV 对象的回收策略(Reclaim Policy)用于设置与之绑定的 PVC 释放资源之后,对于遗留数据的处理。

  • 保留(Retained)

保留回收策略允许用户手动回收资源。当 PVC 对象被删除时,PV 卷仍然存在,对应的数据卷被视为"已释放(released)"。由于以前的数据仍然保留在数据中,所以它对于其他的PVC是不可用的。管理员能够通过下面的步骤手工回收存储卷:

1)删除PV:在PV被删除后,在外部设施中相关的存储资产仍然还在;

2)根据情况,手动清除所关联的存储资产上的数据。

3)手动删除存储资产,如果需要重用这些存储资产,则需要创建新的PV。

  • 删除(Deleted)

对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。

  • 回收(Recycle)

回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态供应。

2.2 持久化卷

在Kubernetes中,PV 通过各种插件进行实现。

2.2.1 持久化卷类型
  • awsElasticBlockStore、azureDisk、cephfs
  • csi、fc、flexVolume、gcePersistentDisk、glusterfs
  • hostPath、iscsi、local、nfs、portworxVolume
  • rbd、vsphereVolume
2.2.2 存储卷模式

针对 PV 持久卷,Kubernetes 支持两种卷模式(volumeModes):Filesystem(文件系统) 和 Block(块)。 volumeMode 是一个可选的 API 参数,如果不进行设定,则默认为Filesystem。

volumeMode 属性设置为 Filesystem 的卷会被 Pod 挂载(Mount) 到某个目录。 如果卷的存储来自某块设备而该设备目前为空,Kuberneretes 会在第一次挂载卷之前 在设备上创建文件系统。

2.2.3 存储卷访问模式

PersistentVolume 卷可以以资源提供者支持的任何方式挂载到主机上。 如下表所示,提供者(驱动)的能力不同,每个 PV 卷的访问模式都会设置为该卷所支持的特定模式。 例如NFS可以支持多个读写客户,但是某个特定的 NFS PV 卷可能在服务器上以只读的方式导出。每个PV都有自己的一系列的访问模式,这些访问模式取决于PV的能力。

  • ReadWriteOnce:卷可以被单个节点以读/写模式挂载
  • ReadOnlyMany: 卷可以被多个节点以只读方式挂载
  • ReadWriteMany:卷可以读写模式被多个节点同时加载

在 CLI 下,访问模式缩写为:

  • RWO:ReadWriteOnce
  • ROX: ReadOnlyMany
  • RWX:ReadWriteMany
    在这里插入图片描述

2.3 实例演示

2.3.1 创建PV
# cat pv-demo.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /data/k8s/pv/pv1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - loc-k8s-node1
 
# kubectl get pv -A
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM          STORAGECLASS    REASON   AGE
local-pv    10Gi       RWO            Retain           Available                  local-storage            1d
2.3.2 创建PVC

# cat pvc-demo.yml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc1
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: local-storage
  resources:
    requests:
      storage: 8Gi
2.3.2 创建PVC
# cat deploy-nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: local-pv
      volumes:
        - name: local-pv
          persistentVolumeClaim:
            claimName: pvc1
 
# kubectl get pvc -A
NAMESPACE   NAME   STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS    AGE
default     pvc1   Bound    local-pv    10Gi       RWO            local-storage   1d


Reference:
https://kubernetes.io/zh/docs/concepts/storage/volumes
https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/
https://www.kubernetes.org.cn/4069.html
http://docs.kubernetes.org.cn/429.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值