[docker] namespace로 알아본 container - 2

김성훈·2023년 3월 1일
0

docker

목록 보기
2/2
post-thumbnail

저번 포스팅에 이어서 docker가 실제로 돌아가는 모습을 엿보러 가보자
docker에 대한 로그를 남기기 위해 터미널에서 다음과 같은 명령어를 사용해보자

strace -f -p $(pidof container) -o docker_log.txt


그럼 위처럼 containerd 프로세스를 추적하게 되고

docker run -it --name debian debain:buster

위의 명령어로 docker 컨테이너를 새로 생성해서 실행시켜보자
그럼 attached 됐다는 메세지와 함께
docker_log.txt 파일에 로그가 남겨지게 되고
로그파일에서 syscall을 추적할 수 있다
log에서는 앞서 공부했던 내용처럼 execve 명령어로
runc 를 실행하는 모습을 볼 수 있고 runc가 실행된 후 로그들을 따라가보면

unshare systemcall을 호출하는데 unshare을 호출하는 바로 윗줄을 주목해보자

prctl(PR_SET_NAME, "runc:[1:CHILD]") = 0

https://man7.org/linux/man-pages/man2/prctl.2.html - prctl
prctl은 process 와 thread를 조작하는 명령어이며 PR_SET_NAME 옵션은 호출 thread의 이름을 지정하는 옵션이다.하지만 thread를 따로 생성해주지는 않아서 혹여 thread를 미리 생성해주는지 찾아봤는데 없었다.

https://stackoverflow.com/questions/30453048/using-prctl-pr-set-name-to-set-name-for-process-or-thread
찾아보니 PR_SET_NAME 옵션이 프로세스의 이름도 바꿀수 있고, 프로세스 상에서 쓰이면 프로세스의 이름이 바뀌고 소속된 thread도 영향을 받고 특정 thread에서 호출하면 그 thread의 이름만 바뀐다고 한다. 실제로 그렇게 동작하는지는 검증해봐야 알 것 같다.

여튼 여기서는 linux 메뉴얼대로 작동하고 있다고 보고 runc:[1:CHILD] 라는 이름의 runc의 하위 thread의 이름이 변경되었다고 생각하자.

https://man7.org/linux/man-pages/man2/unshare.2.html - unshare
이 thread가 unshare을 호출하게 되면 자식 프로세스가 새로 생성이 된다.
여기서 주목할만한 점은 CLONE_NEWPID 라는 옵션이다.

CLONE_NEWPID
This flag has the same effect as the clone(2) CLONE_NEWPID
flag. Unshare the PID namespace, so that the calling
process has a new PID namespace for its children which is
not shared with any previously existing process. The
calling process is not moved into the new namespace. The
first child created by the calling process will have the
process ID 1 and will assume the role of init(1) in the
new namespace. CLONE_NEWPID automatically implies
CLONE_THREAD as well. Use of CLONE_NEWPID requires the
CAP_SYS_ADMIN capability. For further information, see
pid_namespaces(7).

간단하게 정리해보면

  • 새로운 PID namespace를 생성하고 기존의 프로세스와 공유되지 않는다.
  • unshare을 호출한 프로세스는 새 namespcae로 이동하지 않는다.
  • 호출 프로세스에 의해 생성된 자식은 새로운 namespace에서 init(1)의 역할을 수행한다.

이전에 공부했던 docker container의 모든 핵심 동작이 다 들어가있음을 알 수 있다.
컨테이너는 namespace로 격리된 공간이고 runc가 실제로 컨테이너를 생성 및 관리를 하고 있으며 runc의 하위 쓰레드에서 unshare() systemcall 로 새로운 namespace를 만들고 있다는 사실을 알게 되었다.

profile
끊임없는 노력

0개의 댓글