$30 off During Our Annual Pro Sale. View Details »

이게 돼요? 도커 없이 컨테이너 만들기

kakao
December 09, 2022

이게 돼요? 도커 없이 컨테이너 만들기

#Container #Cloud #Backend #Linux #Docker

카카오엔터프라이즈에서는 뉴크루와 클라우드에 관심이 있는 개발자 크루를 대상으로 컨테이너 교육을 진행하고 있습니다.
본 핸즈온은 컨테이너 내부를 이해하기 쉽게 풀어서 설명 드리고 실습을 통해서 체감시켜 드립니다.
- 내가 주니어라면? 웬만한 면접관 보다 더 컨테이너를 잘 알게 됩니다 :-)
- 이미 실무자라면? 컨테이너 장인이 되실 수 있습니다 :-)
- 핸즈온과 컨테이너에 대해 더 궁금하신 분들은 카카오엔터프라이즈 Tech &의 제 글을 참고해 주세요!
- https://tech.kakaoenterprise.com/150

발표자 : sam.0
‘라이딩’과 ‘공부’를 좋아하는. 둘 다 ‘떼지어' 할 때가 가장 신나는 개발자입니다. 검색을 클라우드와 AI로 확장하는데 관심이 많습니다.

kakao

December 09, 2022
Tweet

More Decks by kakao

Other Decks in Programming

Transcript

  1. 김삼영 sam.0 카카오엔터프라이즈 Copyright 2022. Kakao Corp. All rights reserved.

    Redistribution or public display is not permitted without written permission from Kakao. 이게 돼요? 도커 없이 컨테이너 만들기 if(kakao)2022
  2. 컨테이너 왜 써요 ? 다양한 서버 환경 물리 머신 +

    클라우드 서버사양, OS종류, 설치환경, ...
  3. 1대 런타임 리눅스 컨테이너는 리눅스 기술 컨테이너 관리 도구 쿠버네티스

    컨테이너 오케스트레이션 컨테이너 사용 요건 여러대
  4. 실습 환경 준비 https:/ /github.com/sam0kim/container - internal - 맥/윈도우 환경

    : Vagrant + Virtualbox - 기타 환경 : Ubuntu 18.04 환경 준비
  5. 실습 환경 준비 : 맥/윈도우 사용자 https:/ /github.com/sam0kim/container - internal

    - Vagrant fi le 복사 - Mac/윈도우 x86계열 Vagrant fi le Mac M1, arm계열 Vagrant fi le
  6. 실습 환경 준비 : 기타 환경 사용자 https:/ /github.com/sam0kim/container -

    internal - Ubuntu 18.04 환경 준비 - Pre - requisite, Docker 설치
  7. 프롬프트 /tmp# docker run -it busybox # docker run -it

    busybox $ docker run -it busybox docker run -it busybox 루트 계정, 실습 경로 루트 계정, 경로 무관 일반 계정, 경로 무관 프롬프트 없음 - 이전 계정/경로
  8. 김삼영 sam.0 카카오엔터프라이즈 Copyright 2022. Kakao Corp. All rights reserved.

    Redistribution or public display is not permitted without written permission from Kakao. 컨테이너 파일시스템 if(kakao)2022
  9. chroot (사용법) chroot [옵션] NEWROOT [커맨드] (사용예) chroot myroot /bin/sh

    (참고) 커맨드를 지정하지 않으면 $SHELL이 기본값
  10. chroot 해서 sh 실행하기 /tmp# /tmp# mkdir myroot chroot myroot

    /bin/sh chroot: failed to run command ‘/bin/sh’: No such fi le or directory myroot bin sh
  11. /tmp# /tmp# /tmp# /tmp# /tmp# sh 파일 복사 mkdir -p

    myroot/bin; cp /bin/sh myroot/bin/; mkdir -p myroot/{lib64,lib/x86_64- linux-gnu}; cp /lib/x86_64-linux-gnu/libc.so.6 myroot/lib/x86_64-linux-gnu/; cp /lib64/ld-linux-x86-64.so.2 myroot/lib64; myroot
  12. ls 파일 복사 /tmp# /tmp# /tmp# cp /bin/ls myroot/bin/; cp

    /lib/x86_64-linux-gnu/ {libselinux.so.1,libc.so.6,libpcre. so.3,libdl.so.2,libpthread.so.0} myroot/lib/x86_64-linux-gnu/; cp /lib64/ld-linux-x86-64.so.2 myroot/lib64/; myroot
  13. /tmp# # Error, do this: mount -t proc proc /proc

    chroot > ps 실행해 봅시다 chroot myroot /bin/sh ps
  14. # mount: /proc: mount point does not exist. # #

    chroot > ps 실행해 봅시다 mount -t proc proc /proc mkdir /proc mount -t proc proc /proc
  15. /tmp# /tmp# /tmp# nginx 이미지 chroot 해보기 mkdir nginx-root; docker

    export $(docker create nginx) | tar -C nginx-root -xvf -; chroot nginx-root /bin/sh;
  16. nginx 실행 # nginx -g "daemon off;" # curl localhost:80

    👉 호스트에서 확인해 보세요
  17. #include <sys/stat.h> #include <unistd.h> int main(void) { mkdir(".out", 0755); chroot(".out");

    chdir("../../../../../"); chroot("."); return execl("/bin/sh", "-i", NULL); } /tmp/escape_chroot.c 탈옥코드
  18. 루트파일시스템? - 최상위 파일시스템 - 루트디렉토리를 포함 - 하위의 모든

    파일시스템들이 마운트 1) https:/ /dev.to/kcdchennai/linux -fi le - system-4idj 1)
  19. 마운트 네임스페이스를 사용하려면? (사용법) unshare [options] [<program> [<arguments>... ]] (옵션)

    -m,--mount 마운트 네임스페이스 (참고) 프로그램을 지정하지 않으면 $SHELL 기본값
  20. new_root 마운트 /tmp# /tmp# # df -h | grep new_root

    👉 호스트와 비교해 보세요 mkdir new_root; mount -t tmpfs none new_root;
  21. myroot -> new_root 복사 /tmp# # tree new_root 👉 호스트와

    비교해 보세요 cp -r myroot/* new_root
  22. put_old 디렉토리 pivot_root <new_root> <put_old> - new_root : 마운트 포인트

    (신규루트) - put_old : 디렉토리 (기존루트) /tmp# mkdir new_root/put_old new_root
  23. 그런데 말입니다 ... 또? 패키징으로 잘 모으긴 했는데요 중복 ubuntu

    a GB nginx ubuntu (a + b) GB mysql nginx ubuntu (a + b + c) GB tomcat mysql nginx ubuntu (a + b + c + d) GB 이미지 저장, 유통, 관리, 보안 ... 비용
  24. 오버레이 파일시스템 컨테이너 레이어 구조 이미지 "중복 문제"를 해결 -

    여러 이미지 레이어를 하나로 마운트 - Lower 레이어는 ReadOnly - Upper 레이어는 Writable - CoW, copy - on - write (원본유지)
  25. 이미지 중복문제 해결 nginx ubuntu tomcat mysql Upper Merged 이미지

    저장소 컨테이너 nginx ubuntu tomcat mysql nginx ubuntu tomcat mysql
  26. 오버레이 파일시스템 sh ls ps myroot Lower Dir 1 rm

    which tools Lower Dir 2 container Upper Dir rm which ps sh ls merge Merged View
  27. tools Lower Dir 2 준비 /tmp# mkdir tools sh ls

    ps myroot Lower Dir 1 Lower Dir 2
  28. Lower Dir 2 준비 : which 복사 /tmp# /tmp# not

    a dynamic executable /tmp# /tmp# sh ls ps myroot Lower Dir 1 which Lower Dir 2 tools which which ldd /usr/bin/which mkdir -p tools/usr/bin; cp /usr/bin/which tools/usr/bin/;
  29. Lower Dir 2 준비 : rm 복사 /tmp# /tmp# /tmp#

    /tmp# /tmp# /tmp# which rm; ldd /bin/rm; mkdir -p tools/{bin,lib64,lib/ x86_64-linux-gnu}; cp /bin/rm tools/bin/; cp /lib/x86_64-linux-gnu/libc.so.6 tools/lib/x86_64-linux-gnu/; cp /lib64/ld-linux-x86-64.so.2 tools/lib64; sh ls ps myroot Lower Dir 1 rm which tools Lower Dir 2
  30. 오버레이 마운트 /tmp# mount -t overlay overlay -o lowerdir=tools:myroot,upperdir=rootf s/container,workdir=rootfs/work

    rootfs/merge sh ls ps myroot Lower Dir 1 rm which tools Lower Dir 2 container Upper Dir rm which ps sh ls merge Merged View
  31. CoW, Copy On Write /tmp# /tmp# rm rootfs/merge/escape_chroot tree -L

    2 rootfs escape_chroot escape_chroot sh rm ls sh rm ls escape_chroot rm
  32. 컨테이너 전용 루트파일시스템 MEM /bin /lib /etc 프로세스 MEM /bin

    /lib /etc 컨테이너 1) Container vs Process, https:/ /sites.google.com/site/mytechnicalcollection/cloud - computing/docker/container - vs - process 1)
  33. 이미지 중복 문제 해결 MEM MEM 컨테이너 ubuntu nginx 오버레이

    파일시스템 이미지 레이어 단위로 저장 pull
  34. 해결 과제 탈옥 문제 중복 문제 격리 안됨 루트 권한

    자원 보장 네임스페이스 Cgroups "컨테이너 격리와 자원" 편에서 다뤄 보겠습니다 탈옥 문제 pivot_root 중복 문제 오버레이 파일시스템
  35. 김삼영 sam.0 카카오엔터프라이즈 Copyright 2022. Kakao Corp. All rights reserved.

    Redistribution or public display is not permitted without written permission from Kakao. 컨테이너 격리와 자원 if(kakao)2022
  36. 아니 근데 ... 컨테이너에서 호스트의 다른 프로세스들이 다 보여요 컨테이너에서

    호스트의 포트를 사용해요 컨테이너에 루트 권한이 있어요 See
  37. 네임스페이스 사용 방법 (ࢎਊߨ) unshare [২࣌] [೐۽Ӓ۔ [arguments ... ]]

    (옵션) -m, --mount -u, --uts -i, --ipc -p, --pid -n, --net -U, --user
  38. # # 네임스페이스 확인 방법 #2 lsns -p 1 lsns

    -t mnt -p 1 lsns, list namespace -t : 네임스페이스 타입 예) pid, mnt, uts, ... -p : 조회할 process id
  39. 마운트 네임스페이스 - 마운트 포인트 격리 - 최초의 네임스페이스 도커

    2013 2012 USER NET 2009 2008 PID, Cgroups UTS, IPC 2006 2002 MOUNT
  40. # # # # UTS 네임스페이스 unshare -u lsns -p

    $$ hostname ubuntu1804 hostname Sam
  41. IPC 네임스페이스 - IPC, Inter - Process Communication 격리 -

    Shared Memory, Pipe, Message Queue 등 도커 2013 2012 USER NET 2009 2008 PID, Cgroups UTS,IPC 2006 2002 MOUNT
  42. PID 네임스페이스 - PID (Process ID) 넘버스페이스를 격리 - 부모-자식

    네임스페이스 중첩 구조 - 부모 네임스페이스 - (see) -> 자식네임스페이스
  43. pid 1 - init 프로세스 (커널이 생성) - 시그널 처리

    - 좀비, 고아 프로세스 처리 - 죽으면 시스템 패닉 (reboot) 커널 모드 유저 모드
  44. 컨테이너 pid 1 - unshare 할 때 fork 하여 자식

    PID 네임스페이스의 pid1 로 실행 - 시그널 처리 - 좀비, 고아 프로세스 처리 - 죽으면 컨테이너 종료
  45. # PID 네임스페이스 만들기 unshare -fp --mount-proc /bin/sh unshare 옵션

    설명 -p : pid namespace -f : fork --mount-proc : proc 파일시스템 마운트
  46. 프로세스 확인 # ps -ef 컨테이너 # ps -ef |

    grep "/bin/sh" root 2610 2600 unshare -fp --mount-proc /bin/sh root 2611 2610 /bin/sh 호스트 * pid (2611) 값은 실습환경 마다 다릅니다.
  47. PID 네임스페이스 비교 # lsns -t pid -p 1 컨테이너

    # lsns -t pid -p 2611 호스트 * pid (2611) 값은 실습환경 마다 다릅니다.
  48. 컨테이너 pid1 KILL ? # 컨테이너 # kill -SIGKILL 2611

    호스트 * pid (2611) 값은 실습환경 마다 다릅니다.
  49. 네트워크 인터페이스 - 여러 네트워크 네임스페이스에 걸쳐 있을 수 없음

    - 다른 네트워크 네임스페이스로 이동할 수 있음 - 예) veth, bridge, vxlan, ...
  50. 네트워크 네임스페이스 삭제 - 가상 인터페이스 : 삭제됨 - 물리

    인터페이스 : 기존 네임스페이스로 복원됨
  51. # veth pair 설정 ip link add veth0 type veth

    peer name veth1 1) https:/ /man7.org/linux/man - pages/man8/ip - link.8.html 1)
  52. # veth0 IP 설정 ip netns exec RED ip addr

    add 11.11.11.2/24 dev veth0
  53. # veth1 IP 설정 ip netns exec BLUE ip addr

    add 11.11.11.3/24 dev veth1
  54. 네트워크 비교 : RED vs 호스트 RED 호스트 # #

    # nsenter --net=/var/run/netns/RED ip a ip route # # ip a ip route
  55. 네트워크 비교 : RED vs BLUE RED BLUE # #

    # nsenter --net=/var/run/netns/RED ip a ip route # # # nsenter --net=/var/run/netns/BLUE ip a ip route
  56. 실습환경 초기화 # # ip netns del RED; ip netns

    del BLUE; 네트워크 네임스페이스 삭제
  57. USER 네임스페이스 - UID/GID 넘버스페이스 격리 - 컨테이너의 루트권한 문제를

    해결함 - 부모-자식 네임스페이스의 중첩 구조 - UID/GID Remap
  58. $ (안내) 일반계정에서 도커 사용하기 sudo usermod -aG docker {҅੿ݺ}

    - 일반계정에서 docker CLI 사용 ~ docker 그룹에 추가 - 권한 적용을 위해 터미널을 종료 후 재접속 해주세요
  59. # id uid=0(root) gid=0(root) .. 컨테이너 # ps -ef |

    grep "/bin/sh" ... root 27950 27923 ... /bin/sh 호스트 컨테이너 프로세스 계정 확인
  60. USER 네임스페이스 비교 (동일) #readlink /proc/$$/ns/user user:[4026531837] 컨테이너 $ readlink

    /proc/$$/ns/user user:[4026531837] 호스트 * inode (4026531837) 값은 실습환경 마다 다릅니다.
  61. 도커의 root 사용 - 패키지 인스톨이 쉽다 - 시스템 리소스

    이용에 제약이 없다 But ... 보안에 취약
  62. # id uid=0(root) gid=0(root) .. 컨테이너 # ps -ef |

    grep "/bin/sh" ... vagrant 27517 27488 ... /bin/sh 호스트 컨테이너 프로세스 계정 확인
  63. USER 네임스페이스 비교 (다름) #readlink /proc/$$/ns/user user:[4026532193] 컨테이너 $ readlink

    /proc/$$/ns/user user:[4026531837] 호스트 * inode (4026531837) 값은 실습환경 마다 다릅니다.
  64. 도커의 USER 네임스페이스 지원 - 도커 v1.10+ - 호스트 UID/GID

    Remap - 보안관점에서 큰 진보 - But, 기본 설정은 USER 네임스페이스를 쓰지 않음
  65. [요약] 네임스페이스 종류 네임스페이스 구분 설명 마운트 네임스페이스 마운트 포인트

    격리 (2002) UTS 네임스페이스 hostname, domain name 격리 (2006) IPC 네임스페이스 IPC 격리 (2006) PID 네임스페이스 pid 넘버스페이스 격리 (2008) 네트워크 네임스페이스 네트워크 스택 가상화 및 격리 (2009) USER 네임스페이스 UID/GID 넘버스페이스 격리 (2012)
  66. Cgroups - Cgroups, Control Groups - 컨테이너 별로 자원을 분배하고

    limit 내에서 운용 도커 2013 2012 USER NET 2009 2008 UTS, IPC 2006 2002 MOUNT Cgroups
  67. Cgroup 파일시스템 - 자원 할당과 제어를 파일시스템으로 제공합니다 - Cgroup

    네임스페이스로 격리할 수 있습니다 1) man cgroups, https:/ /man7.org/linux/man - pages/man7/cgroups.7.html 1)
  68. 실습 준비 $ # # - 실습은 root 계정으로 진행합니다

    - 실습을 위해 아래 툴을 설치해 주세요 sudo -Es apt install -y cgroup-tools apt install -y stress
  69. mycgroup 생성 호스트 /# /# cgcreate -a root -g cpu:mycgroup

    tree /sys/fs/cgroup/cpu/mycgroup CPU 사용률 설정
  70. mycgroup CPU사용률 설정 컨테이너 /# cgset -r cpu.cfs_quota_us=30000 mycgroup; CPU

    사용률 계산 (%CPU) cpu.cfs_quota_us / cpu.cfs_period_us * 100
  71. Cgroups 실습 요약 - "Cgroup 파일시스템"으로 리소스 관리 - "제어그룹"

    (mycgroup) 생성 - "제어그룹" (mycgroup) 리소스 설정 - "제어그룹" (mycgroup) 프로세스 할당
  72. 단원 마무리 mount uts, ipc pid, cgroups net user chroot

    1979 2002 2006 2008 2009 2012 2013 2015
  73. 김삼영 sam.0 카카오엔터프라이즈 Copyright 2022. Kakao Corp. All rights reserved.

    Redistribution or public display is not permitted without written permission from Kakao. 도커 없이 컨테이너 만들기 if(kakao)2022
  74. 이미지 준비 : tools 실습용 tools 준비 - ping :

    컨테이너 통신 테스트 - stress : 컨테이너 부하 테스트 - hostname : 호스트네임 변경 - umount : put_old 제거
  75. # # 이미지 준비 : tools 복사 wget https:// raw.githubusercontent.com/sam0kim/

    container-internal/main/scripts/ copy_tools.sh; bash copy_tools.sh;
  76. # 컨테이너 네트워크 ip link add veth0 netns RED type

    veth peer name veth1 netns BLUE 1) https:/ /man7.org/linux/man - pages/man8/ip - link.8.html 1)
  77. # # 컨테이너 네트워크 ip netns exec RED ip addr

    add dev veth0 11.11.11.2/24; ip netns exec RED ip link set veth0 up;
  78. # # 컨테이너 네트워크 ip netns exec BLUE ip addr

    add dev veth1 11.11.11.3/24; ip netns exec BLUE ip link set veth1 up;
  79. # # # RED Cgroups 설정 echo 40000 > /sys/fs/cgroup/cpu/red/

    cpu.cfs_quota_us; echo 209715200 > /sys/fs/cgroup/memory/ red/memory.limit_in_bytes; echo 0 > /sys/fs/cgroup/memory/red/ memory.swappiness; 40% 200MB swap off
  80. # # RED Cgroups 할당 echo "1" > /sys/fs/cgroup/cpu/red/ cgroup.procs;

    echo "1" > /sys/fs/cgroup/memory/red/ cgroup.procs; namespaces : mount, uts, net, ipc, pid cgroups (red) : cpu 40%, memory 200M
  81. # 오버레이 마운트 mount -t overlay overlay -o lowerdir=/ tmp/tools:/tmp/myroot,upperdir=/redfs/

    container,workdir=/redfs/work /redfs/ merge myroot container stress ping tools stress ping merge ping stress
  82. # # # put_old 제거 mount -t proc proc /proc;

    umount -l put_old; rm -rf put_old;
  83. # # # BLUE Cgroups 설정 echo 40000 > /sys/fs/cgroup/cpu/blue/

    cpu.cfs_quota_us; echo 209715200 > /sys/fs/cgroup/memory/ blue/memory.limit_in_bytes; echo 0 > /sys/fs/cgroup/memory/blue/ memory.swappiness; 40% 200MB swap off
  84. # # BLUE Cgroups 할당 echo "1" > /sys/fs/cgroup/cpu/blue/ cgroup.procs;

    echo "1" > /sys/fs/cgroup/memory/blue/ cgroup.procs; namespaces : mount, uts, net, ipc, pid cgroups (blue) : cpu 40%, memory 200M
  85. # # # put_old 제거 mount -t proc proc /proc;

    umount -l put_old; rm -rf put_old;
  86. RED 메모리 리소스 확인 RED 호스트 # # # stress

    --vm 1 --vm-bytes 195M stress --vm 1 --vm-bytes 196M stress --vm 1 --vm-bytes 200M top RED : memory 200MB, swap off #
  87. 지금까지 ... - chroot ... and 문제들 - 컨테이너 전용

    루트파일시스템 - 컨테이너 격리와 자원 - 직접 만들어 본 컨테이너
  88. 더 봐야 할 것들 - 컨테이너 네트워크 - 컨테이너 표준화

    - 컨테이너 오케스트레이션 가상네트워크 통신 인터페이스 쿠버네티스