github地址: https://github.com/kubernetes-incubator/external-storage/tree/master/local-volume
简介
Local Volume 表示挂载的本地存储设备,如磁盘、分区或目录,而 Local Volume 只能用作静态创建的 PersistentVolume,与 HostPath 卷相比,Local Volume 可以以持久的方式使用,而无需手动将 pod 调度到节点上,因为系统会通过查看 PersistentVolume 上的节点关联性来了解卷的节点约束。
emptyDir、hostPath以及local volume简介
- emptyDir类型的Volume在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。
- hostPath类型则是映射node文件系统中的文件或者目录到pod里。在使用hostPath类型的存储卷时,也可以设置type字段,支持的类型有文件、目录、File、Socket、CharDevice和BlockDevice。
- Local volume 允许用户通过标准PVC接口以简单且可移植的方式访问node节点的本地存储。 PV的定义中需要包含描述节点亲和性的信息,k8s系统则使用该信息将容器调度到正确的node节点。
emptyDir和hostPath在功能上的异同分析
- 二者都是node节点的本地存储卷方式;
- emptyDir可以选择把数据存到tmpfs类型的本地文件系统中去,hostPath并不支持这一点;
- hostPath除了支持挂载目录外,还支持File、Socket、CharDevice和BlockDevice,既支持把已有的文件和目录挂载到容器中,也提供了“如果文件或目录不存在,就创建一个”的功能;
- emptyDir是临时存储空间,完全不提供持久化支持;
- hostPath的卷数据是持久化在node节点的文件系统中的,即便pod已经被删除了,volume卷中的数据还会留存在node节点上;
hostPath与local volume在功能上的异同分析
- 二者都基于node节点本地存储资源实现了容器内数据的持久化功能,都为某些特殊场景下提供了更为适用的存储解决方案;
- 前者时间很久了,所以功能稳定,而后者因为年轻,所以功能的可靠性与稳定性还需要经历时间和案例的历练,尤其是对Block设备的支持还只是alpha版本;
- 二者都为k8s存储管理提供了PV、PVC和StorageClass的方法实现;
- local volume实现的StorageClass不具备完整功能,目前只支持卷的延迟绑定;
- hostPath是单节点的本地存储卷方案,不提供任何基于node节点亲和性的pod调度管理支持;
- local volume适用于小规模的、多节点的k8s开发或测试环境,尤其是在不具备一套安全、可靠且性能有保证的存储集群服务时;
配置local volume
IP地址 | 作用 |
---|---|
192.168.1.155 | k8s master |
192.168.1.156 | k8s worker |
192.168.1.157 | k8s worker |
静态local volume
在master节点创建StorageClass
==StorageClass与延迟绑定==
- 官方推荐在使用local volumes时,创建一个StorageClass并把volumeBindingMode字段设置为“WaitForFirstConsumer”。
- 虽然local volumes还不支持动态的provisioning管理功能,但我们仍然可以创建一个StorageClass并使用延迟卷绑定的功能,将volume binding延迟至pod scheduling阶段执行。
- 这样可以确保PersistentVolumeClaim绑定策略将Pod可能具有的任何其他node节点约束也进行评估,例如节点资源要求、节点选择器、Pod亲和性和Pod反亲和性。
# mkdir -p /data/k8s/yaml/kube-system/local-volume
# cat > /data/k8s/yaml/kube-system/local-volume/StorageClass.yaml << EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
EOF
# kubectl apply -f /data/k8s/yaml/kube-system/local-volume/StorageClass.yaml
storageclass.storage.k8s.io/local created
在master节点创建local volume资源文件
# cat > /data/k8s/yaml/kube-system/local-volume/prometheus-pv.yaml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-volume-test
spec:
capacity:
storage: 20Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /data/pvdata/local-volume-test
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node01
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: example-local-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: local-storage
EOF
# kubectl apply -f /data/k8s/yaml/kube-system/local-volume/prometheus-pv.yaml
persistentvolume/local-volume-test created
persistentvolumeclaim/example-local-claim created
在worker节点创建本地目录
# mkdir -p /data/pvdata/local-volume-test
在master节点启动应用测试
cat > /data/k8s/yaml/kube-system/local-volume/test-local-volume.yaml << EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: local-volume-test
name: local-volume-test
spec:
replicas: 1
selector:
matchLabels:
app: local-volume-test
template:
metadata:
labels:
app: local-volume-test
spec:
containers:
- image: busybox
name: local-volume-test
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "while true; do sleep 2; echo $(date) $(hostname)>> /mnt/test/test.log; done" ]
volumeMounts:
- name: local-data
mountPath: /mnt/test
volumes:
- name: local-data
persistentVolumeClaim:
claimName: example-local-claim
EOF
# kubectl apply -f /data/k8s/yaml/kube-system/local-volume/test-local-volume.yaml
deployment.extensions/local-volume-test created
# kubectl get pods
NAME READY STATUS RESTARTS AGE
local-volume-test-79c8f678b6-g6s9b 1/1 Running 0 9s
# kubectl get pv|grep local-stor
local-volume-test 20Gi RWO Delete Bound default/example-local-claim local-storage 3m3s
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
example-local-claim Bound local-volume-test 20Gi RWO local-storage 3m6s
到worker节点查看
# cat /data/pvdata/local-volume-test/test.log
Tue Aug 13 10:41:54 CST 2019 master
Tue Aug 13 10:41:54 CST 2019 master
Tue Aug 13 10:41:54 CST 2019 master
在StatefulSet控制器中使用
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: example-local-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage-1
resources:
requests:
storage: 5Gi
---
kind: StatefulSet
...
volumeClaimTemplates:
- metadata:
name: example-local-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage-1
resources:
requests:
storage: 5Gi