doina

一个小菜鸟运维工程师.

k8s local volume存储卷

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
点赞

发表评论

邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据