리눅스 프로세스 격리 기술 발전의 역사

출처 https://speakerdeck.com/kakao/ige-dwaeyo-dokeo-eobsi-keonteineo-mandeulgi?slide=200
모든 실습 내용 및 이미지는 위 출처를 바탕으로 공부했습니다 !
change root의 약자로 프로세스와 자식 프로세스들의 / 디렉토리를 다른 디렉토리로 변경하는 명령어 ( 탈옥이 가능하여 현재는 사용하지 않음 )
ls /
bin dev home lib32 libx32 media opt root sbin srv tmp var
boot etc lib lib64 lost+found mnt proc run snap sys usr
ls -l
total 16
drwx------ 3 root root 4096 Aug 31 18:41 snap-private-tmp
drwx------ 3 root root 4096 Aug 31 18:41 systemd-private-49c8ef62ce5a361aae477-chrony.service-4
drwx------ 3 root root 4096 Aug 31 18:41 systemd-private-49c8ef62ce5e361aae477-systemd-logind.service-8
drwx------ 3 root root 4096 Aug 31 18:41 systemd-private-49c8ef62ce5a461aae477-systemd-resolved.service-5
root@MyServer:/tmp# mkdir myroot
root@MyServer:/tmp# ls
myroot
# chroot 사용법 : [옵션] NEWROOT [커맨드]
# chroot 명령어 사용 시, 새로운 root 디렉토리로 변경 할 디렉토리 지정 + 실행할 명령어 실해
root@MyServer:/tmp# chroot myroot /bin/sh
chroot: failed to run command ‘/bin/sh’: No such file or directory
# tree myroot
myroot
0 directories, 0 files
현재는 myroot 디렉토리 내에 아무 파일이 존재 하지 않아 /bin/sh를 파일이 없어 실행할 수 없다고 뜸
# which sh
/usr/bin/sh
p# which sh
/usr/bin/sh
root@MyServer:/tmp# ldd /bin/sh
linux-vdso.so.1 (0x00007ffd55b08000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000780439c00000)
/lib64/ld-linux-x86-64.so.2 (0x0000780439f8e000)
sh 명령어 실행 시 필요한 의존성 확인을 위해 ldd명령어로 확인
libc.so.6 패키지와 /lib64/ld-linux-x86-64.so.2패키지 의존성 확인
mkdir -p myroot/bin
cp /usr/bin/sh myroot/bin/
mkdir -p myroot/{lib64,lib/x86_64-linux-gnu}
cp /lib/x86_64-linux-gnu/libc.so.6 myroot/lib/x86_64-linux-gnu/
cp /lib64/ld-linux-x86-64.so.2 myroot/lib64
# tree myroot/
myroot/
├── bin
│ └── sh
├── lib
│ └── x86_64-linux-gnu
│ └── libc.so.6
└── lib64
└── ld-linux-x86-64.so.2
4 directories, 3 files

정상 작동 확인
# ls
/bin/sh: 1: ls: not found
myroot아래에는 sh 명령어 밖에 없고 ls 명령어가 없으니 ls 명령어가 안되는 것은 당연
# which ls
/usr/bin/ls
# ldd /usr/bin/ls
linux-vdso.so.1 (0x00007ffd087a2000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x0000764815cb9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000764815a00000)
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x0000764815969000)
/lib64/ld-linux-x86-64.so.2 (0x0000764815d11000)
# cp /usr/bin/ls myroot/bin/
root@MyServer:/tmp# cp /lib/x86_64-linux-gnu/{libselinux.so.1,libc.so.6,libpcre2-8.so.0} myroot/lib/x86_64-linux-gnu/
cp /lib64/ld-linux-x86-64.so.2 myroot/lib64
root@MyServer:/tmp# tree myroot
myroot
├── bin
│ ├── ls
│ └── sh
├── lib
│ └── x86_64-linux-gnu
│ ├── libc.so.6
│ ├── libpcre2-8.so.0
│ └── libselinux.so.1
└── lib64
└── ld-linux-x86-64.so.2
4 directories, 6 files
# chroot myroot /bin/sh
# ls /
bin lib lib64
# cd ../../../
# pwd
/
진짜 경로는 아래와 같음
$ pwd
/tmp/myroot
cd 명령어로 아무리 위로 가봐도 myroot 이상으로는 갈 수 없음
경로 자체를 격리하여 프로세스를 격리하는 것을 확인할 수 있음
root@MyServer:/tmp# # copy ps
ldd /usr/bin/ps;
cp /usr/bin/ps /tmp/myroot/bin/;
cp /lib/x86_64-linux-gnu/{libprocps.so.8,libc.so.6,libsystemd.so.0,liblzma.so.5,libgcrypt.so.20,libgpg-error.so.0,libzstd.so.1,libcap.so.2} /tmp/myroot/lib/x86_64-linux-gnu/;
mkdir -p /tmp/myroot/usr/lib/x86_64-linux-gnu;
cp /usr/lib/x86_64-linux-gnu/liblz4.so.1 /tmp/myroot/usr/lib/x86_64-linux-gnu/;
cp /lib64/ld-linux-x86-64.so.2 /tmp/myroot/lib64/;
# copy mount
ldd /usr/bin/mount;
cp /usr/bin/mount /tmp/myroot/bin/;
cp /lib/x86_64-linux-gnu/{libmount.so.1,libc.so.6,libblkid.so.1,libselinux.so.1,libpcre2-8.so.0} /tmp/myroot/lib/x86_64-linux-gnu/;
cp /lib64/ld-linux-x86-64.so.2 /tmp/myroot/lib64/;
# copy mkdir
ldd /usr/bin/mkdir;
cp /usr/bin/mkdir /tmp/myroot/bin/;
cp /lib/x86_64-linux-gnu/{libselinux.so.1,libc.so.6,libpcre2-8.so.0} /tmp/myroot/lib/x86_64-linux-gnu/;
cp /lib64/ld-linux-x86-64.so.2 /tmp/myroot/lib64/;
# tree 확인
tree myroot
linux-vdso.so.1 (0x00007ffdda77d000)
libprocps.so.8 => /lib/x86_64-linux-gnu/libprocps.so.8 (0x00007c8f6a53b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007c8f6a200000)
libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007c8f6a474000)
/lib64/ld-linux-x86-64.so.2 (0x00007c8f6a5c0000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007c8f6a449000)
libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x00007c8f6a131000)
liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x00007c8f6a111000)
libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x00007c8f6a43c000)
libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007c8f69fd3000)
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007c8f69fad000)
linux-vdso.so.1 (0x00007ffe02b04000)
libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x000071cb60503000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x000071cb604d7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000071cb60200000)
libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x000071cb604a0000)
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x000071cb60169000)
/lib64/ld-linux-x86-64.so.2 (0x000071cb6055c000)
linux-vdso.so.1 (0x00007ffcf73b5000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007b2db8137000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007b2db7e00000)
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007b2db80a0000)
/lib64/ld-linux-x86-64.so.2 (0x00007b2db817d000)
myroot
├── bin
│ ├── ls
│ ├── mkdir
│ ├── mount
│ ├── ps
│ └── sh
├── lib
│ └── x86_64-linux-gnu
│ ├── libblkid.so.1
│ ├── libc.so.6
│ ├── libcap.so.2
│ ├── libgcrypt.so.20
│ ├── libgpg-error.so.0
│ ├── liblzma.so.5
│ ├── libmount.so.1
│ ├── libpcre2-8.so.0
│ ├── libprocps.so.8
│ ├── libselinux.so.1
│ ├── libsystemd.so.0
│ └── libzstd.so.1
├── lib64
│ └── ld-linux-x86-64.so.2
└── usr
└── lib
└── x86_64-linux-gnu
└── liblz4.so.1
7 directories, 19 files
# chroot myroot /bin/sh
# ps
Error, do this: mount -t proc proc /proc
# ls /proc
ls: cannot access '/proc': No such file or directory
ps 명령어에서 필요한 /proc 디렉토리가 마운트 되어 있지 않기 때문
원래는 /proc가 마운트가 되어 있음 -> ps명령어가 /proc 디렉토리에서 정보를 가져옴
# mkdir /proc
# mount -t proc proc /proc
# mount -t proc
proc on /proc type proc (rw,relatime)
이제 chroot에서 proc가 확인이 되고
# ps
PID TTY TIME CMD
1130 ? 00:00:00 sudo
1131 ? 00:00:00 su
1132 ? 00:00:00 bash
2672 ? 00:00:00 sh
2694 ? 00:00:00 ps
ps명령어가 확인 됨
-> ps 명령어를 사용하기 위해서는 /proc가 마운트 되어야 한다
root@MyServer:/tmp# mount -t proc
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
proc on /tmp/myroot/proc type proc (rw,relatime)
root@MyServer:/tmp# sudo umount /tmp/myroot/proc
root@MyServer:/tmp# mount -t proc
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
chroot 에서 mount 한 건 원래 루트에서도 확인이 가능
원래 루트에서 마운트 해제
root@MyServer:docker export $(docker create nginx) | tar -C nginx-root -xvf -;
root@MyServer:/tmp/nginx-root# docker export $(docker create nginx) | tar -C nginx-root -xvf -;
컨테이너 이미지는 실행되는 프로세스의 동작에 필요한 모든 관련 파일을 묶어서 패키징되기 때문에 nginx 실행에 필요한 모든 프로세스 동작 관련 파일이 nginx-root 디렉토리에 복사 된것을 확인 할 수 있음

-> 컨테이너 엔진이 있으면 모든 컨테이너를 실행할 수 있는 것에 대한 원리
chroot nginx-root/ /bin/sh
# ls /
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
nginx-root 컨테이너의 sh로 들어온 것과 유사
# nginx -g "daemon off;"
chroot 프로세스에서 nginx를 실행하더라도 원래 터미널에서는 nginx 프로세스 목록이 확인 가능
root@MyServer:~# ps -ef | grep nginx
root 2776 2773 0 19:50 pts/1 00:00:00 nginx: master process nginx -g daemon off;
systemd+ 2777 2776 0 19:50 pts/1 00:00:00 nginx: worker process
root 2779 2678 0 19:50 pts/3 00:00:00 grep --color=auto nginx
curl 을 통해 접근도 가능
root@MyServer:~# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
마치 컨테이너 하나 실행된 것 같은거 같은 느낌
소켓정보도 확인 가능
root@MyServer:~# ss -tnlp
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=2777,fd=6),("nginx",pid=2776,fd=6))
chroot는 탈옥이 가능함 -> 사용 X
vi escape_chroot.c
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
mkdir(".out", 0755);
chroot(".out");
chdir("../../../../../");
chroot(".");
return execl("/bin/sh", "-i", NULL);
}
gcc -o myroot/escape_chroot escape_chroot.c
tree -L 1 myroot
file myroot/escape_chroot
myroot
├── bin
├── escape_chroot
├── lib
├── lib64
├── proc
└── usr
# ls /
bin escape_chroot lib lib64 proc usr
# cd ../../
# cd ../../
# ls
bin escape_chroot lib lib64 proc usr
# ls /
bin escape_chroot lib lib64 proc usr
# 탈옥 코드 실행
# ./escape_chroot
# ls /
bin dev home lib32 libx32 media opt root sbin srv tmp var
boot etc lib lib64 lost+found mnt proc run snap sys usr
root@MyServer:~# ls /
bin boot dev etc home lib lib32 lib64 libx32 lost+found media mnt opt proc root run sbin snap srv sys tmp usr var
탈옥에 성공하여 chroot 실행하기 전 원래 터미널의 / 와 같아진 것을 확인 가능
-> chroot 탈옥이 가능하기 때문에 컨테이너 사용하는 시스템에서 사용이 어려움 -> pivot_root사용
chroot 차단을 위해, pivot_root + mount ns(호스트 영향 격리)를 사용 : 루트 파일 시스템을 변경(부착 mount) + 프로세스 환경 격리

루트 자체를 pivot -> 새로운 루트 디렉토리를 pivot -> 신규 /처럼 보고 put_old만 격리 시키면 됨
os 자체에서는 그대로 있지만 pivot 했기 때문에 컨테이너 자체에서는 오른쪽 그림처럼 보임
탈옥 코드 실행해도 탈옥이 되지 않음

마운트 네임스페이스 : 마운트 포인트를 격리(unshare 명령어를 통해)
쿠버네티스 네임스페이스와는 다른 개념
X 라는 것을 M으로 마운트하여 격리

X 아래에 파일을 생성하더라도 보이지 않고 격리 되게 됨

두 개를 결합하여 호스트에 영향 없이 탈옥이 불가능하게 프로세스 격리
새로운 네임스페이스를 만들고 나서 프로그램을 실행 하는 명령어
# unshare --mount /usr/bin/sh

1은 unshare하여 마운트한 새로운 네임스페이스 2는 기존 터미널
mount unshare 시 부모 프로세스의 마운트 정보를 복사해서 자식 네임스페이스를 생성하기 때문에 처음에는 동일한 결과가 나옴
# mkdir new_root
# mount -t tmpfs none new_root
# ls -l
# ls -l
total 28
-rw-r--r-- 1 root root 187 Aug 31 19:55 escape_chroot.c
drwxr-xr-x 8 root root 4096 Aug 31 19:56 myroot
drwxrwxrwt 2 root root 40 Aug 31 21:06 new_root
drwxr-xr-x 18 root root 4096 Aug 31 19:45 nginx-root
drwx------ 3 root root 4096 Aug 31 18:41 snap-private-tmp
drwx------ 3 root root 4096 Aug 31 18:41 systemd-private-49c8ef62ce5a42de477-chrony.service-4D
drwx------ 3 root root 4096 Aug 31 18:41 systemd-private-49c8ef62ce5a42d2bd2b77-systemd-logind.service-8
drwx------ 3 root root 4096 Aug 31 18:41 systemd-private-49c8ef62ce5a42d2e477-systemd-resolved.service-59
# tree new_root
new_root
0 directories, 0 files
tmpfile system을 마운트
현재 아무것도 없는 상태

findmnt -A
└─/tmp/new_root none tmpfs rw,relatime,inode64
unshare에서는 mount 정보가 보이지만 원래 터미널에서는 보이지 않음
# cp -r myroot/* new_root
# tree new_root
new_root
├── bin
│ ├── ls
│ ├── mkdir
│ ├── mount
│ ├── ps
│ └── sh
├── escape_chroot
├── lib
---
root@MyServer:/tmp# tree new_root/
new_root/
0 directories, 0 files
차이가 나는 것을 다시 한 번 확인

기존에 알고 있던 / 파일 시스템을 바꾼다는 개념

사용법
# pivot_root <new_root> <put_old>

루트 파일 시스템이 바뀌었는지 보고

가장 중요한 ! 탈옥이 되는지 확인해보기
# mkdir new_root/put_old
cd new_root # pivot_root 는 실행 시, 변경될 root 파일시스템 경로로 진입
pivot_root . put_old # [신규 루트] [기존 루트]
# pivot_root . put_old
# cd /
# ls /
bin escape_chroot lib lib64 proc put_old usr
# ls put_old
bin dev home lib32 libx32 media opt root sbin srv tmp var
boot etc lib lib64 lost+found mnt proc run snap sys usr
root@MyServer:/tmp# ls /
bin dev home lib32 libx32 media opt root sbin srv tmp var
boot etc lib lib64 lost+found mnt proc run snap sys usr
/ 은 다르지만 put_old와는 기존 터미널과 같음을 확인
# ./escape_chroot
# ls /
bin escape_chroot lib lib64 proc put_old usr
# cd ../../../
# ls /
bin escape_chroot lib lib64 proc put_old usr
탈옥이 되지 않는 모습을 확인
-> chroot 와 다르게 아무리 위로 가도 탈옥이 되지 않는 모습
-> 도커나 컨테이너를 사용하는 시스템에서 사용

여러 이미지 레이어를 하나로 마운트 하여 이미지 중복 문제를 해결


1. tools 레이어 추가
2. upper dir 올리기
root@MyServer:/tmp# tree myroot/
myroot/
├── bin
│ ├── ls
│ ├── mkdir
│ ├── mount
│ ├── ps
│ └── sh
├── escape_chroot
위 실습에서 사용한 myroot를 LowerDir1로 사용
# mkdir tools
# which which
/usr/bin/which
root@MyServer:/tmp# ldd /usr/bin/which
not a dynamic executable
root@MyServer:/tmp# mkdir -p tools/usr/bin;
root@MyServer:/tmp# cp /usr/bin/which tools/usr/bin/;
which 명령어는 따로 의존성이 없음
# mkdir -p tools/{bin,lib64,lib/x86_64-linux-gnu};
root@MyServer:/tmp# cp /bin/rm tools/bin/
root@MyServer:/tmp# cp /lib/x86_64-linux-gnu/libc.so.6 tools/lib/x86_64-linux-gnu/
root@MyServer:/tmp# cp /lib64/ld-linux-x86-64.so.2 tools/lib64
이렇게 하면 myroot이미지와 tools 이미지가 준비과 된 것
mkdir -p rootfs/{container,work,merge}
root@MyServer:/tmp# tree rootfs
rootfs
├── container # upper 디렉토리
├── merge # 통합 뷰 - 밑에 있는 하위 레이어를 다 보는 뷰 (실제 오버레이 마운트 포인트)
└── work # 조회 시 보이지는 않지만, container디렉토리의 업데이트를 보장하기 위한 디렉토리
# mount -t overlay overlay -o
lowerdir=tools:myroot,upperdir=rootfs/container/,
workdir=rootfs/work/ rootfs/merge
위 명령어로 아래와 같은 구조로 만듬

root@MyServer:/tmp/rootfs# tree -L 2 .
.
├── container
├── merge
│ ├── bin
│ ├── escape_chroot
│ ├── lib
│ ├── lib64
│ ├── proc
│ └── usr
└── work
└── work
통합 뷰인 merge가 채워져있음
root@MyServer:/tmp# tree -L 2 myroot/{bin,usr}
myroot/bin
├── ls
├── mkdir
├── mount
├── ps
└── sh
myroot/usr
└── lib
└── x86_64-linux-gnu
2 directories, 0 files
---------------------------
root@MyServer:/tmp# tree -L 2 rootfs/merge/{bin,usr}
rootfs/merge/bin
├── ls
├── mkdir
├── mount
├── ps
├── rm
└── sh
rootfs/merge/usr
├── bin
│ └── which
└── lib
└── x86_64-linux-gnu
3 directories, 1 file
rootfs에는 rm이라는 파일과 which가 추가 된 것을 확인할 수 있음
-> 오버레이 마운트가 잘 된 것을 확인할 수 있음
# rm rootfs/merge/escape_chroot
root@MyServer:/tmp# ls /tmp/rootfs/merge/
bin lib lib64 proc usr
root@MyServer:/tmp# ls myroot
bin escape_chroot lib lib64 proc usr
merge에서는 지워졌지만 myroot 상에는 남아있음

container 디렉토리에는 노란색으로 표시된 파일이 생성 -> 화이트아웃 -> 삭제 마킹

escape_chroot를 삭제한 것은 LowerDir에서 삭제한 것이고 삭제 된 정보가 upper 디렉토리에 씌어지게 됨 -> myroot 변경 없이 upper 디렉토리만 변경 정보를 관리 해줌 -> 원본을 보장 할 수 있게 됨
남아 있는 문제
# unshare [option] [program]
option list
-m --mount
-u --uts
-i --ips
-p --pid
-n --net

Mount(파일시스템), Network(네트워크), PID(프로세스 id), User(계정), ipc(프로세스간 통신), Uts(Unix time sharing, 호스트네임), cgroup
위 그림 처럼 다 합쳐서 쓰는게 아니라 NET는 따로 호스트의 것을 사용할 수 있다는 뜻

컨테이너 안에서 다르게 보이는 이유는 -> 네임스페이스 !
다른 PID 네임스페이스이기 때문에 다른 프로세스로 보임
모든 프로세스는 7개의 네임스페이스를 가짐
터미널 2개 모두 관리자 권한으로 진행
# ls -al /proc/$$/ns
total 0
dr-x--x--x 2 root root 0 Aug 31 22:03 .
dr-xr-xr-x 9 root root 0 Aug 31 19:50 ..
lrwxrwxrwx 1 root root 0 Aug 31 22:03 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 mnt -> 'mnt:[4026531841]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 net -> 'net:[4026531840]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 time -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Aug 31 22:03 uts -> 'uts:[4026531838]'
네임스페이스 별로 어떤 inode에 속하는지 알 수 있음
root@MyServer:/tmp# readlink /proc/$$/ns/mnt
mnt:[4026531841]
root@MyServer:/tmp# readlink /proc/$$/net
root@MyServer:/tmp# lsns -p 1
NS TYPE NPROCS PID USER COMMAND
4026531834 time 108 1 root /sbin/init
4026531835 cgroup 108 1 root /sbin/init
4026531836 pid 108 1 root /sbin/init
4026531837 user 108 1 root /sbin/init
4026531838 uts 104 1 root /sbin/init
4026531839 ipc 108 1 root /sbin/init
4026531840 net 108 1 root /sbin/init
4026531841 mnt 101 1 root /sbin/init
root@MyServer:/tmp# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026531834 time 108 1 root /sbin/init
4026531835 cgroup 108 1 root /sbin/init
4026531836 pid 108 1 root /sbin/init
4026531837 user 108 1 root /sbin/init
4026531838 uts 104 1 root /sbin/init
4026531839 ipc 108 1 root /sbin/init
4026531840 net 108 1 root /sbin/init
4026531841 mnt 101 1 root /sbin/init
-t 네임스페이스 타입, -p 조회할 PID
NPROCS : 해당 네임스페이스에 속해있는 프로세스 갯수
PID : 해당 네임스페이스의 (최초) 주인 프로세스
root@MyServer:/tmp# lsns -t mnt -p 1 # 프로세스 1번의 ns 정보가 나옴
NS TYPE NPROCS PID USER COMMAND
4026531841 mnt 101 1 root /sbin/init
root@MyServer:/tmp# lsns -t mnt -p $$ # 현재프로세스($$) 셸이 사용하고 있는
NS TYPE NPROCS PID USER COMMAND
4026531841 mnt 101 1 root /sbin/init
실제로 더 많이 사용하는 명령어 - 시스템 네임스페이스를 보는 명령어
4026531841를 바탕으로 프로세스 1번과 현재 셸이 사용하는 프로세스의 마운트 네임스페이스가 똑같다 -> 호스트 네임스페이스를 같이 사용 -> 동일한 호스트 네임스페이스 공간에 있다
Mount (mnt) Namespace : 2002년 마운트 포인트 격리, 최초의 네임스페이스
root@MyServer:/tmp# lsns -t mnt -p 1
NS TYPE NPROCS PID USER COMMAND
4026531841 mnt 101 1 root /sbin/init
root@MyServer:/tmp# lsns -t mnt -p $$
NS TYPE NPROCS PID USER COMMAND
4026531841 mnt 101 1 root /sbin/init
현재 mnt 동일하게 실행
-m 옵션을 주면 [명령어]를 mount namespace 를 isolation 하여 실행
명령어를 지정하지 않으면 환경변수 $$Shell 실행 됨
root@MyServer:/tmp# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026531834 time 109 1 root /sbin/init
4026531835 cgroup 109 1 root /sbin/init
4026531836 pid 109 1 root /sbin/init
4026531837 user 109 1 root /sbin/init
4026531838 uts 105 1 root /sbin/init
4026531839 ipc 109 1 root /sbin/init
4026531840 net 109 1 root /sbin/init
**4026532234 mnt 2 2996 root -bash** -> mnt가 바뀜
root@MyServer:/tmp# lsns -p 1
NS TYPE NPROCS PID USER COMMAND
4026531834 time 109 1 root /sbin/init
4026531835 cgroup 109 1 root /sbin/init
4026531836 pid 109 1 root /sbin/init
4026531837 user 109 1 root /sbin/init
4026531838 uts 105 1 root /sbin/init
4026531839 ipc 109 1 root /sbin/init
4026531840 net 109 1 root /sbin/init
4026531841 mnt 101 1 root /sbin/init
inode가 다른 것으로 보아 mnt가 다르게 실행된 것을 확인 -> mnt ns가 격리 된 것
격리 되서 PID가 2996으로 다름
# exit
logout
root@MyServer:~# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026531834 time 110 1 root /sbin/init
4026531835 cgroup 110 1 root /sbin/init
4026531836 pid 110 1 root /sbin/init
4026531837 user 110 1 root /sbin/init
4026531838 uts 106 1 root /sbin/init
4026531839 ipc 110 1 root /sbin/init
4026531840 net 110 1 root /sbin/init
4026531841 mnt 102 1 root /sbin/init
root@MyServer:~# lsns -p $$^C
root@MyServer:~# lsns -p 1
NS TYPE NPROCS PID USER COMMAND
4026531834 time 110 1 root /sbin/init
4026531835 cgroup 110 1 root /sbin/init
4026531836 pid 110 1 root /sbin/init
4026531837 user 110 1 root /sbin/init
4026531838 uts 106 1 root /sbin/init
4026531839 ipc 110 1 root /sbin/init
4026531840 net 110 1 root /sbin/init
4026531841 mnt 102 1 root /sbin/init
빠져 나오게 되면 원래 처럼 같은 indoe의 mnt 확인 가능
호스트 경로를 직접 마운트 시 주의사항 : 예를 들어 호스트 최상위 루트 디렉토리 (/) 마운트 시 보안상 어떤 문제가 있을지
(추가)
2006년, Unix Time Sharing (여러 사용자 작업 환경 제공하고자 서버 시분할 나눠쓰기), 호스트명, 도메인명 격리
서버 한 대가 비싸니까 여러명이 사용하기 위해 만들어짐 (호스트네임도 바꿔서 다르게 ~)
-u 옵션을 주면 [명령어]를 UTS namespace 를 isolation 하여 실행
root@MyServer:/tmp# unshare -u
root@MyServer:/tmp# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026531834 time 111 1 root /sbin/init
4026531835 cgroup 111 1 root /sbin/init
4026531836 pid 111 1 root /sbin/init
4026531837 user 111 1 root /sbin/init
4026531839 ipc 111 1 root /sbin/init
4026531840 net 111 1 root /sbin/init
4026531841 mnt 103 1 root /sbin/init
4026532235 uts 2 3036 root -bash
root@MyServer:/tmp# lsns -p 1
NS TYPE NPROCS PID USER COMMAND
4026531834 time 111 1 root /sbin/init
4026531835 cgroup 111 1 root /sbin/init
4026531836 pid 111 1 root /sbin/init
4026531837 user 111 1 root /sbin/init
4026531838 uts 105 1 root /sbin/init
4026531839 ipc 111 1 root /sbin/init
4026531840 net 111 1 root /sbin/init
4026531841 mnt 103 1 root /sbin/init
root@MyServer:/tmp# hostname
MyServer
터미널 1
root@MyServer:/tmp# hostname KEN
root@MyServer:/tmp# hostname
KEN
터미널 2
root@MyServer:/tmp# hostname
MyServer
터미널 1과 터미널2 의 uts가 격리되었기 때문에 다르게 보이는 것
2006년, Inter-Process Communication 격리, 프로세스 간 통신 자원 분리 관리 - Shared Memory, Pipe, Message Queue 등
프로세스 간 통신자원에 대한 물리 격리
root@MyServer:/tmp# unshare -i
root@MyServer:/tmp# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026531834 time 109 1 root /sbin/init
4026531835 cgroup 109 1 root /sbin/init
4026531836 pid 109 1 root /sbin/init
4026531837 user 109 1 root /sbin/init
4026531838 uts 105 1 root /sbin/init
4026531840 net 109 1 root /sbin/init
4026531841 mnt 102 1 root /sbin/init
4026532234 ipc 2 3056 root -bash
root@MyServer:/tmp# lsns -p 1
NS TYPE NPROCS PID USER COMMAND
4026531834 time 109 1 root /sbin/init
4026531835 cgroup 109 1 root /sbin/init
4026531836 pid 109 1 root /sbin/init
4026531837 user 109 1 root /sbin/init
4026531838 uts 105 1 root /sbin/init
4026531839 ipc 107 1 root /sbin/init
4026531840 net 109 1 root /sbin/init
4026531841 mnt 102 1 root /sbin/init
shared memory 정보 확인
root@MyServer:/tmp# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
root@MyServer:/tmp# docker run --rm --name test1 --ipc=shareable -it ubuntu bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
31e907dcc94a: Pull complete
Digest: sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab63ee
Status: Downloaded newer image for ubuntu:latest
root@ffa52d23a07a:/# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
root@ffa52d23a07a:/# ipcmk -M 2000
Shared memory id: 0
root@ffa52d23a07a:/# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0xe1180fdd 0 root 644 2000 0
root@ffa52d23a07a:/# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026531834 time 2 1 root bash
4026531837 user 2 1 root bash
4026532236 mnt 2 1 root bash
4026532237 uts 2 1 root bash
4026532238 ipc 2 1 root bash
4026532239 pid 2 1 root bash
4026532240 net 2 1 root bash
4026532298 cgroup 2 1 root bash
root@MyServer:/tmp# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026531834 time 116 1 root /sbin/init
4026531835 cgroup 115 1 root /sbin/init
4026531836 pid 115 1 root /sbin/init
4026531837 user 116 1 root /sbin/init
4026531838 uts 111 1 root /sbin/init
4026531839 ipc 115 1 root /sbin/init
4026531840 net 115 1 root /sbin/init
4026531841 mnt 108 1 root /sbin/init
ipc inode 가 다른 것을 확인
docker run --rm --name test2 --ipc=container:test1 -it ubuntu bash


ipc가 같은 것을 볼 수 있음
파드 안에 여러개 컨테이너 뜰 때 ipc 공유 가능
2008년, Process ID 격리

init 프로세스 (커널이 생성 ) 매우 중요
시그널 처리
좀비, 고아 프로세스 처리
죽으면 시스템 패닉(reboot)
root@MyServer:/tmp# ps -ef | head -n 3
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 18:41 ? 00:00:05 /sbin/init
root 2 0 0 18:41 ? 00:00:00 [kthreadd]
커널이 최초 실행되는 init 확인 가능
컨테이너에서 이 프로세스 죽으면 pid 네임스페이스도 죽음
컨테이너 실행하자마자 죽는이유 : fork 된 프로스세가 죽어서
-p 옵션을 주면 [명령어]를 PID namespace 를 isolation 하여 실행합니다
-f(fork) : PID namespace 는 child 를 fork 하여 새로운 네임스페이스로 격리함
--mount-proc : namespace 안에서 ps 명령어를 사용하려면 /proc 를 mount 하기위함
unshare -fp --mount-proc /bin/sh
root@MyServer:/tmp# echo $$
3019
root@MyServer:/tmp# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 1.3 101892 12772 ? Ss 18:41 0:05 /sbin/init
root 2 0.0 0.0 0 0 ? S 18:41 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< 18:41 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< 18:41 0:00 [rcu_par_gp]
root 5 0.0 0.0 0 0 ? I< 18:41 0:00 [slub_flushwq]
root 6 0.0 0.0 0 0 ?
....
-----
# echo $$
1
# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 22:43 pts/3 00:00:00 /bin/sh
root 2 1 0 22:44 pts/3 00:00:00 ps -ef
# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 2892 1664 pts/3 S 22:43 0:00 /bin/sh
root 3 0.0 0.3 10464 3200 pts/3 R+ 22:44 0:00 ps aux
아래 터미널2에서 lsns -t pid -p <위 출력된 PID>와 비교
# lsns -t pid -p 1
NS TYPE NPROCS PID USER COMMAND
4026532235 pid 2 1 root /bin/sh
root@MyServer:/tmp# ps aux | grep '/bin/sh'
root 3457 0.0 0.1 6192 1792 pts/3 S 22:43 0:00 unshare -fp --mount-proc /bin/sh
root 3458 0.0 0.1 2892 1664 pts/3 S+ 22:43 0:00 /bin/sh
root 3465 0.0 0.2 7008 2304 pts/1 S+ 22:46 0:00 grep --color=auto /bin/sh
root@MyServer:/tmp# lsns -p 3458
NS TYPE NPROCS PID USER COMMAND
4026531834 time 110 1 root /sbin/init
4026531835 cgroup 110 1 root /sbin/init
4026531837 user 110 1 root /sbin/init
4026531838 uts 106 1 root /sbin/init
4026531839 ipc 110 1 root /sbin/init
4026531840 net 110 1 root /sbin/init
4026532234 mnt 2 3457 root unshare -fp --mount-proc /bin/sh
4026532235 pid 1 3458 root /bin/sh
호스트에서 볼때와 내부에서 볼때 pid가 다른 것을 볼 수 있음
호스트에서 자식 프로세스를 볼 수 있음
4026532235로 pid inode가 같은것을 확인 가능
# fork
# sleep 10000
root@MyServer:/tmp# ps aux | grep sleep
root 3477 0.0 0.1 6192 1920 pts/3 S+ 22:52 0:00 sleep 10000
root 3480 0.0 0.2 7008 2304 pts/1 S+ 22:52 0:00 grep --color=auto sleep
root@MyServer:/tmp# kill -SIGKILL $(pgrep sleep)
# sleep 10000
Killed
sleep 프로세스가 죽은 것을 확인 가능
/bin/sh를 죽인다면 ?root@MyServer:/tmp# kill -SIGKILL $(pgrep sleep)
root@MyServer:/tmp# ps aux | grep '/bin/sh'
root 3468 0.0 0.1 6192 1792 pts/3 S 22:48 0:00 unshare -fp --mount-proc /bin/sh
root 3469 0.0 0.1 2892 1664 pts/3 S+ 22:48 0:00 /bin/sh
root 3483 0.0 0.2 7008 2304 pts/1 S+ 22:53 0:00 grep --color=auto /bin/sh
root@MyServer:/tmp# kill -SIGKILL 3469
# Killed
프로세스가 종료되는 것을 볼 수 있음
https://docs.docker.com/engine/containers/run/#exit-status
https://blog.naver.com/alice_k106/221310477844
https://komodor.com/learn/exit-codes-in-containers-and-kubernetes-the-complete-guide/
https://squarelab.co/blog/argo-exit-status-143/
컨테이너에서는 uid=0으로 보여도 실제로 호스트에서는 uid=1000
패키지 설치가 쉬움
시스템 리소스 이용에 제약이 없다... 하지만 보안에 취약
ubuntu@MyServer:~$ docker run -it ubuntu /bin/sh
# whoami
root
# id
uid=0(root) gid=0(root) groups=0(root)
컨테이너 내부에서는 루트로 보임
ubuntu@MyServer:~$ id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),2
5(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),119(netdev),120(lxd),999(docker)
ubuntu@MyServer:~$ ps -ef | grep "/bin/sh"
root 3554 3526 0 23:00 pts/0 00:00:00 /bin/sh
외부에서 볼 때도 root인 상태
# readlink /proc/$$/ns/user
user:[4026531837]
ubuntu@MyServer:~$ readlink /proc/$$/ns/user
user:[4026531837]
ubuntu유저와 user가 같음 -> 호스트에 영향이 미치면 root로 실행 가능한 위험한 상태
컨테이너를 탈취 후, 해당 프로세스를 기반으로 호스트에 Action 이 가능할 경우, root 계정 권한 실행이 가능 ⇒ 보안상 취약
unshare -U --map-root-user /bin/sh
# whoami
root
# id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)
# readlink /proc/$$/ns/user
user:[4026532234]
---
ubuntu@MyServer:~$ readlink /proc/$$/ns/user
user:[4026531837]
터미널 1과 터미널2의 user inode 다른것을 확인
ubuntu@MyServer:~$ ps -ef |grep "/bin/sh"
ubuntu 3631 771 0 23:06 pts/0 00:00:00 /bin/sh
ubuntu 3637 2620 0 23:07 pts/2 00:00:00 grep --color=auto /bin/sh
우분투 계정으로 실행된 것을 확인
https://docs.docker.com/engine/security/userns-remap/
https://kubernetes.io/ko/docs/concepts/workloads/pods/user-namespaces/
https://kubernetes.io/ko/docs/tasks/configure-pod-container/user-namespaces/
https://docs.docker.com/engine/security/userns-remap/
ubuntu@MyServer:~$ id ubuntu
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu)
ubuntu@MyServer:~$ cat /etc/subuid
ubuntu:100000:65536
ubuntu@MyServer:~$ cat /etc/subgid
ubuntu:100000:65536
dockerd --userns-remap="ubuntu":ubuntu"
{
"userns-remap": "ubuntu"
}
systemctl restart docker
root@MyServer:/var/lib/docker# ll
total 56
drwx--x--- 13 root 100000 4096 Aug 31 23:22 ./
drwxr-xr-x 42 root root 4096 Aug 31 18:55 ../
drwx--x--- 12 root 100000 4096 Aug 31 23:22 100000.100000/
# docker run -it ubuntu bash
root@MyServer:/var/lib# readlink /proc/$$/ns/user
user:[4026531837]
---
root@bfb10d99609b:/# readlink /proc/$$/ns/user
user:[4026532235]
100000 4602 4581 0 23:26 pts/0 00:00:00 bash
user inode가 다르고 ps -ef 시 root가 아닌 유저로 실행 되는 것을 확인 할 수 있음
이렇게 설정하게 되면 앞으로 실행되는 모든 컨테이너에 기본으로 적용되게 됨
해제 하고 싶다면 --userns=host 명령어를 컨테이너 실행할 때 사용하면 됨 -> 이 경우 PID와 NET 네임스페이스를 공유하게 됨
--privileged 옵션을 컨테이너 실행 시 사용하면 --userns=host와 같은 효과
쿠버네티스에서
https://kubernetes.io/ko/docs/concepts/workloads/pods/user-namespaces/
https://kubernetes.io/ko/docs/tasks/configure-pod-container/user-namespaces/
시간을 격리시킴으로써 자신만의 time offeset을 사용할 수 있게 됨
이를 통해 프로세스가 Host와 다른 날짜와 시간을 갖게 됨
# unshare -T --boottime 100000000
root@MyServer:~# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026532233 time 2 5368 root -bash
root@MyServer:~# lsns -p $$
NS TYPE NPROCS PID USER COMMAND
4026531834 time 108 1 root /sbin/init
시간 네임스페이스 격리
root@MyServer:~# date -s "28 OCT 2015 18:32:40"
Mon Oct 28 18:32:40 KST 2013
---
root@MyServer:~# date
Mon Oct 28 18:36:17 KST 2013
---
root@MyServer:~# date
Mon Oct 28 18:36:19 KST 2013
격리된 공간하고 다를 줄 알았는데 똑같다..
offset을 바꾸는거라 timezone이나 NTP만 바꾸는듯..
https://m.blog.naver.com/love_tolty/222674500739root@MyServer:~# export TZ="America/New_York" root@MyServer:~# date Mon Oct 28 05:46:01 EDT 2013 ----- root@MyServer:~# date Mon Oct 28 04:46:04 CDT 2013
프로세스는 /proc/self/cgroup에 가상화된 새로운 cgroup 마운트를 가지게 됨
unshare -C
---
root@MyServer:~# lsns -p $$ -t cgroup
NS TYPE NPROCS PID USER COMMAND
4026531835 cgroup 111 1 root /sbin/init
---
root@MyServer:~# lsns -p $$ -t cgroup
NS TYPE NPROCS PID USER COMMAND
4026532233 cgroup 2 6052 root -bash
echo 10 > cpu.max
-bash: echo: write error: Invalid argument
cgroup이란? : Cpu, Disk I/O, Memory, Network 등 자원 사용을 제한/격리 시키는 커널 기능
cgroups인가? cgroup 인가?

컨테이너 별로 자원을 분배하고 limit 내에서 운용

하나 또는 복수의 장치를 묶어서 그룹
프로세스가 사용하는 리소스 통제

자원 할당과 제어를 파일시스템으로 제공
cgroup 네임스페이스로 격리가 가능
ubuntu@MyServer:~$ mount -t cgroup
ubuntu@MyServer:~$ mount -t cgroup2
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
ubuntu@MyServer:~$ findmnt -t cgroup2
TARGET SOURCE FSTYPE OPTIONS
/sys/fs/cgroup cgroup2 cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot
# cgroup2 이외에 proc, bpf 도 있음
findmnt -A
TARGET SOURCE FSTYPE OPTIONS
/ /dev/nvme0n1p1 ext4 rw,relatime,discard,errors=remount-ro
...
├─/proc proc proc rw,nosuid,nodev,noexec,relatime
...
├─/sys sysfs sysfs rw,nosuid,nodev,noexec,relatime
│ ├─/sys/kernel/security securityfs securityfs rw,nosuid,nodev,noexec,relatime
│ ├─/sys/fs/cgroup cgroup2 cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot
│ ├─/sys/fs/pstore pstore pstore rw,nosuid,nodev,noexec,relatime
│ ├─/sys/firmware/efi/efivars efivarfs efivarfs rw,nosuid,nodev,noexec,relatime
│ ├─/sys/fs/bpf bpf bpf rw,nosuid,nodev,noexec,relatime,mode=700
# stat -fc %T /sys/fs/cgroup/
cgroup2fs
현재는 cgroup2 가 동작하고 있음
cgroupv1만 지원 시, cgroup2 출력되지 않음
ubuntu@MyServer:~$ grep cgroup /proc/filesystems
nodev cgroup
nodev cgroup2
ubuntu@MyServer:~$ sleep 100000
----
ubuntu@MyServer:~$ cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 0 72 1
cpu 0 72 1
cpuacct 0 72 1
blkio 0 72 1
memory 0 72 1
devices 0 72 1
freezer 0 72 1
net_cls 0 72 1
perf_event 0 72 1
net_prio 0 72 1
hugetlb 0 72 1
pids 0 72 1
rdma 0 72 1
misc 0 72 1
$ cat /proc/$(pgrep sleep)/cgroup # sleep이 실행되고 있는 프로세스 id의 디렉토리
0::/user.slice/user-1000.slice/session-11.scope
tree /proc/$(pgrep sleep) -L 2 # sleep 실행한 프로세스의 정보를 확인 가능
├── ns
│ ├── cgroup -> cgroup:[4026531835]
│ ├── ipc -> ipc:[4026531839]
│ ├── mnt -> mnt:[4026531841]
│ ├── net -> net:[4026531840]
│ ├── pid -> pid:[4026531836]
│ ├── pid_for_children -> pid:[4026531836]
│ ├── time -> time:[4026531834]
│ ├── time_for_children -> time:[4026531834]
│ ├── user -> user:[4026531837]
│ └── uts -> uts:[4026531838]
$ ls /sys/fs/cgroup
cgroup.controllers cgroup.threads init.scope memory.pressure sys-kernel-config.mount
cgroup.max.depth cpu.pressure io.cost.model memory.reclaim sys-kernel-debug.mount
cgroup.max.descendants cpu.stat io.cost.qos memory.stat sys-kernel-tracing.mount
cgroup.pressure cpuset.cpus.effective io.pressure misc.capacity system.slice
cgroup.procs cpuset.mems.effective io.prio.class misc.current user.slice
cgroup.stat dev-hugepages.mount io.stat proc-sys-fs-binfmt_misc.mount
cgroup.subtree_control dev-mqueue.mount memory.numa_stat sys-fs-fuse-connections.mount
cat /sys/fs/cgroup/cgroup.controllers # 제공 가능한 컨트롤러 (제어가능한 리소스 목록)
cpuset cpu io memory hugetlb pids rdma misc
cgroup의 최상위 디렉토리
tree /sys/fs/cgroup/ -L 1
└── user.slice
tree /sys/fs/cgroup/ -L 2
└── user-1000.slice
tree /sys/fs/cgroup/user.slice -L 1
user-1000.slice
tree /sys/fs/cgroup/user.slice/user-1000.slice -L 1
└── user@1000.service
tree /sys/fs/cgroup/user.slice/user-1000.slice -L 2
── user@1000.service
├── app.slice
├── cgroup.controllers
├── cgroup.events
├── cgroup.freeze
├── cgroup.kill
├── cgroup.max.depth
├── cgroup.max.descendants
├── cgroup.pressure
├── cgroup.procs
현재 세션에서 점유하고 있는 정보도 확인할 수 있음
apt install cgroup-tools stress -y
stress -c 1

htop 으로 자원 사용률 확인
프로세스 1개만 큼 사용하고 있음
root@MyServer:~# cd /sys/fs/cgroup/
root@MyServer:/sys/fs/cgroup# mkdir test_cgroup_parent && cd test_cgroup_parent
root@MyServer:/sys/fs/cgroup/test_cgroup_parent# tree
.
├── cgroup.controllers
├── cgroup.events
├── cgroup.freeze
├── cgroup.kill
├── cgroup.max.depth
├── cgroup.max.descendants
├── cgroup.pressure
root@MyServer:/sys/fs/cgroup/test_cgroup_parent# cat cgroup.controllers
cpuset cpu io memory hugetlb pids rdma misc
# 제어 가능목록 확인
root@MyServer:/sys/fs/cgroup/test_cgroup_parent# cat cgroup.subtree_control
root@MyServer:/sys/fs/cgroup/test_cgroup_parent# echo "+cpu" >> /sys/fs/cgroup/test_cgroup_parent/cgroup.subtree_control
root@MyServer:/sys/fs/cgroup/test_cgroup_parent# cat cgroup.subtree_control
cpu
echo 100000 1000000 > /sys/fs/cgroup/test_cgroup_parent/cpu.max
root@MyServer:/sys/fs/cgroup/test_cgroup_parent# mkdir test_cgroup_child && cd test_cgroup_child
root@MyServer:/sys/fs/cgroup/test_cgroup_parent/test_cgroup_child# echo $$ > /sys/fs/cgroup/test_cgroup_parent/test_cgroup_child/cgroup.procs
root@MyServer:/sys/fs/cgroup/test_cgroup_parent/test_cgroup_child# cat /sys/fs/cgroup/test_cgroup_parent/test_cgroup_child/cgroup.procs
5055
5254
root@MyServer:/sys/fs/cgroup/test_cgroup_parent/test_cgroup_child# cat /proc/$$/cgroup
0::/test_cgroup_parent/test_cgroup_child
stress -c 1

cpu 사용량이 10프로로 제한 된 것을 확인
echo 1000000 1000000 > /sys/fs/cgroup/test_cgroup_parent/cpu.max # 나누면 1

다시 cpu 전부를 사용하는 모습 확인
exit
sudo su -
rmdir /sys/fs/cgroup/test_cgroup_parent/test_cgroup_child
rmdir /sys/fs/cgroup/test_cgroup_parent
cgoup v1 경우
# 아래는 cgroup v1 경우 --------------------------- ## 1. 제어그룹 생성 : mycgroup ### -a : owner 설정 (control group's file) ### -g : cgroup 설정 <controllers>:<path> ### -g cpu:mycgroup ~ cpu controller 를 사용하고 path 는 mycgroup cgcreate -a root -g cpu:mycgroup tree /sys/fs/cgroup/cpu/mycgroup ## 2. 제어그룹 리소스 설정 : CPU 사용률 설정 ### cpu 사용률(%CPU) ### cpu.cfs_quota_us / cat cpu.cfs_period_us * 100 ### 참고 1000us = 1ms ### cpu사용률(30%)을 설정 (30,000/100,000)x100=30% cgset -r cpu.cfs_quota_us=30000 mycgroup cat /sys/fs/cgroup/cpu/mycgroup/cpu.cfs_quota_us ## 3. 제어그룹 프로세스 할당 : stress 실행 cgexec -g cpu:mycgroup stress -c 1
root@MyServer:~# echo "+memory" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
+memory
root@MyServer:~# echo "+io" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
+io
root@MyServer:/sys/fs/cgroup/test_cgroup_parent# echo "500M" > memory.max

echo "252:0 wbps=10485760" > /sys/fs/cgroup/parent/io.max
echo $$ > /sys/fs/cgroup/parent/child/cgroup.procs