container runtime에 대하여 - Part1 OCI & CRI & Container runtime

양승현·2023년 9월 11일
1

kubernetes

목록 보기
12/18
post-thumbnail

컨테이너의 표준 OCI (Open Container Initiative) 등장

  • Container라는 개념이 생긴 초반 많은 IT 회사들은 컴퓨터 전체를 가상화하는 가상머신에 비해 오버헤드가 적은 container 기술 기반의 제품을 출시하였다.
container란
hostOS의 커널을 공유하며, 애플리케이션과 바이너리, 라이브러리 등을 패키지로 묶어 배포하는 컨테이너는 서로 다른 컴퓨팅 환경에서 애플리케이션을 안정적으로 실행할 수 있으며 개발 환경에 구애 받지 않고 빠른 개발과 배포가 가능하다는 장점이 있다.
  • 하지만 container 기술(포맷과 런타임)에 대한 확실한 규격이 없었기 때문에, container runtime 별로 서로 다른 interface를 가지며 중구난방화 되었고 이에 주요 IT업체(Redhat, Docker ETC)들은 가상머신과 마찬가지로 컨테이너도 컨테이너 내부에 저장되는 소프트웨어를 담고 있는 파일들을 패키징할 수 있는 container 포맷과 런타임에 대한 개방형 업계 표준을 만들기위해 OCI를 구성하였다.
이 과정에서 kubernetes project는 컨테이너 런타임이 kubernetes와 함께 작동할 수 있는 표준 API를 제공하는 CRI(Container Runtime Interface)를 구현하여 kubelet과 Container Runtime 간의 호환이 될 수 있었다.
  • 이후 OCI는 컨테이너 런타임 명세와 이미지 명세를 준수하는 표준을 제시하고 있으며, 현재 대부분의 컨테이너 런타임은 이를 따르고 있다.
현재 OCI는 Linux Foundation 산하의 오픈 소스 단체이다.
  • 간략하게 설명하자면 컨테이너 런타임에 대한 표준이다.

OCI 표준 요구 사항

  • OCI 표준 컨테이너가 만족해야할 5가지 원칙이 존재한다.
원칙내용
표준 동작(Standard Operations)• 표준 컨테이너 도구들을 이용해서 컨테이너의 생성, 시작, 정지가 가능해야 함
• 표준 파일 시스템 도구를 통해서 컨테이너의 스냅샷과 복사가 가능해야 함
• 표준 네트워크 도구들을 통해서 컨테이너의 업로드와 다운로드가 가능해야 함
내용 중립성(Content-agnostic)• 표준 컨테이너는 컨테이너가 담고 있는 애플리케이션의 종류에 상관없이 표준 동작들이 동일하게 동작해야 함
인프라 중립성(Infrastructure-agnostic)• 표준 컨테이너는 OCI 지원 인프라라면 종류에 상관없이 컨테이너 실행이 가능해야 함
자동화를 위한 설계(Designed for Automation)• 표준 컨테이너는 컨테이너 내용과 인프라 종류에 상관없이 동일한 표준 동작을 지원하기때문에 자동화가 용이함
산업 수준의 배포(Industrygrade delivery)• 표준 컨테이너는 기업 규모에 상관없이 산업 수준의 배포가 가능해야 함

[출처] 클라우드 상호운용성 확보 가이드라인 Vol.2(2017) – 한국정보통신기술협회(TTA)


CRI (container runtime interface)

  • 초기 kubernetes에서는 Docker를 컨테이너 런타임으로 사용하기 위해 dockershim과 같은 도구를 kubelet 소스 코드 내부에 하드 코딩으로 통합되어 구현되었는데, docker engine의 인터페이스 변경에 맞게 계속해서 수정하여 사용하였다.
  • 이렇게 통합된 프로세스는 kubelet에 대한 깊은 이해가 필요했고 kubernetes 커뮤니티에 상당한 유지보수 오버헤드를 발생시켰으며, kubernetes는 계속해서 다양한 container runtime마다 kubelet을 수정하여 kubelet과 통합하기에는 무리가 있었기 때문에, kubernetes에서는 kubelet의 수정없이 여러 container runtime을 지원하기 위해 kubelet과 container runtime간의 통신을 위한 주요 gRPC 프로토콜을 정의하였는데 이것이 CRI이다.
  • container runtime들은 해당 CRI의 스펙에 맞추어 CRI 컴포넌트를 구현하여 쉽게 kubelet과 호환될 수 있었으며, containerd, CRI-O와 같은 container runtime들은 CRI 규격에 맞게 인터페이스를 구현하고 있다.
  • kubelet은 CRI에 출실한 인터페이스를 통해 컨테이너 런타임들과 통신하여 컨테이너를 관리하는 동작을 수행할 수 있다.
- CRI를 간단히 요약하면 클러스터 컴포넌트를 다시 컴파일하지 않아도 쿠버네티스(Kubelet)이 다양한 컨테이너 런타임을 사용할 수 있도록 하는 플러그인 인터페이스 정의이다.

  • kubernetes에서 container runtime은 kubelet과 통신하여 컨테이너를 생성, 종료하고 관리하는 동작을 실행하며, 파드가 노드에서 실행될 수 있도록 클러스터의 각 노드에 컨테이너 런타임(고수준 & 저수준 컨테이너 런타임)을 설치해야 한다.
$ grep containerd k8s-cluster.yml
## docker for dockershim, CRIO for CRI-O and containerd for containerd
## Default: containerd
container_manager: containerd 

컨테이너 관리 시스템

  • 컨테이너 관리 시스템은 세가지 계층으로 나눌 수 있다.
  • High-level Container Management와 Container Engine 간의 인터페이스 사양은 CRI이다.
  • Container Engine과 Container Runtime 간의 인터페이스 사양은 OCI이다.

High-level Container Managemen

  • 컨테이너 관리 및 제어를 위한 UI 레이어이다.
  • 사용자에게 가장 친숙한 하위 시스템이기도 한 컨테이너의 관리, 제어 및 사용 인터페이스를 직접 구현한다.

High-level & Low-level container runtime

  • 위 사진은 이지미가 컨테이너로 실행되는 과정이다.
  • docker는 이미지 압축, 압축 해제, 컨테이너 실행 단계 중 컨테이너 실행(3번) 부분만을 표준화 하였고, 이로 인해 런타임은 고수준(high-level) 컨테이너 런타임과 OCI 표준화된 저수준(Low-level) 컨테이너 런타임으로 나뉘게 되었다.
저수준 - 실제 컨테이너로 실행하는 역할  EX) runc (OCI 표준)
고수준 - 이미지 전송, 이미지 관리, 이미지 압출 풀기, 실행 중인 컨테이너들의 모니터링 및 관리, 이미지 실행과 관련된 API 제공 등 EX) containerd(OCI 표준), CRI-O(OCI 표준)

저수준(Low-level) 컨테이너 런타임

  • 컨테이너 실행 계층이며, 구체적으로 컨테이너 실행 환경을 구축하고 컨테이너 프로세스를 실행하는 일을 담당한다.
  • 이 레이어를 간단히 컨테이너 런타임이라고 부르는 것이 일반적이다.
  • 컨테이너는 linux namespace와 cgroups를 통해 구현된다.
namespace - 각 컨테이너에 대해 파일 시스템이나 네트워킹과 같은 시스템 리소스를 가상화
cgroups - 각 컨테이너가 안에서 사용할 수 있는 리소스(cpu, memory)의 양을 제한하는데 사용
  • 저수준(Low-level) 컨테이너 런타임은 이 namespace와 cgroup을 설정한 다음 해당 namespace 및 cgroup 내에서 명령을 실행한다.
  • 대표적인 저수준(Low-level) 컨테이너 런타임 runc는 도커에서 컨테이너 실행을 위해 개발됬으나, OCI 런타임 표준을 위해 독립적인 라이브러리로 사용 되었다.
  • 저수준(Low-level) 컨테이너 런타임은 컨테이너를 실행하는 역할을 하지만, 이미지로부터 컨테이너를 실행하기 위해서는 고수준(high-level) 컨테이너 런타임을 필요로 한다.

고수준(high-level) 컨테이너 런타임

  • 컨테이너 상태 및 리소스 공급. 이미지 관리, 네트워크 액세스, 컨테이너 상태, 저수준 런타임 호출을 포함하여 컨테이너 및 기타 기능을 실행한다.
  • 이 레이어를 컨테이너 엔진(Container Engine)이라고 부르는 것이 일반적이다.
  • 컨테이너 엔진의 핵심은 컨테이너를 실행하고 컨테이너 수명주기를 관리하는 데 필요한 리소스를 준비하는 것이다.
  • kubernetes 생태계에서 컨테이너 오케스트레이션 시스템은 CRI 인터페이스를 통해 컨테이너 엔진을 호출한다.
  • CRI 인터페이스를 지원하는 컨테이너 엔진으로는 주로 docker, rkt, 파우치, Containerd, cri-o 등이 있으며, 그 중 Containerd와 CRI-O가 가장 활발하게 사용되고 있다.
  • 이미지 관리, 압축 해제, 저수준(Low-level) 컨테이너 런타임으로 전달 등 저수준(Low-level) 컨테이너 런타임보다 더 고수준의 작업을 수행한다.
  • 보통 Daemon Process 형태로 동작하며, Remote API를 제공하여 외부에서 컨테이너를 실행하거나 모니터링이 가능하다.
  • container를 실행하기 위해 저수준(Low-level) 컨테이너 런타임 위에 배치된다.
  • 컨테이너 실행을 위해서는 저수준(Low-level) 컨테이너 런타임과 고수준(high-level) 컨테이너 런타임이 필요한데, kubernetes v1.24 이전에서는 OCI 런타임과 함께 docker가 해당 역할을 하였다.
  • 도커는 고수준(high-level) 컨테이너 런타임인 docker-containerd를 제공하였으며, contanerd도 저수준(Low-level) 컨테이너 런타임인 runc와 마찬가지로 도커에서 컨테이너 실행을 위해 개발되었으나 독립적인 라이브러리로 사용되었다.

kubernetes에서 docker 지원을 중단한 이유

  • 컨테이너는 runtime engine 위에서 관리된다.
  • 런타임 엔진은 컨테이너와 하드웨어의 사이 중간에 있으며, 서로 간의 통신을 하여 컨테이너가 필요한 연산을 할 수 있도록 한다.
  • 대표적인 컨테이너 런타임 엔진으로 containerd, runc, cri-o가 있다.
  • Docker engine도 컨테이너 런타임 엔진이며 containerd와 runc를 포함하고 있다.
  • containerd와 runc는 OCI를 충족하는 프로그램으로 Docker Engine은 하나의 패키지가 아닌 containerd(고수준)와 runC(저수준)로 각각 나뉘어 컨테이너를 관리한다.
  • 초기 docker engine은 사용자의 편의성을 위해 docker engine 패키지에 컨테이너 관리 도구들을 담았는데, 이후 컨테이너 오케스트레이션 도구인 kubernetes가 컨테이너 관리 도구로 docker를 채택해 호환성을 제공하였다.
  • docker는 CRI 사양이 발명되기 전에 존재했기 때문에, 쿠버네티스 프로젝트는 어댑터 구성 요소인 dockershim을 만들었고, dockershim 어댑터는 kubelet이 docker가 CRI 호환 런타임인 것처럼 docker와 상호 작용할 수 있게 해주었다.
  • 하지만 docker가 버전 업데이트를 하면 kubernetes와의 의존성 문제가 생겨나기 시작했다.
  • kubernetes에서는 컨테이너를 동작시키기 위해 docker만이 아닌 CRI 사양에 맞는 containerd와 같은 컨테이너 런타임만을 사용해 업데이트 혹은 다른 런타임을 통해 교체하여 컨테이너를 만들 수 있었다.
  • CRI는 이런 종류의 유연성을 허용하도록 설계되었고, kubelet은 CRI를 지원하기 시작했다.
  • 이에 Docker(dockershim)를 지속적으로 지원하는 것은 비효율적이고 불필요하다고 판단하여 현재 kubernetes는 v1.24부터 docker를 지원하지 않는다.
  • docker는 CRI는 준수하지 않았지만 OCI는 준수하고 있기 때문에, docker를 통해서 빌드한 이미지들도 OCI 표준을 따르는 다른 컨테이너 런타임(containerd or CRI-O)들을 통해서 그대로 사용할 수 있다.

0개의 댓글