CRI
1. 개요
1. 개요
CRI(Container Runtime Interface)는 쿠버네티스가 컨테이너를 실행하기 위해 사용하는 컨테이너 런타임과 통신하는 표준 인터페이스이다. 쿠버네티스의 핵심 컴포넌트인 kubelet이 다양한 컨테이너 런타임을 일관된 방식으로 제어할 수 있게 해주는 플러그인 메커니즘이다.
이 인터페이스는 주로 gRPC 프로토콜을 통해 정의되며, Pod와 컨테이너의 생명주기 관리(생성, 시작, 중지, 삭제), 이미지 관리(풀, 목록 조회, 삭제), 컨테이너 상태 및 로그 조회 등의 핵심 기능을 표준화한다. CRI의 도입 이전에는 쿠버네티스가 도커 엔진에 강하게 결합되어 있었으나, CRI는 런타임에 대한 의존성을 제거하고 다양한 런타임을 지원하는 유연한 아키텍처를 가능하게 했다.
CRI는 쿠버네티스 생태계에서 컨테이너 오케스트레이션 레이어와 실제 컨테이너 실행 레이어를 분리하는 중요한 추상화 계층 역할을 한다. 이를 통해 사용자는 애플리케이션의 요구사항이나 운영 환경에 맞춰 containerd, CRI-O 등의 런타임을 자유롭게 선택할 수 있다.
2. CRI의 등장 배경
2. CRI의 등장 배경
쿠버네티스 초기 버전은 컨테이너 런타임과의 통합을 위해 도커에 강하게 결합되어 있었다. 구체적으로, kubelet은 내부적으로 Docker Engine의 네이티브 API와 라이브러리를 직접 호출하여 파드와 컨테이너를 관리했다. 이 방식은 당시 가장 널리 사용되던 컨테이너 런타임인 Docker를 빠르게 지원할 수 있다는 장점이 있었지만, 근본적인 유연성 문제를 야기했다.
다른 컨테이너 런타임(예: rkt)을 지원하려면 쿠버네티스 코어 코드 내에 해당 런타임 전용의 통합 코드를 추가해야 했다. 이는 코드베이스를 복잡하게 만들었을 뿐만 아니라, 새로운 런타임이 등장할 때마다 쿠버네티스 프로젝트 자체가 변경되어야 하는 번거로움과 유지보수 부담을 초래했다. 컨테이너 생태계가 성장하며 다양한 런타임(containerd, CRI-O 등)에 대한 요구가 증가하자, 이러한 강결합 아키텍처는 한계에 부딪혔다.
이러한 배경에서, 쿠버네티스는 컨테이너 런타임과의 통합 방식을 근본적으로 재설계하기로 결정했다. 그 결과물이 2016년 말 쿠버네티스 1.5 버전에서 알파 기능으로 도입된 CRI이다. CRI는 기본적으로 kubelet과 컨테이너 런타임 사이에 표준화된 gRPC 기반의 프로토콜을 정의한다. 이를 통해 kubelet은 내부 구현을 변경하지 않고도, CRI를 구현한 어떠한 컨테이너 런타임과도 통신할 수 있게 되었다.
CRI의 등장은 쿠버네티스 생태계에 큰 전환점을 가져왔다. 이 표준 인터페이스를 통해 런타임 제공자는 쿠버네티스 코어에 기여하지 않고도 독자적으로 호환 가능한 런타임을 개발하고 유지보수할 수 있게 되었다. 이는 곧 컨테이너 런타임 영역에서의 건강한 경쟁과 혁신을 촉진했으며, 쿠버네티스가 다양한 배포 환경과 요구사항에 더욱 잘 적응할 수 있는 기반을 마련했다.
3. CRI의 주요 구성 요소
3. CRI의 주요 구성 요소
CRI는 gRPC 기반의 프로토콜로 정의되며, 주로 두 가지 핵심 서비스 인터페이스를 통해 쿠버네티스 kubelet과 컨테이너 런타임 간의 통신을 표준화한다.
첫 번째 핵심 구성 요소는 런타임 서비스(RuntimeService)이다. 이 서비스는 컨테이너와 Pod의 라이프사이클을 직접 관리하는 책임을 진다. 주요 기능으로는 Pod 샌드박스(인프라 컨테이너)의 생성과 삭제, Pod 내에서의 일반 컨테이너 생성/시작/중지/삭제, 컨테이너 실행 정보 및 로그 스트림 조회, 컨테이너 내에서의 명령어 실행(exec) 등이 포함된다. 런타임 서비스는 컨테이너가 실행되는 환경을 구축하고 관리하는 모든 작업을 처리한다.
두 번째 핵심 구성 요소는 이미지 서비스(ImageService)이다. 이 서비스는 컨테이너 이미지의 저장소로부터의 가져오기(pull), 로컬 시스템 내 이미지 목록 조회, 이미지 상태 확인 및 불필요한 이미지 삭제 등의 작업을 담당한다. 이미지 서비스는 컨테이너 실행에 필요한 애플리케이션 패키지인 이미지를 관리하는 레이어를 제공하며, 런타임 서비스와 분리되어 있어 이미지 관리의 효율성과 보안성을 높인다.
이 두 서비스는 아래 표와 같은 범주의 작업을 정의한다.
서비스 인터페이스 | 주요 작업 범주 | 예시 메서드 |
|---|---|---|
RuntimeService | Pod 샌드박스 관리 |
|
컨테이너 라이프사이클 |
| |
상태 정보 조회 |
| |
실행 및 로그 |
| |
ImageService | 이미지 관리 |
|
이러한 명확한 인터페이스 분리는 쿠버네티스가 다양한 컨테이너 런타임을 유연하게 지원하면서도 일관된 방식으로 컨테이너 오케스트레이션을 수행할 수 있는 기반을 마련한다.
3.1. 런타임 서비스 (RuntimeService)
3.1. 런타임 서비스 (RuntimeService)
런타임 서비스는 CRI의 핵심 구성 요소 중 하나로, 컨테이너와 Pod의 라이프사이클을 관리하는 기능을 제공합니다. 이 서비스는 쿠버네티스의 kubelet이 gRPC 프로토콜을 통해 호출하는 일련의 API로 정의됩니다.
주요 기능은 다음과 같습니다.
기능 | 설명 |
|---|---|
PodSandbox 관리 | Pod의 격리된 실행 환경인 PodSandbox를 생성, 시작, 중지, 삭제합니다. |
컨테이너 관리 | PodSandbox 내에서 개별 컨테이너를 생성, 시작, 중지, 삭제합니다. |
상태 조회 | 실행 중인 PodSandbox와 컨테이너의 상태 및 목록을 조회합니다. |
실행 명령 | 실행 중인 컨테이너 내에서 명령어를 실행합니다. |
로그 스트리밍 | 컨테이너의 표준 출력(stdout) 및 표준 에러(stderr) 로그를 스트리밍합니다. |
이 서비스를 통해 kubelet은 특정 컨테이너 런타임(containerd, CRI-O 등)의 내부 구현 세부사항을 알 필요 없이, 표준화된 인터페이스만으로 컨테이너를 제어할 수 있습니다. 예를 들어, RunPodSandbox 호출은 리눅스 환경에서 네임스페이스와 cgroups를 설정하는 작업에 대응하며, 그 안에서 CreateContainer와 StartContainer 호출이 이어져 애플리케이션 컨테이너가 실행됩니다.
3.2. 이미지 서비스 (ImageService)
3.2. 이미지 서비스 (ImageService)
이미지 서비스는 컨테이너 런타임 인터페이스 스펙에서 정의된 두 가지 핵심 gRPC 서비스 중 하나이다. 이 서비스는 컨테이너 이미지의 생명주기 관리에 대한 표준화된 작업을 제공한다. 주요 책임은 컨테이너 실행에 필요한 컨테이너 이미지를 레지스트리에서 가져오고(pull), 로컬 시스템에서 관리하며, 더 이상 필요하지 않을 때 제거하는 것이다.
이미지 서비스가 제공하는 주요 메서드는 다음과 같다.
메서드 | 주요 기능 |
|---|---|
| 지정된 이미지 참조(예: |
| 로컬에 캐시된 모든 컨테이너 이미지 목록을 반환한다. |
| 특정 이미지의 상세 정보(이미지 ID, 크기, 태그 등)를 조회한다. |
| 로컬 시스템에서 지정된 이미지를 삭제한다. |
| 이미지가 저장된 파일 시스템의 사용량 정보를 반환한다. |
이 서비스는 쿠버네티스의 kubelet이 컨테이너 실행 전에 필요한 이미지를 확보하는 과정을 추상화한다. 예를 들어, 파드 명세에 nginx:latest 이미지가 정의되어 있으면, kubelet은 CRI를 통해 런타임의 이미지 서비스에 PullImage 요청을 보낸다. 이후 실제 풀 작업과 이미지 저장 형식(예: OCI 이미지 형식)은 각 CRI 구현체(containerd, CRI-O 등)가 담당한다. 이를 통해 쿠버네티스는 다양한 컨테이너 런타임과 이미지 형식을 일관된 방식으로 사용할 수 있다.
4. 주요 CRI 구현체
4. 주요 CRI 구현체
CRI의 주요 구현체는 쿠버네티스 클러스터에서 컨테이너 런타임을 통합하는 데 사용되는 소프트웨어 구성 요소이다. 각 구현체는 CRI gRPC API를 준수하면서도 설계 철학과 관리 복잡도에서 차이를 보인다.
가장 널리 사용되는 구현체는 다음과 같다.
구현체 | 설명 | 주요 특징 |
|---|---|---|
도커(Docker)에서 분리된 산업 표준 컨테이너 런타임 | 성능과 안정성이 뛰어나며, OCI 표준을 완벽히 준수함. 현재 쿠버네티스의 사실상(de facto) 표준 런타임이다. | |
쿠버네티스 전용으로 설계된 경량화된 CRI 구현체 | 불필요한 기능을 제거하여 가볍고 보안에 중점을 둠. OpenShift 및 다른 쿠버네티스 배포판에서 사용된다. | |
Docker Engine (via dockershim) | 과거에 널리 사용된 방식 | CRI를 직접 지원하지 않는 Docker Engine을 위해 쿠버네티스 노드 에이전트(kubelet) 내에 포함된 어댑터 컴포넌트였다. 현재는 사용이 중단되었다[1]. |
containerd는 풍부한 기능 세트와 생산 환경에서 검증된 성능으로 인해 가장 일반적인 선택이다. CRI-O는 쿠버네티스와의 긴밀한 통합과 최소한의 설계 원칙을 추구하는 환경에서 선호된다. 과거에는 Docker Engine을 사용하기 위한 임시 방편으로 dockershim이 널리 사용되었지만, 이는 유지보수 부담을 초래했고 결국 표준화된 CRI 구현체로의 전환을 촉진하는 계기가 되었다. 이러한 구현체들의 경쟁과 발전은 CRI 생태계의 건강성과 혁신을 이끌었다.
4.1. containerd
4.1. containerd
containerd는 리눅스와 윈도우를 위한 산업 표준 컨테이너 런타임이다. 2017년 도커(Docker)로부터 분리되어 독립적인 오픈소스 프로젝트로 발전했으며, 현재 클라우드 네이티브 컴퓨팅 재단(CNCF)의 졸업 프로젝트이다. 이는 CRI를 완벽하게 구현하여 쿠버네티스와의 통합을 핵심 목표로 삼았다.
containerd는 높은 수준의 안정성, 성능 및 확장성을 제공한다. 주요 아키텍처는 데몬 프로세스(containerd)와 클라이언트 라이브러리(ctr, crictl)로 구성된다. 내부적으로는 이미지 전송 및 관리, 컨테이너 실행과 생명주기 관리, 로컬 스토리지 및 네트워크 인터페이스 관리 등의 핵심 기능을 모듈화된 방식으로 처리한다. 쿠버네티스는 kubelet 내의 CRI 플러그인(containerd/cri)을 통해 containerd의 gRPC API를 호출하여 파드(Pod)와 컨테이너를 관리한다.
다른 런타임과 비교했을 때 containerd의 주요 특징은 다음과 같다.
특징 | 설명 |
|---|---|
아키텍처 | 도커 엔진에 비해 경량화되고 모듈화된 설계를 채택했다. |
성능 | 직접적인 통합으로 인해 오버헤드가 적고 시작 속도가 빠르다. |
안정성 | CNCF 졸업 프로젝트로서 대규모 프로덕션 환경에서 광범위하게 검증되었다. |
기능 범위 | 컨테이너 런타임의 핵심 기능에 집중하며, 고급 기능은 플러그인을 통해 확장한다. |
이러한 특징으로 인해 containerd는 많은 클라우드 서비스 제공자와 엔터프라이즈 쿠버네티스 배포판의 기본 런타임으로 채택되고 있다. 또한 OCI 표준 런타임 스펙(예: runc)을 하위 구성 요소로 사용하여 컨테이너를 실제로 실행함으로써 개방성과 호환성을 유지한다.
4.2. CRI-O
4.2. CRI-O
CRI-O는 쿠버네티스를 위한 경량 컨테이너 런타임 인터페이스 구현체이다. 리눅스 기반 시스템에서 쿠버네티스 kubelet이 컨테이너를 실행하고 관리하기 위해 설계된 오픈소스 소프트웨어이다. CRI-O는 쿠버네티스 CRI 명세를 완전히 준수하며, OCI 호환 런타임을 사용하여 컨테이너를 직접 실행하는 데 특화되어 있다.
주요 구성 요소로는 kubelet과의 통신을 담당하는 CRI 인터페이스 서버, 컨테이너 이미지 관리를 위한 라이브러리, OCI 런타임을 관리하는 중간 계층, 그리고 컨테이너 네트워크 인터페이스를 설정하는 모듈 등이 포함된다. 일반적으로 기본 OCI 런타임으로 runc를 사용하며, Podman의 이미지 라이브러리를 활용한다. 이는 도커 엔진과 같은 모놀리식 런타임에 비해 의존성이 적고, 쿠버네티스에 최적화된 간결한 아키텍처를 특징으로 한다.
특징 | 설명 |
|---|---|
목표 | 쿠버네티스 전용 경량 런타임 |
아키텍처 | |
주요 구성 요소 | CRI 서버, 이미지 라이브러리, 컨테이너 런타임 관리자 |
기본 OCI 런타임 | |
주요 사용처 | OpenShift, 베어메탈 쿠버네티스, 보안이 중요한 환경 |
CRI-O는 안정성과 보안에 중점을 두어 개발되었다. 불필요한 기능을 제거함으로써 공격 표면을 줄이고, 컨테이너 생명주기 관리가 쿠버네티스의 요구에 집중된다. 이로 인해 레드햇 OpenShift를 비롯한 여러 엔터프라이즈급 쿠버네티스 배포판에서 선호하는 런타임으로 채택되었다. 또한 containerd와 함께 쿠버네티스 생태계에서 가장 널리 사용되는 CRI 구현체 중 하나이다.
4.3. Docker Engine (via dockershim)
4.3. Docker Engine (via dockershim)
도커 엔진은 초기 쿠버네티스의 기본 컨테이너 런타임이었다. 그러나 쿠버네티스가 CRI를 도입하면서, 도커 엔진은 CRI를 직접 지원하지 않아 호환성 문제가 발생했다. 이 문제를 해결하기 위해 쿠버네티스 프로젝트는 dockershim이라는 특별한 어댑터 컴포넌트를 개발하여 통합했다.
dockershim은 쿠버네티스의 kubelet에 포함된 코드로, CRI API 요청을 도커 엔진이 이해할 수 있는 형식으로 변환하는 역할을 했다. 이는 도커 엔진이 OCI 표준 런타임인 containerd를 내부적으로 사용했음에도 불구하고, 쿠버네티스가 도커 고유의 API와 통신해야 하는 간접 계층을 만들어냈다. 결과적으로 이 아키텍처는 불필요한 복잡성을 증가시키고 유지보수 부담을 키우는 원인이 되었다.
쿠버네티스 커뮤니티는 이러한 복잡성을 줄이고 CRI를 완전히 준수하는 런타임으로의 이전을 장려하기로 결정했다. 이에 따라 dockershim은 쿠버네티스 1.20 버전에서 사용 중단(deprecated)되었으며, 1.24 버전에서 완전히 제거되었다[2]. 이 변경으로 인해 사용자는 containerd나 CRI-O와 같은 직접적인 CRI 구현체로 전환해야 했다.
dockershim의 제거는 쿠버네티스 생태계의 성숙을 상징하는 중요한 사건이었다. 이는 CRI 표준의 중요성을 강화하고, 보다 가볍고 효율적인 런타임 아키텍처로의 전환을 촉진했다. 도커 엔진 자체는 여전히 개발 도구나 독립적인 컨테이너 플랫폼으로 사용될 수 있지만, 쿠버네티스 클러스터 내에서는 표준화된 CRI 런타임을 사용하는 것이 권장된다.
5. CRI의 동작 원리
5. CRI의 동작 원리
쿠버네티스 컨트롤 플레인의 kubelet은 파드 명세를 받으면, gRPC를 통해 CRI를 구현한 런타임의 RuntimeService 인터페이스를 호출한다. 첫 단계는 RunPodSandbox 메서드를 호출하여 파드의 실행 환경인 파드 샌드박스를 생성하는 것이다. 이 샌드박스는 파드 수준의 네트워크 네임스페이스와, 필요시 오버레이 파일시스템을 제공하는 컨테이너로, 파드 내 모든 컨테이너가 공유하는 기반 환경이 된다.
파드 샌드박스가 준비되면, kubelet은 파드 내 각 컨테이너를 순차적으로 생성한다. 이 과정은 주로 두 단계로 이루어진다. 먼저 PullImage 메서드를 통해 이미지 서비스에 특정 컨테이너 이미지를 풀하도록 요청한다. 이미지가 로컬에 존재하면 이 단계는 생략될 수 있다. 그 다음, CreateContainer 메서드를 호출하여 풀된 이미지와 컨테이너 실행 명령어, 자원 제한 등의 설정을 전달한다. CRI 런타임은 이 정보를 바탕으로 OCI 호환 런타임 스펙을 생성하고, 하부의 컨테이너 런타임(예: runc)에게 컨테이너를 생성하도록 지시한다. 마지막으로 kubelet은 StartContainer 메서드를 호출하여 생성된 컨테이너를 실행한다.
파드와 컨테이너의 생명주기 동안 kubelet은 CRI 인터페이스를 통해 지속적으로 상태를 모니터링하고 관리한다. 주요 작업은 다음과 같다.
작업 | 메서드 | 설명 |
|---|---|---|
상태 조회 |
| 샌드박스와 컨테이너의 실행 상태, IP 주소, 시작 시간 등을 확인한다. |
로그 수집 |
| 컨테이너의 표준 출력(stdout)과 표준 오류(stderr) 로그를 스트리밍하여 가져온다. |
명령 실행 |
| 실행 중인 컨테이너 내에서 특정 명령어를 실행한다(예: 진단 목적). |
리소스 정리 |
| 컨테이너나 파드를 중지시키고, 관련 리소스를 삭제한다. |
이러한 일련의 과정을 통해 kubelet은 다양한 하부 컨테이너 런타임의 구체적인 구현 차이를 신경 쓰지 않고, 일관된 방식으로 파드와 컨테이너를 관리할 수 있다.
5.1. Pod 생성 및 관리 흐름
5.1. Pod 생성 및 관리 흐름
쿠버네티스의 컨트롤 플레인 컴포넌트인 kubelet은 파드 명세를 받으면, CRI를 통해 지정된 컨테이너 런타임과 통신하여 파드의 생명주기를 관리한다.
파드 생성 흐름은 일반적으로 다음과 같은 단계를 거친다.
1. 파드 샌드박스 생성: kubelet은 먼저 RuntimeService.RunPodSandbox RPC를 호출한다. 이 호출은 파드의 네트워크(CNI)와 리눅스 네임스페이스를 포함하는 격리 환경을 생성한다.
2. 컨테이너 생성: 샌드박스가 준비되면, 파드 명세에 정의된 각 컨테이너에 대해 RuntimeService.CreateContainer를 호출한다. 이때 컨테이너의 이미지, 명령어, 환경 변수, 마운트 포인트 등의 설정이 전달된다.
3. 컨테이너 시작: 생성된 컨테이너는 RuntimeService.StartContainer 호출을 통해 실행된다.
4. 상태 관리: kubelet은 주기적으로 RuntimeService.ListPodSandbox와 RuntimeService.ListContainers를 호출하여 파드와 컨테이너의 상태를 모니터링하고, 이상이 감지되면 복구 절차를 시작한다.
파드 삭제 시에는 역순으로 진행되어 컨테이너 중지, 컨테이너 삭제, 최종적으로 파드 샌드박스 삭제가 이루어진다. 이 모든 상호작용은 gRPC를 기반으로 한 표준 CRI 프로토콜을 통해 이루어지므로, kubelet은 내부 구현을 알 필요 없이 어떤 CRI 호환 런타임과도 동일한 방식으로 작업을 수행할 수 있다.
5.2. 이미지 풀 및 컨테이너 실행
5.2. 이미지 풀 및 컨테이너 실행
쿠버네티스 k블릿은 파드 명세에 정의된 컨테이너 이미지를 실행하기 위해, 컨테이너 런타임 인터페이스 클라이언트를 통해 CRI 런타임 서비스에 요청을 보냅니다. 이 과정은 크게 이미지 풀(Pull)과 컨테이너 생성(Create) 및 실행(Start) 단계로 나뉩니다.
먼저 이미지 풀 단계에서 k블릿은 RuntimeService.PullImage RPC 호출을 실행합니다. 이 호출에는 필요한 컨테이너 이미지의 참조(예: nginx:latest)와 인증 정보 등이 포함됩니다. CRI 런타임(예: containerd 또는 CRI-O)은 이 요청을 받아 지정된 컨테이너 레지스트리에서 이미지를 다운로드하고 로컬에 저장합니다. 이미지는 일반적으로 오픈 컨테이너 이니셔티브 이미지 표준 형식으로 관리됩니다. 이미지가 이미 로컬에 존재하는 경우, 런타임은 풀 과정을 생략할 수 있습니다.
이미지 준비 후, 컨테이너 실행 단계가 이어집니다. k블릿은 RuntimeService.CreateContainer 호출을 통해 컨테이너를 생성합니다. 이 호출에는 파드의 샌드박스 ID, 앞서 풀한 이미지 참조, 컨테이너 실행을 위한 명령어와 인자, 환경 변수, 마운트 포인트, 자원 제한 등 상세한 구성 정보가 포함됩니다. CRI 런타임은 이 정보를 바탕으로 OCI 호환 런타임 스펙 파일(예: config.json)을 생성하고, 하위 컨테이너 런타임(예: runc)을 호출하여 실제 컨테이너 프로세스를 생성합니다. 컨테이너는 먼저 정지된(created) 상태로 만들어지며, 최종적으로 RuntimeService.StartContainer RPC 호출이 이루어지면 지정된 명령어가 실행되어 컨테이너가 가동됩니다.
단계 | CRI RPC 호출 | 주체 | 주요 작업 |
|---|---|---|---|
이미지 가져오기 |
|
| 레지스트리에서 OCI 표준 이미지를 로컬로 다운로드 |
컨테이너 생성 |
|
| 이미지, 명령어, 자원 제한 등을 기반으로 OCI 런타임 번들을 생성하고 컨테이너를 생성(정지 상태) |
컨테이너 실행 |
|
| 생성된 컨테이너 내부에서 정의된 애플리케이션 프로세스를 시작 |
6. CRI의 장점과 가치
6. CRI의 장점과 가치
CRI는 쿠버네티스가 컨테이너 런타임을 사용하는 방식을 근본적으로 표준화하여 여러 가지 중요한 장점과 가치를 제공한다.
가장 큰 장점은 표준화와 이로 인한 유연성이다. CRI가 도입되기 전에는 쿠버네티스가 도커 엔진에 강하게 결합되어 있었다. CRI는 gRPC 기반의 명확한 API를 정의함으로써, 쿠버네티스 kubelet과 다양한 컨테이너 런타임 사이의 통신 인터페이스를 표준화했다. 이로 인해 사용자는 특정 런타임에 종속되지 않고, 자신의 요구사항에 가장 적합한 런타임을 자유롭게 선택할 수 있게 되었다. 예를 들어, 보안성이 강화된 CRI-O를 선택하거나, 성능과 안정성에 중점을 둔 containerd를 선택하는 것이 가능해졌다. 이는 쿠버네티스 생태계의 다양성과 유연성을 크게 증진시켰다.
또한, CRI는 커뮤니티 생태계의 활성화와 기술 혁신을 촉진하는 가치를 지닌다. 표준화된 인터페이스는 새로운 컨테이너 런타임 프로젝트의 진입 장벽을 낮춘다. 개발자들은 복잡한 쿠버네티스 내부 구조 전체를 이해할 필요 없이, CRI 명세를 구현하기만 하면 쿠버네티스와 호환되는 런타임을 만들 수 있다. 이는 가상 Kubelet이나 특정 하드웨어에 최적화된 런타임과 같은 혁신적인 프로젝트가 등장하는 토대를 마련했다. 결과적으로, 쿠버네티스는 단일 벤더의 기술에 의존하는 플랫폼에서 다양한 공급자와 프로젝트가 경쟁하고 협력하는 건강한 생태계 중심의 플랫폼으로 진화할 수 있었다.
마지막으로, CRI는 유지보수성과 업그레이드의 용이성을 향상시킨다. 런타임과 오케스트레이션 엔진의 관심사가 명확히 분리되면서, 각 구성 요소는 독립적으로 발전하고 업데이트될 수 있다. 쿠버네티스의 핵심 개발팀은 런타임의 세부 구현보다는 오케스트레이션 로직에 집중할 수 있고, 런타임 제공자는 CRI 명세를 준수하는 한 자유롭게 기능을 개선할 수 있다. 이는 시스템 전체의 안정성과 발전 속도를 높이는 데 기여한다.
6.1. 표준화와 유연성
6.1. 표준화와 유연성
쿠버네티스 생태계가 성장하면서 다양한 컨테이너 런타임이 등장했지만, 각 런타임은 쿠버네티스와 통합하기 위해 고유한 인터페이스를 필요로 했다. 이는 쿠버네티스 코드베이스의 복잡성을 증가시키고 새로운 런타임의 통합을 어렵게 만드는 문제점이었다.
CRI는 이러한 문제를 해결하기 위해 표준화된 gRPC 기반의 API를 정의한다. 이 표준 인터페이스를 통해 쿠버네티스 kubelet은 containerd, CRI-O 등 어떠한 CRI 호환 런타임과도 일관된 방식으로 소통할 수 있다. 결과적으로 쿠버네티스 코어 프로젝트는 런타임별 내부 코드를 유지 관리할 필요가 없어지고, 런타임 개발자는 표준 사양에 맞춰 구현하기만 하면 쉽게 통합할 수 있다.
이 표준화는 사용자에게 뛰어난 유연성을 제공한다. 사용자는 특정 애플리케이션 요구사항, 성능 특성, 보안 정책에 가장 적합한 컨테이너 런타임을 자유롭게 선택할 수 있다. 예를 들어, 보안이 중요한 환경에서는 gVisor나 Kata Containers 같은 격리 수준이 높은 런타임을, 성능이 중요한 환경에서는 가벼운 CRI-O를 선택할 수 있다. 이는 모든 워크로드에 단일 런타임을 강제하는 종속성에서 벗어나게 해준다.
표준화된 인터페이스는 혁신을 촉진한다. 런타임 벤더나 커뮤니티는 쿠버네티스 코어에 영향을 주지 않고 독자적으로 새로운 기능을 개발하고 최적화할 수 있다. 이는 OCI 표준과 함께 건강한 컨테이너 생태계의 기반을 마련했다.
6.2. 커뮤니티 생태계 활성화
6.2. 커뮤니티 생태계 활성화
CRI는 컨테이너 런타임과 오케스트레이션 플랫폼 사이에 명확한 표준 인터페이스를 정의함으로써, 다양한 런타임 구현체들이 경쟁하고 협력할 수 있는 생태계를 조성하는 데 기여했다. 이전에는 쿠버네티스가 특정 런타임(주로 Docker)에 강하게 결합되어 있어, 다른 런타임을 통합하는 과정이 복잡하고 번거로웠다. CRI는 이러한 종속성을 제거하고, 누구나 표준을 준수하는 런타임을 개발하여 쿠버네티스에 통합할 수 있는 길을 열었다.
이로 인해 containerd와 CRI-O 같은 경량화되고 특화된 런타임 구현체가 빠르게 등장하고 성장할 수 있었다. 각 구현체는 서로 다른 설계 철학과 최적화 포인트를 가지고 시장에서 경쟁하며, 이는 전반적인 컨테이너 런타임 기술의 발전과 성능 향상으로 이어졌다. 사용자는 애플리케이션의 요구사항과 운영 환경에 맞춰 가장 적합한 런타임을 자유롭게 선택할 수 있게 되었다.
구현체 | 주요 특징 | 관리 주체 |
|---|---|---|
산업계 표준, 안정성과 광범위한 생태계 지원 | CNCF (Cloud Native Computing Foundation) | |
쿠버네티스 네이티브, 경량화 및 보안에 중점 | 쿠버네티스 커뮤니티 |
이러한 개방형 생태계는 커뮤니티의 기여와 혁신을 촉진한다. 개발자와 기업들은 CRI 명세를 구현하거나, 기존 구현체의 기능을 개선하거나, 새로운 도구와 플러그인을 개발하는 방식으로 생태계에 참여한다. 결과적으로 쿠버네티스는 단일 벤더의 기술 로드맵에 구애받지 않고, 전체 커뮤니티의 집단 지성에 의해 진화하는 강력하고 유연한 플랫폼으로 자리 잡을 수 있었다.
7. CRI 사용 사례 및 배포 환경
7. CRI 사용 사례 및 배포 환경
CRI는 주로 쿠버네티스 클러스터의 노드에서 컨테이너 런타임을 운영하기 위해 사용된다. 가장 대표적인 사용 사례는 쿠버네티스의 kubelet이 CRI를 통해 다양한 컨테이너 런타임과 통신하여 Pod와 컨테이너의 생명주기를 관리하는 것이다. 이를 통해 사용자는 애플리케이션의 배포 플랫폼인 쿠버네티스는 그대로 유지하면서, 하부의 컨테이너 실행 엔진을 프로젝트 요구사항이나 선호도에 따라 containerd나 CRI-O 등으로 자유롭게 선택할 수 있다.
CRI를 지원하는 런타임의 선택은 배포 환경과 운영 목표에 따라 결정된다. 대규모 프로덕션 환경에서는 안정성과 성능, 간결한 아키텍처를 중시하여 containerd나 CRI-O가 널리 채택된다. 반면, 개발 환경이나 소규모 배포에서는 친숙성과 도구 생태계를 이유로 Docker Engine을 CRI 호환 모드(dockershim)로 사용하기도 했다[3].
다양한 퍼블릭 클라우드의 관리형 쿠버네티스 서비스와 주요 온프레미스 배포판은 CRI를 표준 인터페이스로 채택하고 있다.
배포 환경 | 일반적으로 사용되는 CRI 런타임 | 비고 |
|---|---|---|
Google Kubernetes Engine (GKE) | containerd | 기본 런타임으로 제공 |
Amazon Elastic Kubernetes Service (EKS) | containerd | Docker 지원 단계적 종료 후 containerd로 전환 |
Azure Kubernetes Service (AKS) | containerd | 2020년 이후 기본 런타임 |
Red Hat OpenShift | CRI-O | Red Hat이 주도적으로 개발한 런타임 통합 |
VMware Tanzu | containerd | 주요 배포판의 기본 런타임 |
로컬 개발 환경 (minikube, kind 등) | containerd, Docker | 사용자가 선택 가능한 런타임 옵션 제공 |
이 표준화 덕분에 하이브리드 및 멀티 클라우드 환경에서도 일관된 방식으로 컨테이너 워크로드를 운영할 수 있으며, 새로운 컨테이너 런타임이 등장하더라도 CRI 표준을 준수하기만 하면 기존 쿠버네티스 생태계에 통합될 수 있다.
8. CRI와 관련된 기술 및 표준
8. CRI와 관련된 기술 및 표준
CRI는 단독으로 동작하지 않으며, 컨테이너 생태계 내 다른 핵심 기술 및 표준과 긴밀하게 연계되어 작동한다. 가장 직접적인 관계는 OCI와 쿠버네티스이다.
CRI는 쿠버네티스 kubelet이 컨테이너 런타임과 통신하기 위한 표준 gRPC 프로토콜을 정의한다. 이는 쿠버네티스가 특정 런타임에 종속되지 않고도 Pod와 컨테이너를 관리할 수 있게 하는 추상화 계층 역할을 한다. CRI의 구현체(예: containerd, CRI-O)는 이 프로토콜을 준수하여 쿠버네티스와 통합된다. 한편, 컨테이너 실행의 실제 표준은 OCI가 제공한다. OCI는 컨테이너 이미지 형식(OCI Image Specification)과 컨테이너 런타임 규격(OCI Runtime Specification)을 정의한다. 대부분의 CRI 구현체는 내부적으로 runc와 같은 OCI 호환 런타임을 사용하여 최종적으로 컨테이너를 생성하고 실행한다[4]. 따라서 CRI는 쿠버네티스와 런타임 간의 관리 인터페이스를 표준화하고, OCI는 런테임의 저수준 실행 행위를 표준화하는 상호 보완적인 관계에 있다.
이러한 표준화 조합은 생태계에 큰 유연성을 부여했다. 아래 표는 CRI가 관련 주요 기술 간의 관계를 어떻게 연결하는지 보여준다.
계층 | 주체/표준 | 역할 | 상호 관계 |
|---|---|---|---|
조정(Orchestration) | 쿠버네티스 (kubelet) | 클러스터와 워크로드 조정 | CRI 클라이언트. CRI 프로토콜을 통해 런타임에 명령을 전달한다. |
런타임 인터페이스 | CRI (Container Runtime Interface) | 표준 통신 프로토콜 | 쿠버네티스와 다양한 컨테이너 런타임을 연결하는 중계 계층이다. |
런타임 구현체 | containerd, CRI-O 등 | CRI 프로토콜 구현 | CRI 요청을 받아 이미지 관리, 컨테이너 생명주기 등을 처리한다. |
실행 표준 | OCI (Open Container Initiative) | 저수준 컨테이너 실행 표준 | 런타임 구현체가 내부적으로 OCI 호환 도구(runc 등)를 사용해 컨테이너를 실행한다. |
이 구조 덕분에 사용자는 쿠버네티스 버전을 유지한 채로 CRI 호환 런타임을 자유롭게 선택하거나 교체할 수 있으며, 런타임 벤더는 OCI 표준을 준수하는 한 독자적인 최적화를 진행할 수 있다. 이는 도커 엔진에 대한 의존성을 끊고(dockershim 제거) 보다 모듈화되고 경쟁적인 컨테이너 생태계를 구축하는 데 기여했다.
8.1. OCI (Open Container Initiative)
8.1. OCI (Open Container Initiative)
OCI는 컨테이너 런타임과 이미지의 개방형 표준을 정의하는 업계 컨소시엄이다. 리눅스 재단의 프로젝트로 2015년 도커(Docker)와 다른 업계 리더들에 의해 설립되었다. OCI의 주요 목표는 컨테이너 기술의 기본 요소에 대한 공개 사양(open specification)을 제공하여 벤더 중립성과 상호 운용성을 보장하는 것이다.
OCI는 주로 두 가지 핵심 사양을 관리한다. 첫 번째는 컨테이너의 생명주기를 관리하는 런타임 표준인 OCI 런타임 사양(Runtime Specification)이다. 이 사양은 컨테이너를 실행하고 관리하기 위한 런타임의 동작과 인터페이스를 정의한다. 두 번째는 컨테이너 이미지의 포맷, 구성, 배포를 정의하는 OCI 이미지 사양(Image Specification)이다. 이 표준 이미지 포맷은 다양한 도구와 플랫폼 간에 이미지를 호환 가능하게 만든다.
사양 이름 | 주요 내용 | 참조 구현체 예시 |
|---|---|---|
OCI 런타임 사양 | 컨테이너 실행 환경, 파일 시스템 번들 구성, 생명주기 관리 명령어 정의 | |
OCI 이미지 사양 | 이미지 매니페스트, 레이어 포맷, 구성 파일(JSON)의 구조 정의 | 도커 이미지 v2.2+ |
CRI는 쿠버네티스가 컨테이너 런타임과 통신하기 위한 플러그인 인터페이스라면, OCI는 그러한 런타임이 내부적으로 컨테이너를 실행하기 위해 준수해야 하는 하위 수준의 표준이다. 일반적인 동작 흐름에서 쿠버네티스(CRI 인터페이스)는 OCI 호환 런타임(예: containerd, CRI-O)을 호출하고, 해당 런타임은 최종적으로 OCI 사양을 구현한 도구(예: runc)를 사용하여 컨테이너를 생성한다. 이 계층화된 구조는 CRI 구현체의 다양성을 허용하면서도, 최종 컨테이너 실행의 표준화와 안정성을 보장한다.
8.2. Kubernetes
8.2. Kubernetes
CRI는 쿠버네티스가 컨테이너 런타임을 사용하기 위한 핵심 인터페이스이다. 쿠버네티스는 컨테이너 오케스트레이션 플랫폼으로서, 파드 생성, 스케줄링, 네트워킹, 스토리지 관리 등 광범위한 작업을 담당한다. 그러나 컨테이너의 실제 생성과 생명주기 관리라는 구체적인 작업은 외부 런타임에 위임한다. CRI는 쿠버네티스의 kubelet 컴포넌트와 이러한 컨테이너 런타임 사이의 통신 표준을 정의하여, 양측이 서로의 내부 구현细节에 구애받지 않고 협력할 수 있게 한다.
쿠버네티스가 CRI를 도입하기 전에는 도커 엔진과 직접 통합되어 있었다. 이는 쿠버네티스 생태계를 도커에 지나치게 종속시키고, 다른 컨테이너 런타임의 통합을 어렵게 만들었다. CRI는 gRPC 기반의 프로토콜로, 런타임이 파드 샌드박스(주로 파우스 네트워크 네임스페이스) 생성, 컨테이너 시작/정지/삭제, 이미지 풀, 로그 수집 등의 작업을 수행하기 위해 구현해야 하는 메서드들을 명시한다. 이를 통해 쿠버네티스는 단일한 인터페이스를 통해 containerd, CRI-O 등 다양한 호환 런타임을 자유롭게 선택하고 사용할 수 있다.
CRI의 도입은 쿠버네티스 아키텍처의 모듈화와 확장성을 크게 향상시켰다. 런타임 제공자는 표준 인터페이스만 준수하면 쿠버네티스와 호환되는 제품을 만들 수 있으며, 사용자는 특정 런타임에 갇히지 않고 요구사항에 맞는 최적의 도구를 선택할 수 있다. 이는 OCI 표준과 결합되어 컨테이너 생태계의 건강한 분업과 혁신을 촉진하는 기반이 되었다.
