k8s 数据管理

Kubernetes Volume 

  为了持久化保存容器的数据,可以使用 Kubernetes Volume。Volume 的生命周期独立于容器,Pod的容器可能被销毁和重建,但是Volume会被保留。

    本质上,kubernetes Volume 是一个目录,这一点与Docker Volume类似。当Volume被mount到Pod,Pod中所有的容器都可以访问这个Volume。 Kubernetes Volume 也支持多种backend类型、包括emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph 等,Volume 提供了对各种backend的抽象,容器在使用Volume读写数据的时候不需要关系数据到底是存放在本地节点的文件系统还是云硬盘上。对它来说,所有类型的Volume都只是一个目录。

emptyDir

   emptyDir Volume 是Host上的一个空目录。emptyDir Volume对于容器来说是持久的,对于Pod则不是。当Pod从节点删除时,Volume的内容也会被删除。但如果只是容器被销毁而Pod还在,则Volume不受影响。
emptyDir Volume 的生命周期与Pod一致。
Pod 中所有的容器都可以共享Volume,它们可以指定各自的mount路径。
这里我们模拟一个producer-consumer 场景。Pod有两个容器Producer和consumer,它们之间共享了一个Volume。producer负责往Volume 中写数据,consumer则是从Volume读取数据。
apiVersion: v1
kind: Pod
metadata:
  name: producer-consumer
spec:
  containers:
  - image: centos
    name: producer
    volumeMounts:
    - mountPath: /producer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - echo "hello world" > /producer_dir/hello; sleep 30000
  - image: centos
    name: consumer
    volumeMounts:
    - mountPath: /consumer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - cat /consumer_dir/hello; sleep 30000

  volumes:
  - name: shared-volume
    emptyDir: {}
  kubectl logs 显示容器consumer 成功读到了producer写入的数据,验证了两个容器共享emptyDir Volume。
因为emptyDir 是Docker Host文件系统里的目录,期效果相当于执行了docker run -v /producer_dir 和docker run -v
/consumer_dir .通过docker inspect 查看容器的详细配置信息,发现两个容器都mount了同一个目录

  /var/lib/kubelet/pods/b609d0d2-c47f-11e9-835c-00163e100228/volumes/kubernetes.io~empty-dir/shared-volume 就是emptyDir 在Host上的真正路径

  emptyDir 是Host上创建的临时目录,其优点是能够方便地为Pod中的容器提供共享存储,不需要额外的配置。它不具备持久性,如果Pod不存在了,emptyDir 也就没有了。根据这个特性,emptyDir特别适合Pod中容器需要临时共享存储空间的场景。比如前面的生产者消费者用例。

hostPath

    hostPath Volume 的作用是将Docker Host 文件系统中已经存在的目录mount给Pod的容器。大部分应用不会使用hostPath Volume,因为这实际上增加了Pod与节点的耦合,限制了Pod的使用。不过那些需要访问Kubernetes或Docker内部数据(配置文件和二进制库)的应用则需要使用hostPath,如果Pod 被销毁了,hostPath对应的目录还是会被保留,不过一旦Host崩溃,hostPath 也就无法访问了。

apiVersion: v1
kind: Pod
metadata:
name: producer-consumer
spec:
containers:
- image: centos
name: producer
volumeMounts:
- mountPath: /producer_dir
name: shared-volume
args:
- /bin/sh
- -c
- echo "hello world" > /producer_dir/hello; sleep 30000
volumes:
- name: shared-volume
hostPath:
path: /home/k8s/2019-08-30 #宿主机挂载点

外部存储

  如果Kubernetes 部署在云上,那么可以直接使用云硬盘作为Volume 

  Kubernetes Volume 也可以使用主流的分布式存储,比如Ceph、GlustetFS  等

  Ceph文件系统的/some/path/in/side/cephfs 目录被mount到容器路径/test/ceph
相当于emptyDir和hostPath,这些Volume类型的最大特点就是不依赖Kubernetes。Volume的底层基础设施由独立的存储系统管理,与Kubernetes集群是分离的。数据被持久化后,即是整个Kubernetes崩溃也不会受损。

 PersistentVolume & PersistemtVolumeClaim

  Persistent Volume (PV) 是外部存储系统中的一块存储空间,由管理员创建和维护。与Volume 一样,PV具有持久性,生命周期独立于Pod
PersistentVolumeClaim(PVC)是对PV的申请(Claim)。PVC通常由普通用户创建和维护。需要为Pod分配存储资源时,用户可以创建一个PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,Kubernretes会查找并提供满足条件的PV。
有了PersistentVolumeClaim ,用户只需要告诉Kubernetes需要什么样的资源,而不必关心真正空间从哪里分配、如何访问等底层细节信息。这些Storage Provider的底层信息交给管理员来处理,
Kubernetes 支持多种类型的PersiistentVolume,比如Ceph、NFS等

创建PV

下面创建一个PV ,配置文件为 nfs-pv.yaml

kind: PersistentVolume
apiVersion: v1
metadata:
name: mysql
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-a
nfs:
path: /nfsdata/mysql-pv
server: 172.18.211.44

capacity : 指定PV的容量为1GB

accessModes : 指定访问模式为ReadWriteOnce ,支持的访问模式有:
  • ReadWriteOnce : 表示PV能以read-write模式mount到单个节点
  • ReadOnlyMany:表示PV能以read-only模式mount到多个节点
  • ReadWriteMany:表示PV能以read-write 模式mount到多个节点。
persistentVolumeReclaimPolicy 指定PV的回收策略为Recycle,支持的策略有:
  • Retain:表示需要管理员手动回收
  • Recycle:表示清除PV中的数据,效果相当于执行 rm -rf  /thevolume/*
  • Delete:表示删除StorageProvider 上对应的存储资源。
storageClassName: 指定PV 的class为nfs-a。相当于为PV设置了一个分类。PVC以指定classs申请相应class的PV
创建mypv1:
kubectl  apply -f nfs-pv.yaml

 

STATUS 为 Available,表示 mypv1 就绪,可以被 PVC 申请。

创建PVC

接下来创建 PVC mypvc1,配置文件 nfs-pvc1.yml 如下:
PVC 就很简单了,只需要指定 PV 的容量,访问模式和 class。
执行命令创建 mypvc1:
从 kubectl get pvc 和 kubectl get pv 的输出可以看到 mypvc1 已经 Bound 到 mypv1,申请成功。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs

kubetl apply -f  mypvc.yaml

 从 kubectl get pvc 和 kubectl get pv 的输出可以看到 mypvc1 已经 Bound 到 mypv1,申请成功。

创建Pod

接下来就可以在Pod 中使用存储了,Pod配置文件Pod1.yml

apiVersion: v1
kind: Pod
metadata:
  name: mypod1
spec:
  containers:
    - name: mypod1
      image: busybox
      args:
      - /bin/sh
      - -c
      - sleep 300000
      volumeMounts:
      - mountPath: "/mydata"
        name: mydata
  volumes:
    - name: mydata
      persistentVolumeClaim:
        claimName: mypvc1

验证

在 Pod中创建文件并写入内容,

kubectl  exec -it mypod1   -- sh -c  "echo 2 >>  /mydata/hello"

可以看到 /mydata/hello确实已经保存在nfs的服务器目录/nfsdata中了1

PV的回收

 先删pod 再删pvc 最后删pv

# kubectl apply -f mypod.yaml
# kuectl apply -f  mypvc.yaml

删除pvc之后pv的状态变为Available,,此时解除绑定后则可以被新的 PVC 申请。

/nfsdata文件中的文件被删除了

 

为 PV 的回收策略设置为 Recycle,所以数据会被清除,但这可能不是我们想要的结果。如果我们希望保留数据,可以将策略设置为 Retain

删除pv

# kubectl apply -f nfs-pv.yaml
PV 还支持 Delete 的回收策略,会删除 PV 在 Storage Provider 上对应存储空间。NFS 的 PV 不支持 Delete,支持 Delete 的 Provider 有 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。

PV的动态供给

前面的例子中,我们提前创建了PV,然后通过PVC 申请PV 并在Pod中使用,这种方法叫作静态供给(Static Provision)
动态供给(Dynamical Provision),即如果没有满足PVC条件的PV ,会动态创建PV。相比静态供给,动态供给有明显的优势:不需要提前创建PV,减少了管理员的工作量,效率高。
 
动态供给是通过StorageClass实现的,StorageClass 定义了如何创建PV
基于gfs的动态供给参考
 
基于nfs的动态供给参考

 

问题

pv  始终处于Terminating”状态,而且delete不掉。

解决方法

kubectl patch pv  pvname  -p '{"metadata":{"finalizers":null}}'

 

 

posted @ 2019-08-30 15:30  xmc_2022  阅读(164)  评论(0)    收藏  举报