• K8s 里如何优雅地使用 /dev/shm 实现容器间共享内存


    1. 从 docker run 的 --shm-size 参数聊起

    今天无意见看到算法同学写的一个 docker run 命令用到了 --shm-size 参数。没错,接着他想将这些容器跑到 K8s 里,于是我就得开始思考 --shm-size 在 K8s 里对应的特性是什么了。

    我猜 K8s 里会有优雅的方式来实现一样的目的,最终我也找到了那个优雅的方法。不过这个过程还是稍稍坎坷,我在在网上看一圈,找到的前2种方案都有点“丑陋”,但是给人一种“只能这样”的错觉。最后看到第三条路的时候,我不禁拍了一下大腿:“我X!太帅了!”。于是乎,我想让你们也拍一下大腿,然后就有了此文。行,且往下看。

    2. Linux 里的 /dev/shm

    Linux 里有一个 /dev/shm 目录,shm 代表共享内存(Shared Memory)。如果这是你第一次听说 shm,可能会有点疑惑:“这东西到底是内存还是磁盘”。其实 /dev/shm 是一个临时文件系统,让你用操作磁盘中的文件一样的方式来将读写内存。换言之,你可以用文件读写的语法来操作“/dev/shm/a.txt”,但是这个文件本质是存在内存里的,所以读写速度会非常快。

    有了 /dev/shm,你就可以让一个进程非常高效地存取一些临时文件,或者让多个进程非常高效的“共享内存”。这种“进程间快速共享内存”的能力对于很多机器学习框架来说非常有用。

    顺口提一下,可能大伙平时接触最多的进程间通信(IPC)方式是 Socket 和 RPC,这类走网络通信的方式可以实现跨主机的 IPC,应用场景更广。不过上帝给你开了一扇门,就不会多给你开一堆窗,Socket 和 RPC 的通信效率肯定就没有“共享内存”来得快了。(可能你心里在想 http 协议,没错,http 用的更多,但是一般 http 不被归入进程间通信方式。)

    3. Docker 对共享内存的支持

    在 Linux 系统中,/dev/shm 的大小一般为物理内存的一半。Docker 在启动容器的时候,默认给容器设置的 /dev/shm 大小是 64M。(你品,你细品,是不是自定义容器内 shm 大小的需求就产生了?)

    Docker 在 shm 大小的配置上提供了两种支持:

    1. docker run 支持通过 --shm-size=1g 这种方式指定一个容器的 shm 大小;
    2. Docker 配置 daemon.json 中可以通过 "shared-memory-size": "1G" 配置指定容器启动的默认 shm 大小。

    不难猜到,--shm-size 参数的优先级会比 shared-memory-size 配置高。

    4. K8s 里如何设置 /dev/shm 大小

    K8s 里没有原生提供啥直观的 shm 配置方式。但是为了让应用能够尝到“共享内存”的滋味,YAML 工程师还是得给出方案。

    4.1 方案一:修改节点的 Docker 配置

    Sao 操作来了,因为 Docker 支持 shared-memory-size 配置,所以直接修改节点的 daemon.json 配置,那不就让所有 Pod 都能够用起来更大的 share memory 了?

    我就不演示了。反正基本满足需求,但是冥冥之中又让你觉得哪里不太对劲,总之吧,不优雅。

    4.2 方案二:通过 Volume 挂载一个大目录到 Pod 的 /dev/shm

    不就是让 Pod 内的 /dev/shm 大一点嘛,那就挂卷呀:

    apiVersion: v1
    kind: Pod
    metadata:
      name: shared-memory-pod
    spec:
      containers:
        - name: mycontainer
          image: your_image_name
          volumeMounts:
            - name: shared-memory-volume
              mountPath: /dev/shm
      volumes:
        - name: shared-memory-volume
          emptyDir: {}
    

    如果用 PVC 的方式,后端存储系统支持限定卷大小的话,这里就能精准分配 shm 的大小了。总之,业务能跑起来。(你是不是已经忍不住要开喷了?忍忍。我知道,这种方式通过磁盘上的文件来实现“共享内存”,功能走通了,性能不达标。)

    到这一步,我以为“方案一”挺合理的,改改 Docker 的启动参数,似乎影响不大,没啥大坏处,妥。

    不过更进一步,K8s 真的不支持配置 shm?这个需求听起来合理呀,为什么没有被实现呢?继续搜一搜,我在 stackoverflow 上看到了第三种玩法。

    4.3 方案三:用 K8s 的方式共享内存

    且看这段配置:

    apiVersion: v1
    kind: Pod
    metadata:
      name: shared-memory-pod
    spec:
      volumes:
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: "1Gi"
      containers:
        - name: mycontainer
          image: your_image_name
          volumeMounts:
            - name: dshm
              mountPath: /dev/shm
    
    

    行吧,破案了。之前我也不知道 emptyDir 可以配置 medium: Memory

    5. 总结

    散了吧,总结啥。大周五的,早点回家。

  • 相关阅读:
    java计算机毕业设计体育用品购物系统源码+系统+数据库+lw文档
    Java刷题面试系列习题(一)
    回归预测 | MATLAB实现PCA-BP主成分降维结合BP神经网络多输入单输出回归预测
    专利申请流程详解
    使用Adobe illustrator (AI)快速制作图标
    Docker安装Tomcat容器并部署web项目
    【SpringMVC】使用Eclipse创建第一个SpringMVC项目
    2Pai荣湃 π161E61 Pai161E61 5.0kVrms 200Mbps 六通道数字隔离器代替Si8661ED-B-IS
    9种艺术类型Vapeplot颜色包---全平台可用
    引导流程分析——BIOS 与 UEFI
  • 原文地址:https://www.cnblogs.com/daniel-hutao/p/17903993.html