Linux에서 컨테이너를 만들어 보자.
컨테이너의 핵심은 '격리(isolation)'이다. 여기서 2가지 격리를 구현해야 한다.
1) 파일시스템 격리 -> chroot
2) 프로세스 격리 -> unshare ( namespace )
파일시스템 격리
파일시스템 격리는 chroot로 구현된다.
chroot는 root의 경로가 변경된 또 다른 쉘(shell)을 띄우는 것이다. 터미널로 접속하면 우리는 정해진 위치를 root로 하여 쉘(shell) 프로그램을 구동하여 터미널에 접속한다. chroot는 또 다른 경로를 root로 하여 쉘을 구동한다. 쉘이 바라보는 루트는 달라지지만 쉘이 커널로 전송하는 경로는 동일하다. 그러므로 달라진 루트 위치에 bin폴더, proc 폴더, lib 폴더를 복사 및 생성하면 마치 서버 안에 또 다른 서버가 생성된 것처럼 보이게 만들 수 있다.
#/bin/bash
# root로 지정할 디렉토리 생성
mkdir -p /home/namespace/box
# binary 파일 및 lib 복사하기
mkdir -p /home/namespace/box/bin
mkdir -p /home/namespace/box/lib
mkdir -p /home/namespace/box/lib64
cp -v /usr/bin/kill /home/namespace/box/bin/
cp -v /usr/bin/ps /home/namespace/box/bin/
cp -v /bin/bash /home/namespace/box/bin/
cp -v /bin/ls /home/namespace/box/bin/
cp -v /usr/sbin/ip /home/namespace/box/bin/
cp -r /lib/* /home/namespace/box/lib/
cp -r /lib64/* /home/namespace/box/lib64/
# binary 파일이 접근 할 proc 디렉토리 생성하기
# proc 디렉토리는 커널 내부 정보를 파일형태로 제공
mkdir -p /home/namespace/box/proc
mount -t proc proc /home/namespace/box/proc
# root 경로 지정하여 bash쉘 실행하기
chroot /home/namespace/box /bin/bash
위 쉘을 실행하면, 컨테이너에 필요한 binary 파일이 생성되고 binary 파일들이 필요한 커널 내부 정보를 proc 디렉토리를 통해 제공할 수 있다. 그리고 chroot를 통해 지정된 경로를 root로 인식하는 bash쉘을 실행할 수 있다.
하지만 문제가 있다.
파일시스템은 격리되었지만 격리라고 볼 수가 없다. 왜냐하면 호스트 프로세스가 컨테이너 프로세스를 실행하였기 때문에 호스트와 컨테이너는 부모-자식 관계로 동일한 네임스페이스를 공유한다. 동일한 네임스페이스를 공유하기에, 커널이 proc 디렉토리로 호스트와 동일한 프로세스 정보를 공유하여 자식도 부모처럼 같은 프로세스 정보를 볼 수 있다. 다시말하여 자식인 컨테이너가 호스트에서 동작 중인 프로세스에 영향을 줄 수 있다. 심지어 kill 도 할 수 있는 것이다.
프로세스 격리 ( unshare )
자식이 부모의 프로세스 정보를 볼 수 없도록 네임스페이스를 생성해서 격리해야 한다.
#/bin/bash
mkdir -p /home/namespace/box
mkdir -p /home/namespace/box/bin
mkdir -p /home/namespace/box/lib
mkdir -p /home/namespace/box/lib64
cp -v /usr/bin/kill /home/namespace/box/bin/
cp -v /usr/bin/ps /home/namespace/box/bin/
cp -v /bin/bash /home/namespace/box/bin/
cp -v /bin/ls /home/namespace/box/bin/
cp -v /usr/sbin/ip /home/namespace/box/bin/
cp -r /lib/* /home/namespace/box/lib/
cp -r /lib64/* /home/namespace/box/lib64/
# proc 디렉토리 생성하기
mkdir -p /home/namespace/box/proc
# unshare 명령어로 네임스페이스 따로 생성해서 chroot 프로세스 실행하기
unshare -p -n -f --mount-proc=/home/namespace/box/proc chroot /home/namespace/box /bin/bash
unshare 명령어를 사용하면 chroot로 실행되는 /bin/bash는 호스트랑은 다른 네임스페이스를 공유하게 된다.
-p : pid 네임스페이스 격리
-n : 네트워크 인터페이스 격리
-f : 자식프로세스 생성 후 네임스페이스 격리하기
--mount-proc : 호스트와 분리된 네임스페스 전용 /proc 제공하기
bash-5.2# ps -ef
UID PID PPID C STIME TTY TIME CMD
0 1 0 0 12:09 ? 00:00:00 /bin/bash
0 2 1 99 12:09 ? 00:00:00 ps -ef
bash-5.2# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
link/tunnel6 :: brd :: permaddr ba76:c2cd:ea6d::
그럼 위와 같이, chroot로 실행된 /bin/bash가 1번 프로세스 PID가 되고 네트워크도 격리된 가상의 네트워크가 형성된다. 이로써 컨테이너와 호스트의 프로세스가 격리된 환경이 구현되었다.
격리되었다고 해도 자식이 부모를 못 볼 뿐이지 부모는 자식을 볼 수 있다. 프로세스는 트리 방식의 계층구조로 실행되기 때문에 자식 전용 네임스페이스도 부모(호스트) 단에서 확인이 가능하다.
root@kind-control-plane:/proc/1019# cat status
Name: coredns
//중략....
NStgid: 1019 1
NSpid: 1019 1
NSpgid: 1019 1
NSsid: 1019 1
coredns는 kubernetes에서 dns를 담당하는 파드이다. coreDNS 프로세스는 컨테이너 안에서 프로세스 PID는 1번이지만 호스트 노드에서 1019이다. 이렇듯 부모인 호스트는 자식인 컨테이너 안의 네임스페이스도 확인이 가능하다.
PID namespace | 프로세스 ID 공간 (논리적 PID) | 데이터를 처리하는 프로세스 격리 |
NET namespace | 네트워크 인터페이스, 라우팅 테이블 등 | 데이터가 들어오는 입구 격리 |
MNT namespace | 마운트된 파일시스템 트리 | 데이터가 오가는 디렉토리 격리 |
IPC namespace | 공유 메모리, 세마포어, 메시지큐 등 | 데이터를 공유하는 메모리 격리 |
USER namespace | UID/GID 매핑 | 데이터에 접근하는 유저 격리 |
chroot로 파일시스템을 격리하고
unshare로 네임스페이스를 생성하여 프로세스를 격리하면
기본적이고 간단한 컨테이너를 직접 구현할 수 있다.
참고자료
https://product.kyobobook.co.kr/detail/S000203332747
코어 쿠버네티스 | 제이 비아스 - 교보문고
코어 쿠버네티스 | 쿠버네티스의 핵심 사항을 이해하려면 반드시 이 책을 읽어 보자!현실에서 쿠버네티스의 배포는 힘든 작업입니다. 작은 구성 오류나 설계 문제도 시스템을 망칠 수 있습니다.
product.kyobobook.co.kr
'DevOps > Linux' 카테고리의 다른 글
ubuntu 패키지 설치시 GPG Key가 필요한 이유 (2) | 2025.07.29 |
---|---|
DMZ망에 APT Mirror 서버 구축하기 (2) | 2025.07.23 |
파일시스템에 볼륨 추가하기 (2) | 2025.07.18 |
[Linux] CLI로 Disk의 파티션 및 파일시스템 생성하기 (0) | 2025.03.13 |
[Linux] 좀비 프로세스란? ( Zombie Process, Defunct Process ) (0) | 2025.03.11 |