CentOS 기반 시스템 리소스 관리를 위한 CGroup 과 cgred 적용 방법

CGroup 기술 개요 및 핵심 기능

리눅스 커널이 제공하는 리소스 제어 메커니즘 중 하나인 CGroup(Control Group)은 실행 중인 프로세스 집단에 대해 하드웨어 자원의 할당량을 정의하고 모니터링할 수 있게 해줍니다. Google 엔지니어 팀에 의해 제안되어 초기에는 '프로세스 컨테이너'로 불리다가, 혼란을 줄이기 위해 현재와 같은 명칭으로 변경되어 내장되었습니다.

이 기술을 활용하면 CPU 사이클, 물리적 메모리 크기, 네트워크 대역폭 등 다양한 리소스의 상한선을 설정하거나 우선순위를 조정할 수 있습니다. 또한 활성 상태의 시스템에서도 동적으로 그룹 구성을 변경하여 자원 접근을 제한하거나 특정 프로세스를 일시 정지 (Freezer) 시킬 수 있습니다.

주요 하위 시스템 (Subsystems)

  • CPU: 프로세서 사용 시간 배분 제어
  • CPUacct: CPU 소비 통계 수집
  • Memory: RAM 및 스왑 영역 사용량 제한
  • Blkio: 블록 디바이스의 입출력 속도 조절
  • Freezer: 작업 일시 정지 및 복원
  • Net_cls: 네트워크 패킷 분류 및 QoS 연동

cgrules 데몬의 역할

CGroup 설정을 직접 매번 수행하기 번거롭다면 /etc/cgrules.conf 파일을 통해 자동화할 수 있습니다. 이를 감시하며 규칙에 따라 프로세스를 해당 CGroup 으로 이동시키는 역할을 하는 것이 cgred(또는 cgrulesd) 데몬입니다.

설정 파일의 기본 형식은 다음과 같습니다.

<사용자>          <서브시스템>      <컨트롤그룹 경로>
<사용자>:<명령>   <서브시스템>      <컨트롤그룹 경로>

예를 들어, 특정 사용자가 특정 명령을 실행할 때만 IO 한도를 적용하려면 사용자명 뒤에 명령어를 추가하여 지정을 합니다.

operator:backup   blkio   /limit/slow_disk
@finance_team     memory  /limit/restricted_ram

상단 예시에서는 'operator' 사용자가 backup 유틸리티를 사용할 때만 느린 IO 정책을 적용하며, @기호를 사용하면 그룹에 속한 모든 회원에게 규칙이 적용됩니다. 별표 (*) 는 모든 항목을 의미하는 와일드카드입니다.

CPU 처리량 제어 실습

1. 활성화된 서브시스템 확인

먼저 시스템에 마운트 되어 있는 CGroup 계층 구조를 파악합니다.

# lssubsys -m
cpu         /cgroup/cpu
cpuacct     /cgroup/cpuacct
memory      /cgroup/memory
blkio       /cgroup/blkio

2. 구성 파일 수정

/etc/cgconfig.conf 에 두 가지 정책 그룹을 정의합니다. 하나는 CPU 사용 비중을 낮게 설정하고, 다른 하나는 상대적으로 높게 설정하는 방식입니다.

group cpu_low_share{
    cpu{
        # 표준값 1024 대비 낮은 값 설정
        cpu.shares = 200; 
    }
}

group cpu_high_share{
    cpu{
        cpu.shares = 1000;
    }
}

3. 서비스 재가동 및 검증

변경 사항을 반영하기 위해 cgconfig 서비스를 재시작합니다.

# service cgconfig restart
# ls /cgroup/cpu/
cpu_high_share  cpu_low_share  ... 

해당 디렉토리 내부를 확인하면 새로 생성된 그룹 폴더를 확인할 수 있으며, 각 그룹별로 cpu.shares 파일 값을 조회하면 설정된 수치가 반영되었는지 알 수 있습니다.

4. 테스트 환경 구축

정확한 비교를 위해 CPU 코어 중 하나를 오프라인 상태로 만든 뒤 부하 테스트를 진행합니다.

# echo 0 > /sys/devices/system/cpu/cpu1/online
# lscpu | grep "On-line"

각 그룹에 속하게 하여 데이터 생성 명령 (dd) 을 동시에 실행합니다. CPU Shares 가 높은 그룹이 상대적으로 더 많은 시간을 할당받아 작업 완료 시간이 짧아지는 것을 time 명령어나 top 유틸리티로 관찰할 수 있습니다.

# Terminal A: 저우선순위 실행
# cgexec -g cpu:cpu_low_share time dd if=/dev/zero of=/dev/null bs=1M count=50000

# Terminal B: 고우선순위 실행
# cgexec -g cpu:cpu_high_share time dd if=/dev/zero of=/dev/null bs=1M count=50000

결과적으로 shares 값이 큰 프로세스가 CPU 스케줄링에서 유리함을 얻어 단위 시간당 처리량이 증가함을 확인할 수 있습니다.

메모리 사용량 제한 설정

1. 메모리 한도 정의

프로세스가 사용할 수 있는 최대 물리 메모리 크기를 바이트 단위로 지정합니다. 이는 스왑 공간 사용 여부와 상관없이 하드 리미트를 설정하는 것입니다.

group restricted_memory{
    memory{
        # 256MB 제한 (268,435,456 bytes)
        memory.limit_in_bytes = 268435456;
        # 스왑 포함 총 제한 (물리 + 스왑 합계)
        memory.memsw.limit_in_bytes = 536870912; 
    }
}

2. 가상 파일 시스템을 이용한 테스트

실제 메모리 부족 상황을จำลอง하기 위해 tmpfs 타입의 가상 파티션을挂载 합니다.

# mkdir /mnt/memtest
# mount -t tmpfs -o size=1G none /mnt/memtest
# df -h /mnt/memtest

제한된 그룹 내에서 이 마운트 포인트에 대용량 파일을 작성하려는 시도를 하면, 설정한 한도를 초과했을 때 시스템이 작업을 강제로 종료 (OOM Killer) 하거나 작성을 차단합니다.

# cgexec -g memory:restricted_memory dd if=/dev/zero of=/mnt/memtest/file_a bs=1M count=300
# [Expected: 작업 실패 또는 KILL]

반면 제한치 이내인 200MB 크기의 파일 생성은 정상적으로 이루어집니다.

블록 디바이스 입출력 (IO) 제어

디스크 액세스 속도를 제한하려면 커널의 IO 스케줄러가 cfq 알고리즘을 사용하고 있는지 먼저 확인해야 합니다.

# cat /sys/block/sda/queue/scheduler
[cfq] deadline noop anticipatory

기본적으로 cfq 가 선택되어 있다면 weight 값이나 throttle 규칙을 적용할 수 있습니다. cgconfig.conf 에 다음과 같이低速 및 고속 그룹을 구분합니다.

group io_slow{
    blkio{
        blkio.weight = 100;
    }
}

group io_fast{
    blkio{
        blkio.weight = 1000;
        # 읽기 속도 제한: 장치 Major:Minor 속도 (bytes/sec)
        blkio.throttle.read_bps_device="252:0 5000000"; 
    }
}

여기서 숫자는 디바이스의 경로를 식별하는 것이며, 실제 값은 lsblk 등을 통해 확인 후 적용해야 재부팅 시에도 유지되는 효과를 볼 수 있습니다. iotop 도구를 띄워두면서 병렬로 데이터를 복사하면 weight 비율만큼 전송 속도가 차이 나는 것을 수치적으로 확인 가능합니다.

사용자별 자동 규칙 적용

매번 cgexec 로 그룹을 지정하는 것이 비효율적이라면 cgred 를 이용하여 사용자 권한을 기준으로 자동으로 할당하도록 설정합니다.

# /etc/cgrules.conf 편집
db_admin   blkio   io_slow/
app_user   cpu     cpu_high_share/

이 경우 db_admin 계정이 로그인하여 작업을 시작하면 시스템이 백그라운드에서 해당 세션과 프로세스를 자동으로 io_slow 그룹으로 소속시킵니다. 규칙 엔진의 동작 여부를 점검하려면 데몬을 재시작하고 로그 상태를 모니터링합니다.

# service cgred restart
# ps aux | grep cgred

다중 서브시스템 통합 설정

보통 각 리소스는 별도의 경로드에 마운트되지만, 관리 편의성을 위해 여러 서브시스템을 단일 경로에 통합하여 마운트할 수도 있습니다. 예를 들어 CPU 와 메모리 제어를 동일한 트리 구조에서统一管理 하고자 할 때 적용합니다.

mount {
    cpuset   = /cgroup/sysctrl;
    cpu      = /cgroup/sysctrl;
    memory   = /cgroup/sysctrl;
    blkio    = /cgroup/io_ctrl;
    devices  = /cgroup/dev_access;
}

이렇게 설정하면 /cgroup/sysctrl 경로 아래로 CPU 와 메모리 관련 파일들이 모두 등장하게 되며, 하나의 그룹 정의 내에 두 가지 리소스를 동시에 제어할 수 있습니다. 적용 후에는 반드시 cgconfig 서비스를 재실행하고 기존 세션을 정리한 후 새로운 마운트 정보를 검증해야 합니다.

태그: CentOS linux-kernel cgroup cgred resource-management

7월 7일 16:18에 게시됨