본문 바로가기
Docker

[Docker] 07. 컨테이너 리소스 할당 제한

by 별준 2021. 7. 14.

Contents

  • 컨테이너 메모리 제한
  • 컨테이너 CPU 제한
  • Block I/O 제한

컨테이너를 생성하는 run, create 커맨드에서 컨테이너의 리소스 할당량을 조정하도록 옵션을 설정할 수 있습니다.

아무런 옵션을 입력하지 않는다면, 컨테이너는 호스트의 리소스를 제한없이 사용할 수 있습니다. 제품 단계의 컨테이너를 고려한다면 컨테이너의 리소스 할당을 제한해 호스트와 다른 컨테이너의 동작을 방해하지 않도록 하는 것이 좋습니다. 그렇지 않다면 호스트의 리소스를 전부 점유해 다른 컨테이너들뿐 아니라 호스트 자체의 동작이 멈출 수 있습니다.

 

현재 컨테이너에 설정된 리소스 제한을 확인하는 가장 쉬운 방법은 docker inspect 명령어를 입력하는 것입니다.

("HostConfig" 에서 찾아볼 수 있습니다.)

만약 이미 생성된 컨테이너의 리소스 제한 설정을 변경하려면 update 명령어를 사용하면 됩니다.

ex) docker update --cpuset-cpus=1 <container>

 

1. 컨테이너 메모리 제한

컨테이너의 메모리는 docker run 커맨드에 --memory 옵션을 지정하여 제한할 수 있습니다.

입력할 수 있는 단위는 m(megabyte), g(gigabyte)이며, 제한할 수 있는 최소 메모리는 4MB 입니다.

docker run -d \
	--memory="1g" \
    --name memory_1g \
    nginx

위의 커맨드로 생성한 뒤 inspect 커맨드로 메모리의 값을 확인하면 1GB의 값이 설정되었음을 알 수 있습니다.

 

컨테이너 내에서 동작하는 프로세스가 컨테이너에 할당된 메모리를 초과하면 컨테이너는 자동으로 종료되기 때문에 어플리케이션에 따라 메모리를 적절하게 할당하는 것이 좋습니다.

4MB의 메모리로 mysql 컨테이너를 실행하면 메모리가 부족하여 컨테이너가 실행되지 않고 종료되는 것을 확인할 수 있습니다.

docker run -d --name memory_4m \
    --memory=4m \
    mysql:5.7
 
docker ps -a --format "table {{.ID}}\t{{.Status}}\t{{.Names}}"

 

기본적으로 컨테이너의 Swap 메모리는 메모리의 2배로 설정되지만 별도로 설정할 수도 있습니다.

다음 명령어는 Swap 메모리를 500MB로, 메모리를 200MB로 설정하여 컨테이너를 생성합니다.

docker run -it --name swap_500m \
    --memory=200m \
    --memory-swap=500m \
    ubuntu:20.04

 

2. 컨테이너 CPU 제한

2.1. --cpu-shares

--cpu-shares(-c) 옵션은 컨테이너에 가중치를 설정하여 해당 컨테이너가 CPU를 상대적으로 얼마나 사용할 수 있는지 나타냅니다. 즉, 컨테이너에 CPU를 한 개씩 할당하는 방법이 아니라, 시스템에 존재하는 CPU를 어느 비중만큼 나누어 사용할 것인지 명시하는 옵션입니다.

docker run -it --name cpu_1024 \
	--cpu-shares 1024 \
    changjunlee/ubuntu:stress

--cpu-shares 옵션은 상대적인 값을 가집니다. 아무런 설정을 하지 않았을 때 컨테이너가 가지는 값은 1024로, 이것은 CPU 할당에서 1의 비중을 뜻합니다. 아래의 방법으로 실제로 --cpu-shares 옵션이 어떻게 동작하는지 확인할 수 있습니다.

(stress 커맨드를 사용할 텐데, 해당 커맨드를 설치한 이미지 changjunlee/ubuntu:stress를 사용하거나, 혹은 직접 apt update && apt install stress 커맨드로 설치하면 됩니다.)

  1. 위 명령어와 동일하게 --cpu-shares 옵션에 1024의 값을 할당하는 컨테이너생성
  2. 1개의 프로세스로 CPU에 부하를 주는 명령어 실행(stress 커맨드)
    stress --cpu 1​
  3. 컨테이너를Ctrl + P,Q로 빠져나와 컨테이너의 CPU 사용률 확인
    ps aux | grep stress​

--cpu-shares의 값이 1024로 설정되었지만, 호스트에서 다른 컨테이너가 존재하지 않기 때문에 CPU를 100% 사용하고 있음을 알 수 있습니다.

 

이 상태에서 --cpu-shares 값이 512로 설정된 다른 컨테이너가 같이 실행된다면, 어떻게 될까요?

docker run -it --name cpu_512 \
    --cpu-shares 512 \
    changjunlee/ubuntu:stress

CPU의 사용량이 2:1로 나누어질 것이라고 예상했는데, 책에서 설명하는 결과와 조금 다르게 나왔습니다.

둘다 거의 100%를 차지하고 있는 결과를 얻을 수 있는데, 이는 CPU가 멀티코어기 때문에 각각 다른 코어를 점유하고 있어서 그런 것으로 추측됩니다.

 

다음에 설명할 --cpuset-cpus으로 동일한 CPU를 사용하도록 설정해주면 대략 2:1의 비율로 CPU를 점유하는 것을 확인할 수 있습니다. (2:1이라고 하기에는 약간 차이는 있습니다...)

 

2.2. --cpuset-cpus

호스트에 CPU가 여러 개 있을 때, --cpuset-cpus 옵션을 지정해 컨테이너가 특정 CPU만 사용하도록 설정할 수 있습니다. CPU 집중적인 작업이 필요하다면, 여러 개의 CPU를 사용하도록 설정해 작업을 적절하게 분배하는 것이 좋습니다.

아래 예시는 컨테이너가 3번째 CPU만 사용하도록 설정합니다.

  1. 컨테이너 생성
    docker run -it --name cpuset_2 \
    	--cpuset-cpus=2 \
        changjunlee/ubuntu:stress​
  2. 컨테이너에서 stress 커맨드 실행
    stress --cpu 1​
  3. 컨테이너를 빠져나와 호스트에서 htop 명령어를 사용하여 CPU 사용량 확인
    3번째 CPU의 사용량이 100%인 것을 확인할 수 있습니다.
--cpuset-cpus="0, 3"은 1,4번째 CPU를 사용하고, --cpuset-cpus="0-2"는 1,2,3번째 CPU를 사용한다는 의미입니다.

 

2.3. --cpu-period,--cpu-quota

컨테이너의 CFS(Completely Fair Schedular) 주기는 기본적으로 100ms로 설정되지만 run 명령어 옵션 중 --cpu-period와 --cpu-quota는 이 주기를 변경할 수 있습니다.

CFS는 리눅스 프로세스 스케쥴러이며, CPU의 리소스 할당을 관리합니다.
docker run -it --name quota_1_4 \
	--cpu-period=100000 \
    --cpu-quota=25000 \
    ubuntu:20.04

--cpu-period의 값은 기본적으로 100000이며, 이는 100ms를 의미합니다.

--cpu-quota는 --cpu-period에 설정된 시간 중 CPU 스케쥴링에 얼마나 할당할 것인지를 설정합니다. 위 컨테이너에서 100000 중 25000만큼을 할당해 CPU 주기가 1/4로 감소하게 되고, 이는 일반적인 컨테이너보다 CPU 성능이 1/4정도로 감소하게 됩니다.

즉, 컨테이너는 [-cpu-quota 값] / [--cpu-period 값]만큼 CPU 시간을 할당받습니다.

 

2.4. --cpus

--cpus 옵션은 --cpu-period, --cpu-quota와 동일한 기능을 갖지만, 조금 더 직관적으로 CPU의 개수를 직접 지정한다는 점에서 차이가 있습니다.

예를 들어, --cpus 옵션에 0.5를 설정하게 되면, --cpu-period=100000과 --cpu-quota=50000과 동일하게 컨테이너의 CPU를 제한할 수 있습니다.

docker run -d --name cpus_container \
	--cpus=0.5 \
    changjunlee/ubuntu:stress \
    stress --cpu 1

컨테이너의 사용량을 확인해보면 CPU의 약 50%를 점유하고 있음을 알 수 있습니다.

 

'Docker' 카테고리의 다른 글

[Docker] 09. Private Registry  (0) 2021.07.15
[Docker] 08. 도커 이미지  (0) 2021.07.14
[Docker] 06. 컨테이너 로깅(logging)  (0) 2021.07.13
[Docker] 05. 도커 네트워크  (0) 2021.07.13
[Docker] 04. 도커 볼륨  (0) 2021.07.12

댓글