Container 왜, 어떻게 이렇게 동작하지 궁금하셨던 분들을 위한 설명입니다.

 

CGROUP, NAMESPACE, LXC, SECCOMP를 알고 계시는 리눅스 마스터이시다면(저는 몰랐었어요...;;;) 컨테이너가 이래서 이렇게 동작할거 같네 추측하실 수 있으리라 생각합니다.

 출처 : 

https://github.com/sbueringer/kubecon-slides/blob/master/slides/2017-kubecon-na/Container%20Runtime%20and%20Image%20Format%20Standards%20-%20What%20it%20Means%20to%20be%20%E2%80%9COCI-Certified%E2%80%9D%20%5BI%5D%20-%20Jeff%20Borek%2C%20IBM%20%26%20Stephen%20Walli%2C%20Microsoft%20-%20OCI%20Overview%20and%20Certification%20Program%20for%20CNCF%202017-12-04_Final.pdf

 

1. Cgroup(컨트롤그룹) : 리소스관리

리눅스에서 Cgroup이 어디있는지 제 짧은 지식으로 찾아봤습니다.

메모리, CPU, 블록IO 같은 익숙한 자원들이 보여요!

#cat /proc/cgroups

#subsys_name    hierarchy       num_cgroups     enabled

cpuset  11      4       1

cpu     2       67      1

cpuacct 2       67      1

memory  7       67      1

devices 8       67      1

freezer 3       4       1

net_cls 5       4       1

blkio   6       67      1

perf_event      10      4       1

hugetlb 4       4       1

pids    9       67      1

net_prio        5       4       1

 

검색해 보니 아래와 같습니다.

컨트롤 그룹 (CGROUPS)
CPU 시간, 시스템 메모리, 네트워크 대역폭과 같은 자원이나 이러한 자원의 조합을 시스템에서 실행 중인 사용자 정의 작업 그룹 (프로세스) 간에 할당(리소스 제한)
Blkio — 이 서브시스템은 물리 드라이브 (예: 디스크, 솔리드 스테이트, USB 등)와 같은 블록 장치에 대한 입력/출력 액세스에 제한을 설정합니다.
Cpu — 이 서브시스템은 CPU에 cgroup 작업 액세스를 제공하기 위해 스케줄러를 사용합니다.
Cpuacct — 이 하위 시스템은 cgroup의 작업에 사용된 CPU 자원에 대한 보고서를 자동으로 생성합니다.
Cpuset — 이 서브시스템은 개별 CPU (멀티코어 시스템에서) 및 메모리 노드를 cgroup의 작업에 할당합니다.
devices — 이 서브시스템은 cgroup의 작업 단위로 장치에 대한 액세스를 허용하거나 거부합니다.
freezer — 이 서브시스템은 cgroup의 작업을 일시 중지하거나 다시 시작합니다.
memory — 이 서브시스템은 cgroup의 작업에서 사용되는 메모리에 대한 제한을 설정하고 이러한 작업에서 사용되는 메모리 자원에 대한 보고서를 자동으로 생성합니다.
net_cls — 이 서브시스템은 Linux 트래픽 컨트롤러 (tc)가 특정 cgroup 작업에서 발생하는 패킷을 식별하게 하는 클래식 식별자 (classid)를 사용하여 네트워크 패킷에 태그를 지정합니다.

 

Docker에서도 리소스 관련 옵션을 찾아봅니다. 뭔가 CGROUP을 사용하는 것 같아요! 

Option

Description

-m, --memory=""

Memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M.

--memory-swap=""

Total memory limit (memory + swap, format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g.

--memory-reservation=""

Memory soft limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g.

--kernel-memory=""

Kernel memory limit (format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M.

-c, --cpu-shares=0

CPU shares (relative weight)

--cpus=0.000

Number of CPUs. Number is a fractional number. 0.000 means no limit.

--cpu-period=0

Limit the CPU CFS (Completely Fair Scheduler) period

--cpuset-cpus=""

CPUs in which to allow execution (0-3, 0,1)

--cpuset-mems=""

Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.

--cpu-quota=0

Limit the CPU CFS (Completely Fair Scheduler) quota

--cpu-rt-period=0

Limit the CPU real-time period. In microseconds. Requires parent cgroupsbe set and cannot be higher than parent. Also check rtprioulimits.

--cpu-rt-runtime=0

Limit the CPU real-time runtime. In microseconds. Requires parent cgroupsbe set and cannot be higher than parent. Also check rtprioulimits.

--blkio-weight=0

Block IO weight (relative weight) accepts a weight value between 10 and 1000.

--blkio-weight-device=""

Block IO weight (relative device weight, format: DEVICE_NAME:WEIGHT)

--device-read-bps=""

Limit read rate from a device (format: <device-path>:<number>[<unit>]). Number is a positive integer. Unit can be one of kb, mb, or gb.

--device-write-bps=""

Limit write rate to a device (format: <device-path>:<number>[<unit>]). Number is a positive integer. Unit can be one of kb, mb, or gb.

--device-read-iops=""

Limit read rate (IO per second) from a device (format: <device-path>:<number>). Number is a positive integer.

--device-write-iops=""

Limit write rate (IO per second) to a device (format: <device-path>:<number>). Number is a positive integer.

--oom-kill-disable=false

Whether to disable OOM Killer for the container or not.

--oom-score-adj=0

Tune container’s OOM preferences (-1000 to 1000)

--memory-swappiness=""

Tune a container’s memory swappiness behavior. Accepts an integer between 0 and 100.

--shm-size=""

Size of /dev/shm. The format is <number><unit>. number must be greater than 0. Unit is optional and can be b (bytes), k (kilobytes), m (megabytes), or g (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses 64m.

 

 

진짜 CGROUP을 쓰는지 한번 docker를 수행시켜 봅니다.

# docker run -it --name a1 -m 512m alpine /bin/sh
# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8cd8350dba0d        alpine              "/bin/sh"           7 seconds ago       Up 6 seconds                            a1
# docker inspect a1
            "Memory": 536870912,
# cd /sys/fs/cgroup/memory/docker/8cd8350dba0d4357cb0722199ad640434ed30a4f24425c593178/ | ls
cgroup.clone_children               memory.memsw.failcnt
cgroup.event_control                memory.memsw.limit_in_bytes
cgroup.procs                        memory.memsw.max_usage_in_bytes
memory.failcnt                      memory.memsw.usage_in_bytes
memory.force_empty                  memory.move_charge_at_immigrate
memory.kmem.failcnt                 memory.numa_stat
memory.kmem.limit_in_bytes          memory.oom_control
memory.kmem.max_usage_in_bytes      memory.pressure_level
memory.kmem.slabinfo                memory.soft_limit_in_bytes
memory.kmem.tcp.failcnt             memory.stat
memory.kmem.tcp.limit_in_bytes      memory.swappiness
memory.kmem.tcp.max_usage_in_bytes  memory.usage_in_bytes
memory.kmem.tcp.usage_in_bytes      memory.use_hierarchy
memory.kmem.usage_in_bytes          notify_on_release
memory.limit_in_bytes               tasks
memory.max_usage_in_bytes
# cat memory.limit_in_bytes
536870912
 
딴건 모르겠지만 메모리는 확실히 사용합니다. 나머지도 사용하는 것 같습니다.
Kubernetes를 사용 할 때 OOM-Killer가 왜 자꾸 Docker를 죽이는지 어떻게 설정해야하는지가 궁금하셨다면 여기에서 힌트를 얻으실 수 있을 것같아요.
다음엔 Namespace, LXC 볼게요!