k8s中如何使用shared memory

场景:

需要在训练任务的pod内有两个服务,他们之间通过共享内存方式来交换数据,以获取更高的效率

问题:

注意:/dev/shm即为共享内存的大小

在kvm或者物理机器上,用户可以使用的共享内存为:

root@pve:~# df -h
Filesystem            Size  Used Avail Use% Mounted on
tmpfs                  48G   154M   24G  1% /dev/shm
...
...

但在kubernetes上,Pod里无法使用超过 64MB的shared memory。如下是集群上一个pod的信息,可以看到,/dev/shm的大小是 64MB,通过dd往共享内存写数据时,写到64MB的时候就会报“No space left on device”。

$ kubectl run centos --rm -it --image centos:7 bash
[root@centos-7df8445565-dvpnt /]# df -h|grep shm
Filesystem      Size  Used Avail Use% Mounted on
shm              64M     0   64M   0% /dev/shm
[root@centos-7df8445565-dvpnt /]# dd if=/dev/zero of=/dev/shm/test      bs=1024 count=102400
dd: error writing '/dev/shm/test': No space left on device
65537+0 records in
65536+0 records out
67108864 bytes (67 MB) copied, 0.161447 s, 416 MB/s
[root@centos-7df8445565-dvpnt /]# ls -l -h
total 64M
-rw-r--r-- 1 root root 64M Nov 14 14:33 test
[root@centos-7df8445565-dvpnt /]# df -h|grep shm
Filesystem      Size  Used Avail Use% Mounted on
shm              64M   64M     0 100% /dev/shm

为什么是64M

kubernetes创建的Pod,其共享内存默认64MB,且不可更改。
因为kubernetes本身是没有设置share memory的大小的,64MB其实是docker 默认的共享内存的大小。

docker环境下如何支持更大的shared memory

docker run 的时候,可以通过–shm-size来设置共享内存的大小。

$ docker run  --rm centos:7 df -h |grep shm
shm              64M     0   64M   0% /dev/shm
$ docker run  --rm --shm-size 128M centos:7 df -h |grep shm
shm             128M     0  128M   0% /dev/shm

k8s环境下如何支持更大的shared memory

kubernetes empty dir:

emptyDir volume在一些场景下非常有用,例如在Pod的不同container之间需要共享数据,
可以将同一个emptyDir挂载到两个container中来达到共享的目的。

此时,emtpyDir实际是一个宿主机上的目录,本质上还是磁盘(比如通过sidecar的方式来收集日志)。

kubernetes提供来一种特殊的emptyDir:medium为memory的临时存储。
用户可以将memory介质的emptyDir挂到任何目录,然后将这个目录当作一个高性能的文件系统来使用。

可以将memory介质的empty dir,挂载到 /dev/shm 下,解决共享内存 /dev/shm 不够用的问题

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: xxx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: xxx
  template:
    metadata:
      labels:
        app: xxx
    spec:
      containers:
      - args:
        - infinity
        command:
        - sleep
        image: centos:7
        name: centos
        volumeMounts:
        - mountPath: /dev/shm
          name: cache-volume
      volumes:
      - emptyDir:
          medium: Memory
          sizeLimit: 128Mi
        name: cache-volume

k8s环境下使用更大的shared memory可能发生的问题

使用empty dir的缺点:

1、影响kubernetes调度,因为empty dir并不涉及node的resources,
这样会造成Pod“偷偷”使用了node的内存,但是调度器并不知晓;

2、用户不能及时感知到内存不可用

共享内存受cgroup限制吗

由于普通的内存是受cgroup限制的,那么自然会有一个问题:共享内存受cgroup限制吗?

如果受限制,那么只要给Pod设置memroy limit就可以了,至于用户将内存是用于共享内存,
还是用于普通用途,kubernetes层面并不需要台关心:因为共享内存并不是一个“独立”的内存,
只是包含在memory limit里进行调度,因此也不会影响调度。

需要显示设置sizeLimit

kubelet的eviction manager会监控pod的emptyDir卷使用的空间大小,当使用空间超过该值时,会将该Pod驱逐

可以使用sizeLimit的大小

1、当 Pod 并没有设置memory limit时,此时 shm大小为node的Allocateable Memory大小

2、当Pod 设置了memory limit 但未设置sizeLimit时,shm 大小为Pod 的memory Limit

3、当Pod的medium emptyDir设置sizeLimit时,shm大小为sizeLimit

如何防止pod由于使用共享内存而偷用了node的内存,没被调度器发现

pod的memory request中需要把自己要使用内存的和pod挂载的shm大小一起算进来

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐