【k8s学习】Kubernetes Volume介绍

【本文目标】

  • Kubernetes集群怎样通过Volume做数据持久化的?
  • 持久卷组件 - Persistemt Volume
  • 使用持久卷,组件 - Persistent Volume Claim
  • 在使用持久卷中想要自动创建持久卷,组件 - Storage Class

【前置文章】

  • 【k8s学习】Kubernetes学习——核心组件和架构
  • 【k8s学习】minikube、kubectl、yaml配置文件的介绍
  • 【k8s学习】在minikube上布署MongoDB和MongoExpress
  • 【k8s学习】kubernetes namespace介绍
  • 【k8s学习】Kubernetes Ingress介绍
  • 【k8s学习】Kubernetes打包工具Helm介绍

1. Volume使用场景

1.1 Use Case-1:mysql Pod需要Storage:

假设我们有个项目叫my-app,接连了另一个Pod叫mysql,如果mysql重启了,那么里面存放的数据也会丢失,原因是Kubernetes并没有提供在Pod之外的持久化,一旦Pod重启了,数据就丢失了。

  • Storage that doesn't depend on the pod lifecycle:我们需要在Pod外有存储数据,以便不受Pod重启的影响。
  • Storage must be available on all nodes:假设一个mysql Pod挂掉了,那么admin controller manager发现后,就会让scheduler再找合适的Node重新创建一个Pod,所以新的Pod有可能创建在活着的Worker Node中的任一一个,即这个存储要对所有的节点都可见。
  • Storage needs to survive even if cluster crashes:当所有的节点都挂了,Storage里的数据也不能丢失。
1.2 Use Case-2:my-app本身可能也需要读写文件

比如一些session或是额外的配置等信息,my-app Pod本身,也可能会读写数据,这时候我们就可以配置Persistent Volume,简称pv。

2. Persistent Volume

官网:https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/

2.1 介绍
  • a cluster resource:集群中的一种资源,比如ram内存或是cpu。
  • created via YAML file:和别的组件一样,可以通过YAML文件创建。
    • 创建的时候kind为PersistentVolume
    • spec中定义了一些自有的属性,比如占有空间为多少?(spec.capacity.storage
  • Needs actual physical storage:持久化的地方必须是能支持存储的地方,如集群里的某个存储空间或是集群外的某台Server或是云服务器。所以这里有个问题就是如何让Kubernetes集群读取到这些存储。
  • what type of storage do you need? need to create & manage them by yourself:Persistent Volume更像是一个接口,它只提供了一些规范,至于存储的类型以及创建和管理、备份,都在Kubernetes之外,并不归K8s集群管理。
2.2 yaml配置示例

下述示例中的Storage的地方是NFS文件系统:

apiVersion:
kind: persistentVolume
metadata:
  name: pv-name
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessMode:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.0
  nfs:
    path: /dir/path/on/nfs/server
    server: nfs-server-ip-address

上述spec中定义了三部分:

  • 存储能力
  • 额外的信息比如进入的模式
  • nfs参数

不同的存储类型,配置可能会长不一样。
从官网上可以看到,卷的类型超过了20种:https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

Persistent Volume并不从属于某个命令空间,它是全局的组件。即所有的命名空间下的组件,都可引用到该pv组件。

2.3 Local Volume vs. Remote Volume

根据存放地点分类:

  • Local Volume(在Kubernetes集群内),这种Storage就违反了1.1章的特点2和特点3,即它是跟集群中的某个Node绑定了,所以有可能会挂掉,以及如果集群down了,这个Storage也可能down掉。正因为此,像DB数据库的持久化存储,最好放在集群外,即Remove Volume中。
  • Remote Volume,即集群外部存储,符合1.1章节的三个特点。

什么时候创建Persistent Volume?
如果某个Pod依赖于pv,那么这个pv需要在Pod被创建之前创建。

谁来创建?
一般来说,开发人员需要告诉admin(可能是DevOps Team)某个项目需要用到Persistent Volume,然后DevOps人员根据开发人员的需求,在Kubernetes集群中帮忙定义并创建好了该pv。

在定义好之后,开发人员则需要在具体的Pod的yaml中定义引用该pv,在yaml中声明需要用到某个pv,这时候需要另一个组件,叫Persistent Volume Claim,简称pvc

3. Persistent Volume Claim

官网:

  • https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#binding
  • https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
3.1 Persistent Volume Claim yaml示例

pvc如何找到pv?通过属性例如大小等找到合适的pv:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-name
spec:
  storageClassName: manual
  volumeMode: Filesystem
  accessMode:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

定义了pvc后,怎么在Pod中引用呢?即通过spec.volumes.persistenceVolumeClaim.claimName进行关联:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: pvc-name

【整个过程】
Pod通过pv claim请求volume --> pv claim尝试在集群中找到合适的volume --> 找到的volume才是真正拥有存储空间的地方。 --> 这时候volume会被mounted(挂载)到这个Pod --> 然后才被挂载到Pod中的Container(这也是为什么上述Container中定义了volumeMounts属性) --> 至此,具体的app应用才能读写该volume

pvc并不是全局的组件,它可以被创建到某个namespace下,pvc所属的namespace必须要和Pod相同(因为Pod定义中需要引用到pvc组件)。

3.2 思考:为什么需要这么多层抽像?
  • DevOps人员声明并创建全局组件pv
  • 开发人员声明并创建pvc,并在Pod中使用。

这样设计的主要好处是开发人员友好,因为开发人员并不需要具体知道Storage存放地点(解藕),而只需要使用即可。

3.3 通过spec.volumes引用ConfigMap和Secret

ConfigMap组件和Secret组件:

  • local volumes:这两个组件都是本地存储卷。
  • not created via pv and pvc:不是通过pv和pvc声明创建的。
  • managed by Kubernetes

我们也可以通过volume属性定义这两个组件,然后在container中mounts,以下是示例:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: busybox-container
      image: busybox
      volumeMounts:
        - name: config-dir
          mountPath: /etc/config
  volumes:
    - name: config-dir
      configMap:
        name: bb-configmap

注:一个Pod可以有多个volume claim。

4. Storage Class

官网:https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/

为了让pv创建以及pvc创建更加高效,则需要第三个组件,叫Storage Class,简称sc。

sc可以根据PersistentVolumeClaim的定义,动态的生成pv。

示例:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: storage-class-name
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4
  • via "provisioner" attribute:provisioner意思为供应方,声明了pv的具体提供商,每个Storage类型都有自己的provisioner,在需要的时候查阅官网:https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/#provisioner
  • configure "parameters" for storage we want to request for Persistent Volume:parameters属性定义了pv所需要的信息,例如类型,空间大小等。

sc主要是为了减少DevOps的工具,即可以动态的生成pv,那么谁来引入sc组件呢?答案很明显,是pvc。即开发人员不需要每次让DevOps的人手动创建pv,而是通过Storage Class来自动创建pv。

在pvc中使用:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
spec:
  accessMode:
  - ReadWriteOnce
  resources:
    requests:
      storage: 100Gi
    storageClassName: storage-class-name

【整个过程】

  1. Pod通过pvc请求存储。
  2. pvc通过sc请求存储。
  3. sc自动创建可以满足要求的pv

参考:
https://www.youtube.com/watch?v=X48VuDVv0do

你可能感兴趣的:(【k8s学习】Kubernetes Volume介绍)