🏆 volume
Container
中的文件在磁盘上是临时存放的,这给 Container
中运行的较重要的应用 程序带来一些问题。问题之一是当容器崩溃时文件丢失。kubelet
会重新启动容器, 但容器会以干净的状态重启。 会在同一 Pod
中运行多个容器并需要共享文件时, Kubernetes
卷(Volume) 这一抽象概念能够解决这两个问题。
Kubernetes
支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。 临时卷类型的生命周期与 Pod
相同,但持久卷可以比 Pod
的存活期长。 当 Pod
不再存在时,Kubernetes
也会销毁临时卷;不过 Kubernetes
不会销毁 持久卷。对于给定 Pod
中任何类型的卷,在容器重启期间数据都不会丢失。
卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放 的内容。
使用卷时, 在 .spec.volumes
字段中设置为 Pod
提供的卷,并在 .spec.containers[\*].volumeMounts
字段中声明卷在容器中的挂载位置。 容器中的进程看到的是由它们的 Docker
镜像和卷组成的文件系统视图。 Docker 镜像 位于文件系统层次结构的根部。各个卷则挂载在镜像内的指定路径上。 卷不能挂载到其他卷之上,也不能与其他卷有硬链接。 Pod
配置中的每个容器必须独立指定各个卷的挂载位置。
🌟 卷的类型
Kubernetes支持以下类型的卷:
#awsElasticBlockStore azureDisk azureFile cephfs csi downwardAPI emptyDir fc flocker
#gcePersistentDisk gitRepo glusterfs hostPath iscsi local nfs persistentVolumeClaim
#projected portworxvolume quobyte rbdl scaleI0 secret
#storageos vsphereVolume
🌟 emptyDir
当 Pod
被分配给节点时,首先创建 emptyDir
卷,并且只要该 Pod
在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod
中的容器可以读取和写入 emptyDir
卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 Pod
时,emptyDir
中的数据将被永久删除
容器崩溃并不会导致
Pod
被从节点上移除,因此容器崩溃期间 emptyDir 卷中的数据是安全的。
emptyDir
的一些用途:
- 缓存空间,例如基于磁盘的归并排序。
- 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
- 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
取决于你的环境,emptyDir
卷存储在该节点所使用的介质上;这里的介质可以是磁盘或 SSD
或网络存储。但是,你可以将 emptyDir.medium
字段设置为 "Memory
",以告诉 Kubernetes
为你挂载 tmpfs
(基于 RAM
的文件系统)。 虽然 tmpfs
速度非常快,但是要注意它与磁盘不同。 tmpfs
在节点重启时会被清除,并且你所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。
1️⃣ 配置emptyDir
apiVersion: v1
kind: Pod
metadata:
name: volume-pod-test1
spec:
volumes:
- name: empty-test
emptyDir: {}
containers:
- name: test
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: empty-test
mountPath: /test
2️⃣ 进入pod
[root@master volume]# kubectl exec -it volume-pod-test1 bash
root@volume-pod-test1:/# ls
bin docker-entrypoint.d home media proc sbin test var
boot docker-entrypoint.sh lib mnt root srv tmp
dev etc lib64 opt run sys usr
root@volume-pod-test1:/# cd test/
root@volume-pod-test1:/test# ls
3️⃣ 使用emptyDir创建容器共享目录
apiVersion: v1
kind: Pod
metadata:
name: volume-pod-test1
spec:
volumes:
- name: empty-test
emptyDir: {}
containers:
- name: test1
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: empty-test
mountPath: /test1
- name: test2
image: busybox
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 600s;"]
volumeMounts:
- name: empty-test
mountPath: /test2
🌟 HostPath
也很好理解就是将主机节点的文件系统中你的文件或者目录挂载到集群中
hostPath
的一些用法有:
- 运行一个需要访问
Docker
内部机制的容器;可使用hostPath
挂载/var/lib/docker
路径。 - 在容器中运行
cAdvisor
时,以hostPath
方式挂载/sys
。 - 允许
Pod
指定给定的hostPath
在运行Pod
之前是否应该存在,是否应该创建以及应该以什么方式存在。
除了必需的 path
属性之外,用户可以选择性地为 hostPath
卷指定 type
。支持的 type
值如下:
取值 | 行为 |
---|---|
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。 | |
DirectoryOrCreate | 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。 |
Directory | 在给定路径上必须存在的目录。 |
FileOrCreate | 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。 |
File | 在给定路径上必须存在的文件。 |
Socket | 在给定路径上必须存在的 UNIX 套接字。 |
CharDevice | 在给定路径上必须存在的字符设备。 |
BlockDevice | 在给定路径上必须存在的块设备。 |
当使用这种类型的卷时要小心,因为:
- 具有相同配置(例如基于同一
PodTemplate
创建)的多个Pod
会由于节点上文件的不同 而在不同节点上有不同的行为。 - 下层主机上创建的文件或目录只能由
root
用户写入。你需要在 特权容器 中以root
身份运行进程,或者修改主机上的文件权限以便容器能够写入hostPath
卷。
apiVersion: v1
kind: Pod
metadata:
name: volume-test2-pod
spec:
volumes:
- name: hostpath-test
hostPath:
path: /data
type: Directory
- name: hostpath-test2
hostPath:
path: /data/date
type: FileOrCreate
containers:
- name: test1
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: hostpath-test
mountPath: /data
- name: hostpath-test2
mountPath: /data/date
因为是 Directory
,所以要在 node
节点都创建 /data
目录,在去创建 hostpath
mkdir /data
kubectl create -f volume.hostpath.yaml
进入容器查看
[root@master volume]# kubectl exec -it volume-test2-pod /bin/bash
root@volume-test2-pod:/# cd /data/
root@volume-test2-pod:/data# ls
date
在查看节点
[root@node2 ~]# cd /data/
[root@node2 data]# ls
date
🌟 NFS
NFS客户端将NFS服务端设置好的共享目录挂载到本地某个挂载点,对于客户端来说,共享的资源就相当于在本地的目录下
- 安装nfs工具
[root@master ~]# yum install -y nfs-utils
- 配置挂载规则
[root@master ~]# cat /etc/exports
/nfs *(rw,no_root_squash)
- 创建nfs挂在目录并设置nfs开机自启
[root@master ~]# mkdir /nfs
[root@master ~]# systemctl enable --now nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
[root@master ~]# showmount -e
Export list for master:
/nfs *
- 创建nfs.yaml
[root@master volume]# cat volume-nfs.yaml
apiVersion: v1
kind: Pod
metadata:
name: nfs-pod
spec:
containers:
- image: ubuntu:18.04
name: ubuntu-nfs-pod
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/local/nfs
name: nfs
volumes:
- name: nfs
nfs:
path: /nfs
server: 192.168.200.10
- 创建后查看
[root@master volume]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-pod 0/1 ContainerCreating 0 10m
##发现一直没有起来
- 查看为什么起不了
Mounting command: systemd-run
Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/2f110856-54c4-42e4-b852-abae3abcc327/volumes/kubernetes.io~nfs/nfs --scope -- mount -t nfs 192.168.200.10:/nfs /var/lib/kubelet/pods/2f110856-54c4-42e4-b852-abae3abcc327/volumes/kubernetes.io~nfs/nfs
Output: Running scope as unit run-60150.scope.
mount: wrong fs type, bad option, bad superblock on 192.168.200.10:/nfs,
missing codepage or helper program, or other error
(for several filesystems (e.g. nfs, cifs) you might
need a /sbin/mount.<type> helper program)
In some cases useful info is found in syslog - try
dmesg | tail or so.
Warning FailedMount 11m kubelet, slave MountVolume.SetUp failed for volume "nfs" : mount failed: exit status 32
- 在查看一下在哪个节点
[root@master volume]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-pod 0/1 ContainerCreating 0 24m <none> slave <none> <none>
##可以看见是在slave节点slave节点没有配置nfs
- 在slave节点下载nfs
[root@master volume]# kubectl apply -f volume-nfs.yaml
pod/nfs-pod created
[root@master volume]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-pod 1/1 Running 0 22s
[root@master volume]# kubectl exec -it nfs-pod bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
root@nfs-pod:/# cd /usr/local/nfs/
root@nfs-pod:/usr/local/nfs# ls
root@nfs-pod:/usr/local/nfs# mkdir 1
- 在进入本机的nfs目录查看
[root@master nfs]# ls
1