가상화와 도커, 그리고 쿠버네티스

이숭늉·2025년 5월 21일
0

DevOps

목록 보기
7/19
post-thumbnail

🖥️ 가상화와 도커, 그리고 쿠버네티스

도커, 쿠버네티스를 활용해 서비스는 배포해봤지만, 막상 도커랑 쿠버네티스에 대해 설명해보라는 질문에는 명확히 답하지 못할 것 같았다.
그래서 관련 영상과 서적을 참고해서 이론적인 이해를 보완하려 한다.


💭 가상화 Virtualization

가상화(Virtualization)란 컴퓨터에서 활용하는 리소스를 추상화하는 개념을 의미하는 용어이다. 가상화 개념을 활용해 여러 개의 가상머신을 생성함으로써, 단일 컴퓨팅 자원을 여러 개의 논리적인 자원으로 나누어 동작시킬 수 있다.

탄생 배경

이러한 가상화의 탄생 배경을 살펴보면 때는 1960-70년, 그 당시 소프트웨어의 발전 속도는 하드웨어의 발전 속도를 따라가지 못했다. 소프트웨어가 요구하는 서버 사양에 비해 소프트웨어를 실행 중인 하드웨어의 성능이 훨씬 좋다 보니, 서버의 성능을 10% 수준밖에 활용하지 못하는 엄청난 비효율이 발생했다. 그리하여 하드웨어를 효율적으로 사용하기 위해, 한 대의 서버를 마치 여러 대의 서버처럼 사용할 수 있는 가상화라는 개념이 등장했다고 한다.

가상화의 3가지 방식

이 글의 주제인 서버 가상화 기술은 구현 방식에 따라 다음 3가지로 나눌 수 있다.

  • 호스트 가상화 (Host Virtualization)
  • 하이퍼바이저 가상화 (Hypervisor Virtualization)
  • 컨테이너 가상화 (Container Virtualization)

1. 호스트 가상화 (Host Virtualization)

  • 기존 호스트 운영체제 위해 VirtualBox, VMware 같은 가상화 소프트웨어를 설치하여 사용하는 방식이다.
  • 가상화 소프트웨어는 하이퍼바이저 역할을 하며, 이를 통해 게스트 운영체제를 실행할 수 있다.
    ※ 하이퍼바이저는 하드웨어 위에서 운영체제를 동시에 실행할 수 있도록 관리하는 소프트웨어이다.
  • 장점 : 간단하게 설치하고 사용 가능
  • 단점 : 성능이 낮고, 호스트 OS가 무거우면 전체 시스템 성능 저하

2. 하이퍼바이저 가상화 (Hypervisor Virtualization)

  • 하드웨어(Bare Metal)에 직접 하이퍼바이저를 설치하여 가상 머신을 실행하는 방식이다.
  • 별도의 호스트 OS가 없기 때문에 자원을 효율적으로 사용할 수 있으며, 성능이 뛰어나 클라우드 서비스 업체(AWS, Azure 등)의 기반이 됨.

하이퍼바이저 가상화는 다시 전가상화와 반가상화로 나눌 수 있다.

2-1. 전가상화(Full Virtualization)

  • CPU 명령어까지 포함하여 하드웨어 전체를 완전하게 가상화
  • 게스트 OS는 하드웨어가 진짜인 줄 착각함.
  • 각 VM이 완전히 독립된 환경에서 실행되며, 게스트 OS는 수정 없이 그대로 사용 가능.
  • 단점 : 하이퍼바이저가 모든 명령어를 중간에서 처리해야 하므로 느림.
  • ex : 게스트 OS → "CPU야, 이 명령 실행해줘!" → 하이퍼바이저가 가로채서 대신 실행 → 게스트 OS는 진짜 하드웨어인 줄 앎

2-2. 반가상화(Para Virtualization)

  • 하드웨어 일부만 가상화하고, 게스트 OS가 하이퍼바이저와 직접 통신
  • 게스트 OS가 가상 환경에서 돌고 있음을 인지함.
  • 더 가볍고 빠르지만 게스트 OS가 하이퍼바이저 API를 알아야 하므로 수정이 필요함.
  • ex : 게스트 OS -> "하이퍼바이저야, 이 명령 실행해줘!" -> 하이퍼바이저가 직접 처리 -> 중간 단계 생략, 더 빠름

⇒ 결국 둘 다 게스트 OS와 하이퍼바이저가 소통함.

  • 다만, 전가상화는 하드웨어가 진짜 있다고 생각하므로 CPU 명령이나 메모리 접근 등을 실제 하드웨어에 직접 요청하는 것처럼 동작하며, 하이퍼바이저의 존재를 모름
  • 반가상화는 가상 환경에 있음을 인지하고 있으므로, 하이퍼바이저에 직접 요청 API를 호출함.

이러한 하이퍼바이저 기반 가상화 방식은 OS 전체를 가상화하기 때문에, VM 하나당 하나의 게스트 OS가 필요하다. 하지만 실제 서비스에서는 OS 전체보다는 특정 어플리케이션을 실행하고자 하는 경우가 대부분이므로, 이처럼 OS까지 가상화하는 것은 리소스 측면에서 비효율적일 수 있다. 그리하여 OS 전체를 복제하지 않고, 어플리케이션이 실행되는 데 필요한 환경만 격리해서 제공하는 컨테이너 가상화 방식이 등장했다.

3. 컨테이너 가상화 (Container Virtualization)

  • OS 전체를 가상화하는 대신, 어플리케이션 실행에 필요한 라이브러리와 바이너리만 패키징한다.
  • 컨테이너는 호스트 OS의 커널을 공유하며, Namespace, cgroup, chroot 등을 활용해 각 컨테이너를 격리된 환경으로 만들어준다.
  • 이를 실행하고 관리하는 것이 바로 컨테이너 런타임(Container Engine)이며, 대표적인 기술이 도커이다.
  • 장점 : VM보다 훨씬 가볍고 빠름, 배포와 확장이 쉬움
  • 단점 : 커널 공유로 인해 OS 커널 버전 의존성이 존재

🐋 도커 Docker

  • 도커는 단순 런타임 이상으로 컨테이너 이미지를 빌드, 배포, 실행, 관리하는 오픈소스 기반의 플랫폼이다.

구성 요소

1. Docker CLI (도커 클라이언트)
도커 사용의 시작점은 docker build, docker run, docker pull 같은 명령어 입력이다. 이러한 명령어는 바로 도커 CLI를 통해 입력되며, 내부적으로는 Docker 데몬에게 REST API 요청을 보내는 역할을 한다.
즉, 도커 CLI는 사용자의 명령어르 도커 데몬에게 전달하는 맡단 인터페이스이자 명령어 해석기이다.

2. Docker Daemon (도커 데몬)
dockerd라고도 불리는 도커 데몬은 도커 CLI나 외부 클라이언트로부터 Docker API 요청을 받아 처리한다.
컨테이너 생성, 이미지 관리, 볼륨 생성, 네트워크 설정 등 거의 모든 작업을 총괄한다.

3. containerd
도커 데몬은 내부적으로 containerd라는 런타임에 명령어를 위임한다.
containerd는 컨테이너 실행 및 관리에 특화된 고수준 런타임으로 이미지 풀링, 컨테이너 수명주기 관리 같은 역할을 한다.

4. runc
runc는 컨테이너를 실제로 생성하고 실행하는 저수준 런타임이다. 리눅스의 네임스페이스, cgroup 같은 커널 기능을 직접 제어하며 실제로 컨테이너를 띄운다.

5. container-shim
컨테이너 실행 중에는 runc가 필요하지만, runc는 일회성 실행 도구이다.
runc는 컨테이너를 실행할 때, 커널 기능을 설정하고, 컨테이너 프로세스를 fork/exec 해서 띄우고, 자기 자신은 종료된다. 따라서 runc는 실행 이후의 컨테이너 실행 이후의 stdout, stderr, 상태 추적 등을 관리할 수 없다.
그래서 container-shim가 컨테이너의 부모 프로세스가 되어 컨테이너의 로그를 받아서 containerd에게 전달하고, 컨테이너의 상태를 추적할 수 있다.

예를 들어, 사용자가 docker run라는 명령어를 입력하면
-> Docker CLI가 해당 명령을 파싱해 API 요청 생성
-> Docker Daemon이 요청 수신 후 containerd에 작업 요청
-> containerd가 runc 실행을 통해 컨테이너 시작
-> runc가 커널 기능을 통해 실제 컨테이너 생성
-> containerd-shim이 해당 컨테이너를 관리하며 stdout 등 중계

Docker가 컨테이너를 단일 단위로 실행하고 관리하는 데 탁월한 도구이지만, 점점 규모가 커지고 복잡해지는 실제 서비스 한경에서 수십, 수백 개의 컨테이너들을 실행하고 관리할 수 있는 도구가 필요했다. 이러한 이유로 등장한 것이 바로 Kubernetes이다.


🕸️ 쿠버네티스 Kubernetes

쿠버네티스는 단일 컨테이너가 아닌 컨테이너들의 집합, 즉 서비스 단위로 묶인 여러 컨테이너의 수명 주기 전체를 자동화하여 관리하는 오픈소스 플랫폼이다. 오토스케일링, 자동 복구, 롤링 업데이트, 서비스 디스커버리, 로드밸런싱 등의 다양한 기능을 제공한다.

구조

쿠버네티스는 마스터-노드 구조를 기반으로 동작한다.

Control Plane (제어 플레인)

  • 클러스터 전체 상태를 관리하는 두뇌
  • 모든 컴포넌트 간 통신을 중계하는 kube-apiserver, 클러스터의 상태를 저장하는 etcd, 파드가 어느 노드에 배치될지 결정하는 scheduler 등으로 구성됨.

Worker Node (노드)

  • 실제 컨테이너가 실행되는 서버
  • 노드의 상태를 제어 플레인에 보고하고 명령을 수행하는 kubelet, 네트워크 라우팅 및 로드밸런싱을 담당하는 kube-proxy, 그리고 Container Runtime 등으로 구성됨.
  • 쿠버네티스는 더 가볍고 단순한 구조로 컨테이너를 실행하기 위해 런타임으로 도커가 아닌 도커 내부 핵심 런타임인 containerd만 사용한다.

이 글은 여기서 마치고 다음 글에서 각각 도커와 쿠버네티스에 대해 더 자세하게 작성해보도록 하겠다.

profile
부지런히 살자

0개의 댓글