Kubernetes中的本地存储意味着在每一个节点服务器上本地可用的存储设备或文件系统。本文介绍Kubernetes中现有的本地存储解决方案,包括官方原生支持的存储方式以及社区的一些常见方案。node
目前官方支持如下3种本地存储方式:git
当 Pod 指定到某个节点上时,首先建立的是一个emptyDir
卷,而且只要 Pod 在该节点上运行,卷就一直存在。 就像它的名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载emptyDir
卷的路径可能相同也可能不一样,可是这些容器均可以读写emptyDir
卷中相同的文件。 当 Pod 由于某些缘由被从节点上删除时,emptyDir
卷中的数据也会永久删除。github
注意:容器崩溃并不会致使 Pod 被从节点上移除,所以容器崩溃时 `emptyDir` 卷中的数据是安全的。
emptyDir
的一些用途:docker
默认状况下, emptyDir
卷存储在支持该节点所使用的介质上;这里的介质能够是磁盘或 SSD 或网络存储,这取决于您的环境。 可是,您能够将 emptyDir.medium
字段设置为 "Memory"
,以告诉 Kubernetes 为您安装 tmpfs(基于 RAM 的文件系统)。 虽然 tmpfs 速度很是快,可是要注意它与磁盘不同。 tmpfs 在节点重启时会被清除,而且您所写入的全部文件都会计入容器的内存消耗,受容器内存限制约束。数据库
emptyDir的位置应该在运行pod的给定节点上的/var/lib/kubelet/pods/{podid}/volumes/kubernetes.io~empty-dir/
目录下。ubuntu
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - image: my-app-image name: my-app volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {}
Pod中的全部容器共享使用emptyDir卷。所以,咱们使用emptyDir的一个场景是,Pod中init容器负责到配置中心或是秘钥管理中心拉取一些配置,而后写入到emptyDir中,这样业务容器就能够读取到配置。
hostPath
卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。 虽然这不是大多数 Pod 须要的,可是它为一些应用程序提供了强大的逃逸机会。后端
例如,hostPath
的一些用法有:api
hostPath
挂载 /var/lib/docker
路径。hostPath
方式挂载 /sys
。hostPath
在运行 Pod 以前是否应该存在,是否应该建立以及应该以什么方式存在。除了必需的 path
属性以外,用户能够选择性地为 hostPath
卷指定 type
。缓存
例如:安全
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - image: my-app-image name: my-app volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: path: /data #directory on host type: Directory #optional
type: Directory
定义目录必须在主机上已经存在,所以在使用主机路径以前,您必须首先在该目录中手动建立它。
类型的其余值是DirectoryOrCreate
,File
,FileOrCreate
。若是* OrCreate在主机上尚不存在,将动态建立。
使用此卷类型的缺点:
Local PV(本地持久化存储),指的就是利用机器上的磁盘来存放业务须要持久化的数据,和远端存储相似,此时数据依然独立于 Pod 的生命周期,即便业务 Pod 被删除,数据也不会丢失。
同时,和远端存储相比,本地存储能够避免网络 IO 开销,拥有更高的读写性能,因此分布式文件系统和分布式数据库这类对 IO 要求很高的应用很是适合本地存储。
可是,在使用本地永久卷时,有一些重要的限制和注意事项须要考虑:
Local PV和hostPath区别
为了更好地了解本地持久卷的好处,将其与HostPath卷进行比较颇有用。 HostPath卷将主机节点文件系统中的文件或目录装载到Pod中。一样,本地永久卷将本地磁盘或分区安装到Pod中。
最大的区别是Kubernetes调度程序了解本地持久卷属于哪一个节点。对于HostPath卷,调度程序可能会将引用HostPath卷的pod移至其余节点,从而致使数据丢失。可是对于本地持久卷,Kubernetes调度程序可确保始终将使用本地持久卷的容器调度到同一节点。
尽管能够经过持久卷声明(PVC)引用HostPath卷,也能够在pod定义中直接内联HostPath卷,可是只能经过PVC引用本地持久卷。因为Persistent Volume对象是由管理员管理的,所以,Pod不能访问主机上的任何路径,所以能够提供额外的安全优点。
其余好处包括支持在安装期间格式化块设备以及使用fsGroup进行卷全部权。
如何使用Local PV?
工做负载可使用与远程存储后端相同的PersistentVolumeClaim接口请求本地持久卷。这使得跨集群,云和本地环境轻松交换存储后端。
首先,应该建立一个StorageClass来设置volumeBindingMode:WaitForFirstConsumer
来启用卷拓扑感知调度。该模式指示Kubernetes等待绑定PVC,直到Pod开始使用它。
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer
而后,能够配置并运行外部静态预配器,觉得节点上的全部本地磁盘建立PV。
$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE local-pv-27c0f084 368Gi RWO Delete Available local-storage 8s local-pv-3796b049 368Gi RWO Delete Available local-storage 7s local-pv-3ddecaea 368Gi RWO Delete Available local-storage 7s
以后,经过建立带有volumeClaimTemplates的PVC和Pod或StatefulSet,工做负载能够开始使用PV。
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
一旦StatefulSet启动并运行,PVC都将绑定:
$ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE local-vol-local-test-0 Bound local-pv-27c0f084 368Gi RWO local-storage 3m45s local-vol-local-test-1 Bound local-pv-3ddecaea 368Gi RWO local-storage 3m40s local-vol-local-test-2 Bound local-pv-3796b049 368Gi RWO local-storage 3m36s
当再也不须要磁盘时,能够删除PVC。外部静态预配器将清理磁盘,并使PV再次可用。
社区的一些方案:
TopoLVM
TopoLVM,一个用于本地存储的新CSI插件,可以使用LVM动态配置卷。它实现了动态卷配置,原始块卷,文件系统指标,并将实如今线卷大小调整和临时卷。
架构
TopoLVM 组件包括:
topolvm-controller
: CSI controllertopolvm-scheduler
: 用于TopoLVM 的scheduler extender topolvm-node
: CSI node 服务lvmd
: 管理LVM卷的gRPC 服务特性
因为不是k8s原生方案,因此在使用前,咱们须要先安装。关于安装,你们参考官方文档便可。
示例:
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: topolvm-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: topolvm-provisioner --- apiVersion: v1 kind: Pod metadata: name: my-pod labels: app.kubernetes.io/name: my-pod spec: containers: - name: ubuntu image: quay.io/cybozu/ubuntu:18.04 command: ["/usr/local/bin/pause"] volumeMounts: - mountPath: /test1 name: my-volume volumes: - name: my-volume persistentVolumeClaim: claimName: topolvm-pvc