Docker & Kubernetes

도커 컨테이너 자원 할당 제한하기

beekei 2022. 12. 27. 20:25
반응형

컨테이너 자원 할당 제한

컨테이너를 생성하는 run, create 명령어에서 컨테이너의 자원 할당량을 조정하도록 옵션을 입력할 수 있다.

옵션을 설정하지 않으면 자원을 무제한으로 사용하기 때문에 호스트에 무리가 가게 되면 다른 컨테이너까지 영향이 미칠 수 있기 때문에 설정하는 것이 좋다.

 

docker inspect 명령어를 사용해 현재 컨테이너의 설정된 자원 제한을 확인할 수 있다.

$ docker inspect mysql
...
"HostConfig": {
    ...
    "KernelMemory": 0,
    "KernelMemoryTCP": 0,
    "MemoryReservation": 0,
    "MemorySwap": 0,
    "MemorySwappiness": null,
    "OomKillDisable": null,
    "PidsLimit": null,
    "Ulimits": null,
    "CpuCount": 0,
    "CpuPercent": 0,
    "IOMaximumIOps": 0,
    "IOMaximumBandwidth": 0,
    ...
}

컨테이너 메모리 제한

docker run 명령어에 --memory 옵션을 사용해 컨테이너의 메모리를 제한할 수 있다.

입력할 수 있는 단위는 m(메가바이트), g(기가바이트)이며 제한할 수 있는 최소 메모리는 4MB다.

$ docker run -d -it \
--name ubuntu \
--memory=1g \
ubuntu:20.4

$ docker inspect ubuntu | grep "Memory"
            "Memory": 1073741824,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 2147483648,
            "MemorySwappiness": null,

기본적으로 컨테이너의 Swap 메모리는 메모리의 2배로 설정되지만 --memory-swap 명령어를 사용해 별도로 지정할 수 있다.

$ docker run -d -it \
--name ubuntu \
--memory=1g \
--memory-swap=3g \
ubuntu:20.4

$ docker inspect ubuntu | grep "Memory"
            "Memory": 1073741824,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 3221225472,
            "MemorySwappiness": null,

컨테이너 CPU 제한

--cpu-shares

---cpu-shares 옵션은 컨테이너당 CPU를 1개씩 할당하는 것이 아니라 어느 비중만큼 사용할 것이지 설정할 수 있다.

$ docker run -i -t \
--name ubuntu \
--cpu-shares 1024 \
ubuntu:20.04

---cpu-shares 옵션은 상대적인 값으로 설정하므로 아무런 설정을 하지 않았을 때 기본으로 가지는 값은 1024(CPU 1)이다.

--cpuset-cpus

호스트에 CPU가 여러 개 존재한다면 --cpuset-cpus 옵션을 사용하여 특정 CPU만 사용하도록 설정할 수 있다.

$ docker run -i -t \
--name ubuntu \
--cpuset-cpus 1 \
ubuntu:20.04

CPU의 index로 설정하기 때문에 0부터 1번째 CPU를 뜻한다.(위 예제는 2번째 CPU 사용)

복수의 CPU를 사용할 때는 ,(콤마)로 구분이 가능하고 -(하이픈)으로 구간 설정도 가능하다.

예) --cpuset-cpus=0,2(1번째, 3번째 CPU 사용) --cpuset-cpus=0-2(1번째 ~ 3번째 CPU 사용)

 

위에 생성한 컨테이너로 접속해 1개의 CPU만큼 stress를 줬을 때 2번째 CPU를 100% 사용하는 것을 확인할 수 있다.

$ root@da1eab149884:/# stress --cpu 1
$ root@da1eab149884:/# htop

--cpu-period, --cpu-quota

컨테이너의 CFS(Completely Fair Scheduler) 주기는 기본적으로 100ms로 설정되지만 --cpu-period와 --cpu-quata 옵션으로 변경이 가능하다.

$ docker run -i -t \
--name ubuntu \
--cpu-period=100000 \
--cpu-quota=25000 \
ubuntu:20.04

위 예제는 100000(100ms) 중 25000만큼 할당해 CPU 주기가 1/4로 줄어들었으므로 CPU 성능이 1/4로 감소한다.

즉,  --cpu-quota값 / --cpu-period값만큼 CPU 시간을 할당받는다.

--cpus

--cpus 옵션은 --cpu-period, --cpu-quata 옵션과 동일한 기능이지만 더 직관적으로 CPU의 개수를 직접 지정한다.

$ docker run -i -t \
--name ubuntu \
--cpus=0.5 \
ubuntu:20.04

위 예제는 CPU의 약 50% 점유하도록 설정하였다.(--cpu-period=100000 --cpu-quata=50000)

병렬 처리를 위해 CPU를 많이 소모하는 워크로드를 수행해야 한다면 --cpuset-cpus 옵션을 사용하는 것이 좋다.
특정 컨테이너가 특정 CPU에서만 동작하는 CPU 친화성(affinity)을 보장할 수 있고, CPU 캐시 미스 또는 컨텍스트 스위칭과 같이 성능을 하락시키는 요인을 최소화할 가능성이 높아지기 때문이다.

Block I/O 제한

컨테이너에 입출력 제한을 설정하지 않으면 내부에서 파일을 읽고 쓰는 대역폭에 제한이 설정되지 않기 때문에 옵션을 통해 블록 입출력 제한해야 한다.

단, Direct I/O의 경우에만 블록 입출력이 제한되며, Buffered I/O는 제한되지 않는다.

--device-write-bps, --device-read-bps

--device-write-bps, --device-read-bps는 각각 쓰고 읽는 작업의 초당 제한을 kb(킬로바이트), mb(메가바이트), gb(기가바이트) 단위로 제한할 수 있다.

$ docker run -i -t \
--name ubuntu \
--device-write-bps /dev/xvda:1mb \
--device-read-bps /dev/xvda:1mb \
ubuntu:20.04

위 예제는 초당 쓰기 1mb, 읽기 1mb로 설정하였다.

여기서 옵션은 <디바이스>:<제한값> 형태로 설정해야 하는데, AWS EC2에서는 /dev/xvda라는 디바이스를 사용한다.

--device-write-iops, --device-read-iops

--device-write-bps, --device-read-bps는 각각 쓰고 읽는 작업의 초당 제한을 상대적으로 제한할 수 있다.

$ docker run -i -t \
--name ubuntu \
--device-write-iops /dev/xvda:2 \
--device-read-iops /dev/xvda:2 \
ubuntu:20.04

위 예제는 입출력 제한 크기를 2배로 설정하였다.

반응형