ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

kubernetes中的local persistent volume

2019-08-20 10:00:10  阅读:284  来源: 互联网

标签:node pv persistent 调度 volume PV pod local


什么是Local Persistent Volumes

在kubernetes 1.14版本中, Local Persistent Volumes已变为正式版本(GA),Local PV的概念在1.7中被首次提出(alpha),并在1.10版本中升级到beat版本。现在用户终于可以在生产环境中使用Local PV的功能和API了。
首先:Local Persistent Volumes代表了直接绑定在计算节点上的一块本地磁盘。
kubernetes提供了一套卷插件(volume plugin)标准,使得k8s集群的工作负载可以使用多种块存储和文件存储。大部分磁盘插件都使用了远程存储,这是为了让持久化的数据与计算节点彼此独立,但远程存储通常无法提供本地存储那么强的读写性能。有了LPV 插件,kubernetes负载现在可以用同样的volume api,在容器中使用本地磁盘。

这跟hostPath有什么区别

hostPath是一种volume,可以让pod挂载宿主机上的一个文件或目录(如果挂载路径不存在,则创建为目录或文件并挂载)。
最大的不同在于调度器是否能理解磁盘和node的对应关系,一个使用hostPath的pod,当他被重新调度时,很有可能被调度到与原先不同的node上,这就导致pod内数据丢失了。而使用LPV的pod,总会被调度到同一个node上(否则就调度失败)。

如何使用Local PV

首先 需要创建StorageClass

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

注意到这里volumeBindingMode字段的值是WaitForFirstConsumer。这种bindingmode意味着:kubernetes的pv控制器会将这类pv的binding延迟,直到有一个使用了对应pvc的pod被创建出来且该pod被调度完毕。这时候才会将pv和pvc进行binding,并且这时候pv的选择会结合调度的node和pv的nodeaffinity。

-

手动创建PV。但是必须要注意的是,Local PV必须要填写nodeAffinity

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 100Gi
  # volumeMode field requires BlockVolume Alpha feature gate to be enabled.
  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:
          - k8s-n1

注意:目前,Local PV 的本地持久存储允许我们直接使用节点上的一块磁盘、一个分区或者一个目录作为持久卷的存储后端,但暂时还不提供动态配置支持,也就是说:你得先把 PV 准备好。(一台主机就创建一个PV,在nodeAffinity写不同的节点 k8s-n1、 k8s-n2、 k8s-n3),其他内容和一个普通 PV 无异,只是多了一个 nodeAffinity。

-

接下来可以创建各种workload,记得要在workload的模板中声明volumeClaimTemplates。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: local-test
spec:
  serviceName: "local-service"
  replicas: 3
  selector:
    matchLabels:
      app: local-test
  template:
    metadata:
      labels:
        app: local-test
    spec:
      containers:
      - name: test-container
        image: k8s.gcr.io/busybox
        command:
        - "/bin/sh"
        args:
        - "-c"
        - "sleep 100000"
        volumeMounts:
        - name: local-vol
          mountPath: /usr/test-pod
  volumeClaimTemplates:
  - metadata:
      name: local-vol
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "local-storage"
      resources:
        requests:
          storage: 368Gi

注意到这里volumeClaimTemplates.spec.storageClassNamelocal-storage,即我们一开始创建的storageclass实例的名字。

使用Local PV的pod的调度流程

上面这个statefulset创建后,控制器会为其创建对应的PVC,并且会为PVC查找符合条件的PV,但是由于我们在local-storage中配置了WaitForFirstConsumer,所以控制器不会处理pvc和pv的bind;

-

同时,调度器在调度该pod时,predicate算法中也会根据PVC的要求去找到可用的PV,并且会过滤掉“与LPV的affinity”不匹配的node。最终,调度器发现:

  • pv:example-pv满足了pvc的要求;
  • node:example-node满足了pv:example-pv的nodeAffinity要求。

于是乎调度器尝试将pv和pvc bind起来,并且对pod进行重新调度。

-

重新调度pod时调度器发现pod的pvc资源得到了满足(都bound了pv),且bound的pv的nodeAffinity与node:example-node匹配。于是将pod调度到node:example-node上。完成调度。

如何创建LPV

  • 在机器上创建目录: mkdir -p /mnt/disks/ssd1
  • 在机器上执行命令,将某个卷挂载到该目录:mount -t /dev/vdc /mnt/disks/ssd1
  • 在集群中创建对应的storageClass. 参见上文。
  • 手动创建本地卷的PV,或者通过provisioner去自动创建。手动创建的模板见上文。

如何删除LPV

对于已经被bind并被pod使用的LPV,删除一定要按照流程来 , 要不然会删除失败:

  • 删除使用这个pv的pod
  • 从node上移除这个磁盘(按照一个pv一块盘)
  • 删除pvc
  • 删除pv

标签:node,pv,persistent,调度,volume,PV,pod,local
来源: https://blog.51cto.com/2032872/2430897

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有