연구실에서 ‘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) 제거