서비스 개발자를 위한 컨테이너 뽀개기 (a.k.a 컨테이너 인터널)
시작하며
안녕하세요. 카카오엔터프라이즈에서 검색 서비스를 개발하고 있는 검색클라우드기술셀의 Sam(김삼영)입니다. 저는 앞으로 ‘컨테이너 인터널’이라는 주제로 글을 연재할 예정입니다. 그런데 클라우드 개발자도 아닌, 검색 기술 개발자가 왜 컨테이너를? 이라는 질문을 하실 수도 있을 것 같아요. 저는 개발자라는 본캐(본래 캐릭터)와 사내 강사라는 부캐(부가 캐릭터)를 가지고 있습니다. 몇 년 전 제가 동료 크루들과 컨테이너 스터디를 리드한 적이 있었습니다. 사실 처음에는 가볍게 시작했는데, 제가 공부한 컨테이너에 대해 알려주고 또 같이 공부한 크루들에게 잘 이해가 되었는지 확인하다 보니 스터디가 강의처럼 흘러가게 되었어요. 다행히 반응이 꽤 좋아서 다른 팀분들도 듣고 싶다고 하시더라고요. 이렇게 자연스레 ‘컨테이너 인터널’이라는 과정명이 생겼고, 사내 강사라는 부캐를 얻게 되었죠! (아주 가끔은 본캐같이 느껴지기도..)
검색서비스를 위한 컨테이너화
컨테이너를 속속들이 공부하게 된 계기는 3년 전 카카오 검색 서비스의 컨테이너화 작업이었습니다. 카카오 내 다양한 서비스들의 검색 니즈가 늘어나다 보니 모든 요청을 다 수용하기에는 인력 상황이 여의찮았어요. 향후 새로운 서비스의 증가와 검색 요구가 늘어날 것을 예상했을 때, 검색을 잘 모르더라도 서비스 형태로 곧바로 생성하여 적용할 수 있도록 하고 싶었죠. 좀 더 유연한 저장방식과 리소스 활용도를 높이고, 개발과 운영 측면에서의 쉬운 접근을 고려해야 했습니다. 결국 이런 문제점을 해결하기 위한 고민과 그 시도가 컨테이너입니다.
우선, 컨테이너는 호스트 OS(커널)를 사용하기 때문에 성능 저하가 크지 않습니다. 생산성 측면에서도 프로그램 실행에 필요한 모든 것을 하나로 패키징이 가능하고, 서버 환경으로부터 프로세스를 격리하여 실행할 수 있습니다. 또, 여러 컨테이너 간 자원 경합이 발생하지 않도록 리소스 설정이 가능하기에 물리 서버 환경을 고민하지 않고 검색 컴포넌트의 배치를 자동화할 수 있으리라 생각했습니다. 음, 이론적으로는 완벽한 환경이죠?
그런데 시작부터 만만치 않은 도전이 펼쳐집니다.
첫째, 검색 서비스 환경이 컨테이너 위에서 잘 동작할 수 있는지, 장점과 한계는 무엇인지 검증하는 과정이었습니다. 검색은 대량의 데이터와 요청 트래픽을 감당하기 위해 물리서버의 자원과 네트워크를 최대한 활용하도록 구성됩니다. 서비스를 컨테이너 환경으로 옮겨오기 위해서는 컨테이너의 내부 구조 및 가상 네트워크의 구성, 그리고 분산 노드 위에 자동으로 배치하고 관리하는 오케스트레이션(Orchestration)에 대한 이해가 필수불가결했습니다. 이를 위해 기존 물리서버 대비 성능, 안정성, 제약 요소 등 필요한 부분을 직접 테스트하여 확인할 수밖에 없어 보였습니다.
둘째, 검색서비스를 깊게 이해하고 컨테이너와 쿠버네티스를 튜닝하거나 장애진단 등을 지원해 줄 수 있는 조직이 없었기 때문에 직접 공부하고 파악해야 했습니다. 특히, 시중의 컨테이너 관련 책이나 웹상의 정보 대부분은 도커와 쿠버네티스의 기능이나 사용법 같은 특정 부분만 다루고 있어 실제 컨테이너 구현 원리와 동작에 대해 원하는 수준까지 파악하기에는 부족했습니다.
셋째, 사실 제일 어려운 도전은 동료들을 이해시키고 설득하는 과정이었습니다. 함께하는 동료들이 납득하고 협력할 수 있어야 더 크게 발전할 수 있기 때문이지요. 이건 나중에 사석에서 할 이야기일 수도 있겠지만요 ;-)
결국은 제가 직접 다 이해하지 못하면 해결할 수 없는 문제들로 보이더라고요. 그때부터 컨테이너를 더욱 열심히 들여다보기 시작했습니다.
설명하지 못하면 이해한 게 아니라더라
컨테이너는 과거 값비싼 서버를 나눠 쓰는 고민에서 출발하여 오랜 기간 동안 리눅스 기술 토대 위에 잘 쌓아 올려져 왔습니다. 이러한 점에서 컨테이너를 공부하는 것은 단순히 새로운 기술을 배우는 것 이상으로 리눅스나 전산 기초를 더 깊이 이해하는 과정에 가까웠어요. 어떤 요구와 기술을 바탕으로 컨테이너가 발전되어 왔는지 알아보면서 리눅스 커널, 네트워크, 파일시스템, 컴퓨터 구조 등 관련된 기반 지식을 연결 지어 정리하였습니다.
동시에 카카오 검색 서비스의 컨테이너화를 차츰 완성해나갔습니다. 3년쯤 지나 지금은 검색클라우드기술셀이라는 조직에서 여러 크루들과 함께 카카오 검색 서비스 플랫폼을 개발하고 운영하게 되었고요. 그러다 보니 자연스레 컨테이너의 깊숙하고 은밀한 그 내면의 매력에 빠져들게 되었죠.
‘컨테이너 인터널’이라는 사내 교육은 저희 검색팀 크루들을 대상으로 시작하게 되었는데요. 같이 공부했던 크루들이 좋은 소문을 내주셨는지, 많이들 참여하고 싶다고 하셔서 예상치 않게 7차례나 진행하게 되었습니다. 그러다 보니 제가 가장 큰 수혜자가 되었습니다. 설명하지 못하면 이해한 게 아니라는 말처럼 설명하기 위해 컨테이너를 계속 깊이 파게 되었으니까요.
서비스 개발자를 위한 '컨테이너 인터널'
저와 같은 서비스를 만드는 개발자라면 이제는 컨테이너 내부를 누구보다 잘 이해해야 한다고 생각합니다. 물론 자신이 담당하는 서비스 또한 잘 알아야 하죠. 컨테이너를 아무리 잘 안다고 해도 담당 서비스를 알지 못하면 트러블슈팅이나 성능 개선이 어려울 수 있기 때문입니다. 저 또한 담당하는 서비스와 컨테이너라는 환경 사이 그 어딘가는 항상 그레이존으로 남아있습니다. 예전과 비교하면 그 영역이 조금 줄었을 뿐이지요. 그래서 저와 같은 고민을 하는 서비스 개발자들을 위해 제가 공부했던 ‘컨테이너 내부'에 대한 내용을 글로 연재해 보려고 합니다.
개발자로서 컨테이너 관련 지식이 전혀 없는 분들이라도 기초부터 잘 쌓아 올려 접근하기 쉽도록, 컨테이너를 사용해 보았거나 이미 알고 계신다면 원리를 알아가는 재미를 느끼실 수 있도록 풀어내 보겠습니다. 모쪼록 서비스 개발자들에게 실질적인 도움이 되었으면 좋겠습니다.
앞으로의 연재는 다음의 내용을 담을 예정입니다.
- 첫 번째, 컨테이너의 개념과 컨테이너를 이루는 기술들을 알아봅니다.
- 두 번째, 컨테이너 내부의 파일시스템 구조를 독립적으로 유지할 수 있게 하는 마운트 네임스페이스와 효율적인 컨테이너 구조를 구성하기 위한 오버레이 파일시스템에 대해 알아봅니다.
- 세 번째, 컨테이너 네트워크 호스트 안에 가상 네트워크를 만들고 컨테이너 간 통신을 구현해 봅니다. 이를 바탕으로 서로 다른 호스트의 컨테이너 간 가상 네트워크 통신을 구현해 봅니다.
- 네 번째, 네임스페이스에서 제공하는 격리와 Cgroups를 이용한 컨테이너 리소스 제한을 소개합니다.
- 다섯 번째, 앞에서 다루었던 내용들을 총망라하여 도커없이 완전한 컨테이너를 만들어봅니다.
이번 글은 '예고편'이자 '컨테이너 인터널 실습을 준비하기 위한 가이드' 정도로 생각해주시면 됩니다. 앞으로 이어질 글에서는 컨테이너에 대한 보다 효율적인 학습을 위해 대부분의 테스트를 직접 해보실 수 있도록 핸즈온 가이드를 드릴 예정인데요. 이번 연재에서 계속 언급하게 될 꼭 이해하고 넘어가야 할 몇 개의 기술 개념에 대해 이해하는 것부터 시작해보겠습니다. 최대한 쉽게 풀어서 친절하게 설명해 드릴께요.
주요 기술 개념 먼저 익히기
클라우드
먼저 클라우드(Cloud)입니다. 클라우드라는 용어를 누가 처음 사용했고, 어디서 처음 언급되었는지 알 수 있는 공식자료는 없습니다. 웹(Web)과 일부 책에서는 구글 에릭슈미트가 발표에서 처음 언급했다거나 구글 개발자들 대화 중에 (구글의 IDC 센터가 전 세계 각 지에 퍼져 있어) 본인이 개발한 애플리케이션이 어디로 배포됐는지 모르겠다는 의미로 “구름 (Cloud) 저편 어딘가에 있다”는 표현에서 유래됐다 등 다양한 설들이 있습니다.
“클라우드”에 대한 미국 국립 표준 기술연구소(NIST)의 정의는 다음과 같습니다. “공유 구성이 가능한 컴퓨팅 리소스(네트워크, 서버, 스토리지, 애플리케이션)의 통합으로 어디서나 간편하게, 요청에 따라 네트워크를 통해 언제든 접근하는 것을 가능하게 하는 모델이다. 이는 최소한의 이용 절차 또는 서비스 공급자의 상호 작용을 통해, 신속히 할당되어 제공된다.” 하지만 이 정의대로 클라우드가 컴퓨팅 리소스를 공유할 수 있고, 간편하게 요청 기반으로 제공할 수 있으려면 가상화와 API(Application Programming Interface) 또한 반드시 이해해야 합니다.
가상화
가상화의 사전적 의미는 “Something is not real.(실제가 아닌)”으로, 컴퓨팅에서는 “a hardware environment that is not real.” 즉, 실제가 아닌 하드웨어 환경을 의미합니다. 가상화(Virtualization)는 가짜(not real) 하드웨어 환경을 만들어 내는 기술로, 실제 물리장비인 호스트와 가상머신인 게스트를 구분합니다.
호스트(Host) | 가상화 소프트웨어(이하 하이퍼바이저)를 구동하는 물리 시스템 |
게스트(Guest) | 하이퍼바이저(Hypervisor) 위에 설치되는 가상머신(Virtual Machine) |
가상화에는 컨테이너 가상화, 네트워크 가상화, 하이퍼바이저 가상화, 스토리지 가상화 등 다양한 기술 스택이 존재합니다. 그중 우리는 앞의 세 가지 영역의 가상화에 대해 알아보겠습니다.
하이퍼바이저(소프트웨어) 가상화
하이퍼바이저는 한 대의 머신에서 다수의 운영체제를 동시에 실행하는 소프트웨어로, 하드웨어를 가상화합니다. 가상머신 모니터(VMM, Virtual Machine Monitor) 라고도 합니다. 몇 가지 타입이 존재하고, 예를 들면 오락실 게임을 PC에서 돌릴 때 사용하는 에뮬레이터와 유사합니다. 본 연재에서는 “하이퍼바이저”에 대해서는 컨테이너와 비교 정도로만 다룹니다.
컨테이너(애플리케이션) 가상화
컨테이너는 애플리케이션 구동에 필요한 모든 것들을 패키징하고 격리된 환경에서 실행합니다. “컨테이너" 기반의 가상화로 애플리케이션 실행환경을 가상화합니다. “패키징"과 “격리된 실행"이라는 특징 때문에 서버별 환경에 영향받지 않고 사람의 개입 없이 자동으로 배포할 수 있습니다. 이 컨테이너가 우리가 앞으로 자세하게 다룰 내용입니다.
네트워크 가상화
네트워크의 한정된 물리주소라는 제약을 해결하고, 물리 IP 사용으로 인한 여러 의존성 구성을 가상 네트워크를 통해 추상화하여 단순하고 유연하게 할 수 있습니다. 이후에 작성할 컨테이너 네트워크편에서 자세하게 다룰 예정입니다.
API
API(Application Programming Interface)는 가상화를 통해 가능해진 하드웨어와 애플리케이션 제공을 “추상화(인터페이스)”하는 레이어입니다. 추상화를 하는 목적은 인터페이스(Interface)를 정의함으로써 리소스의 요청 및 제어 방법을 표준화하고, 이를 기준으로 리소스 딜리버리를 위한 인프라 체계를 정의하기 위함입니다. 추상화는 세부 구현을 가림으로써 합의된 인터페이스 범주 내에서 다양한 구현이 가능하고, 필요에 따라 교체하여 사용할 수 있습니다.
API는 명세로 랩핑 되는데, 다양한 리소스에 연결된 API들이 명세 안에서 목적에 맞게 구성됩니다. 명세는 오픈스택, 쿠버네티스 등 오케스트레이션 도구 위에서 컨트롤러들을 부리기 위한 일종의 작업 지시서로, 컴퓨팅 리소스 할당, 가상 네트워크 구성, 컨테이너 배치, 오토스케일링 등 다양한 작업을 자동화합니다.
컨테이너
컨테이너(Container)를 얘기하기에 앞서 도커(Docker) 얘기를 살짝 하고 가보겠습니다. 도커는 마치 "컨테이너"를 지칭하는 일반 명사처럼 두루 사용되고 있죠. 대화를 하다 보면 컨테이너에 관련된 내용에서 도커 컨테이너, 도커 이미지, 도커라이즈드 등 다들 습관처럼 도커란 용어가 입에 착 붙어서 나오게 되는데요. 사실 도커는 컨테이너 관련 제품인 도커를 만든 회사의 이름입니다. 도커는 컨테이너를 세상에 널리 알리며 주목받았고, 컨테이너를 다루는 도구와 플랫폼을 개발하고 있습니다. 지금은 도커 말고도 여러 회사가 도커와 같은 컨테이너 런타임, 컨테이너 플랫폼 개발을 하고 있습니다.
자, 그럼 컨테이너란 무엇일까요? 컨테이너란 격리된 환경과 제한된 리소스로 제어되는 프로세스를 의미합니다. "격리된 환경"과 "제한된 리소스" 뭔가 어렵게 보이지만 호스트가 다세대주택이라고 생각해볼게요. 이 다세대 주택은 여러 가족이 들어와 편안하게 살 수 있도록 독립적인 공간을 만들고, 생활에 필요한 전기와 수도, 가스도 공급해 줍니다. (참고로 … 집주인은 ‘커널(kernel)’이십니다) 컨테이너는 다세대 주택 안에 이렇듯 독립적으로 마련된 공간과 같습니다. 즉, 어플리케이션이 다른 프로세스의 영향을 받지 않게 격리하고 주어진 리소스 안에서 실행될 수 있게 해주죠. 그런데 꼭 따로 한 집씩 살림을 차려줘야 할까요? 그냥 같이 어우러져 살 수는 없는 것일까요?
또 다른 예를 들어볼게요. 어릴 적 집에서 PC를 같이 써 본 경험을 떠올려 보세요. PC를 공유하다 보면 내가 설치한 프로그램을 누나가 지운다거나, 웹서핑하다가 바이러스에 걸린다거나, 동생이 이상한 프로그램을 설치해서 잘 동작하던 프로그램이 안 돌아간다거나 했던 적이 한 번쯤 있었을 것 같습니다. 서버는 훨씬 다양한 경로로 서버 관리자, 개발자, 원격사용자(FTP, HTTP, SSH, ...) 등 더 많은 사람이 이용하고 있는데요. 같이 쓰다 보면 당연히 서로 영향을 주고받습니다. 누군가 서버의 FTP로 1TB짜리 대용량 파일 업로드를 시작하면 같은 서버를 이용하는 다른 사용자들은 타임아웃이나 응답이 느려지는 경험을 하게 될 수도 있고요. (잘못 작성된) 특정 애플리케이션이 서버의 cpu와 memory를 과도하게 사용하여 다른 애플리케이션이 리소스 부족으로 실패하거나 행업(Hang Up)될 수도 있습니다. 해당 서버가 실서비스를 운영하는 상황이면 서버 관리자와 각 애플리케이션 담당자들은 더욱 예민해질 수 있는 상황이죠.
같이 살려면 서로 조금씩 희생하고 배려하는 자세가 필요합니다. 그럼 애플리케이션에 ‘배려’라는 프로그래밍을 구현해야 할까요? 글쎄요. 한 방법일 수는 있을 것 같은데… 배려하려면 상대방을 알아야 하겠죠. 같이 사는 프로세스가 많지 않다면 cpu, memory 등 리소스도 서로 얼마씩 사용할지 합의하고, 함께 쓰는 라이브러리 버전도 합의해 볼 만 합니다. 하지만 불특정 다수가 사용하는 서버에서 어떤 애플리케이션이 설치되고 어떤 라이브러리가 사용될지 예상하기는 쉽지 않습니다. 그리고 서버가 한두 대가 아니라면 더 파악하기 어렵겠지요.
컨테이너는 배려를 구현하는 것보다는 앞서 설명해드린 프로세스 간 서로를 격리시키고 각자 필요한 환경을 꾸려서 실행하는 방법인 다세대주택의 방식으로 해결합니다. 그리고 공유 자원(cpu, memory, network ..)에 대해서 프로세스별로 할당치 만큼만 사용하도록 제한함으로써 누군가 자원을 과도하게 소비하여 피해를 주는 일이 없도록 합니다.
격리된 환경은 배포에도 장점이 됩니다. 서버 환경은 여러 사람의 손을 거치며 시간이 지날수록 변하게 되고, 새로 설치된 서버는 하드웨어, 커널 버전, 시스템 프로그램, 라이브러리 등 이전과 다르게 구성될 가능성이 높습니다. 일 년 전에 애플리케이션을 설치했던 서버에 다시 동일한 애플리케이션을 설치한다고 생각해 봅시다. 일 년 동안 서버가 아무 변경 없이 동일한 상태로 유지가 되었다고 보장할 수 있을까요? 대부분 확신하기 어렵습니다. 동일한 애플리케이션이라도 달라진 환경에 대한 대응을 누군가 해주어야 하는데요. 애플리케이션 실행에 필요한 프로그램이나 관련 의존성 라이브러리들이 서버에 설치되어 있는지, 설치된 버전은 맞는지, 설정에 오류가 없는지 등을 관리자가 일일이 확인해 보아야 합니다.
컨테이너에서는 실행파일뿐만 아니라 의존성 라이브러리, 설정 등 실행에 필요한 모든 것들을 “이미지”라고 하는 것에 모아 패키징함으로써 이 “이미지”에 있는 살림살이만으로도 서버 환경에 의존하지 않고 실행되는 것을 보장합니다.
VM vs 컨테이너
격리된 환경을 제공하는 방법은 컨테이너만 있는 게 아닙니다. 앞에서도 언급한 VM(Virtual Machine, 가상머신) 은 많이들 아실 것 같습니다. VMware 나 Parallels 등의 프로그램을 이용하면 윈도우즈(Windows)나 Mac에서 다른 운영체제(이하, OS)를 설치하여 사용이 가능한데 이것이 바로 VM 입니다. 아마도 Mac, 우분투(Ubuntu) 등 윈도우 이외의 OS를 써보신 분들은 공공기관, 은행 사이트나 인터넷 강의 시청을 위해 VM으로 윈도우를 설치하여 사용해 본 경험이 한 번쯤 있으실 것 같습니다. 저는 (Mac 용 스타크래프트가 없던 시절) Mac에 윈도우 VM을 설치하여 스타크래프트를 즐겼던 기억이 있네요.
VM은 컨테이너보다 훨씬 강력한 격리를 제공합니다. “하이퍼바이저” 라는 소프트웨어가 하드웨어 리소스를 가상화하고, 그 위에 별도의 운영체제가 설치됩니다. 이 운영체제는 서버의 “호스트OS”와 구분해서 “게스트OS“ (이하, GuestOS)라고 부릅니다. 하이퍼바이저는 서버 위에 여러 종류의 GuestOS를 VM으로 실행할 수 있습니다.
이처럼 VM은 서버 안에 또 다른 서버가 있는 것처럼 별도의 OS 환경으로 동작하는데요. 부팅과정도 있고, 여러 프로그램을 설치하여 사용하는 방식이 일반적인 물리 서버를 사용하는 것과 동일합니다. 반면, 컨테이너는 (GuestOS 없이) 호스트 OS를 사용하고 프로세스를 격리하여 실행하는 방식으로 VM과는 매우 다릅니다. 원래 컨테이너는 리눅스 커널에서 지원하는 기능들로 만들어지기에 윈도우, 맥 등 다른 OS에서는 동작하지 않습니다. 이에 비해 VM은 다양한 종류의 OS를 설치하고 구동할 수 있습니다. 그렇다면 Mac이나 윈도우에서도 컨테이너 사용이 가능한 것은 어찌 된 것일까요? 이것은 윈도우나 Mac 에서 컨테이너 지원을 위해 리눅스 VM을 올리고 그 위에서 컨테이너를 기동하기 때문입니다.
컨테이너와 VM을 비교해 보았는데요. 참고로 근래에는 컨테이너 개념이 “리눅스 컨테이너”에 국한되기보다는 격리된 환경의 관점에서 경량 VM까지 아울러서 좀 더 폭넓게 해석되는 경향이 있습니다.
컨테이너는 VM에 비해 작고 빠릅니다. 컨테이너는 호스트 커널에서 바로 처리되고 하드웨어를 직접 관리하는 반면에 VM은 GuestOS가 하드웨어 사용 시 하이퍼바이저의 처리를 기다려야 합니다. 하이퍼바이저는 여러 GuestOS를 상대해야 하고, 하드웨어는 한정된 자원이다 보니 개별 GuestOS의 사정에 맞춰서 리소스를 제공하기 쉽지 않습니다. 이런 이유로 컨테이너와 VM의 성능 차이가 발생할 수밖에 없긴 하지만, 둘 다 각자 클라우드에서 필요한 역할이 있습니다.
컨테이너는 애플리케이션을 패키징하고 서버 환경에 제약 없이 구동할 수 있기 때문에 일종의 “앱" 자판기가 가능합니다. 그리고 VM은 하드웨어를 가상화하고 그 위에 다양한 GuestOS를 올리는 “컴퓨팅" 자판기가 가능합니다. 자판기라고 표현한 이유는 코인만 넣으면 즉, 요청만 하면 원하는 제품을 제공해 주기 때문입니다. AWS, Azure, GCP 등 퍼블릭(Public) 클라우드 환경에서는 실제로 VM 기반으로 인프라를 구성하고 그 위에서 컨테이너 형태로 애플리케이션을 구성해 다양한 IT 리소스를 명세와 API 기반으로 자동화하여 제공하고 있습니다.
지금까지 컨테이너의 개념에 대해서 간단히 살펴보았는데요. 사실, 컨테이너는 어느 하루 아침에 docker run 명령어로 바로 실행할 수 있게 나온 것이 아닙니다. 컨테이너는 “프로세스 격리"라는 문제를 오랜 세월에 걸쳐 풀어오면서 필요한 요건들이 하나 둘 씩 생겨났고 그것들을 구현해 온 결과이죠. 도커(회사)는 이러한 결과물들을 모아 개발에 활용할 수 있는 수준으로 정리하여 2013년 “도커 플랫폼”을 공개합니다.
쿠버네티스
‘쿠버네티스’는 도커와 같은 컨테이너 런타임을 통해 컨테이너를 ‘오케스트레이션’하는 플랫폼입니다. 컨테이너 오케스트레이션이란 용어는 거창하지만, 컨테이너에 필요한 설정과 관리, 적절한 노드로 배치, 모니터링 등을 제공하는 것을 의미합니다. 어느 정도 감이 오시나요?
쿠버네티스는 물리머신에서 사람이 해왔던 업무 대부분을 (혹은 그 이상으로) 해결하는데요. 사람이 거의 개입하지 않고도 배포부터 운영관리의 다양한 부분을 자동화할 수 있습니다. 구글의 사례를 통해 어떻게 대규모 서버에 배포와 관리를 할 수 있는지, 쿠버네티스 탄생의 역사를 조금 살펴보겠습니다.
구글은 이미 오래전에 매주 20억 개가 넘는 컨테이너를 생성하고 운영하였습니다. 이 정도 규모에 사람을 마냥 늘려서 대응하는 것은 매우 비효율적이죠. 그래서 구글은 ‘borg’라는 사내 플랫폼을 이용해 컨테이너를 관리하게 됩니다. 2014년에는 ‘borg의 오픈소스 버전’인 ‘쿠버네티스’를 만들어 CNCF(Coud Native Computing Foundation)에 기증(2016)하게 되는데요, 이게 바로 지금 우리가 쓰고 있는 쿠버네티스의 시작인 셈입니다.
당시 구글은 10여 년에 걸친 대규모 서비스 워크로드 운영 경험을 기반으로 쿠버네티스를 만들었다고 발표합니다. 20억 개의 컨테이너를 관리하는 상상을 해보세요! 이 많은 수의 컨테이너들을 실행하게 될 수많은 서버가 세계 데이터 센터에 나뉘어 있고, 컨테이너마다의 필요와 요구사항을 판단하여 배치해야 합니다. 가히 구글 개발자들이 “구름(클라우드) 너머 저 어딘가에”라고 할만하죠.
쿠버네티스는 사용자의 명세를 기반으로 컨테이너의 스펙에 적합한 노드를 자동으로 선정합니다. 전 세계 서버들을 컨테이너의 스펙과 비교하여 필터링하고 추려진 노드들을 스코어링(Scoring)하여 가장 최적인 노드로 컨테이너를 배치합니다. 개발자는 노드가 어떤 서버에 배치되었는지 몰라도 됩니다. 쿠버네티스가 노드 선정과 배포를 더 간단하게 할 수 있었던 것은 컨테이너가 실행환경을 포함하고 있고 서버에 따라 영향을 받지 않기 때문이었습니다. 컨테이너가 없었다면 구글은 정말로 전세계 데이터센터에 수십억 개의 애플리케이션을 설치할 인력을 고민했을지도 모릅니다.
쿠버네티스는 명세(일종의 작업지시서)를 기반으로 다양한 “컨트롤러”가 협력하는 방식으로 동작하는데요, 여러 종류의 빌트인 컨트롤러들이 있고 필요하면 커스텀 컨트롤러를 구현할 수도 있습니다. 각 컨트롤러는 각자 처리하는 명세를 정의하고 그에 맞춰 구현됩니다. 컨트롤러는 (사람 대신) 컨테이너를 배치하고, (사람 대신) 상태를 모니터링하고, (사람 대신) 상태가 달라지면 명세에 정의된 스펙대로 맞추려는 노력도 합니다. 이것이 어떻게 가능한지 궁금하시죠? 음, 컨테이너 연재 이후에 쿠버네티스 연재도 한번 진행해봐야겠네요.
마치며
글로 쓸까 말까 고민하기를 정말 거짓말 하나 안 보태고 100번은 했던 것 같습니다. 그래도 한편을 완성하니 생각보다 더 뿌듯하네요! 앞으로 연재할 내용 중에 혹시 이해가 어렵거나 궁금한 점이 있으시다면 제 페이스북과 블로그를 통해 편하게 연락해주세요. 제가 공유해둔 여러 컨테이너 기술 정보도 확인하시고요. :-)
마지막으로, 컨테이너의 세계로 여행을 시작하는 여러분들 환영합니다. 앞으로 즐거운 여정이 될 수 있도록 잘 가이드 해보겠습니다!
참고 자료
- Mastering KVM Virtualization (2016) by Humble 외
- Xen으로 배우는 가상화 기술의 이해 (2014) by 박은병, 김태훈 외
- 그림으로 배우는 클라우드 인프라와 API의 구조 (2017) by 히라야마 쯔요시 외
- 오픈스택을 다루는 기술 (2017) by 장현정
- Large-scale cluster management at Google with Borg (2015) by Eric Tune 외
- Performance Evaluation of Docker Container and Virtual Machine (2020) by Amit MPotdar 외
- Container’s Anatomy (2015, slideshare) by Jérôme Petazzoni
- Linux Container Performance Analysis (2017, 유튜브) by Brendan Gregg
- Docker overview (도커 공식 사이트)