七、Kubernetes持久化存储-Volume-emptyDir-HostPath-NFS
Volume
一、Volumes
Container(容器)中的磁盘文件是短暂的,当容器崩溃时,kubelet 会重新启动容器,但最初的文件将丢失,Container 会以最干净的状态启动。另外,当一个 Pod 运行多个 Container 时,各个容器可能需要共享一些文件。
Kubernetes Volume 可以解决这两个问题。
一些需要持久化数据的程序才会用到 Volumes,或者一些需要共享数据的容器需要volumes。
Redis-Cluster:nodes.conf,保存了各个节点的IP地址,不能保存域名。所以这个文件就不能使用configmap,所以使用共享存储,做一个持久化。
NFS存储效率低,单点。
日志收集的需求:需要在应用程序的容器里面加一个 sidecar(边车容器),这个容器是一个收集日志的
容器,比如 filebeat,它通过 volumes 共享应用程序的日志文件目录。
Volumes:官方文档 https://kubernetes.io/docs/concepts/storage/volumes/
背景
Docker 也有卷的概念,但是在 Docker 中卷只是磁盘上或另一个 Container 中的目录,其生命周期不受管理。虽然目前 Docker 已经提供了卷驱动程序,但是功能非常有限,例如从Docker1.7 版本开始,每个 Container 只允许一个卷驱动程序,并且无法将参数传递给卷。
另一方面,Kubernetes 卷具有明确的生命周期,与使用它的 Pod 相同。因此,在Kubernetes中的卷可以比 Pod 中运行的任何 Container 都长,并且可以在 Container 重启或者销毁之后保留数据。Kubernetes 支持多种类型的卷,Pod 可以同时使用任意数量的卷。
从本质上讲,卷只是一个目录,可能包含一些数据,Pod 中的容器可以访问它。要使用卷 Pod需要通过.spec.volumes 字段指定为 Pod 提供的卷,以及使用.spec.containers.volumeMounts 字段指定卷挂载的目录。从容器中的进程可以看到由 Docker 镜像和卷组成的文件系统视图,卷无法挂载其他卷或具有到其他卷的硬链接,Pod 中的每个 Container 必须独立指定每个卷的挂载位置。
Types of volumes
- awsElasticBlockStore (removed)
- azureDisk (removed)
- azureFile (deprecated)
- cephfs
- cinder (removed) ----OpenStack的
- configMap
- csi ------ 云原生
- downwardAPI
- emptyDir
- fc (fibre channel)
- flexVolume (deprecated)
- gcePersistentDisk (removed)
- gitRepo (deprecated)
- glusterfs (removed)
- hostPath ----挂载宿主机的路径
- iscsi
- local
- nfs
- persistentVolumeClaim
- portworxVolume (deprecated)
- Portworx CSI migration
- projected
- rbd
- RBD CSI migration
- secret
- vsphereVolume (deprecated)
- Using subPath
- Resources
- Out-of-tree volume plugins
- Mount propagation
二、Volumes EmptyDir实现数据共享
同一个Pod中的多个容器能够共享Pod级别的存储卷Volume。
Volume可以被定义为各种类型,多个容器各自进行挂载操作,将一个Volume挂载为容器内部需要的目录。
emptyDir
和上述 volume 不同的是,如果删除 Pod,emptyDir 卷中的数据也将被删除,一般 emptyDir卷用于 Pod 中的不同 Container 共享数据。它可以被挂载到相同或不同的路径上。
默认情况下,emptyDir 卷支持节点上的任何介质,可能是 SSD、磁盘或网络存储,具体取决于自身的环境。可以将emptyDir.medium 字段设置为 Memory,让 Kubernetes 使用 tmpfs(内存支持的文件系统),虽然 tmpfs 非常快,但是 tmpfs 在节点重启时,数据同样会被清除,并且设置的大小会被计入到 Container 的内存限制当中。
使用 emptyDir 卷的示例,直接指定 emptyDir 为{}即可:
创建yaml文件
# vim nginx-deploy-emptyDir.yamlapiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginxemptyname: nginxempty
spec:progressDeadlineSeconds: 600replicas: 2revisionHistoryLimit: 10selector:matchLabels:app: nginxemptystrategy:rollingUpdate:maxSurge: 25%maxUnavailable: 25%type: RollingUpdatetemplate:metadata:creationTimestamp: nulllabels:app: nginxemptyspec:containers:- image: nginx:1.15.2imagePullPolicy: IfNotPresentname: nginxresources: {}terminationMessagePath: /dev/termination-logterminationMessagePolicy: FileterminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /opt #第一个容器的挂载目录name: share-volume- image: nginx:1.15.2imagePullPolicy: IfNotPresentname: nginx2command:- sh- -c- sleep 3600resources: {}terminationMessagePath: /dev/termination-logterminationMessagePolicy: FileterminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /mnt #第二个容器的挂载目录name: share-volumednsPolicy: ClusterFirstrestartPolicy: AlwaysschedulerName: default-schedulersecurityContext: {}terminationGracePeriodSeconds: 30volumes:- name: share-volumeemptyDir: {}#medium: Memory #使用内存#注意:同一个pod,两个nginx会暂用80端口,导致pod报错。
创建并确认
[root@k8s-master01 practice]#kubectl create -f nginx-deploy-emptyDir.yaml
deployment.apps/nginxempty created
[root@k8s-master01 practice]#kubectl get po
NAME READY STATUS RESTARTS AGE
nginxempty-54dd97bd5d-5sg5h 2/2 Running 0 56s
nginxempty-54dd97bd5d-cfnbc 2/2 Running 0 56s
进入容器测试
# 1) 进入pod的第一个容器nginx,创建文件,写入内容
[root@k8s-master01 practice]#kubectl exec -it nginxempty-54dd97bd5d-5sg5h -c nginx -- bash
root@nginxempty-54dd97bd5d-5sg5h:/opt# df -Th
Filesystem Type Size Used Avail Use% Mounted on
overlay overlay 50G 6.8G 44G 14% /
tmpfs tmpfs 64M 0 64M 0% /dev
tmpfs tmpfs 7.9G 0 7.9G 0% /sys/fs/cgroup
/dev/mapper/centos-root xfs 50G 6.8G 44G 14% /opt
shm tmpfs 64M 0 64M 0% /dev/shm
tmpfs tmpfs 16G 12K 16G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs tmpfs 7.9G