Control Groups

Control Groups

History

  • 2006년 구글 엔지니어가 시작
  • 커널 v2.6.24에 merge되고 LXC, systemd 등으로 확산
  • 커널 v4.5에 cgroup v2 merge
    • 현재 v1에 있는 12개의 서브시스템(컨트롤러) 중 I/O, memory와 PID 컨트롤러가 먼저 포함
    • cgroup v1과 일단 같이 공존

 

특징

  • cgroup은 태스크들 세트의 aggregating/partitioning 매커니즘이며, 태스크들 세트에는 계층화 그룹으로 관리.
  • cgroup은 파일시스템이며 마운트하여 사용
    • mount -t tmpfs cgroup_root /sys/fs/cgroup
    • mkdir /sys/fs/cgroup/cpuset
    • mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
  • cgroup 자체만으로는 동작 중인 task의 그루핑만 한다.
  • 자원(cpu, memory, disk, device)등의 분배는 subsystem이 필요

 

기능

  • Access: cgroup별 디바이스들의 사용
  • Resource limiting: 자원(memory, cpu, device, …)의 사용제한
  • Prioritization: 누구에게 CPU와 메모리를 더 많이…
  • Accounting: cgroup별 자원 사용량
  • Control: freezing & check pointing
  • Injection: 패킷 태깅

 

사용 방법

  • 사용하고자 하는 서브시스템들을 각각 mount한 후 해당 cgroup에 대한 서브 디렉토리를 만들고 속성 파일을 설정하여 사용하는 방법
    • 예) mount -t cgroup -o net_prio none /sys/fs/cgroup/net_prio
  • cgroup-tools(libcgroup)를 설치하여 사용하는 방법
    • 예) apt install cgroup-tools
    • 예) yum install libcgroup

 

Cgroup Tool 명령어

다음은 cgroup을 관리하는 명령어들이다.

  • cgclassify
    • 동작 중인 태스크를 지정한 cgroup으로 이동
  • cgclear
    • cgroup 파일 시스템을 언로드
  • cgcreate
    • 새로운 cgroup을 생성
  • cgdelete
    • cgroup을 삭제
  • cgexec
    • 태스크를 지정한 cgroup에서 실행
  • cgget
    • 지정한 cgroup의 파라미터를 출력
  • cgset
    • 지정한 cgroup의 파라미터를 설정
  • cgsnapshot
    • 지정한 cgroup의 설정 파일을 생성
  • lscgroup
    • 모든 cgroup들을 리스트
  • lssubsys
    • 지정한 서브시템에 포함된 cgroup 계층화 리스트
  • cgconfigparser
    • cgroup 파일 시스템 셋업

 

다음 파일은 libcgroup 설정 파일이다.

  • cgconfig.conf

 

subsystem (Controller)

커널 v5.10 기준 14개의 서브시스템을 지원한다.

  • cpuset, cpu, cpuacct, io, memory, devices, freezer, net_cls, perf_event, net_prio, hugetlb, pids, rdma, debug

 

cgroup1

 


장점

CPU 코어 할당

  • CPU 코어별 jobs 배치
  • 코어 스위칭 코스트 감소

cgroup2

 

CPU Usage 할당

  • jobs별 우선 순위
  • 리소스 세그멘테이션

cgroup3

 

Device Access

  • isolation (visibllity)
  • segmentation
  • whitelist/blacklist

cgroup4

 

계층 관리

cgroup5

 


서브시스템별 사용 사례

 

현 시스템 내부 subsystem 목록

현재 mount되어 사용가능한 cgroup 서브시스템 목록을 다음과 같이 3가지 방법으로 알아본다.

 

1. proc 인터페이스 사용
$ cat /proc/cgroups
#subsys_name    hierarchy       num_cgroups     enabled
cpuset  3       9       1
cpu     9       9       1
cpuacct 9       9       1
blkio   6       9       1
memory  4       9       1
devices 10      88      1
freezer 5       9       1
net_cls 8       9       1
perf_event      7       9       1
net_prio        8       9       1
hugetlb 2       9       1

 

2. lssubsys 명령어 사용
$ lssubsys
cpuset
cpu
cpuacct
blkio
memory
devices
freezer
net_cls
perf_event
net_prio
hugetlb
pids
rdma

 

3. 디렉토리를 출력
ls /sys/fs/cgroup/
blkio  cpu  cpuacct  cpuset  devices  freezer  hugetlb  memory  net_cls  net_prio  perf_event  pids  rdma  unified

 

CONFIG_SCHED_AUTOGROUP

유저별 그룹화하여 사용할 수 있도록 사용자의 로긴/로그오프시에 cgroup이 자동으로 생성/소멸된다. 이 기능을 사용하는 경우 task별로 균등하게 자원을 배치하는 것을 유저별로 균등하게 자원을 배치할 수 있는 장점이 있다.

 

다음과 같은 계층 구조를 사용한다.

  • <subsystem>/system.slice
    • 시스템 서비스가 사용되는 cgroup 이다.
  • <subsystem>/user.slice/user-<유저번호>.slice/ session-c<세션번호>.scope
    • 유저와 세션에 따라 cgroup이 자동으로 추가된다.

memory 서브시스템

다음은 memory 서브시스템의 루트 디렉토리 내용을 보여준다.

$ ls /sys/fs/cgroup/memory
cgroup.clone_children  cpuacct.stat          cpu.cfs_period_us  cpu.stat           tasks
cgroup.procs           cpuacct.usage         cpu.cfs_quota_us   notify_on_release  user.slice
cgroup.sane_behavior   cpuacct.usage_percpu  cpu.shares         release_agent

 

메모리 배정

다음과 같이 cpuset 서브시스템에 A라는 cgroup을 생성하고 100M 메모리를 배정한 후, 특정 태스크(sample_app)를 A에 지정하여 실행한다.

$ cgcreate -g memory:/A

$ lscgroup -g memory:/
cpuset:/
cpuset:/A

$ cgset -r memory.limit_in_bytes=104857600 A
$ cgget -g memory:/A
/A:
/A:
memory.use_hierarchy: 1
memory.kmem.tcp.usage_in_bytes: 0
memory.soft_limit_in_bytes: 9223372036854771712
memory.force_empty:
memory.pressure_level:
memory.move_charge_at_immigrate: 0
memory.kmem.tcp.max_usage_in_bytes: 0
memory.max_usage_in_bytes: 0
memory.oom_control: oom_kill_disable 0
        under_oom 0
        oom_kill 0
memory.stat: cache 0
        rss 0
        rss_huge 0
        shmem 0
        mapped_file 0
        dirty 0
        writeback 0
        pgpgin 0
        pgpgout 0
        pgfault 0
        pgmajfault 0
        inactive_anon 0
        active_anon 0
        inactive_file 0
        active_file 0
        unevictable 0
        hierarchical_memory_limit 104857600
        total_cache 0
        total_rss 0
        total_rss_huge 0
        total_shmem 0
        total_mapped_file 0
        total_dirty 0
        total_writeback 0
        total_pgpgin 0
        total_pgpgout 0
        total_pgfault 0
        total_pgmajfault 0
        total_inactive_anon 0
        total_active_anon 0
        total_inactive_file 0
        total_active_file 0
        total_unevictable 0
memory.kmem.slabinfo:
memory.limit_in_bytes: 1048576000
memory.swappiness: 60
memory.kmem.failcnt: 0
memory.kmem.max_usage_in_bytes: 0
memory.usage_in_bytes: 0
memory.failcnt: 0
memory.kmem.tcp.failcnt: 0
memory.kmem.limit_in_bytes: 9223372036854771712
memory.kmem.usage_in_bytes: 0
memory.kmem.tcp.limit_in_bytes: 9223372036854771712

$ cgexec -g memory:/A sample_app

 

Swapness 설정

글로벌 설정은 다음 proc 인터페이스를 통해 변경할 수 있다.

  • proc/sys/vm/swappiness

cgroup별로도 Swapness를 설정할 수 있다.

  • <memcg>/memory.swappiness

 

VMPressure 설정

 


cpuset 서브시스템

 

Core 배정

다음과 같이 cpuset 서브시스템에 A라는 cgroup을 생성하고 2~3번 core를 배정한 후, 특정 태스크(sample_app)를 A에 지정하여 실행한다.

  • cpuset.mems에도 사용할 노드 번호를 지정해줘야 한다.
$ cgcreate -g cpuset:/A

$ lscgroup -g cpuset:/
cpuset:/
cpuset:/A

$ cgset -r cpuset.cpus="2-3" A
$ cgset -r cpuset.mems=0 A
$ cgget -g cpuset:/A
/A:
cpuset.memory_pressure: 0
cpuset.memory_migrate: 0
cpuset.mem_exclusive: 0
cpuset.memory_spread_slab: 0
cpuset.cpu_exclusive: 0
cpuset.effective_mems: 0
cpuset.effective_cpus: 2-3
cpuset.sched_load_balance: 1
cpuset.mems: 0
cpuset.mem_hardwall: 0
cpuset.sched_relax_domain_level: -1
cpuset.cpus: 2-3
cpuset.memory_spread_page: 0

$ cgexec -g cpuset:/A sample_app

 


cpu 서브시스템

 

커널/유저 사용 시간 확인

커널이 사용한 시간과 유저가 사용한 시간을 틱 수로 보여준다.

$ cat /sys/fs/cgroup/cpu/A/cpuacct.stat
user 47289
system 5

 

cpu 점유율(shares) 배정

  • A , B 두 그룹을 만들고 일반 태스크의 우선 순위(nice 0)보다 A 그룹에 2배의 우선 순위(nice -3과 유사), B 그룹에 4배의 우선 순위(nice -6)를 배정하였다.
$ cgcreate -g cpu:/A
$ cgcreate -g cpu:/B 
$ lscgroup -g cpu:/
cpu,cpuacct:/
cpu,cpuacct:/A
cpu,cpuacct:/B
$ cgset -r cpu.shares=2048 A
$ cgset -r cpu.shares=4096 B
$ cgget -g cpu:/A
/A:
cpu.cfs_period_us: 100000
cpu.stat: nr_periods 0
        nr_throttled 0
        throttled_time 0
cpu.shares: 2048
cpu.cfs_quota_us: -1
$ cgclassify -g cpu:/A <A 그룹에 배정할 pid들>
$ cgclassify -g cpu:/B <B 그룹에 배정할 pid들>

 

CFS 태스크의 Bandwidth 배정

$ cgcreate -g cpu:/A

$ lscgroup -g cpu:/
cpu,cpuacct:/
cpu,cpuacct:/A
$ cgset -r cpu.cfs_period_us=100000 A
$ cgset -r cpu.cfs_quota_us=50000 A
$ cgget -g cpu:/A
/A:
cpu.cfs_period_us: 100000
cpu.stat: nr_periods 2
        nr_throttled 0
        throttled_time 0
cpu.shares: 1024
cpu.cfs_quota_us: 50000
$ cgexec -g cpu:/A sample_app

 

그룹 RT Bandwidth 설정

 

Uclamp 설정

다음 속성 파일들을 사용한다.

  • <cpucg>/cpu.uclamp.{min,max}
    • 0 ~ max
  • /proc/sys/kernel/sched_util_clamp_util_{min,max}
    • 1024

 


구조

cgroup6

 

cgroup7

 


 

 

참고

 

 

Control Group v2

 

댓글 남기기