Search

리눅스에서 직접 컨테이너 만들기 without Docker

연구실에서 ‘Serveless Survey’ 논문을 읽고 세미나를 준비하는 과정에서 서버리스 함수를 실행시키는 환경 중 하나인 Container(컨테이너)에 대해서 제대로 이해하고 싶었다. 컨테이너를 직접 만들어보면, 확실히 이해하지 않을까 싶었는데 엄청난 영상을 찾았다… 위의 영상을 토대로 정리한 내용이니 참고하면 좋을 것 같다.

컨테이너 필수 요소

컨테이너를 만들기 위해서는:
컨테이너만을 위한 자체적인 File System(파일 시스템)
프로세스가 볼 수 있는 것(what you can see)을 제한하는 Namespace(네임스페이스)
프로세스가 사용할 수 있는(what you can use) 자원을 제한하는 Cgroups(Control groups)
이렇게 3가지가 필요하다.
이제 위 이미지와 같은 ‘RED’ 라는 컨테이너를 만들어보자.

Network 설정

ip netns add RED ip netns add BLUE ip link add veth0 netns RED type veth peer name veth1 netns BLUE
Bash
복사
Network 네임스페이스인 RED, BLUE를 생성한다.
그리고 가상 이더넷(veth)를 만들고 각각 RED, BLUE에 하나씩 꼽아준다.
ip netns exec RED ip addr add dev veth0 11.11.11.2/24 ip netns exec RED ip link set veth0 up ip netns exec BLUE ip addr add dev veth1 11.11.11.3/24 ip netns exec BLUE ip link set veth1 up
Bash
복사
RED, BLUE에 IP 주소를 각각 11.11.11.2/24와 11.11.11.3/24를 할당해준다.
그리고 가상 이더넷의 전원을 켜준다.
ls /var/run/netns
Bash
복사
파일 형태로 네트워크 정보만 netns 파일 아래에서 관리가 되고 있다.
현재 프로세스가 할당된 상태는 아니다.

Cgroups 생성 및 설정

mkdir /sys/fs/cgroup/cpu/red mkdir /sys/fs/cgroup/memory/red
Bash
복사
RED 라는 디렉토리를 만드는 것만으로 Cgroup이 생성된다.
ls /sys/fs/cgroup/cpu/red
Bash
복사
cpu를 관리하는 파일들인데, 이는 커널이 자동으로 넣어준다. (memory도 마찬가지)
echo 40000 > /sys/fs/cgroup/cpu/red cpu.cfs_quota_us echo 10000 > /sys/fs/cgroup/cpu/red cpu.cfs_period_us echo 209715200 > /sys/fs/cgroup/memory/red/memory.limit_in_bytes echo 0 > /sys/fs/cgroup/memory/red/memory.swappiness
Bash
복사
CPU는 40%로 제한, Memory는 200MB로 제한한다.
Swap off: 메모리가 부족할 때, 디스크를 사용하는데 이 기능을 끔 ⇒ 드라마틱하게 메모리가 부족한 경우를 보기 위해서 끔

Namespace로 컨테이너 격리

unshare -m -u -i -fp nsenter --net=/var/run/netns/RED /bin/ns
Bash
복사
unshare: 새로운 네임스페이스를 생성해서 해당 네임스페이스 안에서 명령어를 실행하는 명령어
-m: 새로운 Mount Namespace 생성. 파일시스템을 분리한다.
-u: 새로운 UTS Namespace 생성. 호스트명과 도메인명을 격리한다.
-i: 새로운 IPC Namespace 생성. 프로세스 간 통신 리소스(세마포어, 메시지 큐 등)를 격리한다.
-fp: 자식 프로세스를 새로운 PID Namespace에 생성(fork)한다.
nsenter: 이미 존재하는 네임스페이스에 접근(enter)하는 명령어
--net=/var/run/netns/RED: RED 라는 이미 만들어진 Network Namespace에 접근
/bin/sh: 최종적으로 실행되는 명령어 또는 프로그램. 보통 네임스페이스 안에서 실행될 초기화 작업이 있음.
hostname RED
Bash
복사
호스트네임을 RED로 변경한다.

Cgroups 할당

echo "1" > /sys/fs/cgroup/cpu/red/cgroup.procs echo "1" > /sys/fs/cgroup/memory/red/cgroup.procs
Bash
복사
1번 프로세스를 Cgroup RED 그룹으로 포함을 시킨다.
왜 1번? 조금 전에 PID Namespace을 격리해서 컨테이너 안에서 프로세스가 1번임

File System

파일 생성
mkdir /redfs mkdir /redfs/container mkdir /redfs/work mkdir /redfs/merge
Bash
복사
Overlay 마운트
mount -t overlay overlay -o lowerdir=/tmp/tools:/tmp/myroot, upperdir=/redfs/container, workdic=/redfs/work /redfs/merge
Bash
복사
/redfs/merge/ │ ├── lowerdirs: /tmp/tools, /tmp/myroot → 읽기 전용 ├── upperdir: /redfs/container → 사용자 변경 반영 └── workdir: /redfs/work → 내부 작업 처리 → 이 모든 것을 하나로 합쳐 /redfs/merge에 마운트
Bash
복사
lowerdir=/tmp/tools:/tmp/myroot
읽기 전용 계층
upperdir=/redfs/container
파일을 수정/삭제/생성할 때 실제로 반영되는 위치
사용자가 /redfs/merge 안에서 뭔가를 만들거나 바꾸면, 실제로 이 디렉토리에 반영됨
workdir=/redfs/work
OverlayFS가 내부적으로 변경을 추적하는 데 필요한 작업 디렉토리
마운트 지점: /redfs/merge
유저가 실제로 접근하게 되는 통합된 뷰를 제공하는 디렉토리
여기서는 /tmp/tools, /tmp/myroot, /redfs/container가 합쳐서 한 디렉토리처럼 보여짐
pivot_root
mkdir -p /redfs/merge/put_old cd /redfs/merge pivot_root . put_old cd /
Bash
복사
pivot_root 전
pivot_root 후
mount -t proc proc /proc umount -l put_old rm -rf put_old
Bash
복사
pivot_root 후
host의 파일 시스템(put_old) 제거

RED 컨테이너 완성