Kubernetes에서 사용 가능한 CRI 비교
containerd vs CRI-O vs cri-dockerd
Kubernetes에서 사용 가능한 CRI 비교
쿠버네티스에서 컨테이너를 실행하려면 반드시 CRI(Container Runtime Interface)가 필요하다. 현재 쿠버네티스 환경에서 가장 널리 선택되는 옵션은 다음 세 가지다.
- containerd
- CRI-O
- cri-dockerd
각 런타임은 태생적 배경과 목표가 다르기 때문에 구조, 성능, 운영 방식에도 차이가 있다.
이 글에서는 세 런타임을 비교하고, 어떤 환경에서 어떤 런타임을 선택해야 하는지 정리한다.
1. containerd
containerd는 원래 Docker 내부의 핵심 엔진이었지만, 컨테이너 표준화를 위해 CNCF 독립 프로젝트로 분리된 런타임이다.
현재 Kubernetes에서 가장 널리 사용되며, 쿠버네티스 공식 문서에서도 권장하는 런타임이다.
containerd의 역할
- 컨테이너 생성·시작·중지
- 이미지 Pull/Push
- snapshotter를 통한 루트 파일시스템 관리
- OCI 런타임(runc) 실행
- 내장된 CRI 플러그인으로 kubelet과 직접 통신
containerd 구조:
1
2
3
4
5
6
7
8
9
Kubernetes (kubelet)
│
▼
┌──────────────────────┐
│ containerd │ ← CRI 플러그인 내장 (Containerd 자체가 CRI 서버)
└──────────────────────┘
│
▼
runc (OCI)
2. CRI-O
CRI-O는 Red Hat이 중심이 되어 개발한, 오직 Kubernetes만을 위한 컨테이너 런타임이다.
containerd가 범용 컨테이너 런타임이라면, CRI-O는 Kubernetes 최적화에 초점을 두고 있다.
CRI-O의 특징
- 쿠버네티스 CRI 구현을 최소한의 구성요소로 설계
- containerd보다 컴포넌트가 더 단순함
- 이미지 레이어 관리에 OverlayFS 기반 사용
- 보안을 위해 SELinux, seccomp, AppArmor 등과 높은 통합성
- PodSandbox 개념을 K8s CRI에 맞춰 구현
CRI-O 구조
1
2
3
4
5
6
7
8
9
Kubernetes (kubelet)
│
▼
┌──────────────────────┐
│ CRI-O │ ← K8s 전용 CRI 런타임
└──────────────────────┘
│
▼
runc
containerd와의 차이
- containerd는 범용 런타임 / CRI-O는 Kubernetes 전용
- CRI-O는 Docker 생태계 기능이 없음
- containerd보다 구성이 더 단순
- RHEL, OpenShift 계열에서 기본 선택지
3. cri-dockerd
쿠버네티스 1.24 이전에는 kubelet 내부에서 dockershim이 포함되어 Docker를 직접 사용할 수 있었다.
dockershim 제거 이후, Docker를 계속 Kubernetes에서 쓰기 위해 탄생한 것이 cri-dockerd다.
cri-dockerd의 역할
- Kubernetes의 CRI 요청 ↔ Docker API로 매핑
- Docker 기반 워크로드를 그대로 K8s에서 유지
cri-dockerd 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Kubernetes (kubelet)
│
▼
┌──────────────────────┐
│ cri-dockerd │ ← CRI 어댑터
└──────────────────────┘
│ Docker API
▼
┌──────────────────────┐
│ Docker Engine │ ← containerd 내부 포함
└──────────────────────┘
│
▼
containerd → runc
즉, 가장 레이어가 많고 가장 복잡한 구조다.
4. 기능 및 구조 비교
성능 비교
| 항목 | containerd | CRI-O | cri-dockerd |
|---|---|---|---|
| 오버헤드 | 낮음 | 낮음 | 중간~높음 |
| 컨테이너 실행 속도 | 빠름 | 가장 빠름(단순 구조) | Docker API 경유로 느림 |
| 이미지 관리 | 다양한 snapshotter | OverlayFS 중심 | Docker 방식 |
보안 기능
| 기능 | containerd | CRI-O | cri-dockerd |
|---|---|---|---|
| seccomp | 지원 | 강화됨 (K8s 기본 프로필) | Docker 의존 |
| AppArmor | 지원 | 지원 | Docker 의존 |
| SELinux | 제한적 | 최적화 | Docker 의존 |
운영 난이도
| 런타임 | 운영 난이도 |
|---|---|
| CRI-O | 가장 단순 |
| containerd | 단순하지만 설정 옵션 다양 |
| cri-dockerd | Docker까지 관리해야 해서 가장 복잡 |
호환성
| 항목 | containerd | CRI-O | cri-dockerd |
|---|---|---|---|
| Kubernetes 공식 권장 | ✔ | ✔ | ✘ |
| Docker CLI 사용 | ✘ | ✘ | ✔ |
| 기존 Docker 워크로드 재사용 | ✘ | ✘ | ✔ 강점 |
5. 핵심 차이 정리
| 항목 | containerd | CRI-O | cri-dockerd |
|---|---|---|---|
| 역할 | K8s가 직접 사용하는 범용 컨테이너 런타임 | K8s 전용으로 설계된 경량 컨테이너 런타임 | Docker를 K8s에서 쓰기 위한 CRI 어댑터 |
| K8s CRI 지원 | 네이티브 지원 | 네이티브 지원 (CRI만을 위해 개발됨) | Docker는 CRI 미지원 → 중간 어댑터 필요 |
| 의존성 | 독립 실행 | 독립 실행 | Docker Engine 필수 |
| 실행 경로 | kubelet → containerd → runc | kubelet → CRI-O → runc | kubelet → cri-dockerd → Docker → containerd → runc |
| 설치 복잡도 | 단독; 비교적 단순 | 단독; 가장 단순 | Docker + cri-dockerd 두 가지 설치 필요 |
| 오버헤드 | 낮음 | 가장 낮음 (K8s 전용 구조) | Docker API 경유로 가장 많음 |
| 보안 | AppArmor / Seccomp / SELinux 일부 지원 | SELinux·Seccomp 통합 강화 | Docker 보안 모델 의존 |
| 권장 여부 | Kubernetes 기본 런타임로 가장 많이 사용됨 | RHEL/OpenShift 또는 보안·단순성 중시 환경에 적합 | 기존 Docker 중심 환경만 유지용 |
