본문 바로가기
스터디 이야기/Kubernetes Advanced Networking Study

[KANS] 컨테이너 격리 - 2. namespace

by lakescript 2024. 8. 29.
더보기

이 스터디는 CloudNet@에서 진행하는 KANS 스터디를 참여하면서 공부하는 내용을 기록하는 블로그 포스팅입니다.

CloudNet@에서 제공해주는 자료들을 바탕으로 작성되었습니다.

 

이전 글에 이어서 작성된 게시글입니다.

 

컨테이너 격리

이전에 살펴봤던 pivot_root, mount namespace를 통해 격리된 filesystem 환경을 실습해보았습니다. 그런데 그것들이 컨테이너라고 한다면 컨테이너에서 host의 다른 프로세스들이 보이거나, 컨테이너에 root 권한이 있거나.. 하는 문제점이 보여집니다. 

namespace

그래서 프로세스 자체에 격리된 환경을 제공하는 namespace라는 메커니즘이 등장합니다. 리눅스의 커널을 사용하여 동작하며 모든 프로세스는 타입별로 네임스페이스에 속하고, 자식 프로세스는 부모의 네임스페이스를 상속한다는 특징이 있습니다. 나아가 프로세스는 네임스페이스 타입별로 일부는 호스트(root) 네임스페이스를 사용하고 일부는 컨테이너의 네임스페이스를 사용할 수 있습니다. 즉, mount 네임스페이스는 컨테이너의 것으로 격리하고, network 네임스페이스는 호스트 것을 사용할 수 있습니다.

 

프로세스 별 namespace 확인 실습

관리자 권한 및 /tmp 디렉토리로 이동

sudo su -
cd /tmp

 

네임스페이스 확인 방법 1 : 프로세스 별 네임스페이스 확인

ls -al /proc/$$/ns

 

현재 processor가 어떤 system namespace(inode)에 속하는지 확인해보겠습니다.

 

네임스페이스 확인 방법 2 : lsns - List system namespaces

lsns -p $$

lsns 명령어를 사용하여 system namespace 정보를 확인합니다. 위 명령어는 -p 옵션을 주어 특정 process에 대한 system namespace(inode)(아래의 사진에서 NS 필드)를 확인합니다.

 

lsns -t mnt -p 1
lsns -t mnt -p $$

 

 

 

mount namespace를 통한 격리 확인

unshare -m

이전 게시글에서 실습했었던 unshare 명령어가 mount namespace 명령어입니다.

UTS Namespace를 통한 격리

UTS Namespace는 Unix Time Sharing의 약자로 여러 사용자 작업 환경 제공하고자 서버 시분할 나눠쓰는 이슈를 해결하고자 고안된 방법으로 호스트명, 도메인명을 격리합니다.

unshare -u

 

IPC Namespace를 통한 격리

Inter-Process Communication의 약자로 격리, 프로세스 간 통신 자원 분리 관리하는데 사용됩니다. (예시 Shared Memory, Pipe, Message Queue 등)

unshare -i

 

PID Namespace를 통한 격리

 

보통 process는 부모-자식 네임스페이스 중첩 구조입니다. 그렇기 때문에 부모 네임스페이스에서는 자식 네임스페이스를 볼 수 있습니다. 하지만 PID namespace를 통해 PID를 격리하면 다른 네임스페이스에 있는 프로세스는 서로의 PID를 참조할 수 없게 됩니다.

 

echo $$

격리하기전 pid를 확인하도록 하겠습니다. 결과는 아래의 사진처럼 2748로 확인됩니다.

 

unshare -fp --mount-proc /bin/sh

-fp 옵션을 주어 PID namespace 격리를 진행합니다. 이때 옵션으로 --mount-proc를 설정하는데 이는 namespace 안에서 ps 명령어를 사용하려면 /proc 를 mount 하기위함입니다. 

그 후 echo로 pid를 현재 쉘의 pid 확인하면 1로 PID가 격리된 것을 확인하실 수 있습니다.

ps -ef

ps명령어를 통해 확인해보아도 PID가 1로 설정되어있는 것을 확인 할 수 있습니다.

이는 격리된 namespace 내부에서 PID를 조회했을 떄의 결과들입니다. 하지만 PID namespace는 부모 namespace에서 자식 namespace를 볼 수 있으니 외부에서 ps 명령어를 통해 확인해보겠습니다.

ps -aux | grep '/bin/sh'

위에서 확인했듯이 격리하기전 pid인 2748이 보여집니다.

 

USER namespace를 통한 격리

컨테이너의 루트권한 문제를 해결한 namespace 격리 방법으로, 부모-자식 네임스페이스의 중첩 구조를 갖게 됩니다. 즉, namespace의 안과 밖의 UID/GID 를 다르게 설정할 수 있습니다.

 

whoami

격리하기전 whoami 명령어를 통해 현재 사용자를 확인합니다.

 

unshare -U --map-root-user /bin/sh

unshare 명령어에 -U 옵션을 주어 User namespace를 통한 격리를 실행합니다. 그 후 whoami 명령어로 사용자를 확인해보겠습니다.

root로 보여지면서 User namespace 격리가 되었습니다.

ps -ef | grep "/bin/sh"

외부에서  ps 명령어로 확인해보겠습니다.

부모 namespace에서는 ubuntu로 보여지는 것을 확인하실 수 있습니다.