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
장점
CPU 코어 할당
- CPU 코어별 jobs 배치
- 코어 스위칭 코스트 감소
CPU Usage 할당
- jobs별 우선 순위
- 리소스 세그멘테이션
Device Access
- isolation (visibllity)
- segmentation
- whitelist/blacklist
계층 관리
서브시스템별 사용 사례
현 시스템 내부 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 설정
- 참조: VMPressure | 문c
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 배정
- A 그룹에 속한 태스크를 절반 정도의 bandwidth를 부여한다. (50% 스로틀링)
$ 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 설정
- 참고: Scheduler -9- (RT Scheduler) | 문c
Uclamp 설정
다음 속성 파일들을 사용한다.
- <cpucg>/cpu.uclamp.{min,max}
- 0 ~ max
- /proc/sys/kernel/sched_util_clamp_util_{min,max}
- 1024
구조
참고
- Documentation/cgroups/cgroups.txt
- cgroup – (task) control group (1) | F/OSS study
- cgroup – (task) control group (2) | F/OSS study
- Ressource Management in Linux with Control Groups | Linux-Kongress 2010 – download pdf
- Introduction to Control Groups (Cgroups) | RedHat
- Introduction to Linux Control Groups (Cgroups) | Sysadmincasts
- An introduction to cgroups and cgroupspy | CloudSigma – 다운로드 pdf
Control Group v2
- Control Group v2 | kernel.org
- Understanding the new control groups API | LWN.net
- Container Performance Analysis | Netflix – 다운로드 pdf
- Control Groups (cgroups) | Man7.org – 다운로드 pdf
- cgroup controllers | Intel – 다운로드 pdf
- cgroupv2: Linux’s new unified control group system | Facebook – 다운로드 pdf
- cgroup v2 migration at Google | Google – 다운로드 pdf