kubernetes中的local persistent volume

什么是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集群的工作负载可以使用多种块存储和文件存储。大部分磁盘插件都使用了远程存储,这是为了让持久化的数据与计算节点彼此独立,但远程存储通常无法提供本地存储那么强的读写性能。有了Local PV 插件,kubernetes负载现在可以用同样的volume api,在容器中使用本地磁盘。(分布式文件系统和数据库一直是 Local PV 的主要用例)

这跟hostPath有什么区别

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

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

使用Local PV的pod的调度流程

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

-

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

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

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

-

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

如何创建Local PV

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

如何删除Local PV

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

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

注意事项

  • 使用local pv时必须定义nodeAffinity,Kubernetes Scheduler需要使用PV的nodeAffinity描述信息来保证Pod能够调度到有对应local volume的Node上。
  • 创建local PV之前,你需要先保证有对应的storageClass已经创建。并且该storageClass的volumeBindingMode必须是WaitForFirstConsumer以标识延迟Volume Binding。
  • 节点上local volume的初始化需要我们人为去完成(比如local disk需要pre-partitioned, formatted, and mounted. 共享存储对应的Directories也需要pre-created),并且人工创建这个local PV,当Pod结束,我们还需要手动的清理local volume,然后手动删除该local PV对象。因此,persistentVolumeReclaimPolicy只能是Retain
  • Local PV在生产中使用,也是需要谨慎的,毕竟它本质上还是使用的是节点上的本地存储,如果没有相应的存储副本机制,那意味着一旦节点或者磁盘异常,使用该volume的Pod也会异常,甚至出现数据丢失,除非你明确知道这个风险不会对你的应用造成很大影响或者允许数据丢失。

Local volumes的最佳实践

  • 为了更好的IO隔离效果,建议将一整块磁盘作为一个存储卷使用;
  • 为了得到存储空间的隔离,建议为每个存储卷使用一个独立的磁盘分区;
  • 避免重新创建同名的 Node,否则会导致新 Node 无法识别已绑定旧 Node 的 PV 否则,系统可能会认为新Node节点包含旧的PV。
  • 对于具有文件系统的存储卷,建议在fstab条目和该卷的mount安装点的目录名中使用它们的UUID(例如ls -l /dev/disk/by-uuid的输出)。 这种做法可确保不会安装错误的本地卷,即使其设备路径发生了更改(例如,如果/dev/sda1在添加新磁盘时变为/dev/sdb1)。 此外,这种做法将确保如果创建了具有相同名称的另一个节点时,该节点上的任何卷仍然都会是唯一的,而不会被误认为是具有相同名称的另一个节点上的卷。

原文地址:https://blog.51cto.com/2032872/2430897

时间: 2024-09-29 11:18:25

kubernetes中的local persistent volume的相关文章

Kubernetes中,两种常见类型的Volume深度实践

一.背景 存储资源在所有计算资源中扮演着十分重要的角色,大部分业务场景下都有可能使用到各类存储资源.在Kubernetes中,系统通过Volume对集群中的容器动态或静态提供存储资源.通常情况下,我们可以认为容器或者Pod的生命周期时短暂的,当容器被销毁时,容器内部的数据也同时被清除.为了持久化保存容器的数据,Kubernetes引入了Volume,类似于Docker的Volume(Docker also has a concept of volumes, though it is somewh

Kubernetes中的PV和PVC是啥

引入了一组叫作Persistent Volume Claim(PVC)和Persistent Volume(PV)的API对象,大大降低了用户声明和使用持久化Volume的门槛. 在Pod的Volumes中,只要声明类型是persistentVolumeClaim,指定PVC的名字,当创建这个PVC对象,k8s就自动为它绑定一个符合条件的Volume,这个Volume,从PV来 PVC和PV的设计,类似"接口"和"实现"的思想,开发者只知道使用"接口&qu

Kubernetes 中的pv和pvc

原文地址:http://www.cnblogs.com/leidaxia/p/6485646.html 持久卷 PersistentVolumes 本文描述了 Kubernetes 中的 PersistentVolumes.要求读者有对卷 (volumes) 所有了解. 简介 存储管理跟计算管理是两个不同的问题.PersistentVolume 子系统,对存储的供应和使用做了抽象,以 API 形式提供给管理员和用户使用.要完成这一任务,我们引入了两个新的 API 资源:PersistentVol

大神教你轻松玩转Docker和Kubernetes中如何运行MongoDB微服务

本文介绍了利用Docker和Kubernetes搭建一套具有冗余备份集合的MongoDB服务,从容器对CI和CD引发的改变入手,讨论了容器技术对MongoDB带来的挑战和机会,然后实战如何部署一套稳定的MongoDB服务,非常的干货 介绍 想尝试在笔记本电脑上运行MongoDB么?希望通过执行一个简单的命令,然后就有一个轻量级.自组织的沙盒么?并可再通过一条命令就可以移除所有的痕迹么? 需要在多个环境中运行相同的应用程序栈?创建自己的容器镜像,使得开发.测试.操作和支持团队启动一份完全相同的环境

如何在Kubernetes中管理有状态应用

在Kubernetes中,StatefulSet被用来管理有状态应用的API对象.StatefulSets在Kubernetes 1.9版本才稳定.StatefulSet管理Pod部署和扩容,并为这些Pod提供顺序和唯一性的保证.与Deployment相似的地方是,StatefulSet基于spec规格管理Pod:与Deployment不同的地方是,StatefulSet需要维护每一个Pod的唯一身份标识.这些Pod基于同样的spec创建,但互相之间不能替换,每一个Pod都保留自己的持久化标识.

kubernetes中的Pod简述与实践

Pod的概念详细的Pod解释可参考k8s官网,关于Pod的概念主要有以下几点:(1)Pod是kubernetes中你可以创建和部署的最小也是最简的单位.一个Pod代表着集群中运行的一个进程:(2)在Kubrenetes集群中Pod的使用方式:(3)Pod中如何管理多个容器 理解Pod上面已经说了"Pod是kubernetes中你可以创建和部署的最小也是最简的单位.一个Pod代表着集群中运行的一个进程."Pod中封装着应用的容器(有的情况下是好几个容器),存储.独立的网络IP,管理容器如

kubernetes中部署Heketi和GlusterFS(二)

kubernetes中部署Heketi和GlusterFS(二)在上一节中,Heketi的部署方式还不能用于生产环境,因为Heketi Pod的数据并没有持久化,容易导致heketi的数据丢失,Heketi的数据保存在/var/lib/heketi/heketi.db文件中,因此需要把此目录挂载到GlusterFS分布式存储中. 按照上一节的步骤,执行heketi-cli topology load --json=topology-sample.json $ echo $HEKETI_CLI_S

Kubernetes中Pod间共享内存方案

摘要:一些公共服务组件在追求性能过程中,与业务耦合太紧,造成在制作基础镜像时,都会把这些基础组件都打包进去,因此当业务镜像启动后,容器里面一大堆进程,这让Kubernetes对Pod的管理存在很大隐患.为了让业务容器瘦身,更是为了基础组件自身的管理更独立和方便,将基础组件从业务镜像中剥离并DaemonSet容器化部署.然而一些基础组件Agent与业务Pod之间通过共享内存的方式进行通信,同一Node中跨Pod的共享内存方案是首先要解决的问题. 为什么要将公共基础组件Agent进行DaemonSe

第三章 pod:运行于kubernetes中的容器

本章内容涵盖 创建. 启动和停止 pod 使用标签组织 pod 和其他资源 使用特定标签对所有 pod 执行操作 使用命名空间将多个 pod 分到不重叠的组中 调度 pod 到指定类型的工作节点 上一章 已经大致介绍了在 Kubemetes 中创建的基本组件,包括它们的基本功 能概述. 那么接下来我们将更加详细地介绍所有类型的 Kubemetes 对象(或资源), 以便你理解在何时. 如何及为何要使用每一个对象. 其中 pod 是 Kubemetes 中最为 重要的核心概念,而其他对象仅仅是在管