Split View: containerd 아키텍처 내부 분석
containerd 아키텍처 내부 분석
containerd 아키텍처 내부 분석
containerd는 업계 표준 컨테이너 런타임으로, Docker에서 분리되어 독립 프로젝트로 발전했습니다. Kubernetes CRI(Container Runtime Interface)를 구현하며, 컨테이너의 전체 생명주기를 관리합니다.
1. containerd 개요
1.1 위치와 역할
containerd는 컨테이너 스택에서 중간 계층에 위치합니다:
Kubernetes (kubelet)
|
v (CRI gRPC)
containerd
|
v (OCI runtime)
runc / kata / gVisor
|
v
Linux kernel (namespaces, cgroups)
주요 역할:
- 이미지 관리 (pull, push, unpack)
- 컨테이너 생명주기 관리 (create, start, stop, delete)
- 스냅샷 관리 (overlayfs, native 등)
- 네임스페이스 격리
- 태스크(프로세스) 관리
1.2 핵심 설계 원칙
- 심플함: 하나의 일을 잘 수행
- 플러그인 기반: 모든 기능이 플러그인으로 구현
- OCI 호환: OCI 이미지 스펙과 런타임 스펙 준수
- gRPC API: 모든 상호작용은 gRPC를 통해
2. gRPC API 구조
2.1 주요 서비스
containerd는 다음 gRPC 서비스를 제공합니다:
- Containers: 컨테이너 메타데이터 관리
- Content: 콘텐츠 주소 저장소 (이미지 레이어 등)
- Images: 이미지 메타데이터 관리
- Namespaces: 네임스페이스 관리
- Snapshots: 스냅샷(파일시스템 레이어) 관리
- Tasks: 실행 중인 프로세스 관리
- Events: 이벤트 스트리밍
- Leases: 리소스 참조 관리 (GC 방지)
2.2 네임스페이스
containerd의 네임스페이스는 Kubernetes 네임스페이스와 다릅니다. containerd 내부에서 리소스를 격리하는 메커니즘입니다:
- k8s.io: Kubernetes(CRI)가 사용하는 네임스페이스
- moby: Docker가 사용하는 네임스페이스
- default: 기본 네임스페이스
# 네임스페이스별 컨테이너 확인
ctr -n k8s.io containers list
ctr -n moby containers list
3. 플러그인 시스템
3.1 플러그인 타입
containerd의 모든 기능은 플러그인으로 구현됩니다:
| 타입 | 설명 | 예시 |
|---|---|---|
| Service | gRPC 서비스 구현 | containers, content, images |
| Snapshotter | 파일시스템 스냅샷 관리 | overlayfs, native, devmapper |
| Runtime | 컨테이너 런타임 | io.containerd.runc.v2 |
| GC | 가비지 컬렉션 | metadata GC |
| Content Store | 콘텐츠 저장소 | local content store |
| Metadata | 메타데이터 저장소 | bolt metadata store |
| Differ | 레이어 diff 계산 | walking differ |
3.2 플러그인 등록
// 플러그인 등록 예시
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ServicePlugin,
ID: "containers-service",
Requires: []plugin.Type{
plugin.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
m, err := ic.Get(plugin.MetadataPlugin)
// 서비스 초기화 로직
return newContainerService(m), nil
},
})
}
3.3 의존성 해결
containerd는 시작 시 모든 플러그인의 의존성을 분석하고 올바른 순서로 초기화합니다:
- 모든 등록된 플러그인 수집
- 의존성 그래프 구성
- 위상 정렬(topological sort)로 초기화 순서 결정
- 순서대로 플러그인 초기화
3.4 플러그인 설정
containerd의 설정 파일(config.toml)에서 플러그인별 설정:
version = 2
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.9"
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
4. CRI 구현
4.1 CRI 서비스
containerd는 CRI gRPC 서비스를 내장 플러그인으로 구현합니다:
-
RuntimeService: Pod/컨테이너 생명주기 관리
- RunPodSandbox, StopPodSandbox, RemovePodSandbox
- CreateContainer, StartContainer, StopContainer, RemoveContainer
- ExecSync, Exec, Attach, PortForward
- ListContainers, ContainerStatus, ListPodSandbox
-
ImageService: 이미지 관리
- PullImage, ListImages, ImageStatus, RemoveImage
- ImageFsInfo
4.2 CRI 요청 흐름
kubelet의 Pod 생성 요청이 처리되는 과정:
- kubelet이 CRI의 RunPodSandbox 호출
- containerd가 pause 컨테이너 생성 (네트워크 네임스페이스 설정)
- CNI 플러그인 호출하여 네트워크 구성
- kubelet이 CRI의 CreateContainer + StartContainer 호출
- containerd가 shim 프로세스를 통해 컨테이너 실행
5. Shim v2 아키텍처
5.1 Shim의 역할
Shim은 containerd와 실제 컨테이너 런타임(runc) 사이의 중간 프로세스입니다:
containerd --> shim (containerd-shim-runc-v2) --> runc --> container process
Shim의 책임:
- containerd가 재시작되어도 컨테이너를 유지
- 컨테이너의 stdin/stdout/stderr 관리
- 컨테이너 종료 코드 수집
- OOM 이벤트 보고
5.2 Shim v2 프로토콜
Shim v2는 ttrpc(tiny-ttrpc) 프로토콜을 사용합니다. ttrpc는 gRPC의 경량 버전으로:
- protobuf 메시지 직렬화
- Unix 도메인 소켓 통신
- gRPC보다 낮은 메모리 사용
- HTTP/2 오버헤드 없음
5.3 Shim 생명주기
- containerd가 shim 바이너리를 실행 (fork/exec)
- shim이 ttrpc 소켓을 생성하고 주소를 반환
- containerd가 ttrpc를 통해 shim과 통신
- shim이 runc를 호출하여 컨테이너 생성/실행
- containerd 재시작 시 기존 shim에 재연결
5.4 다양한 Shim 구현
| Shim | 런타임 | 설명 |
|---|---|---|
| containerd-shim-runc-v2 | runc | 기본 OCI 런타임 |
| containerd-shim-kata-v2 | Kata | 경량 VM 기반 |
| containerd-shim-runsc-v1 | gVisor | 사용자 공간 커널 |
| containerd-shim-wasm | Wasm | WebAssembly 런타임 |
6. 메타데이터 저장소
6.1 BoltDB 메타데이터
containerd는 BoltDB를 메타데이터 저장소로 사용합니다:
- 컨테이너 정의 (이름, 이미지, 스펙 등)
- 이미지 메타데이터 (태그, 다이제스트, 레이어 등)
- 스냅샷 메타데이터
- Lease 정보
- 네임스페이스 정보
/var/lib/containerd/
io.containerd.metadata.v1.bolt/
meta.db # BoltDB 메타데이터
io.containerd.content.v1.content/
blobs/sha256/ # 콘텐츠 저장소
io.containerd.snapshotter.v1.overlayfs/
snapshots/ # overlayfs 스냅샷
6.2 가비지 컬렉션
containerd의 GC는 참조되지 않는 리소스를 정리합니다:
- Lease로 보호되지 않는 콘텐츠
- 사용되지 않는 스냅샷
- 연결이 끊긴 메타데이터
7. 정리
containerd의 플러그인 기반 아키텍처는 높은 확장성과 유연성을 제공합니다. Shim v2의 프로세스 격리 모델은 containerd 재시작에도 컨테이너를 안정적으로 유지하며, ttrpc를 통한 효율적인 통신으로 오버헤드를 최소화합니다. 다음 글에서는 containerd의 이미지 관리와 스냅샷 시스템을 상세히 분석합니다.
containerd Architecture Internals
containerd Architecture Internals
containerd is the industry-standard container runtime, originally extracted from Docker and developed as an independent project. It implements the Kubernetes CRI (Container Runtime Interface) and manages the complete container lifecycle.
1. containerd Overview
1.1 Position and Role
containerd sits in the middle layer of the container stack:
Kubernetes (kubelet)
|
v (CRI gRPC)
containerd
|
v (OCI runtime)
runc / kata / gVisor
|
v
Linux kernel (namespaces, cgroups)
Key responsibilities: image management, container lifecycle management, snapshot management, namespace isolation, and task (process) management.
1.2 Core Design Principles
- Simplicity: Do one thing well
- Plugin-based: All functionality implemented as plugins
- OCI compliant: Follows OCI image and runtime specs
- gRPC API: All interactions through gRPC
2. gRPC API Structure
2.1 Key Services
containerd provides these gRPC services: Containers, Content, Images, Namespaces, Snapshots, Tasks, Events, and Leases.
2.2 Namespaces
containerd namespaces are different from Kubernetes namespaces -- they isolate resources within containerd internally:
- k8s.io: Used by Kubernetes (CRI)
- moby: Used by Docker
- default: Default namespace
3. Plugin System
3.1 Plugin Types
All containerd functionality is implemented as plugins: Service, Snapshotter, Runtime, GC, Content Store, Metadata, and Differ.
3.2 Dependency Resolution
At startup, containerd analyzes all plugin dependencies and initializes them in the correct order via topological sort.
3.3 Plugin Configuration
version = 2
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.9"
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
4. CRI Implementation
4.1 CRI Services
containerd implements CRI as a built-in plugin:
- RuntimeService: Pod/container lifecycle (RunPodSandbox, CreateContainer, StartContainer, etc.)
- ImageService: Image management (PullImage, ListImages, etc.)
4.2 CRI Request Flow
- kubelet calls RunPodSandbox via CRI
- containerd creates pause container (sets up network namespace)
- CNI plugin called for network configuration
- kubelet calls CreateContainer + StartContainer
- containerd runs container through shim process
5. Shim v2 Architecture
5.1 Shim Role
The Shim is an intermediate process between containerd and the actual container runtime (runc):
containerd --> shim (containerd-shim-runc-v2) --> runc --> container process
Responsibilities: keeping containers alive across containerd restarts, managing stdin/stdout/stderr, collecting exit codes, reporting OOM events.
5.2 Shim v2 Protocol
Shim v2 uses ttrpc (tiny-ttrpc), a lightweight alternative to gRPC with protobuf serialization, Unix domain socket communication, lower memory usage, and no HTTP/2 overhead.
5.3 Various Shim Implementations
| Shim | Runtime | Description |
|---|---|---|
| containerd-shim-runc-v2 | runc | Default OCI runtime |
| containerd-shim-kata-v2 | Kata | Lightweight VM-based |
| containerd-shim-runsc-v1 | gVisor | User-space kernel |
| containerd-shim-wasm | Wasm | WebAssembly runtime |
6. Metadata Store
containerd uses BoltDB for metadata storage including container definitions, image metadata, snapshot metadata, lease information, and namespace information.
/var/lib/containerd/
io.containerd.metadata.v1.bolt/meta.db
io.containerd.content.v1.content/blobs/sha256/
io.containerd.snapshotter.v1.overlayfs/snapshots/
7. Summary
containerd's plugin-based architecture provides high extensibility and flexibility. The Shim v2 process isolation model keeps containers stable across containerd restarts, and efficient communication via ttrpc minimizes overhead. The next post covers containerd's image management and snapshot system in detail.