前言:
kubernetes的持久化存储前面学习的时候好像有很多误区,在此,做一个准确的总结,并且与各位能够有一个深入的探讨。
A,为什么需要持久化存储?
不管是怎么学习kubernetes,都需要先弄明白一件事,学的目的是什么?因此,我们需要先搞清楚,为什么需要持久化存储,原因如下:
在k8s中部署的应用都是以pod容器的形式运行的,因为Pod是有生命周期的,如果pod不挂载数据卷,那pod被删除或重启后这些数据会随之消失,如果想要长久的保留这些数据就要用到pod数据持久化存储。
例如,web服务,数据库服务,这些服务很多都是有状态的,这么说吧,比如nginx发布一个项目,你总不可能自己docker build一个镜像,把项目打进镜像,然后kubernetes在启动这个镜像吧,并且对外提供服务的时候,比如账号注册这些动态数据,如果pod意外挂掉了,岂不是懵逼了?因此,我们需要把pod内的一些数据做本地(或者远程)存储并且期限是永久的。
B,存储方案介绍
数据持久化存储的迫切性是能够理解了,那么,数据是应该或者说可以存储到哪里呢(也可以理解为存储方案)?
方案有很多,目前,Kubernetes 支持的存储卷可简单归为以下类别,它们也各自有着不少的实现插件。
1)临时存储卷:emptyDir。
2)本地存储卷:hostPath 和 local。
3)网络存储卷:
云存储——awsElasticBlockStore、gcePersistentDisk、azureDisk 和 azureFile。
网络文件系统——NFS、GlusterFS、CephFS 和 Cinder。
网络块设备——iscsi、FC、RBD 和 vSphereVolume。
网络存储平台——Quobyte、PortworxVolume、StorageOS 和 ScaleIO。
4)特殊存储卷:Secret、ConfigMap、DownwardAPI 和 Projected。
5)扩展支持第三方存储的存储接口(Out-of-Tree 卷插件):CSI 和 FlexVolume。
下面是kubernetes大致支持的一些存储方案,可以看到有最为常用的local,nfs,iscsi,ceph,cinder等等类型。茫茫多的持久化存储方案,当然是先学习最基本的那几种了:hostpath,local,nfs
[root@master coredns]# k explain pv.spec KIND: PersistentVolume VERSION: v1 RESOURCE: spec <Object> DESCRIPTION: Spec defines a specification of a persistent volume owned by the cluster. Provisioned by an administrator. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes PersistentVolumeSpec is the specification of a persistent volume. FIELDS: accessModes <[]string> AccessModes contains all ways the volume can be mounted. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes awsElasticBlockStore <Object> AWSElasticBlockStore represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore azureDisk <Object> AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. azureFile <Object> AzureFile represents an Azure File Service mount on the host and bind mount to the pod. capacity <map[string]string> A description of the persistent volume's resources and capacity. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity cephfs <Object> CephFS represents a Ceph FS mount on the host that shares a pod's lifetime cinder <Object> Cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md claimRef <Object> ClaimRef is part of a bi-directional binding between PersistentVolume and PersistentVolumeClaim. Expected to be non-nil when bound. claim.VolumeName is the authoritative bind between PV and PVC. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding csi <Object> CSI represents storage that is handled by an external CSI driver (Beta feature). fc <Object> FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. flexVolume <Object> FlexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. flocker <Object> Flocker represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running gcePersistentDisk <Object> GCEPersistentDisk represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk glusterfs <Object> Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://examples.k8s.io/volumes/glusterfs/README.md hostPath <Object> HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath iscsi <Object> ISCSI represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin. local <Object> Local represents directly-attached storage with node affinity mountOptions <[]string> A list of mount options, e.g. ["ro", "soft"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options nfs <Object> NFS represents an NFS mount on the host. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs nodeAffinity <Object> NodeAffinity defines constraints that limit what nodes this volume can be accessed from. This field influences the scheduling of pods that use this volume. persistentVolumeReclaimPolicy <string> What happens to a persistent volume when released from its claim. Valid options are Retain (default for manually created PersistentVolumes), Delete (default for dynamically provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be supported by the volume plugin underlying this PersistentVolume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming photonPersistentDisk <Object> PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine portworxVolume <Object> PortworxVolume represents a portworx volume attached and mounted on kubelets host machine quobyte <Object> Quobyte represents a Quobyte mount on the host that shares a pod's lifetime rbd <Object> RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md scaleIO <Object> ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. storageClassName <string> Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass. storageos <Object> StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod More info: https://examples.k8s.io/volumes/storageos/README.md volumeMode <string> volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. vsphereVolume <Object> VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine
一,emptyDir 本地存储
emptyDir存储卷可以看作是Pod上的一个临时目录,其生命周期和Pod相同,Pod创建时被创建,Pod删除时被删除,通常用于数据缓存和临时存储。
例子:
deploy-nginx.yam
说明:
medium 有两个值,一个是不写就是默认的,这个是在pod运行的节点上的本地目录,一个是Memory,此时的数据是存放到内存的。
sizeLimite 也是有两个值,一个是不写就是默认的,此时不限制空间的使用,如果medium的值是Memory,此时默认是节点的内存一半。(例如,17服务器8G内存,那么,最多缓存4G,也就是最多占用4G内存)
apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx strategy: {} template: metadata: labels: app: nginx spec: containers: - image: nginx name: nginx resources: {} volumeMounts: - name: cache-volume mountPath: /cache volumes: - name: cache-volume emptyDir: medium: sizeLimit: 128Mi
假设部署此deployment,查询此pod在192.168.217.17这个节点上,先进入pod的/cache目录echo一个文件,文件内容为hello world:
[root@master ~]# k exec -it nginx-f9df8c74f-gf9vz -- /bin/bash root@nginx-f9df8c74f-gf9vz:/# cd cache/ root@nginx-f9df8c74f-gf9vz:/cache# echo "hello world " >test.fiel root@nginx-f9df8c74f-gf9vz:/cache# exit
在192.168.217.17上find此文件,可以看到有这么一个文件,路径比较长:
[root@slave1 ~]# find / -name test.fiel /var/lib/kubelet/pods/db7976ed-4c86-4dae-ba2a-92d4dbc7b1e0/volumes/kubernetes.io~empty-dir/cache-volume/test.fiel [root@slave1 ~]# cat /var/lib/kubelet/pods/db7976ed-4c86-4dae-ba2a-92d4dbc7b1e0/volumes/kubernetes.io~empty-dir/cache-volume/test.fiel hello world
删除此pod,还是在17服务器上查看,可以看到没有这个文件了:
[root@slave1 ~]# cat /var/lib/kubelet/pods/db7976ed-4c86-4dae-ba2a-92d4dbc7b1e0/volumes/kubernetes.io~empty-dir/cache-volume/test.fiel cat: /var/lib/kubelet/pods/db7976ed-4c86-4dae-ba2a-92d4dbc7b1e0/volumes/kubernetes.io~empty-dir/cache-volume/test.fiel: No such file or directory1.
此,emptyDir这种方式的持久化存储并不持久,只能用于一些临时存储数据和缓存的场景。
二,hostpath 本地存储
hostPath是将工作节点上的目录或文件关联到Pod上的一种卷类型,类似于Docker的bind mount,hostPath卷的生命周期和工作节点相同。hostPath存储卷在Pod需要访问节点上的文件时很有用。
(a)
hostPath存储卷定义在Pod资源的spec.volumes.hostPathz字段,可嵌套使用的字段有两个:
path <string>:用于指定工作节点上的目录路径
type <string>:用于指定工作节点之上的存储类型
(b)
关于type字段,目前支持的值有下面这些:
DirectoryOrCreate:指定的目录不存在时,自动将其创建为0755权限的空目录,属主和属组都为kubelet
Directory:事先必须存在的目录
FileOrCreate:指定的不存在时,自动将其创建为0644权限的空文件,属主和属组都为kubelet
File:事先必须存在的文件
Socket:事先必须存在的Socket文件
CharDevice:事先必须存在的字符设备路径
BlockDevice:事先必须存在的文件设备路径
(c)
[root@master ~]# k explain deploy.spec.template.spec.volumes.hostPath KIND: Deployment VERSION: apps/v1 RESOURCE: hostPath <Object> DESCRIPTION: HostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling. FIELDS: path <string> -required- Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath type <string> Type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath
最后的网址有比较齐全的官方示例,下面的文件也是通过官方示例改造的。
The supported values for field type
are: