도커 컨테이너에서는 여러가지 자원을 할당할 수 있는데, 할당하지 않으면 해당 컨테이너는 마음대로 호스트의 자원을 사용한다. (CPU, MEMORY, swap 등) 따라서 어플리케이션에 따라 사용하는 자원의 양을 제한하는 것은 매우 중요하다. 이러한 자원 제한은 cgroup의 기능을 도커 명령어로 손쉽게 사용할 수 있다.
docker container run 명령을 실행할 때, 아래 옵션들 (외에 추가로 많음) 을 사용해서 컨테이너의 자원을 어떻게 쓸지 정의할 수 있다. 이러한 제한이 없으면, 컨테이너는 Host OS의 자원을 제한없이 사용한다. 옵션 설정을 통해 다른 컨테이너의 동작 간섭을 방해하지 않게 할 수 있다. 생성 후 변경 시에는 docker update 명령으로 변경을 할 수 있다. 이러한 리소스 제한 기능은 리눅스의 cgroups 기능을 활용하는 것이다.
이러한 성능 제한 작업을 수행하면서 htop 등으로 모니터링 하여 변화를 테스트 할 수 있다. htop 사용을 위해서는 다음 링크를 참고한다.
2020/06/10 - [Performance] - Linux 시스템 모니터링 Tool - htop
Linux 시스템 모니터링 Tool - htop
htop은 기존의 top보다 더 향상된 시스템 모니터링 툴로서, 프로세스 뷰어 및 프로세스 관리자이다. top 과 두드러지게 다른점은 htop은 색을 사용하여 좀 더 효과적인 시각화를 꾀했고, 또한 CPU 각��
watch-n-learn.tistory.com
* 메모리 제한
메모리 관련 옵션
--memory, -m, --memory-swap 등
1. nginx의 메모리 사이즈를 1G로 제한하기
docker run -d --memory=1g --name=nginx_mem_1g nginx
# 참고 : swap 관련 메시지 발생하는 경우
WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
grub을 수정해야 함. 호스트에서, vi /etc/default/grub 에 GRUB_CMDLINE_LINUX_DEFAULT="cgroup_enable=memory swapaccount=1" 을 추가해야 함. 이후 grub rebuild 수행 후 리스타트
2. 메모리 확인
- Memory 부분이 1073741824 값이 나온다. 이것은 Byte 단위이다.
- 참고로, 이렇게 제한하지 않고 그냥 컨테이너를 생성하는 경우 다음과 같이 Memory 부분이 0으로 나온다.
# 참고 : 컨테이너 내부에서 시스템 정보를 확인할 때
- 컨테이너에서 /proc/meminfo에서는 해당 컨테이너가 아닌 해당 호스트의 정보가 나온다.
- 커널 버전이라던지, cpu 개수라던지 등도 마찬가지이다.
* swap 메모리 제한
1. ubuntu OS의 swap 메모리 사용을 300MB 로 제한하기
docker run --memory=200m --memory-swap=300m -it ubuntu /bin/bash
2. swap 메모리 확인
# 참고 : 만약, 사용하는 컨테이너에 실제 사이즈와 맞지않게 메모리를 제한하면 FAIL 발생한다.
docker run -it --memory=4m --name=mysql mysql:5.7
ERROR : mysqld faile whild attempting to check config
* CPU 제한
CPU를 제한하는 데는 여러가지 옵션이 있다. 그 중 대표적인 옵션만 설명한다.
# 참고
CPU 부하를 주기 위해 alicek106이 만든 stress라는 컨테이너를 사용한다. 또한 맨 뒤에 --cpu 1은 사용할 cpu의 개수를 의미한다.
1. 특정 코어로 CPU 제한 (--cpuset-cpus)
호스트에 CPU가 여러개 있을 때 --cpuset-cpus를 지정해 컨테이너가 특정 CPU만 쓰도록 할 수 있다. CPU 집중적인 작업이 필요하다면 여러개 CPU를 사용하여 작업을 잘 분배하도록 해야 한다. 아래 예시에서 확인할 수 있다.
* 특정 CPU 코어 1개 사용하도록 허용
docker run -d --cpuset-cpus=3 alicek106/stress stress --cpu 1
* 특정 CPU 코어 2개 사용하도록 허용
docker run -d --cpuset-cpus=0,3 alicek106/stress stress --cpu 2
* 특정 CPU 코어 3개 사용하도록 허용
docker run -d --cpuset-cpus=0-2 alicek106/stress stress --cpu 3
2. CPU 사용 비율 제한하기 (--cpus)
--cpus는 각 컨테이너에게 CPU를 최대 몇 % 할당할 수 있는지를 명시한다. CPU가 1개 기준으로, 값은 0~1이다. 1은 비율을 의미하며 100%를 의미한다. 즉 0.5 로 하면 50%까지 최대 사용할 수 있다는 뜻. 근데 만약 CPU를 3개로 했다면 값은 0~3이 되며 최대값 3이 100%를 의미하게 된다. 정리하면, 컨테이너가 사용하도록 허용한 CPU의 개수에 따라 사용량 최대값이 변한다는 것.
* CPU 3개를 100% 사용
docker run -d --cpuset-cpus=0-2 --cpus=3 alicek106/stress stress --cpu 3
* CPU 3개를 각각 약 33%씩 사용
docker run -d --cpuset-cpus=0-2 --cpus=1 alicek106/stress stress --cpu 3
* CPU 1개를 50% 사용
docker run -d --cpuset-cpus=1 --cpus=0.5 alicek106/stress stress --cpu 1
3. 상대적 가중치 제한 (--cpu-shares)
--cpu-shares는 한 코어에 여러 도커 컨테이너가 작동할 때, 컨테이너간 상대적 가중치이다. 실제 프로세서 클럭 속도와는 관련이 없다. 모든 컨테이너는 기본적으로 1024 값을 가지고 있고, 혼자 한 코어를 사용할 때는 아무 의미가 없다. 한 코어에 두 컨테이너가 시작하는 경우, cpu-share 값을 설정하지 않으면 기본값인 1024를 가지기 때문에 CPU 시간이 둘 다 균등하게 분할된다. (해당 코어를 쓰는 다른 프로세스가 없다고 가정)
만약 두 컨테이너 중 한 컨테이너에 cpu-share 512 값을 설정한다면, 다른 1024의 컨테이너에 비해 CPU 시간이 절반이 사용된다. 그러나 이것이 CPU의 절반만 사용한다는 의미는 아님. 다른 컨테이너가 유휴 상태인 경우, 512로 설정한 컨테이너도 CPU의 100%를 쓸 수 있다. 또한 이러한 가중치 제한은 필요할 때만 수행된다. 사전에 CPU를 제한하는게 아니고, 많은 프로세스가 동시에 CPU를 많이 사용하는 경우 같이 이런 경우에 수행된다. 아래는 여러가지 예시이다.
* 같은 코어를 쓰는 두 컨테이너에 둘 다 1024 값 사용
docker run -d --cpuset-cpus=3 --cpu-shares 1024 alicek106/stress stress --cpu 1
docker run -d --cpuset-cpus=3 --cpu-shares 1024 alicek106/stress stress --cpu 1
둘 다 비슷하게 50%를 사용한다.
* 같은 코어를 쓰는 두 컨테이너에 하나는 1024, 하나는 512 값 사용
docker run -d --cpuset-cpus=3 --cpu-shares 1024 alicek106/stress stress --cpu 1
docker run -d --cpuset-cpus=3 --cpu-shares 512 alicek106/stress stress --cpu 1
한쪽은 70%, 다른 한쪽은 30%정도 사용한다.
* 같은 코어를 쓰는 두 컨테이너에 하나는 1024, 하나는 256 값 사용
docker run -d --cpuset-cpus=3 --cpu-shares 1024 alicek106/stress stress --cpu 1
docker run -d --cpuset-cpus=3 --cpu-shares 256 alicek106/stress stress --cpu 1
한쪽은 80%, 다른 한쪽은 20%정도 사용한다.
* 한 컨테이너만 512값으로 줄 때
docker run -d --cpuset-cpus=3 --cpu-shares 512 alicek106/stress stress --cpu 1
해당 코어를 쓰는 컨테이너가 하나뿐이므로 100% 모두 사용한다.
* 디스크 I/O 제한
도커 컨테이너는 block I/O 관련하여 옵션을 지정하지 않으면 무제한으로 I/O를 사용한다. 이러한 무분별한 I/O 사용을 막기 위해 여러가지 옵션이 있다. - --device-write-bps, --device-read-bps, --device-write-iops, --device-read-iops 등이 있다. 단 direct I/O만 제한하며, bufered I/O는 제한하지 않는다.
또한 이렇게 값을 설정한다 하더라도, 실제 물리 디스크의 성능에 따라 달라질 수 있다. 따라서 제한 없는 상태에서의 디스크 성능을 미리 알고 있어야 하며, 그 상태를 기준으로 제한을 건 후 값이 어떻게 나오는지 테스트 및 검증을 수행해야 한다. 디스크의 block I/O 성능은 초당 얼마 사이즈를 I/O 할 수 있느냐를 알 수 있으면 된다.
여기서는 4가지 옵션 중 --device-write-bps 옵션을 사용하여 초당 쓰기속도를 설정해본다. dd 명령을 사용하여 10메가 파일을 생성할 때 걸리는 시간을 측정한다.
* 초당 1MB로 속도 제한
docker run -it --device-write-bps /dev/sda:1mb ubuntu:14.04 bash
실제로 약 10초가 걸렸다.
* 초당 10MB로 속도 제한
docker run -it --device-write-bps /dev/sda:10mb ubuntu:14.04 bash
실제로 약 0.9초가 걸렸다.
* 운영중에 자원 변경하기
컨테이너를 내렸다 올리지 않고, 값을 업데이트하여 사용량 제한 값을 변경할 수 있다. 다음 예시를 참고할 것.
docker update --cpu-shares 512 컨테이너명
docker update --cpus=0.2 컨테이너명
'Docker Basic' 카테고리의 다른 글
[Docker Basic] 16. Dockerfile을 이용하여 이미지 빌드하기 (0) | 2020.06.13 |
---|---|
[Docker Basic] 16. Docker 데이터 저장 개념 / 기본 명령어 - volume (0) | 2020.06.11 |
[Docker Basic] 14. Docker 중요 명령어 - docker container run (1) | 2020.05.15 |
[Docker Basic] 13. Docker 기본 명령어 - 네트워크 명령 및 예시 (0) | 2020.04.13 |
[Docker Basic] 12. Docker Network 개요 (0) | 2020.04.11 |