https://if.kakao.com/2022/session/104
정리하고 보니 슬라이드랑 똑같네요. 그냥 슬라이드 보세요..
1. 컨테이너 왜씀
서버 환경(OS독립)에 구애 받지 않고 여기에 애플리케이션이 구동에 필요한 모든걸 다 때려박고(올인원 패키지) 프로세스 주변 영향을 받지 않고 격리된 상태로 실행 가능. 그리고 해당 컨테이너가 구동하기 위한 자원을 할당하고 사용할 수 있도록 보장을 할 수 있다.
2. 컨테이너 사용 요건
리눅스
컨테이너는 리눅스 기술임. 근데 윈도우에서도 도커 쓰잖음? 그거는 도커가 백그라운드 프로세스로 리눅스 버츄얼 머신 돌려서 그럼.
런타임
컨테이너 관리 도구(도커 같은)
리눅스, 런타임은 필수이고 이 컨테이너들을 여러 개를 관리하기 위해 쿠버네티스 같은 자동화 도구를 사용함
그래서 요새 많이 사용하는 기술이 도커랑 쿠버네티스임
도커랑 쿠버 사용법은 알지만 컨테이너에 대한 이해가 부족한 사람들이 많음
그래서 우리는 컨테이너에 대한 이해가 필요함.
그래서 여기서는 핸즈온 실습으로 도커 없이 컨테이너를 만드는 것을 함
컨테이너의 역사
컨테이너는 하루 아침에 나온게 아님.
컨테이너의 파일시스템, 격리와 자원에서 같이 실습을 통해 다루어 보고 최종적으로 컨테이너를 직접 만들 것
실습 안내
실습 환경 준비
내 pc는 맥북 m1이라 virtual box가 아직은 정식 지원은 아니고 beta버전에 있다.
https://download.virtualbox.org/virtualbox/7.0.2
https://download.virtualbox.org/virtualbox/7.0.2/VirtualBox-7.0.2_BETA4-154219-macOSArm64.dmg
---
어지간하면 내가 에러 수정하면서 해보려고 했는데 인텔맥/윈도우 대상 실습이라 그냥 보면서 이해하는걸로...
---
Vagrant 이란 Virtualbox등 가상화 소프트웨어를 "CUI(캐릭터 유저 인터페이스)"로 조작하기 위한 소프트웨어이다. 즉, 가상환경 소프트웨어가 설치되어 있지 않다면, Vagrant는 사용할 수 없다
컨테이너 : 격리하는 환경을 통칭해 사용
예시) chroot, pivot_root, namespace... 등
docker run -it busybox
run : 실행
-it 옵션
-i : 외부 입력 가능
-t : tty 환경 가능(terminal 에뮬 구축)
busybox : docker image이름
아무튼 docker로 컨테이너 실행하면 별도 환경임.
그걸 직접 확인하는 좋은 방법은 root directory를 확인하는것
host의 root directory에서 ls 명령어 찍은거랑 container의 root directory에서 ls 명령어 찍으면 다름
df -h 로 해도 다름 (df : display filesystem)
여기서 mounted on 밑에 / 로 된 부분을 보면 다름
ps aux (프로세스) 로 비교해도 1번 프로세스가 다름
ip l (네트워크) 로 비교해도 다름
hostname(호스트네임) 으로 비교해도 다름
container는 root권한을 주지 않는게 좋다.
이 제약을 주지 않았을때
둘 다 id 명령어를 입력하면 uid, gid가 다 root인데 과연 같은 root일까?
docker종료
exit
컨테이너 파일시스템
다뤄야할 문제들
프로세스를 가두자
탈옥을 막아보자
중복을 해결해보자
컨테이너의 기원
- chroot(change root)
fake root를 이용해 바깥으로 못나가게 함
리눅스 ldd 옵션
지정한 프로그램의 의존성을 알려줌
e.g. ldd /bin/sh
chroot fake_root /bin/sh
명령어를 수행하면 fake_root로 root를 바꿔서 실행하는데 뒤에 들어간 sh 명령어를 수행하도록 했다. 그러면 shell이 뜨면서 입력을 받을 수 있기 때문이다. 바로는 사용을 못하고 디렉토리를 다 만들고 의존성까지 다 지정된 위치로 복사해와야 한다. 정말 아무것도 없는 상태이기 때문에 ls 등의 명령어에 대한 의존성부터 명령어 쉘스크립트까지 다 가져와야한다.
berno@Bernoui-MacBookPro makecontainer % chroot
usage: chroot [-g group] [-G group,group,...] [-u user] newroot [command]
chroot
- 경로에 모으고(패키징)
- 경로에 가둬서 실행(격리)
아무튼 여기까지 수행을 하면 이제 저장공간을 mount해주어야한다.
위 상황을 위해 명령어를 하나 하나 다 복사해오고 가져오기 번거롭다.
그래서 우리는 남이 만든 이미지로 chroot를 할 수도 있다.
docker repository에서 nginx이미지를 가져와서 사용해보자.
docker export $(docker create nginx) | tar -C nginx-root -xvf -;
export명령어를 사용하면 뒤에 입력한 이미지를 압축 스트림으로 가져오는데 이걸 파이프라인으로 받아서
tar -C 를 이용해 압축해제하는데 nginx-root디렉토리에 해제한다.
이제 탈옥 시도를 해보자.
아무튼 out을 시도하던 ../ ../../을 하던 뭘 갈겨도 외부 루트로는 안나가져야한다.
이걸 수행했더니 잘 나가지더라.
이래서 chroot는 실제 컨테이너를 만들 때 사용할 수는 없다.
그래서 탈옥을 막으려고 pivot_root를 생각해본다.
루트파일시스템을 pivot하는 기능이다.
루트파일시스템?
최상위 파일시스템(리눅스에서 /를 찍었을때 나오는 디렉토리들 :: /bin, /lib, /etc 등)
루트디렉토리를 포함
하위의 모든 파일시스템들이 마운트
근데 이 루트파일시스템을 피봇하면 당연히 호스트에 영향을 준다.
호스트에 영향을 주지 않으면서 하기 위해 네임스페이스가 개발됨.(2002)
- 마운트 환경 격리만 고려
마운트?
파일시스템을 루트파일시스템의 하위 디렉토리로 부착하는 시스템콜
- 마운트 포인트 : 부착 지점, 접근 지점
- e.g. USB, CDROM 마운트
최초의 네임스페이스 :: 마운트 네임스페이스
이렇게 하면 실제 마운트만 하는 것이기 때문에 격리도 되어있으면서 격리가 된다.
mount -t(type) tmpfs none(메모리) new_root(부착위치 경로)
pivot_root 실행
이제 다시 탈옥을 시도해보자.
다시 escape_chroot를 수행해도 탈옥이 안된다. 왜냐하면 진짜로 real root를 바꿔버려서 escape가 되지 않는다.
자 이제 패키징으로 잘 모으기도 했고 했는데.. 문제가...
ubuntu이미지가 있는데 ubuntu에 nginx나 mysql등이 올라간 이미지를 다시 올리려면 계속 ubuntu가 중복된 체로 이미지를 계속 말아야한다. 중복, 저장 비용이 들어간다.
자 이제 탈옥 문제는 pivot_root로 해결했다. 이제 중복 문제를 해결해보자.
오버레이 파일시스템
이미지 "중복 문제"를 해결
- 여러 이미지 레이어를 하나로 마운트
- Lower 레이어는 ReadOnly (도커 이미지 부분)
- Upper 레이어는 Writable (컨테이너가 올라가면서 새로 생기는 부분)
-- Lower부터 Upper까지 합친걸 Merged View라고 해서 제일 위에 존재하는데 여기서는 이 모든게 합쳐서 보인다.
- CoW, copy-on-write(원본유지)
merged view에서 봤을때는 lower layer에 있는 것도 보이는데 이를 수정하려면 cow를 해서 사용한다.
이제 아래와 같은 문제는 해결이 되었다.
탈옥문제는 pivot_root
중복 문제는 오버레이 파일시스템
아직 격리와 루트권한에 대해 불안정하고 자원 보장에 대해 해결해야한다.
초기의 컨테이너
전용루트파일시스템 으로 충분하다고 생각
문제는
컨테이너에서 호스트의 다른 프로세스들이 다 보이고.. 호스트의 포트를 사용하고.. 루트권한도 있고..
이렇다 보니 우리가 마운트 네임스페이스를 이용해서
프로세스에 격리된 환경을 제공했는데 이후 다양한 네임스페이스들이 생겼다.
네임스페이스의 특징
- 모든 프로세스는 타입별로 네임스페이스에 속함
- 자식 프로세스는 부모의 네임스페이스 상속
네임스페이스 사용 방법
unshare [옵션] [프로그램 [args ...]]
네임스페이스 확인 방법
ls -al /proc/$$/ns
readlink /proc/$$/ns/mnt
lsns -p 1
lsns -t mnt -p 1
-t : 네임스페이스 타입 예)pid, mnt, uts...
-p : 조회할 pid
마운트 네임스페이스
- 마운트 포인트 격리
- 최초의 네임스페이스
unshare -m (shell 경로, 안넣으면 기본 shell로)
lsns -p $$
UTS네임스페이스
- UTS, Unix, Time Sharing(서버 나눠쓰기)
- 호스트명, 도메인명 격리
IPC네임스페이스
- IPC, Inter-Procss Communication 격리
- Shared Memory, Pipe, Message Queue 등
PID네임스페이스
- PID 넘버스페이스를 격리
- 부모-자식 네임스페이스 중첩 구조
- 부모 네임스페이스 - (see) --> 자식네임스페이스
-- 부모 네임스페이스에서는 자식 네임스페이스가 다 보임
pid1
- init프로세스(커널이 생성)
- 시그널 처리
- 좀비, 고아 프로세스 처리
- 죽으면 시스템 패닉(reboot)
컨테이너 pid1
- unshare할 때 fork하여 자식 PID네임스페이스의 pid 1로 실행
- 시그널 처리
- 좀비, 고아 프로세스 처리
- 죽으면 컨테이너 종료
/proc 파일시스템
- 메모리 기반의 가상파일시스템
- 커널이 관리하는 시스템 정보 제공
- 시스템 모니터링과 분석에 활용
네트워크 네임스페이스
- 네트워크 스택 격리
- 네트워크 가상화. 가상 인터페이스(장치) 사용
네트워크 인터페이스
- 여러 네트워크 네임스페이스에 걸쳐 있을 수 없음
- 다른 네트워크 네임스페이스로 이동할 수 있음
- e.g. veth, bridge, vxlan
네트워크 네임스페이스 삭제
- 가상 인터페이스 : 삭제됨
- 물리 인터페이스 : 기존 네임스페이스로 복원됨
USER 네임스페이스
- UID/GID 넘버스페이스 격리
- 컨테이너의 루트권한 문제를 해결함
- 부모-자식 네임스페이스의 중첩 구조
- UID/GID Remap
- 컨테이너 안에서만 root
-- USER 네임스페이스 간 UID/GID Remap
- 도커의 USER네임스페이스 지원
-- 도커 v1.10 부터
-- 호스트 UID/GID Remap
-- 보안관점에서 큰 진보
-- But, 기본 설정은 USER 네임스페이스를 사용하지 않음
컨테이너의 자원
Cgroups
- Cgroups, Control Groups
- 컨테이너 별로 자원을 분배하고 limit 내에서 운용
- 하나 또는 복수의 장치를 묶어서 그룹
- 프로세스가 사용하는 리소스 통제
- Cgroup 파일시스템으로 리소스 관리
- 제어그룹 생성
- 제어그룹 리소스 설정
- 제어그룹 프로세스 할당
Cgroup 파일시스템 (/sys/fs/cgroup)
- 자원 할당과 제어를 파일시스템으로 제공
- Cgroup 네임스페이스로 격리할 수 있다.
리눅스 stress 명령어 : 부하줄 때 사용
stress -c 1
Cgroup의 1번 프로세스에 부하
더 봐야 할 것들
- 컨테이너 네트워크 가상 네트워크 통신
- 컨테이너 표준화 인터페이스
- 컨테이너 오케스트레이션
'뭔가를 봤거나 했다면 올리는 카테고리' 카테고리의 다른 글
if kakao 2022 : jvm warm up 끄적끄적 (0) | 2022.12.18 |
---|---|
if kakao 2022 : 카카오톡 메시징 시스템 재건축 이야기 끄적끄적 (0) | 2022.12.18 |
FastAPI와 안드로이드에서 CORS를 허용하는 방법 (0) | 2022.07.31 |
220721 ~ 220722 정리 (0) | 2022.07.24 |
datadog - gs리테일 웨비나 : 어느날 갑자기 찾아온 Datadog, DevOps 변화의 시작 (0) | 2022.05.27 |