[Docker]#23 도커 리소스 관리 - 기초 사용법 및 관리 방법
도커는 다양한 환경에서 일관된 실행 환경을 제공하는 기술입니다. 그러나 도커 컨테이너가 사용하는 리소스를 적절히 관리하지 않으면 시스템 성능 저하나 리소스 고갈과 같은 문제가 발생할 수 있습니다. 이번 포스팅에서는 도커 컨테이너의 리소스를 제한하고 관리하는 방법을 살펴보겠습니다.
목차
- 도커 리소스 제한의 필요성
- CPU 사용량 제한
- 메모리 사용량 제한
- 블록 I/O (Disk I/O) 제한
- 네트워크 대역폭 제한
- 기타 리소스 관리 기법
- 모니터링 및 최적화
- 결론
1. 도커 리소스 제한의 필요성
도커 컨테이너는 기본적으로 호스트 시스템의 모든 리소스를 사용할 수 있습니다. 즉, 특별히 제한하지 않는 한 컨테이너가 과도한 리소스를 사용하여 다른 컨테이너나 호스트 시스템 자체에 악영향을 줄 수 있습니다. 이러한 문제를 방지하고, 컨테이너 간의 공정한 리소스 분배를 위해 리소스 제한이 필요합니다.
2. CPU 사용량 제한
도커는 컨테이너가 사용할 수 있는 CPU의 양을 제한할 수 있는 다양한 옵션을 제공합니다. 이로써 여러 컨테이너가 동일한 호스트에서 실행될 때 CPU 리소스를 적절히 분배할 수 있습니다.
2.1 --cpus 옵션
--cpus 옵션은 컨테이너가 사용할 수 있는 CPU의 양을 제한합니다. 예를 들어, 컨테이너가 CPU의 50%만 사용하도록 설정하려면 다음과 같이 명령어를 실행합니다:
docker run --cpus="0.5" my_container
이렇게 설정하면 해당 컨테이너는 최대 CPU 시간의 50%만 사용할 수 있습니다.
2.2 --cpu-shares 옵션
--cpu-shares 옵션은 CPU 사용량의 가중치를 설정하는 데 사용됩니다. 이는 절대적인 제한이 아니라 컨테이너 간의 상대적인 우선순위를 지정하는 데 유용합니다. 기본값은 1024이며, 값이 클수록 더 많은 CPU 시간을 얻습니다.
상대적 우선순위라는 개념이 좀 생소하실 수도 있습니다. CPU가 바쁠 때는 낮은 우선순위의 작업이 후순위로 밀려 늦게 처리됩니다. 그런데 CPU가 한가하다면요? 이 때는 낮은 우선순위라도 작업이 수월하게 동작할 것입니다. 이러한 개념으로 이해하시고 --cpu-shares 옵션을 사용하시면 자원 관리가 수월하실 것입니다.
docker run --cpu-shares=512 my_container
이 경우, 컨테이너는 기본값(1024)보다 낮은 우선순위로 CPU 시간을 할당받습니다.
3. 메모리 사용량 제한
메모리 사용량을 제한하는 것은 매우 중요합니다. 컨테이너가 메모리를 과도하게 사용하면 다른 컨테이너와 호스트 시스템의 안정성을 해칠 수 있습니다.
3.1 --memory 옵션
--memory 옵션을 사용하여 컨테이너가 사용할 수 있는 최대 메모리 양을 지정할 수 있습니다. 예를 들어, 컨테이너의 메모리를 512MB로 제한하려면 다음과 같이 설정합니다:
docker run --memory="512m" my_container
이렇게 하면 컨테이너는 최대 512MB의 메모리만 사용할 수 있습니다. 설정한 메모리 한도를 초과하려고 하면 OOM(Out of Memory) 에러가 발생합니다.
3.2 --memory-swap 옵션
--memory-swap 옵션을 사용하면 컨테이너가 사용할 수 있는 스왑 메모리를 지정할 수 있습니다. 이 옵션을 사용하지 않으면 기본적으로 스왑 메모리는 --memory 옵션 값의 두 배로 설정됩니다.
docker run --memory="512m" --memory-swap="1g" my_container
위의 예시는 512MB의 실제 메모리와 512MB의 스왑 메모리(--memory-swap 옵션에서의 할당량 - --memory 옵션에서의 할당량; 여기에서는 1g - 512m), 총 1GB의 메모리를 사용할 수 있도록 설정한 것입니다.
4. 블록 I/O (Disk I/O) 제한
컨테이너가 디스크를 과도하게 사용하면 다른 프로세스의 디스크 접근이 지연될 수 있습니다. 특히, 이미지 처리나 파일 IO를 많이 사용하는 작업 또는 워크스테이션(서버) 등에서는 특히 중요합니다. 이를 방지하기 위해 디스크 I/O 속도를 제한할 수 있습니다.
4.1 --device-read-bps 및 --device-write-bps 옵션
이 옵션들은 각각 디스크 읽기 및 쓰기 속도를 제한합니다. 예를 들어, 특정 디바이스의 읽기 속도를 초당 10MB로 제한하려면 다음과 같이 설정할 수 있습니다:
docker run --device-read-bps /dev/sda:10mb my_container
위의 예제는 /dev/sda 디스크의 읽기 속도를 10mb로 제한합니다. 유사하게 쓰기 속도도 --device-write-bps 옵션을 사용해 제한할 수 있습니다.
4.2 --blkio-weight 옵션
--blkio-weight 옵션은 컨테이너의 블록 I/O 우선순위를 설정합니다. 기본값은 500이며, 100에서 1000 사이의 값을 설정할 수 있습니다. CPU의 가중치를 주는 옵션과 유사하게 동작합니다.
docker run --blkio-weight=300 my_container
이렇게 하면 해당 컨테이너의 블록 I/O 우선순위가 낮아져 디스크 사용 시 다른 컨테이너에 비해 상대적으로 적은 리소스를 사용하게 됩니다.
5. 네트워크 대역폭 제한
컨테이너가 네트워크 대역폭을 과도하게 사용하면 다른 컨테이너나 시스템 전체의 네트워크 성능에 영향을 미칠 수 있습니다. 흔히 데이터가 안 터지는 상황이 연출됩니다. 네트워크 대역폭을 제한하려면 tc(traffic control) 명령어를 사용하거나 --network 옵션을 통해 컨테이너 네트워크를 제한할 수 있습니다.
5.1 tc 명령어를 이용한 네트워크 제한
컨테이너 내부에서 tc 명령어를 사용하여 네트워크 속도를 제한할 수 있습니다. 다음은 예시입니다:
tc qdisc add dev eth0 root tbf rate 1mbit burst 32kbit latency 400ms
위 명령어는 네트워크 인터페이스 eth0의 속도를 1Mbps로 제한합니다.
6. 기타 리소스 관리 기법
6.1 --ulimit 옵션
--ulimit 옵션을 사용하면 컨테이너 내의 프로세스가 사용할 수 있는 파일 핸들, 프로세스 개수 등의 리소스에 대한 제한을 설정할 수 있습니다.
docker run --ulimit nofile=1024:2048 my_container
위 예시는 프로세스가 열 수 있는 파일 핸들의 수를 1024개로, 최댓값을 2048개로 제한합니다.
6.2 cgroup을 이용한 리소스 관리
cgroup은 리눅스 커널 기능으로, 도커는 기본적으로 cgroup을 이용해 리소스를 관리합니다. cgroup을 직접 설정하여 컨테이너 리소스를 보다 세밀하게 제어할 수 있습니다.
7. 모니터링 및 최적화
컨테이너의 리소스 사용량을 모니터링하여 적절히 조정하는 것이 중요합니다. 도커는 기본적으로 docker stats 명령어를 통해 각 컨테이너의 CPU, 메모리, 네트워크, I/O 사용량을 실시간으로 모니터링할 수 있습니다.
docker stats
또한, Prometheus와 Grafana 같은 도구를 활용하면 컨테이너 리소스를 시각화하고, 경고를 설정하며, 최적화를 위한 데이터를 수집할 수 있습니다.
결론
우리가 도커를 사용할 때 다중 애플리케이션이 하나의 호스트에서 사용하게 됩니다. 따라서, 도커 컨테이너 리소스 제한 및 관리 기법은 다중 애플리케이션 운용 환경에서 매우 중요합니다. 위에서 다룬 다양한 옵션을 활용하여 컨테이너를 최적화하고 시스템의 안정성과 성능을 높일 수 있습니다. 리소스 제한을 적절히 적용하면 애플리케이션의 예측 가능성과 신뢰성이 보장됩니다. 또한, 인프라 관리를 통해 비용 절감 효과가 있으며 시스템 안정성이 높아져 서비스 운영이 효율적으로 이루어지게 됩니다.
지금 당장 이러한 리소스 제한들을 모두 익혀 컨테이너를 생성할 때마다 이런 제한들을 할 필요는 없습니다. 하지만 리소스 제한에 대한 내용을 알고 운영환경에서 인프라 비용 등을 모두 생각해야 할 때 이러한 기능들을 활용하는 것은 크게 도움이 되기 때문에 알아두시면 좋겠습니다.
도움이 되셨다면 공감 부탁드리겠습니다. 여러분의 공감이 정말 큰 힘이 됩니다.
감사합니다!