후니의 IT인프라 사전
컨테이너 만들기 4 ) 컨테이너의 격리와 자원보장 방법(네임스페이스) 본문
문제점
전용파일시스템이 있더라도 추가적인 문제들이 있었다. 여전히 컨테이너에서 호스트의 다른 프로세스들이 보이고, 호스트의 네트워크를 공유한다. 여전히 루트 권한을 사용하고 있었다. 이를 개선하기 위해 네임스페이스 개념이 등장한다.
네임스페이스의 특징
앞서 사실 격리를 설명하면서 마운트 네임스페이스를 먼저 살펴보았다.
- 모든 프로세스는 타입별로 네임스페이스에 속한다.
- 자식 프로세스는 부모의 네임스페이스를 상속한다.
네임스페이스 사용방법
unshare [옵션] 프로그램 [[arguments ...]]
옵션
-m(mount)
-u(uts)
-i(ipc)
-p(pid)
-n(net)
-U(user)
실습
실습 전 먼저 네임스페이스를 확인하는 방법을 알아보자.
네임스페이스 확인 방법 #1
proc에서 확인하는 방법이 있다. [] 대괄호 안은 inode 값이 되겠다. readlink를 통해서 바로 확인할 수도 있다.
ls -al /proc/$$/ns
readlink /proc/$$/ns/mnt
네임스페이스 확인 방법 #2
lsns(list namespace)를 통해서 pid 값에 따라 네임스페이스를 확인할 수 있다.
lsns -p 1
lsns -t mnt -p 1
처음부터 확인해보면
NS : 네임스페이스의 아이노드값
TYPE : 네임스페이스 타입
NPROCS : 해당 네임스페이스에 속한 프로세스의 갯수
PID : 해당 네임스페이스에 최초로 속한 프로세스 아이디 (1번의 자식 프로세스들로 구성되었다)
네임스페이스의 종류
Mount namespace
피봇 루트를 하기 위한 최초의 네임스페이스이다. 실제로 실행해보면 다음과 같고 lsns를 통해서 격리여부를 확인할 수 있다.
unshare -m
lsns -p $$
UTS namespace
Unix Time Sharing(서버 나눠쓰기)라는 것으로 호스트명/도메인명을 격리해 여러 사용자가 사용할 수 있도록하는 네임스페이스이다. 쉽게 말해 호스트 네임을 바꾸기 위한 네임스페이스이다.
unshare -u
lsns -p $$
hostname
hostname james
처음 hostname을 찍으면 호스트 정보를 그대로 가지고 있어서 기존 호스트 이름이 나오지만 hostname 명령으로 호스트명을 바꿀 수 있다. 당연히 이것은 지금 격리된 네임스페이스에서 되는 정보이므로 exit하게되면 격리를 벗어나기때문에 사라진다.
IPC namespace
프로세스간 통신 매커니즘이다. Inter-Process Communication 격리, 메모리 공유, 파이프, 메시지 큐 등을 활용하는데 쓰인다. IPC 네임스페이스를 공유하는 프로세스들 끼리만 ipc 통신을 사용할 수 있다고 이해하면 된다.
unshare -i
lsns -p $$
PID namespace
PID(Process ID)의 특징은 부모-자식 네임스페이스의 중첩구조이다. 부모 네임스페이스는 자식네임스페이스의 pid를 확인할 수 있고, 자식 네임스페이스는 부모의 pid와 자신의 pid 즉 2개의 pid 값을 가진다.
PID 1의 특징
- init 프로세스(커널이 생성한다, 참고로 커널은 0번 프로세스이며, 이 커널이 1번 프로세스를 유저 레이어에서 생성한다.)
- 시그널 처리(커널이 보내는 시그널을 자식 프로세스에 전파한다)
- 자식프로세스에서 발생하는 좀비,고아 프로세스를 정리한다
- 1번이 죽으면 시스템이 패닉에 빠진다. (reboot이 필요하다)
그렇다면 컨테이너에서 1번 프로세스는 어떤 의미일까?
일단 컨테이너가 1번 프로세스를 만드는 방식은 unshare할 프로세스에서 fork를 통해서 자식프로세스를 만들게된다. 이렇게 만든 프로세스를 pid 1로 실행하고, 앞서 1번에서 처리하는 시그널 처리와 좀비/고아 프로세스 처리를 담당하도록 직접 설정해야한다. (즉 자동으로 그 역할을 수행할 수는 없다) 그리고 컨테이너의 1번이 죽으면 역시 컨테이너가 종료된다.
PID 네임스페이스 생성
unshare -fp --mount-proc /bin/sh