$ docker run -it -d ubuntu:16.04
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a091c95446e8 ubuntu:16.04 "/bin/bash" 22 seconds ago Up 21 seconds stupefied_chandrasekhar
# 현재 실행중인 컨테이너 PID 추출
reallinux@ubuntu:~$ docker inspect a091c95446e8 | grep Pid
"Pid": 2510,
"PidMode": "",
"PidsLimit": null,
reallinux@ubuntu:~$ cat /proc/2510/cgroup
12:memory:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
11:cpuset:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
10:blkio:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
9:hugetlb:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
8:rdma:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
7:net_cls,net_prio:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
6:pids:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
5:perf_event:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
4:freezer:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
3:cpu,cpuacct:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
2:devices:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
1:name=systemd:/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
0::/docker/a091c95446e8ff8aeed54a745cd1d04d9291357d5e1e1f95f856b1a80f44589c
그렇다면 PID 1의 프로세스의 cgroup은 어떨까?
reallinux@ubuntu:~$ cat /proc/1/cgroup
12:memory:/
11:cpuset:/
10:blkio:/
9:hugetlb:/
8:rdma:/
7:net_cls,net_prio:/
6:pids:/
5:perf_event:/
4:freezer:/
3:cpu,cpuacct:/
2:devices:/
1:name=systemd:/init.scope
0::/init.scope
reallinux@ubuntu:~$ cat /proc/$$/cgroup
12:memory:/user.slice
11:cpuset:/
10:blkio:/user.slice
9:hugetlb:/
8:rdma:/
7:net_cls,net_prio:/
6:pids:/user.slice/user-1000.slice/session-2.scope
5:perf_event:/
4:freezer:/
3:cpu,cpuacct:/user.slice
2:devices:/user.slice
1:name=systemd:/user.slice/user-1000.slice/session-2.scope
0::/user.slice/user-1000.slice/session-2.scope
기본적으로 PID 1번 프로세스의 cgroup을 상속받는다.
그렇기 때문에 1번 프로세스의 cgroup과 현재 프로세스(bash)의 그것이 일치한다.
반면에 격리된 컨테이너의 cgroup은 다름을 확인할 수있다.
프로세스 컨트롤 그룹 즉, cgroup을 제한하여 프로세스들의 하드웨어 자원들을 점유를 제한 해보자.
물리적인 서버를 node라고 해보자.
node 안에 두 개의 컨테이너가 있다.
예를들어, 데이터 분석 컨테이너 때문에 웹 서버 컨테이너의 CPU 사용률이 제한되어 응답속도가 느려지면 안 된다.
따라서, 데이터 분석 컨테이너의 CPU 사용률 제한을 20%로 제한하면, 웹서버는 최대 CPU 사용률 80%를 보장받을 수있다.
이번엔 ubuntu 18.04 버전의 이미지의 컨테이너를 실행시켜보자.
reallinux@ubuntu:~$ sudo docker run -it ubuntu:18.04 /bin/bash
Unable to find image 'ubuntu:18.04' locally
18.04: Pulling from library/ubuntu
7c457f213c76: Pull complete
Digest: sha256:152dc042452c496007f07ca9127571cb9c29697f42acbfad72324b2bb2e43c98
Status: Downloaded newer image for ubuntu:18.04
root@04c61489c3e4:/#
/bin/bash 프로그램이 실행됐을 것이다.
이제 종료시켜 빠져나와보자.
root@04c61489c3e4:/# exit
exit
reallinux@ubuntu:~$
reallinux@ubuntu:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
04c61489c3e4 ubuntu:18.04 "/bin/bash" About a minute ago
reallinux@ubuntu:~$ sudo docker start 04c61489c3e4
04c61489c3e4
reallinux@ubuntu:~$ docker attach 04c61489c3e4
root@04c61489c3e4:/# ls
reallinux@ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
04c61489c3e4 ubuntu:18.04 "/bin/bash" 6 minutes ago Up 2 seconds confident_bell
a091c95446e8 ubuntu:16.04 "/bin/bash" 20 minutes ago Up 20 minutes stupefied_chandrasekhar
reallinux@ubuntu:~$ docker update --cpu-quota=500000 04c61489c3e4
04c61489c3e4
# run 명령어와 함께 cgroup을 변경하여 실행할 수도 있다.
reallinux@ubuntu:~$ docker run --cpu-period=100000 --cpu-quota=50000 -it ubuntu:18.04 /bin/bash
root@aea57f6adafd:/#
CPU 사용률 수치 산정 방법은 아래와 같다.
우선, period 개념이 필요하다.
CPU 스케줄링 단위로, 총 시간을 의미한다. ex) 100ms
100ms 마다 연속된 스케줄링을 한다고 정의 했을 때, cpu-quota를 50ms는 그 절반에 해당하는 시간이고, 전체 CPU 스케줄링 시간의 절반을 CPU 스케줄링을 사용하겠다는 의미다.
우리가 해볼 테스트는 다음과 같다.
컨테이너의 CPU 사용률이 50%가 넘지 않게 제한했다.
벤치마크를 통해 부하를 줬을 때, 정말로 컨테이너의 CPU 사용률이 50%를 넘지 않는지 확인해보는 것이다.
root@aea57f6adafd:/# apt update && apt install sysbench
root@aea57f6adafd:/# sysbench --test=cpu run
WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
sysbench 1.0.11 (using system LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 1
Initializing random number generator from current time
Prime numbers limit: 10000
Initializing worker threads...
Threads started!
CPU 사용률을 25%로 제한은 어떻게 할까?
docker run --cpu-period=100000 --cpu-quota=25000 -it ubuntu:18.04 /bin/bash
cd /sys/fs/cgroup/cpu,cpuacct/docker/{컨테이너ID}
에서 cat cpu.cfs_period_us, cat cpu.cfs_quota_us 를 확인할 수 있다.
즉, 도커는 cgroup과 namespace 를 수정해주는 것일 뿐이다.
(참고로, 강의에서는 cpu,cpuacct/docker/ 디렉터리가 나오고 있다. 하지만 나의 경우 아래와 같이 해야만 했다.)
reallinux@ubuntu:~$ docker run --cpu-period=100000 --cpu-quota=50000 -it ubuntu:18.04 /bin/bash
root@d0f8e5226b63:/# ls /sys/fs/cgroup/cpu,cpuacct/
cgroup.clone_children cpu.shares cpuacct.stat cpuacct.usage_percpu_sys notify_on_release
cgroup.procs cpu.stat cpuacct.usage cpuacct.usage_percpu_user tasks
cpu.cfs_period_us cpu.uclamp.max cpuacct.usage_all cpuacct.usage_sys
cpu.cfs_quota_us cpu.uclamp.min cpuacct.usage_percpu cpuacct.usage_user
root@d0f8e5226b63:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@d0f8e5226b63:/# cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
100000
root@d0f8e5226b63:/# cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
50000