Cloud/Docker

이게 돼요? 도커 없이 컨테이너 만들기 / if(kakao)2022

Tony Lim 2023. 1. 31. 12:49

 흥미 유발

container 기반으로 올린 busybox의 root file system 은 overlay이다.

process가 다르다. container는 2개이고 local은 여러개이다. ip link , hostname도 다 다르고 , id를 쳤을때 container도 local 도 root 이 나오는데 이둘은 과연 같은 root일까?


container file system

프로세스를 가두고 , 탈옥을 막고 , 중복을 해결하자

chroot를 기반으로 process가 Fake root 밖으로 나가지 못하게 한다.

필요한 것들을 fake root 안으로 복사해야 한다.

docker export $(docker crete nginx) | tar -C nginx-root -xvf -

이번엔 남들이 만들어놓은 이미지를 가져와서 chroot 해보자

일일이 옴기는 과정없이  뭔가 많은 파일들이 옮겨져있다.

여기서 nginx -g "daemon off;" 명령어로 실행할 수 있다. 뭔가 chroot만으로 충분히 컨테이너를 구현가능할 것 같다.

chroot 로 만든 격리된 파일에서 해당 프로그램을 실행하면 local의 root directory까지 접근이 가능해진다.

이것을 탈옥이 가능하다 부른다.


탈옥을 막아보자

pivot_root

왼쪽의 빨간 영역의 root file system(container)을 root로 pivoting한다.그리고 기존의 root file system이 put_old 밑에 붙게된다.

이제 탈옥도 불가능하다. 진짜로 root file system을 바뀐것이기 때문에 더이상 fake root가 아니므로

mount namespace 격리를 하고 pivot root 를 통해 host에 영향이 가지 않고 잘 격리된 프로세스를 만들었다.


중복을 해결하자  = 오버레이 파일 시스템

container mount 되게 되면 Merged View 가 되면서 모든 레이어의 내용이 다 보이게 된다.

lower directory에 필요한 binary들을 lib와 함께 복붙하고 위 명령어를 통해 merged view를 생성하였다.

local에는 rm , which 가 없다. 위 에는 (아직 컨테이너는 아지니만) tools layer에 복붙해놓은 rm , which 가 들어있는것을 확인할 수 있다.

rootfs의 merge 디렉토리에있는 escape_chroot를 지워본다. 해당 파일은 원래 local의 Lower Dir1에 있는 내용이다. 하지만 로컬에서 확인 해보면 그대로 있는 것을 알 수 있다.

또한 원래 Upper Dir였던 container directory가 비어있었는데 노란색으로 지웠던 파일이 나타난것을 확인할 수있다.

최상위 merged view에서 escape_chroot가 지워졌다는것을 반영한것이다. 일종의 marking이라 볼 수 있을 것 같다.
이것을 white out 이라 한다.
이로써 기존 base layer는 영향을 받지 않는것을 알 수 있다.


컨테이너 격리와 자원

네임스페이스 특징

1. 모든 프로세스는 타입별로 네임스페이스에 속함
2. 자식 프로세스는 부모의 네임스페이스를 상속함,

 

mount = 최초의 namespace

uts = 호스트명 , 도메인명 격리 , Unix Time Sharing

ipc = Inter Process Communication 격리 , 

pid = Process Id를 격리, 부모-자식 네임스페이스 중첩 구조 

부모 namespace에서 자식 process들이 다 보인다. 자식 namespace에서는 부모의 pid도 가지고 있다. 

pid 1은 init프로세스로 커널이 생성하게된다. 해당 프로세스가 죽게되면 system panic이 오게되고 reboot를 해줘야한다.

커널에서 보내는 시그널들을 전파하고 처리한다.

자식 프로세스 중에서 고아,좀비 프로세스들을 거둬들인다. 

unshare 할때 할때 fork 해서 command를 실행하는 forked process를  pid 1번으로 만든다. 죽으면 container가 종료됨

시그널처리 + 좀비,고아 프로세스 거둬드림 (구현해야함)

pid namespace 를 실행했을때 ps -ef 를 실행하면 container 와 local에서 차이가 있음을 확인한다.

unshare의 명령어의 forked 된 자식프로세스로 /bin/sh가있음을 확인 , PPID로 확인

같은 pid namespace를 가지는것을 알 수 있다. 같은 process인것을 알 수있다. local의 해당 pid로 kill 명령어를 내리면 종료된다. 또한 container 상에서 1번 process이기에 종료되면 container도 종료된다.

 

네트워크 네임스페이스 = 가상 NIC를 부여함, 네트워크 격리

ip link add veth0 type veth peer name veth1

명령어를 통해 veth0 와 veth1를 생성하고 그 둘을 연결해준다.
The "veth0" and "veth1" interfaces are connected together, allowing data to be transmitted between them as if they were directly connected with a physical Ethernet cable. This is useful for network namespace setup and container networking in Linux.

ip netns add Red를 통해 network namespace를 추가한다. 마찬가지로 Blue도 추가해준다.

ip link set veth0 netns RED 를 통해 veth0 를 RED에 넣어준다.

ip netns exec RED ip link set veth0 up = sets the "veth0" virtual Ethernet interface to be up and running in a network namespace named "RED"

ip netns exec RED ip addr add 11.11.11.2/24 dev veth0 = ip address 부여

nsenter --net=/var/run/netns/RED  -> RED로 진입

RED에는 위에서 넣어줬던 veth0 밖에 안보이는것을 확인

격리된 network namespace RED 에서 BLUE로 ping을 통해 연결됨을 확인

 

User namespace

uid , gid numberspace 격리 , 컨테이너의 루트 권한 문제를 해결함

일반계정(vagrant) 에서 실행한 docekr는 root 인것을 확인 -> 이것이 실제 root인지 알아보자

일반 계정에서 실행했음에도 불구하고 root인것을 알 수 있다.

usernamespace가 같다. host의 userid , groupid와 container의 userid ,groupid가 같음을 의미한다.
컨테이너의 root가 host의 root와 같은 계정임을 확인할 수 있다.

일반 계정이 docker를 다룰수있을때 위험한것을 알 수 있다.

이번에는 usernamespace 생성해서 격리해보자

unshare -U --map-root-user /bin/sh -> usernamespace를 생성하고 /bin/sh 실행

container 내부에서만 root로 보인다. id 명령어를 치면

/bin/sh 가 vagrant로 실행되고 root로 실행되지 않았음을 확인

docker는 usernamespace를 기본설정으로 제공하고 있지 않다.


컨테이너 자원

Cgroup

group을 여러개만들고 process는 특정 group에서 속하게 된다. 해당 프로세스는 group에 적혀진 자원의 할당량 만큼 사용할 수 있다.

cgcreate를 통해 mycgroup을 만들면 위 사진 directory에 kernel 다 내용물들을 채워준다. cgroup 도 file로 관리됨을 알 수가 있다.

해당 group에 stress process 를 실행시키니 cgroup에 적힌 정보대로 cpu 사용률이 30을 안넘는것을 확인할 수 있다.


도커없이 컨테이너 만들기

https://www.youtube.com/watch?v=mSD88FuST80&t=6063s&ab_channel=kakaotech