📋 요약
이 글에서는 Docker 환경에서 실행 중인 컨테이너의 CPU, 메모리, 포트 등 리소스를
재시작 없이 동적으로 조정하는 구현 방법과 cgroup 기반 메커니즘을 다룹니다.
이를 통해 클라우드 사업자는 자원 활용률을 극대화하고, 사용자는 서비스 중단 없이
비용 최적화와 가용성을 확보할 수 있는 실질적 운영 전략을 정리합니다.
#Docker #컨테이너리소스관리 #cgroups #동적할당 #클라우드최적화
![[튜토리얼] kt cloud가 자원을 최적화하는 방법: 컨테이너 리소스 동적할당 구현기](https://blog.kakaocdn.net/dna/ReXeT/dJMcad1OHh3/AAAAAAAAAAAAAAAAAAAAAGnALimb9Pll3G4BcVOcMS9K9RI05zP3UOH-zOlWDNMM/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1769871599&allow_ip=&allow_referer=&signature=QjEIOWV1VqfSIU0vDgVf4zA7dDQ%3D)
클라우드 환경에서 애플리케이션을 실행할 때 가장 흔히 사용하는 방식은 가상머신(VM)입니다. 하지만 VM 기반에서는 GPU와 같은 고가의 자원을 한 번 할당하면 실제 사용 여부와 상관없이 지속적으로 과금되는 구조적 한계가 있습니다. 이로 인해 워크로드가 불규칙한 서비스나 연구 환경에서는 비용 낭비가 발생하기 쉽습니다.
반면 컨테이너는 가볍고 빠른 특성 덕분에 CPU·메모리뿐 아니라 GPU 같은 하드웨어 자원도 필요할 때만 동적으로 할당하거나 해제할 수 있는 유연성을 제공합니다. 특히 최근에는 클라우드 사업자들이 컨테이너를 서버리스(Serverless) 형태로 제공하는 사례가 늘어나면서, 사용자는 인프라 관리 부담 없이 필요한 순간에만 자원을 쓰고 그만큼만 비용을 지불할 수 있게 되었습니다.
핵심은 리소스의 최적화와 유연한 할당입니다. 기존에는 컨테이너를 생성할 때 CPU, 메모리, 네트워크 포트 등의 리소스를 고정적으로 설정하고, 이를 변경하려면 컨테이너를 재시작하거나 재배포해야 했죠. 하지만 실행 중인 컨테이너의 리소스를 동적으로 조정할 수 있다면 다양한 측면에서 큰 이점을 얻을 수 있습니다.
첫째, CSP는 리소스 스케줄링의 효율성을 극대화할 수 있습니다. 사용량이 변동하는 워크로드에 맞추어 CPU나 메모리 자원을 즉각적으로 조정할 수 있도록 함으로써, 서버의 자원을 최적의 상태로 유지하고 자원 낭비를 최소화하여 더 많은 컨테이너를 호스트 서버에 수용할 수 있게 됩니다.
둘째, 사용자는 서비스의 요구 사항 변화에 따라 필요한 만큼의 리소스만 실시간으로 추가하거나 제거함으로써 비용을 절감할 수 있습니다. 예를 들어 특정 시간대나 이벤트로 인해 일시적으로 트래픽이 증가할 경우, 환경 설정을 유지한 채 컨테이너 재기동 없이 즉각적인 리소스 확장이 가능해집니다.
셋째, 서비스의 연속성과 가용성이 향상됩니다. 재시작 없이 리소스를 동적으로 조정할 수 있다면, 컨테이너를 중단하는 데서 오는 서비스 다운타임이나 사용자 불편을 최소화하여 서비스 안정성을 보장할 수 있습니다.
이 글에서는 Docker 환경에서 CPU·메모리와 같은 cgroup 기반 리소스 한도를 라이브 상태에서 조정하는 방법을 단계별로 다룹니다. 또한 일반적으로는 불가능한 포트 동적 추가를 실현하기 위해, Docker 데몬을 정지하고 내부 설정 파일을 직접 수정한 뒤 컨테이너를 재기동하는 방식도 소개합니다. 이 접근법은 컨테이너 ID와 상태를 유지한 채 새로운 포트를 반영할 수 있는 사실상 유일한 방법입니다. CPU/Mem/GPU와 같은 주요 리소스를 실행 중에 동적으로 조정하는 방법을 다루고, 이를 통해 CSP와 사용자 모두가 얻을 수 있는 실질적 효과와 활용 방안을 논의하겠습니다.
Docker 컨테이너의 리소스 관리 방식 이해하기
컨테이너의 리소스를 효율적으로 조정하기 위해서는 Docker가 내부적으로 어떤 커널 메커니즘을 사용하는지 이해하는 것이 중요합니다. Docker는 기본적으로 Linux 커널이 제공하는 두 가지 핵심 기능, 네임스페이스(Namespaces)와 컨트롤 그룹(Control Groups, cgroups)을 통해 컨테이너의 리소스를 관리하고 격리합니다.
![[튜토리얼] kt cloud가 자원을 최적화하는 방법: 컨테이너 리소스 동적할당 구현기](https://blog.kakaocdn.net/dna/Ajs0D/dJMcahwrhGX/AAAAAAAAAAAAAAAAAAAAAPLdP6kE2YQYaWFap-K_piyP2C1OSEdL86Exm00L-iLZ/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1769871599&allow_ip=&allow_referer=&signature=Gs1GPt70tmzRSAefJCA69TMWlBE%3D)
첫째, 네임스페이스는 프로세스 ID(PID), 네트워크(NET), 마운트(MNT), UTS, 사용자(USER) 등 시스템 자원을 독립된 이름 공간으로 분리하는 기능입니다. 이를 통해 각 컨테이너는 독립된 프로세스, 네트워크, 파일 시스템 환경을 가지며, 동일 호스트 내에서 충돌 없이 격리된 실행이 가능합니다.
둘째, cgroups는 CPU, 메모리, 디스크 I/O, 네트워크 대역폭 등 하드웨어 리소스의 사용량을 제한, 우선순위화, 모니터링하는 메커니즘입니다. Docker는 컨테이너 실행 시 사용자가 지정한 제한값을 기반으로 cgroups를 생성하여 해당 컨테이너가 사용할 수 있는 최대 리소스를 정의합니다.
중요한 점은, 컨테이너가 실행 중인 상태에서도 cgroups의 파라미터를 갱신하면 커널 레벨에서 곧바로 적용된다는 것입니다. 예를 들어 docker update --cpus나 --memory 명령을 통해 제한을 늘리거나 줄일 수 있으며, 컨테이너 재시작 없이도 새로운 한도가 반영됩니다. (단, 메모리 한도를 낮출 경우 현재 사용량보다 작게 설정하면 OOM 오류가 발생할 수 있으므로 주의가 필요합니다.)
이러한 구조 덕분에 우리는 서비스 중단 없이 CPU나 메모리 같은 핵심 리소스를 실행 중에 동적으로 조정할 수 있고, 이를 통해 인프라 자원의 효율적 운용과 높은 가용성을 동시에 확보할 수 있습니다.
Docker 컨테이너의 리소스 동적 조정 방법 (CPU, Memory)
실행 중인 Docker 컨테이너의 CPU와 메모리 리소스를 동적으로 조정하는 방법을 단계별로 살펴보겠습니다. Docker는 별도의 컨테이너 재시작 없이 실행 중인 컨테이너에 대한 리소스 변경을 지원합니다.
1. CPU 리소스 동적 조정하기
Docker는 CPU 사용을 상한(cap), 상대 가중치(weight), 코어 고정(pin) 관점에서 조정할 수 있습니다.
- 상한(cap): --cpus
CFS quota 기반으로 컨테이너가 사용할 최대 CPU 시간을 제한합니다.
docker update --cpus 2.0 [컨테이너 ID 또는 이름]
최대 “2코어 상당”의 CPU 시간을 사용합니다(호스트 코어 수와 무관하게 200%까지).
- 상대 가중치(weight): --cpu-shares
CPU 경합 시 상대적 우선순위를 조정할 수 있습니다.
docker update --cpu-shares 512 [컨테이너 ID 또는 이름]
기본값은 1024이며, 절반 수준의 우선순위를 설정하려면 512를 입력하면 됩니다.
- 코어 고정(pin): --cpuset-cpus
특정 코어 집합만 사용하도록 고정할 수 있습니다.
docker update --cpuset-cpus "0-1,4" [컨테이너 ID 또는 이름]
이 모든 변경은 즉시 적용되며 컨테이너 재시작이 필요하지 않습니다. 변경 후 상태는 다음처럼 확인할 수 있습니다.
docker inspect -f '{{.HostConfig.NanoCpus}} {{.HostConfig.CpuShares}} {{.HostConfig.CpusetCpus}}' <컨테이너>
docker stats --no-stream
2. 메모리 리소스 동적 조정하기
메모리 한도는 실시간으로 상향/하향 조정할 수 있으나, 하향 시 현재 사용량보다 낮게 설정하면 OOM이 발생할 수 있습니다.
- 상한(cap): --memory
컨테이너가 사용할 수 있는 최대 메모리 크기를 지정합니다.위 명령어는 컨테이너가 최대 4GB의 메모리를 사용할 수 있도록 제한합니다.
docker update --memory 4g [컨테이너 ID 또는 이름]
- --memory-swap 옵션
메모리와 스왑 메모리를 합친 전체 사용량을 제한합니다.이 경우, 컨테이너는 최대 6GB의 메모리와 스왑 메모리를 사용할 수 있습니다.
docker update --memory-swap 6g [컨테이너 ID 또는 이름]
리소스가 부족하여 컨테이너의 서비스 품질이 저하되거나, 사용하지 않는 자원이 낭비되는 경우 위와 같은 명령어로 즉각적인 조정이 가능합니다. 이를 통해 자원 효율성을 높이고, 사용자는 비용 최적화와 서비스 안정성을 모두 확보할 수 있습니다.
다음 문단에서는 포트 추가와 같은 네트워크 리소스의 동적 관리 방법에 대해 살펴보겠습니다.
Docker 컨테이너의 포트 동적 할당 방법
Docker 컨테이너에서 실행 중인 애플리케이션에 외부에서 접근하려면, 호스트의 포트를 컨테이너 내부 포트에 매핑해야 합니다. 이를 포트 매핑(Port Mapping)이라고 하며, 주로 docker run -p 옵션을 통해 컨테이너 생성 시점에 지정합니다.
하지만 운영 중에는 다음과 같은 상황이 발생할 수 있습니다.
- 이미 실행 중인 컨테이너에 추가적인 포트 노출이 필요함
- 진행 중인 작업이나 상태를 유지하면서, 재시작을 최소화하고 싶음
Docker는 공식적으로 실행 중인 컨테이너의 포트 매핑 변경을 지원하지 않기 때문에, 현실적으로는 아래 세 가지 방법을 고려할 수 있습니다.
1. 컨테이너 재실행
컨테이너를 중지하고 삭제한 뒤, 동일한 이미지로 새롭게 포트를 지정하여 실행합니다:
docker stop my-container
docker rm my-container
docker run -d -p 8080:80 --name my-container my-image
이 방식은 상태가 중요하지 않은 컨테이너에 적합합니다. 하지만 이미 데이터가 저장되었거나 설정 변경이 반영된 컨테이너라면, 이 방법은 실용적이지 않습니다.
2. docker commit 후 포트 포함한 새 컨테이너 실행
현재 실행 중인 컨테이너의 상태를 이미지로 저장하고, 해당 이미지로 새 컨테이너를 실행합니다:
docker stop my-container
docker commit my-container my-new-image
docker rm my-container
docker run -d -p 8080:80 --name my-container my-new-image
이 방식은 컨테이너 내부에서의 변경사항(설치된 패키지, 설정 등)을 유지하면서 포트 매핑을 적용할 수 있어 실용성이 높습니다. 다만, 컨테이너 ID나 생성 시각 등 메타데이터는 변경됩니다.
3. Docker 시스템 설정 파일 직접 수정 (무중단 + ID 유지)
Docker 데몬을 중지하고, 컨테이너 설정 파일을 직접 수정하여 포트를 동적으로 추가할 수 있습니다. 이 방식은 컨테이너 ID와 상태를 그대로 유지하면서 포트를 추가하는 유일한 방법입니다.
주요 단계는 다음과 같습니다:
1. 컨테이너 중지 및 Docker 데몬 정지
docker stop my-container
systemctl stop docker
2. 컨테이너 설정 파일 위치 확인
/var/lib/docker/containers/<컨테이너_ID>/hostconfig.json
/var/lib/docker/containers/<컨테이너_ID>/config.v2.json
3. hostconfig.json의 PortBindings 항목 수정
"PortBindings": {
"80/tcp": [{"HostIp": "", "HostPort": "8080"}]
}
4. config.v2.json의 ExposedPorts 항목 추가
"ExposedPorts": {
"80/tcp": {}
}
5. Docker 데몬과 컨테이너 재시작
systemctl start docker
docker start my-container
정상적으로 반영되었다면 docker ps 명령어로 포트가 노출된 것을 확인할 수 있습니다.
PORTS
0.0.0.0:8080->80/tcp
이 방식은 컨테이너 ID와 상태를 그대로 유지하면서 포트 추가가 가능하지만, Docker 내부 설정 파일을 직접 건드리기 때문에 테스트 환경에서 충분한 검증 후 사용하는 것이 좋습니다. 또한 시스템 간 경로 구조나 파일 포맷이 조금씩 다를 수 있으므로 주의가 필요합니다.
마무리
컨테이너 리소스를 실행 중에 동적으로 조정할 수 있다는 점은 클라우드 운영에 있어 효율성, 비용 최적화, 가용성을 동시에 확보할 수 있는 핵심 요소입니다. 특히 실행 중인 Docker 컨테이너에 대해 CPU, 메모리, 포트 등 리소스를 동적으로 조정할 수 있다는 점은 서비스 중단 없이 성능을 최적화할 수 있다는 의미를 가집니다.
이번 글에서는 Docker의 내부 리소스 관리 구조를 살펴보고, 실제로 실행 중인 컨테이너에 대해 리소스를 실시간으로 변경하는 방법들을 정리했습니다. CPU와 메모리는 docker update 명령어를 통해 비교적 간단하게 조정할 수 있었으며, 포트는 상황에 따라 여러 가지 접근법이 필요했습니다. 특히 포트 추가는 설정 파일 직접 수정을 통해 컨테이너 ID와 상태를 유지한 채로도 가능하다는 점에서, 서비스 운영 중단을 최소화해야 하는 환경에서 의미 있는 대안이 될 수 있습니다.
이러한 리소스 동적 할당 기능은 CSP 입장에서는 자원 활용률과 운영 효율성을 극대화하고, 사용자 입장에서는 탄력적인 자원 사용과 비용 최적화를 가능하게 합니다. 앞으로 GPU, 스토리지 등 다른 리소스 영역으로도 이와 같은 유연성이 확대된다면, 클라우드 네이티브 인프라는 더욱 진화된 형태로 발전할 수 있을 것입니다.
다음 글에서는 CPU/메모리/포트보다 한 단계 더 복잡한 주제인 GPU 자원의 런타임 동적 할당에 대해 다룰 예정입니다. GPU와 같은 고가 자원의 효율적 활용은 AI 워크로드에서 핵심 과제입니다. 다음 글에서는 이를 가능하게 하는 런타임 동적 할당 기술과 구현 방법을 소개하겠습니다.
❓ 자주 묻는 질문 (FAQ)
📚 관련/출처
'Tech Story > DevOps & Container' 카테고리의 다른 글
| [실전가이드] OpenStack Helm 배포를 GitOps로 전환: FluxCD+Argo CD 아키텍처 설계와 운영 전략 (0) | 2026.01.14 |
|---|---|
| [가이드] kt cloud에서 사용하는 Umbrella Helm Chart 설계 전략 (1) | 2025.11.19 |
| [분석] ArgoCD 3.0이 선언한 GitOps 새로운 시대: 주요 업데이트 기능 완벽 해부 (0) | 2025.10.16 |
| [사례연구] kt cloud OpenStack GitOps 배포 전략: Genestack 기반 CI/CD 자동화 구축 과정 (2) | 2025.08.05 |
| [기술가이드] cgroup v2 의 eBPF로 마스터하는 컨테이너 리소스 제어 (1) | 2025.05.27 |