容器技术回顾 - Linux 内存文件系统

在上篇:中,我们基于 tmpfs 文件系统,通过 SystemV 方式在不同 Pod 间共享内存。那 tmpfs 是什么文件系统?它有什么特点?

本文我们先来介绍一下 Linux 内存文件系统的几种实现方式,然后我们介绍一下 /dev/shm 以及使用它来实现多 Pod 间共享内存(POSIX 文件方式)。

一、Linux 内存文件系统的三种实现方式

在Linux中可以将一部分内存mount为分区来使用,通常称之为RamDisk技术。RamDisk有三种实现方式:

1、ramdisk

Linux 内核 2.0/2.2 就已经支持,为了能够使用 Ramdisk模拟磁盘文件系统实现容器技术回顾 - Linux 内存文件系统,我们在编译内核时须将 block device 中的 Ramdisk 支持选上,它下面还有两个选项,一个是设定 Ramdisk 的大小,默认是 4096k。

1. 1 创建 ramdisk:


# create a mount point:mkdir /tmp/ramdisk0 # create a filesystem:mke2fs /dev/ram0 # mount the ramdisk:mount /dev/ram0 /tmp/ramdisk0

经过上面三步,我们可以将这个目录看成一个虚拟的分区,使用它就像使用其它的目录一样使用内存了(如果对 ramdisk 的格式化失败,那就是内核不支持 ramdisk)。

注:ramdisk的默认大小 4Mb=4096 blocks,在进行 mke2fs 的时候可以看到相关信息:

mke2fs 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09Linux ext2 filesystem formatFilesystem label=1024 inodes, 4096 blocks204 blocks (4.98%) reserved for the super userFirst data block=1Block size=1024 (log=0)Fragment size=1024 (log=0)1 block group8192 blocks per group, 8192 fragments per group1024 inodes per group

模拟磁盘文件系统实现_模拟磁盘调度算法实验报告_虚拟磁盘工具

此外,我们可以创建多个ramdisk。

1.2 修改大小

在 lilo.conf 文件中加入:

ramdisk_size=10000 (or ramdisk=10000 for old kernels)

这样在你使用lilo命令和重新启动计算机之后,ramdisk 的默认大小将会是 10M。这是一个 /etc/lilo.conf 文件的例子:

boot=/dev/hdamap=/boot/mapinstall=/boot/boot.bprompttimeout=50image=/boot/vmlinuzlabel=linuxroot=/dev/hda2read-onlyramdisk_size=10000

.3 ramdisk 特点

RamDisk就是将内存模拟为硬盘空间。在使用RamDisk时实际上是在使用内存而不是硬盘,所以会提升速度。缺点是断电重启后,目录下的内容将消失,我们可以通过定时备份/rsync的方式消除。

2、ramfs

Ramfs 顾名思义是内存文件系统,它处于虚拟文件系统(VFS)层,它是基于ram的动态文件系统的一种Linux硬盘缓冲机制。

2.1 硬盘缓冲机制

虚拟磁盘工具_模拟磁盘调度算法实验报告_模拟磁盘文件系统实现

一般的在Linux上所有的文件都被缓冲在内存中。内存中的数据页在回写后仍然会保存在内存中以防再次使用,但是回写后的数据会被标识为clean,这样系统就可以用这些内容干别的事情了。同样的,文件数据被回写后也被标识为clean,但是并没有在内存中擦除直到虚拟内存对它再次分配。一个相似的机制也同样适用于目录。

对于 ramfs,它没有回写地址。文件写入 ramfs 中后和平时一样分配目录和页,但是他们回写不了。这就意味着他们的内存永远也不能被标识为 clean,所以他们在期待回收内存的时候不会被虚拟内存释放。

2.2 创建 ramfs

它无需格式化,可以创建多个,只要内存足够,在创建时可以指定其最大能使用的内存大小。

# mkdir  /testRam # mount -t ramfs none /testRAM

缺省情况下,Ramfs被限制最多可使用内存大小的一半。可以通过maxsize(以kbyte为单位)选项来改变。

# mount -t ramfs none /testRAM -o maxsize=2000 (创建了一个限定最大使用内存为2M的ramdisk) 

2.3 ramfs 特点

ramfs and ramdisk

比较老的 ramdisk 在内存区外分配一个综合的块,用它作为文件系统的回写堆。这个块的是固定大小的,所以挂载的文件系统也是固定的。而且额外的开销也很大。

和 ramfs 对比,ramdisk 浪费了空间,让 cpu 做了不必要的工作,弄脏了 cpu 的缓存。总之,ramfs 相对来说比较简单。

模拟磁盘文件系统实现_虚拟磁盘工具_模拟磁盘调度算法实验报告

3、tmpfs

tmpfs 是一个虚拟内存文件系统,它不同于传统的用块设备形式来实现的 Ramdisk,也不同于针对物理内存的 Ramfs。tmpfs 可以使用物理内存,也可以使用交换分区。

在Linux内核中,虚拟内存资源由物理内存(RAM)和交换分区组成容器技术回顾 - Linux 内存文件系统,这些资源是由内核中的虚拟内存子系统来负责分配和管理。tmpfs 向虚拟内存子系统请求页来存储文件,它同 Linux 的其它请求页的部分一样,不知道分配给自己的页是在内存中还是在交换分区中。同 Ramfs 一样模拟磁盘文件系统实现,其大小也不是固定的,而是随着所需要的空间而动态的增加。

tmpfs 会默认挂载到/dev/shm上,默认最大为内存的一半大小,使用 df -h 命令可以看到。

# df -hFilesystem            Size  Used Avail Use% Mounted on/dev/hda1              20G  7.6G   11G  42% /tmpfs                 250M     0  250M   0% /dev/shm

3.1 修改 tmpfs 大小

mount -o size=20G -o remount /dev/shm

如果需要永久修改/dev/shm的值,需要修改/etc/fstab:

tmpfs /dev/shm tmpfs defaults,size=1.5G 0 0 #/etc/fstab中增加该行

然后重新挂载:

mount -o remount /dev/shm

3.2 特点

tmpfs 可以使用主机的 RAM,但它也可以使用交换分区来存储。

4. /dev/shm

/dev/shm 是 linux 操作系统中的共享目录,默认大小为节点上内存的一半。

“shm” 指 shared memory,文件系统为 tmpfs,该目录映射的是主机上的内存而不是磁盘。如果该目录下没有任何文件,占用的实际内存就是 0 字节。

由于该目录的实现特点,同一宿主机上的不同进程可以利用 /dev/shm 进行共享内存通信。

在容器进程中,可以参考下一小节的编排,使用以下的两种方式,实现容器进程间的共享内存通信。

单pod 多 container 挂载同一块内存类型的 volume;

多 pod 调度到同一节点,挂载宿主机的 /dev/shm;

4.1 Kubernetes 启动容器修改

已经启动的容器无法通过配置项修改,只能通过修改编排在该目录上挂载一个内存类型的存储卷解决:

模拟磁盘调度算法实验报告_虚拟磁盘工具_模拟磁盘文件系统实现

apiVersion: v1kind: Podmetadata:  name: test-shmspec:  containers:  - image: busybox:1.32    name: test-container    command: [sh, -c, "sleep infinity" ]    volumeMounts:    - mountPath: /dev/shm      name: cache-volume  volumes:  - name: cache-volume    emptyDir:      medium: Memory      sizeLimit: 500M————————————————

该方法有如下的几个限制和约束:

共用主机的 /dev/shm 实现不同 pod 间内存共享(POSIX 文件方式):

apiVersion: v1kind: Podmetadata:  name: test-shmspec:  containers:  - image: busybox:1.32    name: test-container    command: [sh, -c, "sleep infinity" ]    volumeMounts:    - mountPath: /dev/shm      name: shm    volumes:    - name: shm      hostPath:        path: /dev/shm        type: Directory

4.2 docker 启动容器修改

可以通过在启动容器时增加参数配置(指定大小):

docker run -d --name=test --shm-size=500m busybox:1.32 sleep infinity

共用主机的 /dev/shm:

docker run -d --name=test -v /dev/shm:/dev/shm busybox:1.32 sleep infinity

总结

​我们可以利用 Linux 系统的 /dev/shm 来实现不同 pod 之间的内存共享(POSIX 文件方式)。

当然了,本文只是介绍了原理,在生产上笔者不建议直接使用主机的 /dev/shm。我们可以创建 tmpfs 类型的目录,使用 hostpath 方式挂载到容器中,来实现文件方式的共享(内存文件系统比磁盘文件系统速度快)。

标签: 内存文件系统   实现方式   RamDisk   三种方式   ramdisk

留言评论