글 작성자: 모두의 근삼이

리눅스 IPC는 System V와 POSIX 두가지 표준을 가지고 있는데, System V 모델을 따르는 Shared Memory는 IPC Namespace Isolatior가 제공하는 기능만으로 별도의 작업 없이 사용하는데 큰 문제가 없지만, POSIX 모델의 Shared Memory는 파일 기반으로 관리되는 구조이다.

https://www.technovelty.org/linux/shared-memory-on-linux.html

문제는 쿠버네티스에서 POD가 생성되면 기본적으로 64MB사이즈의 shm 공유메모리 공간이 할당되는데, 이 공간만으로는 제약이 걸리는 상황이 많이 발생한다는 점이다.

이러한 현상과 관련하여 몇가지 상황을 이전에도 경험했었고, 본 글을 작성하는 시점에서는 컨테이너 내에서 tensorflow데이터 로드시 멀티프로세싱 방식으로 데이터를 로드할때 공유메모리 부족에러가 발생했던 점을 미루어 보아, 프로세스간 통신에 POSIX방식의 메모리 공유방식을 활용하는 프로그램들이 64MB보다 많은 데이터를 공유메모리를 통해 융통하려고 하면, 반드시 이러한 에러를 마주하게 되는듯 하다.

Docker만을 이용한 서비스 운영시

도커는 자체적으로 shm 사이즈 조정을 위한 별도의 옵션을 제공하고 있다.

docker run -it --shm-size=256m oracle11g /bin/bash

Kubernetes 환경에서

아쉽게도 쿠버네티스에는 shm사이즈만을 위한 별도의 옵션이 제공되지 않고 있다. 쿠버가 docker도 런타임으로 활용할 수 있는 플렛폼이기에 관련된 옵션을 제공하지 않을까 기대해 보았는데, 아니었다. cri 표준에 관련 인터페이스가 없는 탓일까?(모르겠다. 혹시 관련 내용을 아는 사람이 있다면 공유해주면 감사할듯 하다.)

다행히도, 쿠버네티스의 memory타입 emptyDir 마운트 방식으로 문제를 해결할 수 있었다.

apiVersion: v1
kind: Pod
metadata:
  name: busybox
spec:
  containers:
  - name: busybox
    image: gcr.io/google_containers/busybox:1.24
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        memory: 1Gi
        cpu: 1
    command: ['sh', '-c', 'echo Hello Kubernetes!>/test-pd/mfltest.txt && sleep 3600' ]
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: /dev/shm
      name: shmdir
  volumes:
  - name: shmdir
    emptyDir:
      medium: Memory
      sizeLimit: "256M"

shm 공간에 대해서도 사용량을 제한할 수 있는데, sizeLimit 옵션을 사용하면 된다.

해당 옵션을 사용하더라도 컨테이너 내부에서 df 로 확인할 수 있는 용량은 hostOS의 램 전체크기인데, 실제 사용가능한 용량은 지정한 옵션만큼의 크기이니 걱정하지 않아도 된다.

Filesystem                 Size  Used Avail Use% Mounted on                                                                                                    
/dev/mapper/centos00-root  225G  102G  123G  46% /                                                                                                             
devtmpfs                   128G     0  128G   0% /dev                                                                                                          
tmpfs                      128G     0  128G   0% /dev/shm                                                                                                      
tmpfs                      128G  716M  127G   1% /run                                                                                                          
tmpfs                      128G     0  128G   0% /sys/fs/cgroup                                                                                                
/dev/sda1                 1014M  248M  767M  25% /boot                                                                                                         
overlay                    225G  102G  123G  46% /var/lib/docker/overlay/f7a6c56ae585c0632b9b9cc26fbadbd730359ab6fedea6d30ce0555c3b120f29/merged               
overlay                    225G  102G  123G  46% /var/lib/docker/overlay/89eaa94f9d664dca12c52cb79994059182a4c866aa4c6ad4595dbad3f4ab66eb/merged

테스트를 원한다면 shm공간에 임의의 데이터를 쌓아볼 수 있다. 결과는 메모리 리소스 초과로 인한 컨테이너 재시작일 것이다.(아래 커멘드는 300M의 덤프데이터를 밀어넣는 테스트)

dd if=/dev/zero of=/dev/shm/zero bs=10M count=30

하지만, shm공간 선언부에서 sizeLimit 옵션을 별도로 주지 않아도 POD에 메모리 limit을 걸어주었다면 자동으로 POD의 메모리 사용 제한량까지만 제한이 걸리기 때문에, 특별한 경우가 아니라면 굳이 shm 선언부에 용량제한을 걸어줄 필요가 없다.

반응형