본 포스팅은 2022 Ifkakao 이게 돼요? 도커 없이 컨테이너 만들기를 바탕으로 작성되었다.
현재 대부분의 어플리케이션은 컨테이너 형태로 동작하는데, 도커나 쿠버네티스를 사용하는 방법만 알지, 컨테이너에 대해 들여다보는 노력을 안한 것 같아서, 이를 직접 다뤄보기 위한 시간을 갖게 되었다.
컨테이너를 생성하기 위해 필요한 리눅스 개념들은 chroot, cgroup, namespace 등이 있다고 개념만 이해하고 있었지 정확하게 어떤 요소가 "컨테이너"라는 독립적인 워크로드를 만드는지에 대한 이해를 하기 위함이다.
이를 혼자서 진행하기 보다는, IfKakao에서 "도커 없이 컨테이너 만들기 " 라는 세션을 알고 있었고, 친절하게도 약 2시간 20분에 걸친 핸즈온 강의를 따라가보았다.
오늘은 1:07:12 까지 시청했고, 다음날에 Overlay Mount를 실습부터 이어할 계획이다.
# 간단 후기
빛 sam.0 (문제생길까봐 합성 안했다)
방구석(사실 카페)에 박혀서 이런 정보를 제공받을 수 있다는 것에 죄송할 정도로 잘 알려주신다.
이런게 대기업의 선순환일지, 다른데서 굳이 강의를 사서 듣지 않아도 될 수준이라고 감히 평가한다.
아직 절반도 따라가진 못했지만, 실제로 컨테이너의 필요성부터 어떤 기술들을 통해 컨테이너를 구동할 수 있는지까지, 그 기술에 대한 간략한 역사까지 설명해주신다.
강의 자체를 잘하시는 것도 있고, 필요하거나 궁굼한 부분을 바로바로 알려주셔서 따라가기 좋았다.
사실 많은 내용들이 나오고 환경을 최초에 구성하고 해야해서 1시간 정도 듣는데 약 2시간 반정도 걸린 것 같지만 굉장히 의미있었다.
환경 구성에 대해서도 굉장히 신경을 많이 썼다는걸 알 수 있었는데, X86 프로세서 환경에서의 구성뿐만 아니라, M1과 M2 아키텍처 시스템에서도 실습할 수 있게 준비하는 스크립트를 다 준비해주셨다.
실습 환경 구성에 대한 정보는 아래의 깃허브에서 확인이 가능하다.
M1, M2도 그런데, parallels 사용자까지 고려해주셨다는게 대단하다고 느낄 수 밖에 없었다.
# M1 Mac 환경 구성 간 트러블 슈팅
M1 Mac - Vagrant + Qemu 환경을 사용했다.
이는 아마 윈도우 사용자라면 문제가 없을 것 같은데, 간단한 문제가 있어서 이를 공유한다.
vagrant로 가상머신을 프로비저닝하는 과정에서 잘 되는구나 싶다가, 드문드문 apt 관련 문제가 발생했다(빨간 오류 - 캡처를 못했다).
가상머신이 동작하는 데에는 문제가 없어보여서 그대로 진행했지만, 아래의 두 가지 문제가 존재했다.
1. Vagrantfile을 통해 가상머신을 프로비저닝하면 docker가 실행되어야하는데, 열어보니 docker 데몬이 없었던 점을 확인할 수 있었다.
이는 직접 Docker를 설치하여 해결했다.
2. 가상머신의 인터넷 문제 - DNS 주소를 못가져옴 - temporary failure in name resolution 문제
이는 프로비저닝된 가상머신의 nameserver 문제임을 확인하여 /etc/resolv.con를 수정하여 해결했다
추가로, http://www.google.com으로 ping을 보내면 잘못된 데이터가 왔다는 정보를 확인할 수 있었다.
이를 해결해보려고 하다가, DockerHub 레지스트리에서 이미지는 잘 받아와져서 그대로 사용했다.
M1 환경에서 동작하는 가상머신 문제라서 이를 해결할 능력도 없고, 시간도 없어서 넘어갔다.
이 외의 문제는 발생하지 않았고, 정상적으로 실습을 따라갔다.
# 요약
사진은 안 담을 계획이다. 너무 많아서
컨테이너의 등장과 이 핸즈온을 하는 이유로부터 시작해서, 실습 환경을 구성했다.
컨테이너는 서버 환경에 구애받지 않고, 애플리케이션이 필요한 전용 환경을 제공함으로써 안정적이고 일관된 동작을 보장한다.
컨테이너는 패키징 + 환경 격리 + 자원 보장을 통해서 애플리케이션 전용 환경을 제공한다.
컨테이너를 동작시키기 위해서는 리눅스와 컨테이너 런타임이 필요하다. 대규모 애플리케이션을 운용하기 위해서는 자동화된 오케스트레이션 도구 또한 필수이다.
우선 Docker를 통해 Busybox 컨테이너를 동작시켜 호스트와 컨테이너 내부를 비교하여 컨테이너가 호스트 시스템과는 독립된 공간임을 확인했다.
1. 루트 디렉토리
2. 루트 파일 시스템
3. 프로세스
4. 네트워크
5. 호스트 네임
6. uid, gid
컨테이너와 호스트 파일 시스템의 차이를 어떻게 확인하고, 리눅스 명령어를 통해 컨테이너를 동작시키는 과정을 확인했다.
chroot는 change root로, 예전 서버에 접속하여 악의를 가진 사용자가 서버 내부를 헤집어놓는 상황이 발생해서, 이를 해결하기 위한 방법 중 하나로 제안된 명령어이다.
동작 방식은 사용자 프로세스의 루트 디렉토리를 fake root로 주어, 루트 파일 시스템을 격리한 것과 같다.
chroot를 통해서 프로세스를 가두고, 패키징하여 해당 프로세스 안에서 sh 쉘 명령어를 사용할 수 있도록 하는 방법까지 실습했다.
chroot로 프로세스 격리와 패키징을 수행할 수 있지만, 실제 컨테이너는 chroot로 구동되지 않았는데, 그 이유는 프로세스 스스로 chroot(fake root)를 풀어버릴 수 있었기 때문이다.
준비해주신 C언어 파일을 컴파일하여 직접 chroot 프로세스 내부에서 실제 root 파일시스템으로 접근이 가능한 것을 확인했다.
이를 해결하기 위해서 리눅스 시스템이 부팅할 때 사용하는 pivot_root 기능을 이용하면 완벽한 격리를 고안했고, 추후 namespace 기능이 개발되고 나서 완벽한 격리가 가능해졌다.
모든 요소가 파일인 리눅스 파일 시스템의 구조 상, 루트 파일 시스템 조차도 루트 디렉토리에 마운트가 되는 구조이므로 컨테이너 전용 파일 시스템을 별도로 마운트하여 이를 해결할 수 있다고 생각했다.
호스트에 영향을 주지 않고 pivot_root를 수행하기 위해서 마운트 네임스페이스가 개발되었고, 이를 통해서 격리된 마운트 네임스페이스는 루트 파일시스템으로부터 격리가 가능했다.
즉, 격리된 마운트 네임스페이스에 USB를 연결하면 호스트 상에서는 부착된 USB의 내용을 볼 수 없는 것이다.
이를 통해서 호스트에 영향을 주지 않고 pivot_root를 사용할 수 있게 되었다.
정확하게 얘기하면 mount namespace의 격리와 pivot_root를 이용하여 프로세스의 완벽한 격리가 가능해졌다.
이를를 실습하면서, 직관적으로 이해할 수 있었다.
정리하면,
chroot -> 괜찮나? -> 탈옥 가능! -> 아 딴거.. -> pivot_root 쓰면 될거같은데? ->호스트에 영향을 안줘야해.. -> mount namespace 개발 -> 컨테이너 파일 시스템 분리 가능!
순서로 이해했다.
마지막 부분에선 패키징의 중복 문제를 학습하였다.
패키징된 요소들이 각각 별개의 압축파일로 관리되면 특정 애플리케이션을 패키징하기 위해선 OS Ubuntu 이미지 위에 작성된 애플리케이션이 올라가거나 점점 구조가 커질수록 패키징 크기 또한 증가하게 되었는데, 이는 운영하는 입장에서 저장, 유통 , 보안적, 관리적 측면에서 문제가 발생했다.
즉, 이미지를 관리하기 위한 비용들이 많이 발생했다.
이를 해결하기 위한 시스템이 오버레이 파일 시스템이고 이는 한 덩어리로 저장하지 말고 여러 개의 레이어들을 쌓아서 마운트를 할 수 있다면 중복을 해결할 수 있다는 개념에서 출발했다.
레이어의 구조는 Lower Layer, Upper Layer로 나뉘는데,
Lower Layer는 ReadOnly, Upper Layer는 Writable 하다.
즉, 변경되면 안되는 부분을 Lower Layer에 저장해서, 변경되는 부분만 가져와서 컨테이너를 동작하도록 만들 수 있는 구조이다.
저장소 또한, 이미지를 Layer 단위로 가지고 있고, 필요한 Layer들을 가져와서 마운트 후 실행하는 방법으로 패키징의 중복 저장 문제를 해결했다.
전체 파일 시스템은 Merged View를 통해서 확인이 가능하고, 이러한 오버레이 파일 시스템을 통해서 CoW(원본 보장)을 수행한다.
chroot 실습을 진행하면서, 명령어들의 기능과 의미를 같이 알려주셔서 좋았다.
ldd라는 명령어가 궁금해서 따로 정리했다.
의존성 라이브러리를 확인하이 위해서 ldd라는 명령어를 사용했는데, 이는 "List Dynamic Dependencies"의 약자로 특정 실행 파일이나 공유 라이브러리가 어떤 동적 라이브러리에 의존하는지를 확인할 수 있다.
이를 통해 해당 파일이 실행되기 위해 필요한 다른 라이브러리의 목록을 확인하여, 무엇을 같이 넣어주어야하는지를 파악할 수 있다.
아래에서 다음날 진행한 후기를 확인할 수 있다.
'Infra > Linux' 카테고리의 다른 글
도커 없이 컨테이너 만들기 - 2 (3) | 2023.11.18 |
---|---|
Docker Swarm Cluster 환경에서 Fast-API & MongoDB 연결 - Docker Compose & Secret 사용 (0) | 2023.08.06 |
종강 기념 프로젝트 Step 3 - WPM 자동화 프로젝트 - Prometheus & Grafana 설치 및 DB Replication 설정 자동화(CentOS7) (7) | 2023.06.25 |
종강 기념 프로젝트 Step 2 - WPM 자동화 프로젝트 - 방향 수정 & WPM 설치 및 LB 구성 자동화(CentOS7) (0) | 2023.06.20 |
종강 기념 프로젝트 Step 1 - WPM 자동화 프로젝트 - 고안 & 최초 환경 구성(CentOS7) (0) | 2023.06.18 |