Operating System

cgroup(control group) 이란?

궁금한게 많은 개발자 2024. 11. 4. 15:18

 

cgroup(control group)은 리눅스 커널에서 제공하는 기능으로, 시스템의 리소스(CPU, 메모리, 디스크 I/O, 네트워크 대역폭 등)를 프로스세 그룹으로 제한하고 관리하기 위해 사용됩니다. 주로 단일 또는 프로세스 그룹이 사용하는시스템 자원의 사용 정보를 수집하고, 제한하고, 격리시키는 역할을 합니다. (모든 프로세스에 대해 리소스 사용 정보를 수집)

즉, 프로세스를 계층적인 group으로 구성해서, resource사용을 제한하고 모니터링할 수 있는 linux kernel feature.

 

이는 대규모 시스템 환경에서 효율적인 리소스 관리와 격리를 위해 필수적이며, 특히 컨테이너 시스템(docker, kubernetes)에서 중요한 역할을 합니다. 컨테이너 시스템에서 사용할 리소스를 제한, 격리하여 독립된 프로세스 환경을 만들어주고 계층 구조를 적용할 수 있어 체계적으로 리소스를 관리할 수 있습니다.

 

 

cgroup의 주요 기능으로는 다음과 같습니다.

  • 리소스 제한– cgroup을 사용함으로써 프로세스가 사용할 수 있는 특정 리소스(예: 메모리 또는 CPU)의 양을 제한할 수 있습니다. 이를 통해 시스스템의 안정성을 높이고 리소스 사용을 효율적으로 관리할 수 있습니다.
  • 보고 – 리소스 사용 및 제한은 cgroup 수준에서 모니터링되고 보고되며, 이를 통해 리소스 사용 패턴을 이해하고 필요한 조정을 수행할 수 있습니다.
  • 프로세스 관리 – 프로세스를 그룹으로 관리할 수 있게 해주며, 단일 명령으로 cgroup에 있는 모든 프로세스의 상태(고정, 중지 또는 다시 시작)를 변경할 수 있습니다.
  • 우선순위 할당– 서로 다른 프로세스 그룹에 대해 서로 다른 CPU 스케줄링 또는 I/O 대역폭 우선 순위를 설정할 수 있습니다. 이를 통해 중요한 작업에 더 많은 리소스를 할당하고 중요도가 낮은 프로세스에 리소스를 제한할 수 있습니다.

 

cgroup의 version은 v1과 v2로 나누어지며 v1,v2의 차이점에 대해서는 아래 링크에서 자세히 참고 가능합니다.
https://docs.kernel.org/admin-guide/cgroup-v2.html#issues-with-v1-and-rationales-for-v2

https://lwn.net/Articles/679786/

 

v1과 v2의 가장 큰 차이

  • 계층 구조와 컨트롤러 관리: v1은 각 리소스 컨트롤러가 독립적인 계층을 형성하며, cpu, memory 리소스 마다 별도의 cgroup계층이 형성되며 리소스 마다 다른 계층 구조를 가지지만 v2에서는 모든 리소스 컨트롤러가 단일 계층에서 관리되어 즉, 하나의 cgroup트리에 cpu, memory 모든 리소스 제어가 통합됩니다. (일관된 리소스 제어 및 관리 용이)
  • 컨트롤러 인터페이스 파일: 위 계층 구조의 설명에서처럼 v1의 각 리소스 컨트롤러는 개별 디렉토리와 파일 구조를 가지며 v2에서는 단일 디렉토리에서 각 리소스 컨트롤러 파일이 포함되어 단순화된 인터페이스를 제공합니다.
  • 리소스 분배와 할당 방식: v1은 리소스 제한에 대해 일관성이 부족하여 특정 설정은 복잡하여 cgroup계층 전체에 적용되지 않을 수 있습니다. v2에서는 cgroup.subtree_control과 같은 코어 인터페이스 파일을 통해 상위 cgroup에서 하위 cgroup으로 리소스 할당을 보다 명확하게 정의할 수 있으며 리소스 제어가 일관되게 이루어지게 되었습니다.
  • 프로세스 관리: v1은 하나의 프로세스가 여러 cgroup에 속할 수 있었습니다.(리소스별로 다른 cgroup) 이에 반해 v2에서는 하나의 프로세스는 하나의 cgroup에 속하게 되며 이는 단일 계층 구조이기 때문에 가능합니다.

 

 

cgroup v2는 프로세스를 계층적으로 구성하고 각 계층 별로 시스템 리소스를 제어할 수 있는 기능을 제공하며, 이러한 cgroup은 크게 core와 controller(subsystem)로 나뉘어 있습니다.

core는 주로 process를 계층적으로 관리하는 역할을 하고, subsystem은 resource tracking과 limit제한, cgroup에 속한 process의 행동을 변경하는 역할(resource를 제한하면서 process 중지 또는 재시작)을 주로 맡습니다.

subsystem(controller)의 종류는 다양하며 그 중 일부에 대해 간략히 알아보려 합니다.

  • cpu: cgroup는 시스템이 busy 상태일 때 CPU공유를 최소화 즉 사용량을 제한 할 수 있습니다. 이 서브시스템은 CPU에 cgroup 작업 액세스를 제공하기 위한 스케줄러를 제공합니다. 즉, 스케줄러로 해당 cgroup에 속한 프로세스 CPU 사용 시간을 제어.
  • cpuacct: 프로세스 그룹 별 CPU 자원 사용에 대한 분석 통계를 생성 및 제공합니다. 각 cgroup cpu 사용량 모니터링
  • cpuset: 개별 CPU 및 메모리 노드를 cgroup에 바인딩 하기 위해 사용하는 서브시스템으로 linux의 testset명령과 유사하게 CPU코어를 할당할 수 있는 서브시스템입니다.
  • memory: cgroup에 속한 프로세스의 메모리(프로세스, 커널, swap) 사용량을 제한하고 리포팅을 제공하는 서브시스템으로 초과 시 OOM(out of memory, oom_control로 관리) 발생
  • blkio: 특정 block device에 대한 접근을 제한하거나 제어하기 위한 서브시스템으로, block device(SSD, USB, HDD)에 대한 IO 접근 제한을 설정할 수 있습니다.
  • devices: cgroup의 작업 단위로 device에 대한 접근을 허용하거나 제한합니다. whitelist와 blacklist로 명시되어 있습니다. 
  • freezer: cgroup에 속한 프로세스들의 작업을 일시적으로 정지(suspend)하거나 다시 시작(restore)할 수 있습니다. frozen상태(일시 정지)와 thawed상태(정상 실행)로 전환하는 방식으로 동작합니다.
  • net_cls: 특정 cgroup에 속한 프로세스들의 작업에서 발생하는 패킷을 식별하기 위한 태그(classid)를 지정할 수 있습니다. 이 태그는 방화벽 규칙으로 사용되어 질 수 있으며 네트워크 트래픽을 분류할 수 있게 해줍니다.
  • net_prio: cgroup에 속한 프로세스의 작업에서 생성되는 네트워크 트래픽의 우선순위를 선정할 수 있습니다.  중요한 서비스에 대해 네트워크 우선순위를 높여 중요한 트래픽이 더 빠르게 처리되도록 할 수 있습니다.
  • hugetlb: 특정 cgroup에 속한 프로세스들이 Huge Page 큰 페이지 메모리 사용에 대한 제한을 설정할 수 있습니다.
  • pid: cgroup에 할당할 수 있는 프로세스의 수를 제한할 수 있으며 시스템 안정성을 유지하는데 도움이 됩니다.

cgroup은 가상 파일시스템의 디렉토리로 표시되는 계층 구조로 구성되어 집니다. cgroup의 interface는 cgroupfs라 불리는 persudo-filesystem을 통해 제공되며, cgroupfs의 subdirectory를 생성, 삭제, 변경하면서 정의됩니다.

즉, cgroup의 실체는 파일 시스템이며 cgroup은 오직 프로세스를 그룹화하는 역할만 수행하며, 내부적으로 자원을 제한하고나 할당하는 역할은 위에서 설명한 서브시스템(controller)에서 수행합니다.

 

cgroup은 두 가지 방법으로 사용이 가능한데, cgroup 가상 파일시스템을 마운트하여 파일 및 디렉토리를 조작하여 사용이 가능하고 또 다른 방법으로는 사용자 도구(cgroup-bin, libcgroup)를 통해 가능합니다.

 

 

 

 

이제, cgroup filesystem 디렉토리를 살펴보고자 합니다.

 

# ls /sys/fs/cgroup 
cgroup.controllers      cgroup.procs            cpu.pressure           dev-hugepages.mount  io.cost.qos    memory.numa_stat  misc.capacity                  sys-kernel-config.mount   user.slice
cgroup.max.depth        cgroup.stat             cpu.stat               dev-mqueue.mount     io.pressure    memory.pressure   misc.current                   sys-kernel-debug.mount
cgroup.max.descendants  cgroup.subtree_control  cpuset.cpus.effective  init.scope           io.prio.class  memory.reclaim    proc-sys-fs-binfmt_misc.mount  sys-kernel-tracing.mount
cgroup.pressure         cgroup.threads          cpuset.mems.effective  io.cost.model        io.stat        memory.stat       sys-fs-fuse-connections.mount  system.slice

 

위와 같은 다양한 정보들을 확인할 수 있으며 파일로 존재하는 것과 디렉토리로 존재하는 것이 있습니다. 여기서 디렉토리를 하나 생성하게 되면 어떻게 될까요?

# mkdir /sys/fs/cgroup/test
# ls /sys/fs/cgroup/test 
cgroup.controllers  cgroup.max.depth        cgroup.stat             cpu.pressure    memory.events        memory.max        memory.peak      memory.swap.current  memory.swap.peak      pids.events
cgroup.events       cgroup.max.descendants  cgroup.subtree_control  cpu.stat        memory.events.local  memory.min        memory.pressure  memory.swap.events   memory.zswap.current  pids.max
cgroup.freeze       cgroup.pressure         cgroup.threads          io.pressure     memory.high          memory.numa_stat  memory.reclaim   memory.swap.high     memory.zswap.max      pids.peak
cgroup.kill         cgroup.procs            cgroup.type             memory.current  memory.low           memory.oom.group  memory.stat      memory.swap.max      pids.current

 

디렉토리만 생성했을 뿐인데, 생성한 디렉토리 내부에는 /sys/fs/cgroup의 디렉토리와 비슷한 형태로 파일이 만들어진 것을 확인할 수 있습니다. 이는 디렉토리 생성 시 커널이 자동으로 해당 디렉토리 내부에 파일을 생성해주기 때문입니다. 결국 cgroup은 반복하여 다중 계층 구조를 유지할 수 있게 됩니다.

 

다시 /sys/fs/cgroup으로 돌아가 cgroup.controllers 파일은 어떤 내용을 담고 있는지 확인해보려 합니다.

# cat /sys/fs/cgroup/cgroup.controllers 
cpuset cpu io memory hugetlb pids rdma misc

 

현재 cgroup에서 사용할 수 있는 모든 컨트롤러 목록에 대한 정보를 담고 있습니다. 즉 활성화된 컨트롤러의 목록은 아니며 현재 cgroup에서 지원 가능한, 상위 cgroup에서 사용할 수 있는 컨트롤러를 확인하는 목적으로 사용됩니다.

특정 cgroup에서 실제로 활성화할 컨트롤러를 지정하는데 사용되는 파일은  cgroup.subtree_control입니다.

# cat /sys/fs/cgroup/cgroup.subtree_control 
memory pids

# echo '+cpu -memory' > /sys/fs/cgroup.subtree_control
# cat /sys/fs/cgroup/cgroup.subtree_control
cpu pids

 

위와 같이 +controller, -controller로 표기하여 해당 파일에 저장하면 특정 controller를 활성화하고 비활성화할 수 있습니다.

이 파일을 통해 해당 cgroup의 하위에서 어떤 controller들을 사용할 수 있는지 지정할 수 있게 됩니다.

보통, 하위 cgroup의 cgoup.controllers파일의 내용은 상위 cgroup의 subtree_control 내용과 동일합니다.

 

 

/sys/fs/cgroup의 아래에서 확인할 수 있는 파일들에 대해 전반적으로 살펴보면 "cgroup" prefix를 가진 파일들을 코어 인터페이스 파일이라고 합니다. 코어 인터페이스 파일은 cgroup 자체의 구조와 설정을 관리하는데 사용되며 기본 인터페이스를 제공합니다. cgroup의 계층, 상속, 프로세스 할당 등을 정의하며 각 cgroup이 자체적으로 리소스 제한과 구조를 고나리할 수 있게 하는 역할을 합니다.

반면 cpu, memory 등과 같은 컨트롤러 이름을 prefix로 가지는 파일들을 컨트롤러 인터페이스 파일이라고 합니다. 개별 리소스 관리와 관련된 파일들이며 특정 리소스에 대한 제어와 제한을 설정하거나 현재 사용량을 모니터링하는 역할을 합니다. 각 리소스 컨트롤러가 제공하는 설정 및 상태 파일들이므로 해당 컨트롤러가 활성화된 경우에만 파일이 표시됩니다.

 

 



운영 측면에서 모든 리소스가 중요하겠지만 그 중 cpu, memory에 대한 리소스가 가장 중요하다고 생각하실 것 같습니다. 이에 cpu 컨트롤러에 대해 조금 더 자세히 알아보려 합니다. 다음 포스팅으로..!

https://ks1171-park.tistory.com/248

 

cgroup의 cpu controller (subsystem)

운영 측면에서 모든 리소스가 중요하겠지만 그 중 cpu, memory에 대한 리소스가 가장 중요하다고 생각하실 것 같습니다. 이에 cpu 컨트롤러에 대해 조금 더 자세히 알아보려 합니다. 😎cpu컨트롤러

ks1171-park.tistory.com