Search

도커 없이 컨테이너 만들기

Tags
unix
container
Created
2024/08/31 19:18
Created time
2024/08/31 10:18
category
unix

개요

이전에 학습했던 아래 3가지 주제를 이용하여 도커 없이 완전히 격리된 통신 가능한 컨테이너를 구축

목표

네트워크 네임스페이스 격리에서 이용했던 RED, BLUE 컨테이너 구축
생성된 컨테이너는 cgroup으로 자원 할당
컨테이너 간에는 네트워크 연결로 통신 가능
new_root (Lower Dir 1)와 tools (Lower Dir 2)로 오버레이 파일 시스템을 구축
new_root는 그대로 활용
tools += ping, stress, hostname, umount

Image

new_root

new_root 이미지 레이어는 이전 실습에서 구성해둔 것을 그대로 활용

tools

ping

# 명령어 파일 위치 확인 which ping # 명령어 파일 복사 cp /usr/bin/ping /tmp/tools/usr/bin/ # 명령어 의존 파일 확인 ldd /usr/bin/ping # 명령어 의존 파일 복사 # linux-vdso.so.1는 가상 라이브러리라서 실제로는 존재하지 않는 파일 cp /lib/x86_64-linux-gnu/libcap.so.2 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib/x86_64-linux-gnu/libidn2.so.0 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib/x86_64-linux-gnu/libc.so.6 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib/x86_64-linux-gnu/libunistring.so.2 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib64/ld-linux-x86-64.so.2 /tmp/tools/lib64/ # 디렉토리 구조 확인 tree /tmp/tools
Shell
복사

stress

# 명령어 파일 위치 확인 which stress # 명령어 파일 복사 cp /usr/bin/stress /tmp/tools/usr/bin/ # 명령어 의존 파일 확인 ldd /usr/bin/stress # 명령어 의존 파일 복사 # linux-vdso.so.1는 가상 라이브러리라서 실제로는 존재하지 않는 파일 cp /lib/x86_64-linux-gnu/libm.so.6 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib/x86_64-linux-gnu/libc.so.6 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib64/ld-linux-x86-64.so.2 /tmp/tools/lib64/ # 디렉토리 구조 확인 tree /tmp/tools
Shell
복사

hostname

# 명령어 파일 위치 확인 which hostname # 명령어 파일 복사 cp /usr/bin/hostname /tmp/tools/usr/bin/ # 명령어 의존 파일 확인 ldd /usr/bin/hostname # 명령어 의존 파일 복사 # linux-vdso.so.1는 가상 라이브러리라서 실제로는 존재하지 않는 파일 cp /lib/x86_64-linux-gnu/libc.so.6 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib64/ld-linux-x86-64.so.2 /tmp/tools/lib64/ # 디렉토리 구조 확인 tree /tmp/tools
Shell
복사

umount

# 명령어 파일 위치 확인 which umount # 명령어 파일 복사 cp /usr/bin/umount /tmp/tools/usr/bin/ # 명령어 의존 파일 확인 ldd /usr/bin/umount # 명령어 의존 파일 복사 # linux-vdso.so.1는 가상 라이브러리라서 실제로는 존재하지 않는 파일 cp /lib/x86_64-linux-gnu/libmount.so.1 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib/x86_64-linux-gnu/libc.so.6 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib/x86_64-linux-gnu/libblkid.so.1 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib/x86_64-linux-gnu/libselinux.so.1 /tmp/tools/lib/x86_64-linux-gnu/ cp /lib64/ld-linux-x86-64.so.2 /tmp/tools/lib64/ cp /lib/x86_64-linux-gnu/libpcre2-8.so.0 /tmp/tools/lib/x86_64-linux-gnu/ # 디렉토리 구조 확인 tree /tmp/tools
Shell
복사

Network

이전 실습 때와 동일하게 구성 (일부 명령어 축약식으로 변경)
# 네트워크 네임스페이스 추가 ip netns add RED ip netns add BLUE # veth0, veth1을 생성하면서 netns 연결 ip link add veth0 netns RED type veth peer name veth1 netns BLUE # RED 네임스페이스 ip 주소 할당 및 활성화 ip netns exec RED ip addr add dev veth0 11.11.11.2/24 ip netns exec RED ip link set veth0 up # BLUE 네임스페이스 ip 주소 할당 및 활성화 ip netns exec BLUE ip addr add dev veth1 11.11.11.3/24 ip netns exec BLUE ip link set veth1 up # RED, BLUE의 IP 주소 확인 ip netns exec RED ip l ip netns exec BLUE ip l
Shell
복사

cgroup

컨트롤 그룹 생성

# root 소유의 cpu,memory를 대상으로하는 red 컨트롤 그룹 생성 cgcreate -a root -g cpu,memory:red cgcreate -a root -g cpu,memory:blue # 조회 ls /sys/fs/cgroup/red/ ls /sys/fs/cgroup/blue/
Shell
복사

자원 제한

# cgset 대신 파일에 직접 쓰기도 가능 # cpu 42%, 메모리 42MB 설정 # RED echo 42000 > /sys/fs/cgroup/red/cpu.max echo 44040192 > /sys/fs/cgroup/red/memory.max cat /sys/fs/cgroup/red/cpu.max cat /sys/fs/cgroup/red/memory.max # BLUE echo 42000 > /sys/fs/cgroup/blue/cpu.max echo 44040192 > /sys/fs/cgroup/blue/memory.max cat /sys/fs/cgroup/blue/cpu.max cat /sys/fs/cgroup/blue/memory.max
Shell
복사

컨테이너 실행

네임스페이스 격리

# 터미널 1) mnt, uts, ipc, pid, net를 격리한 RED 컨테이너 (User 격리는 nsenter와 동시에 사용이 잘 안 되는 듯) unshare -m -u -i -fp nsenter --net=/var/run/netns/RED /bin/sh # 터미널 2) mnt, uts, ipc, pid, net를 격리한 BLUE 컨테이너 (User 격리는 nsenter와 동시에 사용이 잘 안 되는 듯) unshare -m -u -i -fp nsenter --net=/var/run/netns/BLUE /bin/sh
Shell
복사

cgroup 할당

# /sys/fs/cgroup/<group>/cgroup.procs 경로에 pid를 추가하면 프로세스를 컨트롤 그룹에 붙일 수 있음 # pid가 격리된 환경에서의 컨테이너의 프로세스는 1번 pid를 가지므로, 이를 추가 # 터미널 1) RED echo "1" > /sys/fs/cgroup/red/cgroup.procs cat /sys/fs/cgroup/red/cgroup.procs # 터미널 2) BLUE echo "1" > /sys/fs/cgroup/blue/cgroup.procs cat /sys/fs/cgroup/blue/cgroup.procs
Shell
복사

OverlayFS

마운트가 격리된 상태에서 오버레이 파일 시스템을 구성하여 마운트
호스트에서는 마운트한 것으로 보이지 않을 뿐더러, 이를 이용하여 pivot_root 시 오버레이 파일 시스템을 / 경로로 취급하게 만드는 것이 가능

RED

# 디렉토리 생성 mkdir /redfs mkdir /redfs/container mkdir /redfs/work mkdir /redfs/merge # 디렉토리 구조 조회 tree /redfs # 오버레이 파일 시스템 마운트 mount -t overlay overlay -o lowerdir=/tmp/tools:/tmp/new_root,upperdir=/redfs/container,workdir=/redfs/work /redfs/merge # 오버레이 파일 시스템 구조 조회 tree /redfs/merge
Shell
복사

BLUE

# 디렉토리 생성 mkdir /bluefs mkdir /bluefs/container mkdir /bluefs/work mkdir /bluefs/merge # 디렉토리 구조 조회 tree /bluefs # 오버레이 파일 시스템 마운트 mount -t overlay overlay -o lowerdir=/tmp/tools:/tmp/new_root,upperdir=/bluefs/container,workdir=/bluefs/work /bluefs/merge # 오버레이 파일 시스템 구조 조회 tree /bluefs/merge
Shell
복사

pivot_root

새로운 루트는 오버레이 파일 시스템을 구성한 마운트 포인트 (RED - /redfs/merge, BLUE - /bluefs/merge)
반드시 마운트 포인트에서 pivot_root를 실행하고, 생성했던 put_old는 기존 루트로 전환됨에 따라 umount로 완전 제거
umount 사용을 위해선 꼭 pivot_root 이후 proc을 마운트 하는 과정 필요
unshare로 pid 격리하는 과정에서 --mount-proc을 사용하는 경우 /etc/mtab이 꼬이면서 mount, umount가 정상 동작하지 않아서 pivot_root 이후 직접 마운트 필요

RED

# put_old 생성 mkdir -p /redfs/merge/put_old # 마운트 포인트로 이동 후, pivot_root cd /redfs/merge pivot_root . put_old # 루트 전환 확인 cd / ls / ls put_old # /proc 디렉토리 생성 mkdir /proc # /proc 디렉토리 proc 마운트 mount -t proc proc /proc # https://man7.org/linux/man-pages/man8/umount.8.html # put_old를 언마운트, -l은 lazy 옵션으로 네트워크 파티션으로 인한 상태 이상 혹은 서버 종료로 멈추는 것을 방지 umount -l put_old # https://stackoverflow.com/questions/17591975/delete-mounting-directory-after-umount-l # 언마운트한 경로는 삭제 가능 rm -rf put_old
Shell
복사

BLUE

# put_old 생성 mkdir -p /bluefs/merge/put_old # 마운트 포인트로 이동 후, pivot_root cd /bluefs/merge pivot_root . put_old # 루트 전환 확인 cd / ls / ls put_old # /proc 디렉토리 생성 mkdir /proc # /proc 디렉토리 proc 마운트 mount -t proc proc /proc # https://man7.org/linux/man-pages/man8/umount.8.html # put_old를 언마운트, -l은 lazy 옵션으로 네트워크 파티션으로 인한 상태 이상 혹은 서버 종료로 멈추는 것을 방지 umount -l put_old # https://stackoverflow.com/questions/17591975/delete-mounting-directory-after-umount-l # 언마운트한 경로는 삭제 가능 rm -rf put_old
Shell
복사

프로세스 및 호스트 네임 확인

# RED, BLUE 각 컨테이너에서 ps -ef hostname
Shell
복사

통신 확인

# RED -> BLUE ping 11.11.11.3 # BLUE -> RED ping 11.11.11.2
Shell
복사

리소스 확인

CPU

# RED, BLUE 각 컨테이너에서 # 설정한 임계치 42% 내로 부하 걸리는 것 확인 가능 stress -c 1
Shell
복사

Memory

# RED, BLUE 각 컨테이너에서 # Memory stress --vm 1 --vm-bytes 41M
Shell
복사

결론

위 과정을 통해 도커처럼 동작하는 도커 없는 컨테이너를 구성
별도 스크립트를 구성하여 딸깍으로 컨테이너 만들도록 작성해보면, 내용이 추가 될 때마다 반영하면서 개선할 수 있을 것으로 보임