[docker] 컨테이너 자원할당 및 부하테스트, 모니터링

2022. 8. 16. 16:34[ 자격증 ]/[ AWS ]

리눅스의 '부하 테스트' 프로그램 - Stress

stress 커맨드를 통해 프로세스의 부하 테스트를 진행할 수 있다.

 

[사용 예시]

stress --cpu 2 : 2개의 코어를 100프로로 사용하도록 하는 부하 테스트를 진행함

stress --vm 2 --vm-bytes <사용할 크기> : 메모리에 일정 크기에 대한 부하를 주고 테스트

 

 

부하 테스트를 컨테이너에서 실행해본다.

 

Dockerfile 작성

FROM debian
RUN apt-get update; apt-get install stress -y
CMD ["/bin/bash", "-c", "stress -c 3"]

cf. -c 옵션은 --cpu와 같음

 

Dockerfile이 위치한 디렉토리로 이동해서 "docker build -t stress ." 커맨드를 수행하여 이미지를 생성한다. (이름은 stress로)

 

 


Container Resource Allocation And Stress Testing

컨테이너에 부하 테스트를 진행하기 위해 우선 컨테이너에 CPU, 메모리, 디스크 등의 리소스를 할당해보자. docker run 커맨드에서 리소스 할당에 관련된 옵션을 지원한다.

 

1. 메모리 자원 할당 및 부하 테스트

docker run -m 100m --memory-swap 100m stress:latest stress --vm 1 --vm-bytes 90m -t 5s

docker run -m 100m --memory-swap 100m stress:latest stress --vm 1 --vm-bytes 350m -t 5s

docker run -m 100m stress:latest stress --vm 1 --vm-bytes 150m -t 5s

1. 첫 번째 커맨드로 컨테이너 실행

- 컨테이너에 할당할 메모리를 100m로 하며 swap도 100m 이므로 swap은 사용하지 않는다. 

- -m 옵션으로 컨테이너에 100m의 메모리를 할당한다.

- --vm-bytes로 90m의 메모리 부하를 일으킨다.

- -t옵션으로 5초 동안 메모리 부하를 일으킨다.

 

2. 두 번째 커맨드로 컨테이너 실행

- 컨테이너에 할당된 메모리는 100m이나 부하를 350m만큼 주었으니 별다른 옵션이 없으면 컨테이너가 죽을 것이다.

- 리눅스는 메모리가 부족하면 특정 프로세스를 잡아 kill 시킨다.

 

3. 세 번째 커맨드로 컨테이너 실행

- swap을 설정하지 않으면 Default로 사용할 수 있는 메모리의 2배 크기만큼 swap으로 설정한다.

- 즉, 최대 200m까지 메모리를 사용할 수 있는 것과 같은 효과이다.

- 부하를 150m를 주었으니 200m를 넘지 않아 작업이 잘 수행될 것이다.

 

 

실행 결과

위에서부터 커맨드 1, 2, 3의 결과이다. 

 

 

cf. swap 허용

만약 "Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap."와 같은 경고 메시지가 뜬다면 /etc/default/grub를 아래와 같이 수정하고 재부팅하자.

# /etc/default/grub
...
GRUB_CMDLINE_LINUX_DEFAULT="cgroup_enable=memory swapaccount=1"
...

# sudo update-grub
# sudo reboot

 

 

 

cf. 메모리 초과로 인한 컨테이너 종료 방지

docker run -d -m 100M --memory-swap 200m --name nginx --oom-kill-disable=true nginx

리눅스는 메모리가 부족하면 특정 프로세스를 잡아 kill 시킨다. 이때 --oom-kill-disable=true 옵션을 사용하면 해당 컨테이너는 kill 되지 않는다. 컨테이너의 상세정보는 "docker inspect nginx"로 확인 가능하다. 명령어 입력 후 "MemorySwap"과 "Memory", "OomKillDisable" 키값을 확인하자.

 

(oom = out-of-memory)

 

 

 


 

 

 

2. CPU 자원 할당 및 부하 테스트

lscpu로 cpu 상태 확인

코어가 12개이고 각 코어는 0번부터 11번까지 번호가 있다.

 

컨테이너 실행 커맨드

docker run --cpuset-cpus 11 --name c1 -d stress:latest stress --cpu 1

docker run --cpuset-cpus 0-2 --name c2 -d stress:latest stress --cpu 1

docker run --cpuset-cpus 0-2 --name c3 -d stress:latest stress --cpu 3 --cpus 3

docker run --cpuset-cpus 3-5 --name c4 -d stress:latest stress --cpu 3 --cpus 1

1. 첫 번째 커맨드

- --cpuset-cpus 11: cpu 코어 11번에서 컨테이너를 실행한다.

- --cpu 1: 사용할 CPU 코어 '개수'를 지정한다.

 

2. 두 번째 커맨드

- --cpuset-cpus 0-2: cpu 코어 0번~2번을 사용하여 컨테이너를 실행한다.

- --cpu 1: 코어는 0~2번을 사용하지만 이 중 1개의 코어만을 사용하겠다는 의미이다. 이는 항상 0~2중 하나만 사용하는게 아니라 시간에 따라 0~2중 하나를 골라서 사용하게 된다.

- --cpus 1: CPU 사용 비율을 명시한다. 

 

3. 세 번째 커맨드

- 0~2번 코어를 사용하면서 총 3개의 코어를 사용하겠다는 의미이다.

 

4. 네 번째 커맨드

- --cpus: cpu 사용 비율을 결정한다. 3개의 코어를 사용하면서 비율을 1로 설정했으므로 각각 코어에 33%씩 할당된다.

 

실행결과 확인(htop)

위 사지은 첫 번째 커맨드(11번 코어에서 실행) 한 결과이다. 11번 코어를 100프로 사용하고 있음을 확인할 수 있다.

 

위 사진은 세 번째 커맨드 결과이다. 코어 0~2번에서 각각 할당되어 실행 중임을 확인할 수 있다.

 

 

cf. --cpu-shares

--cpu-shares는 한 코어에 여러 도커 컨테이너가 작동할 때, 컨테이너 간 CPU를 얼마나 공유할 것인가에 대한 설정이다. 즉, 컨테이너 한 개를 운영 중이라면 의미가 없으며 최소 2개 이상의 컨테이너를 실행시킬 때 의미 있는 값이다. 기본값은 1024이며 2048로 설정하면 다른 컨테이너보다 CPU를 2배 더 공유한다.

docker run -c 2048 --name c1 -d stress:latest

docker run --name c2 -d stress:latest

docker run -c 512 --name c3 -d stress:latest

c 옵션을 사용해서 --cpu-shatres를 설정한다.

docker에서 제공하는 컨테이너 모니터링 명령인 "docker stats"를 통해 실행 중인 컨테이너의 자원 할당 결과를 확인한다. 결과를 확인해보니 세 컨테이너 모두 같은 양의 CPU를 할당받았음을 확인할 수 있다. 아무래도 코어가 12개이다 보니, CPU 자원이 많이 남아서 따로 share를 하지 않은 것 같다. 따라서 아래와 같이 사용할 코어 번호를 명시적으로 설정해주고 다시 확인해본다.

 

docker run -c 2048 --name c1 -d --cpuset-cpus 0-2 stress:latest

docker run --name c2 -d --cpuset-cpus 0-2 stress:latest

docker run -c 512 --name c3 -d --cpuset-cpus 0-2 stress:latest

 

컨테이너가 사용할 코어 번호를 세 컨테이너에 모두 똑같이 준 뒤 결과를 확인해본다.

 

위와 같이 컨테이너 c1, c2, c3가 각각 절반씩 차이나도록 CPU를 할당받았음을 확인할 수 있다.

 

 


 

3. Block I/O(Disk I/O) 자원할당 및 부하 테스트

 

lsblk 명령어로 사용할 디스크를 결정한다. (필자는 SSD(nvme0n1) 선택했음.) 쿼터(Quota)란 사용할 수 있는 디스크 용량을 의미한다.

 

case 1) 쿼터(Quota) 크기 10

docker run -it --rm --device-write-iops /dev/nvme0n1:10 ubuntu:latest /bin/bash

dd if=/dev/zero of=file1 bs=1M count=10 oflag=direct

 

 

컨테이너를 실행함과 동시에 접속해서, dd 명령어로 1M 크기의 블록을 10개 만든 파일을 생성한다. (dd명령 설치 필요)

 

-> 소요시간 약 0.9초 / 1초당 약 11MB 생성

 

 

case 2) 쿼터(Quota) 크기 100

docker run -it --rm --device-write-iops /dev/nvme0n1:100 ubuntu:latest /bin/bash

dd if=/dev/zero of=file1 bs=1M count=10 oflag=direct

쿼터 크기가 100인 컨테이너 생성

 

-> 소요시간 약 0.009초 / 1초당 1GB 생성

 

 

* 결론: 쿼터 크기가 클수록 I/O 작업이 빠르다.

 

 


 

cAdvisor 테스트

cAdvisor는 구글에서 만든, 컨테이너 부하 테스트 도구이다. 

 

cAdvisor 설치

링크에 들어가서 아래와 같이 설치 가이드를 입력한다. 필자는 8888 포트를 사용해 접속할 예정임.

VERSION=v0.36.0 # use the latest release version from https://github.com/google/cadvisor/releases
sudo docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --volume=/dev/disk/:/dev/disk:ro \
  --publish=8888:8080 \
  --detach=true \
  --name=cadvisor \
  --privileged \
  --device=/dev/kmsg \
  gcr.io/cadvisor/cadvisor:$VERSION

설치 후에 브라우저를 통해서 호스트IP:8888을 입력하고 cAdvisor에 접속한다. 접속해서 확인해보면 메모리 사용정보, CPU 정보, 파일 시스템 정보 등을 실시간으로 확인할 수 있다. 특히, 접속 후 Docker Containers를 클릭하면 컨테이너별 리소스 사용량을 자세하게 차드 등의 형식으로 확인할 수 있다.

 

 

 

 


 

정리

1. 컨테이너에서 사용할 컴퓨팅 리소스 할당

- docker run 커맨드의 옵션을 사용 (CPU, memory, disk)

- 참고) docker compose로도 사용 가능

 

2. 부하 테스트

- stress 커맨드 사용

 

3. 컨테이너 모니터링 툴

1) docker에서 제공하는 docker stats 커맨드

2) 구글에서 제공하는 cAdvisor (바로가기)