Skip to content

Split View: containerd CRI 구현: Kubernetes 런타임 통합

|

containerd CRI 구현: Kubernetes 런타임 통합

containerd CRI 구현: Kubernetes 런타임 통합

containerd는 Kubernetes CRI(Container Runtime Interface)를 내장 플러그인으로 구현합니다. 이 글에서는 CRI gRPC 서비스의 구현 상세, Pod Sandbox 관리, 컨테이너 스펙 변환, 스트리밍 API, RuntimeClass, NRI를 분석합니다.


1. CRI gRPC 서비스

1.1 서비스 구조

CRI는 두 개의 gRPC 서비스로 구성됩니다:

CRI gRPC 서비스:

RuntimeService:
  +-- PodSandbox 관리
  |     RunPodSandbox
  |     StopPodSandbox
  |     RemovePodSandbox
  |     PodSandboxStatus
  |     ListPodSandbox
  |
  +-- Container 관리
  |     CreateContainer
  |     StartContainer
  |     StopContainer
  |     RemoveContainer
  |     ListContainers
  |     ContainerStatus
  |     UpdateContainerResources
  |
  +-- 스트리밍
  |     ExecSync
  |     Exec
  |     Attach
  |     PortForward
  |
  +-- 런타임 정보
        Status
        Version

ImageService:
  +-- PullImage
  +-- ListImages
  +-- ImageStatus
  +-- RemoveImage
  +-- ImageFsInfo

1.2 소켓 구성

CRI 소켓:

containerd는 동일한 gRPC 소켓에서 CRI를 제공:
  /run/containerd/containerd.sock

kubelet 설정:
  --container-runtime-endpoint=unix:///run/containerd/containerd.sock

CRI 플러그인이 containerd 서버에 CRI 서비스를 등록:
  플러그인 ID: io.containerd.grpc.v1.cri

2. Pod Sandbox

2.1 Pod Sandbox 개념

Pod Sandbox는 Pod의 격리 환경을 나타냅니다:

Pod Sandbox 구성:

Pod Sandbox = Pause 컨테이너 + 공유 네임스페이스

공유 리소스:
  - 네트워크 네임스페이스 (같은 IP, 포트 공간)
  - IPC 네임스페이스 (프로세스 간 통신)
  - UTS 네임스페이스 (호스트명)
  - PID 네임스페이스 (선택적)

격리 리소스:
  - 마운트 네임스페이스 (컨테이너별)
  - cgroup (컨테이너별 리소스 제한)

2.2 RunPodSandbox 흐름

RunPodSandbox 처리:

1. Sandbox 메타데이터 생성
   - ID 생성
   - 로그 디렉토리 생성
        |
        v
2. Pause 이미지 풀
   - sandbox_image 설정에서 이미지 결정
   - 기본값: registry.k8s.io/pause:3.9
        |
        v
3. Pause 컨테이너 스냅샷 준비
        |
        v
4. OCI 스펙 생성
   - Pause 컨테이너용 최소 스펙
   - 호스트명, DNS 설정 포함
        |
        v
5. 네트워크 네임스페이스 생성
   - /var/run/netns/ 에 네임스페이스 파일 생성
        |
        v
6. CNI 플러그인 호출
   - 네트워크 인터페이스 생성
   - IP 할당
        |
        v
7. Pause 컨테이너 Task 생성 및 시작
        |
        v
8. Sandbox 상태를 SANDBOX_READY로 설정

2.3 Pause 컨테이너

Pause 컨테이너의 역할:

1. 네임스페이스 보유자:
   - 네트워크 네임스페이스의 첫 번째 프로세스
   - App 컨테이너가 종료되어도 네임스페이스 유지
   - 네임스페이스의 생명주기를 Pod에 바인딩

2. PID 1 역할:
   - Pod PID 네임스페이스의 init 프로세스
   - 좀비 프로세스 수거 (reap)
   - 최소 리소스 사용 (약 1MB)

3. 동작:
   - pause() 시스템 콜로 무한 대기
   - SIGTERM 수신 시 종료

3. 컨테이너 스펙 변환

3.1 CRI 요청에서 OCI 스펙으로

스펙 변환 과정:

CRI ContainerConfig:
  - Image
  - Command, Args
  - Envs
  - Mounts
  - Devices
  - SecurityContext
  - Resources
        |
        v
containerd CRI 플러그인이 변환
        |
        v
OCI Runtime Spec:
  - root (이미지 스냅샷 경로)
  - process (커맨드, env, capabilities)
  - mounts (볼륨, 특수 파일시스템)
  - linux.resources (cgroup 설정)
  - linux.namespaces (Sandbox와 공유)
  - hooks (OCI 훅)

3.2 리소스 변환

Kubernetes 리소스 -> OCI 리소스 변환:

CPU:
  requests.cpu: 250m
    -> linux.resources.cpu.shares = 256
       (1000m = 1024 shares 기준)

  limits.cpu: 500m
    -> linux.resources.cpu.quota = 50000
       linux.resources.cpu.period = 100000
       (500m/1000m * 100000us)

Memory:
  limits.memory: 512Mi
    -> linux.resources.memory.limit = 536870912
       (바이트 단위)

  requests.memory:
    -> 스케줄링에만 사용, OCI 스펙에 반영하지 않음

Hugepages:
  limits.hugepages-2Mi: 100Mi
    -> linux.resources.hugepageLimits:
         pageSize: "2MB"
         limit: 104857600

3.3 보안 컨텍스트 변환

SecurityContext -> OCI 스펙 변환:

runAsUser: 1000
  -> process.user.uid = 1000

runAsGroup: 1000
  -> process.user.gid = 1000

readOnlyRootFilesystem: true
  -> root.readonly = true

privileged: true
  -> 모든 capabilities 부여
  -> 모든 디바이스 접근 허용
  -> AppArmor/SELinux/Seccomp 비활성화

capabilities:
  add: ["NET_ADMIN"]
  drop: ["ALL"]
  -> process.capabilities 설정

seccompProfile:
  type: RuntimeDefault
  -> linux.seccomp 프로파일 적용

4. 스트리밍 API

4.1 ExecSync

ExecSync 동작:

동기적으로 컨테이너에서 명령 실행:

1. kubelet이 ExecSync(containerID, cmd, timeout) 호출
        |
        v
2. containerd가 shim에 Exec 요청
        |
        v
3. shim이 runc exec 실행
   - 컨테이너 네임스페이스에 새 프로세스 생성
        |
        v
4. stdout/stderr 캡처
        |
        v
5. 프로세스 종료 대기
        |
        v
6. exit code + stdout + stderr 반환

사용 사례: liveness/readiness probe, kubectl exec (동기)

4.2 Exec (비동기 스트리밍)

Exec 스트리밍 동작:

1. kubelet이 Exec(containerID, cmd, stdin, stdout, stderr) 호출
        |
        v
2. containerd가 스트리밍 URL 반환
   - 스트리밍 서버 주소: https://node:10250/exec/...
        |
        v
3. kubelet이 클라이언트에 URL 전달
        |
        v
4. 클라이언트가 WebSocket/SPDY로 스트리밍 서버 연결
        |
        v
5. 스트리밍 서버가 containerd에 실제 Exec 수행
        |
        v
6. stdin/stdout/stderr 양방향 스트리밍

스트리밍 프로토콜:
  - SPDY (레거시)
  - WebSocket (최신)

4.3 Attach

Attach 동작:

실행 중인 컨테이너의 메인 프로세스에 연결:

1. 스트리밍 URL 생성 (Exec와 유사)
        |
        v
2. 컨테이너의 stdin/stdout/stderr에 연결
   - 새 프로세스를 생성하지 않음
   - 기존 프로세스의 I/O에 직접 연결
        |
        v
3. 양방향 스트리밍

사용 사례: kubectl attach

4.4 PortForward

PortForward 동작:

Pod의 포트에 로컬 트래픽 전달:

1. 스트리밍 URL 생성
        |
        v
2. Pod의 네트워크 네임스페이스에서 socat/nsenter 실행
   - 지정 포트에 TCP 연결
        |
        v
3. 로컬 포트와 Pod 포트 간 양방향 데이터 전달

구현:
  containerd는 Pod의 네트워크 네임스페이스에 진입하여
  대상 포트에 TCP 연결을 생성합니다.

사용 사례: kubectl port-forward

5. RuntimeClass

5.1 RuntimeClass 매핑

RuntimeClass 처리:

1. Kubernetes RuntimeClass 리소스:
   apiVersion: node.k8s.io/v1
   kind: RuntimeClass
   metadata:
     name: kata
   handler: kata

2. kubelet이 CRI RunPodSandbox 호출 시
   runtime_handler = "kata" 전달

3. containerd가 handler를 런타임 설정에 매핑:
   [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata]
     runtime_type = "io.containerd.kata.v2"

4. 해당 shim 바이너리로 Task 생성:
   containerd-shim-kata-v2

5.2 기본 런타임

기본 런타임 설정:

[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

Pod에 runtimeClassName이 없으면 기본 런타임(runc) 사용

5.3 RuntimeClass별 오버헤드

RuntimeClass 리소스 오버헤드:

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kata
handler: kata
overhead:
  podFixed:
    memory: "160Mi"
    cpu: "250m"

오버헤드 처리:
  - kubelet이 Pod 리소스에 오버헤드를 추가
  - 스케줄러가 오버헤드를 포함하여 노드 선택
  - VM 기반 런타임의 고정 비용 반영

6. NRI (Node Resource Interface)

6.1 NRI 개요

NRI는 containerd의 플러그인 확장 메커니즘으로, 컨테이너 생명주기 이벤트에 훅을 등록할 수 있습니다:

NRI 아키텍처:

kubelet -> containerd
               |
               +-- NRI Plugin 1 (리소스 할당)
               +-- NRI Plugin 2 (토폴로지 인식)
               +-- NRI Plugin 3 (모니터링)

NRI 플러그인은 컨테이너 생명주기 이벤트를 수신하고
OCI 스펙을 수정할 수 있습니다.

6.2 NRI 훅 포인트

NRI 훅 포인트:

1. RunPodSandbox:
   - Pod 생성 시 호출
   - Pod 레벨 리소스 할당

2. CreateContainer:
   - 컨테이너 생성 시 호출
   - OCI 스펙 수정 가능
   - CPU 핀닝, 메모리 NUMA 할당 등

3. StartContainer:
   - 컨테이너 시작 시 호출

4. UpdateContainer:
   - 리소스 업데이트 시 호출

5. StopContainer:
   - 컨테이너 중지 시 호출
   - 리소스 해제

6. RemoveContainer:
   - 컨테이너 삭제 시 호출

6.3 NRI 사용 사례

NRI 활용 사례:

1. CPU/메모리 토폴로지 인식 할당:
   - NUMA 노드 인식 CPU 핀닝
   - 메모리를 특정 NUMA 노드에 할당
   - 토폴로지 매니저와 연동

2. 디바이스 리소스 관리:
   - GPU 할당 최적화
   - RDMA 리소스 관리
   - 디바이스 플러그인 보완

3. 보안 정책 적용:
   - 동적 Seccomp 프로파일
   - 런타임 보안 규칙 주입

4. 모니터링/감사:
   - 컨테이너 시작/종료 이벤트 로깅
   - 리소스 사용 추적

7. 이미지 서비스

7.1 이미지 Pull

CRI PullImage 처리:

1. kubelet이 PullImage(imageSpec, authConfig) 호출
        |
        v
2. containerd가 이미지 참조 해석
   - 태그 또는 다이제스트
   - 레지스트리 인증 정보 적용
        |
        v
3. 이미지 다운로드
   - Manifest, Config, Layers
   - k8s.io 네임스페이스에 저장
        |
        v
4. 레이어 언패킹
   - Snapshotter로 스냅샷 체인 생성
        |
        v
5. 이미지 참조(imageRef) 반환

7.2 이미지 캐싱

이미지 캐싱:

containerd의 이미지 캐싱:
  - Content Store에 레이어가 이미 존재하면 다운로드 건너뜀
  - Snapshotter에 스냅샷이 이미 존재하면 언패킹 건너뜀
  - 다이제스트 기반 정확한 중복 제거

kubelet의 이미지 정책:
  imagePullPolicy: Always
    -> 항상 레지스트리 매니페스트 확인 (레이어는 캐시 활용)
  imagePullPolicy: IfNotPresent
    -> 로컬에 없을 때만 Pull
  imagePullPolicy: Never
    -> 로컬 이미지만 사용

8. 모니터링과 디버깅

8.1 CRI 메트릭

containerd CRI 관련 메트릭:

container_runtime_cri_operations_total:    CRI 연산 수
container_runtime_cri_operations_errors_total: CRI 연산 오류 수
container_runtime_cri_operations_latency_seconds: CRI 연산 지연

containerd 내부 메트릭:
  containerd_task_count:                   실행 중인 Task 수
  containerd_container_count:              컨테이너 수
  containerd_image_pull_duration_seconds:   이미지 Pull 소요 시간

8.2 디버깅 도구

디버깅 도구:

1. crictl (CRI CLI):
   crictl ps              # 컨테이너 목록
   crictl pods            # Pod 목록
   crictl images          # 이미지 목록
   crictl inspect CONTAINER_ID  # 컨테이너 상세
   crictl logs CONTAINER_ID     # 컨테이너 로그
   crictl exec -it CONTAINER_ID /bin/sh  # exec

2. ctr (containerd CLI):
   ctr -n k8s.io containers list
   ctr -n k8s.io tasks list
   ctr -n k8s.io images list

3. containerd 로그:
   journalctl -u containerd -f

9. 정리

containerd의 CRI 구현은 Kubernetes와 컨테이너 런타임 사이의 핵심 인터페이스입니다. Pod Sandbox를 통한 Pod 수준의 격리, CRI 요청에서 OCI 스펙으로의 정확한 변환, WebSocket/SPDY 기반 스트리밍, RuntimeClass를 통한 다중 런타임 지원, NRI를 통한 유연한 확장이 주요 특징입니다. 이러한 계층화된 설계로 containerd는 Kubernetes의 안정적인 컨테이너 런타임으로 자리매김하고 있습니다.

[containerd] CRI Implementation: Kubernetes Runtime Integration

containerd CRI Implementation: Kubernetes Runtime Integration

containerd implements the Kubernetes CRI (Container Runtime Interface) as a built-in plugin. This post analyzes the CRI gRPC service implementation details, Pod Sandbox management, container spec translation, streaming API, RuntimeClass, and NRI.


1. CRI gRPC Service

1.1 Service Structure

CRI consists of two gRPC services:

CRI gRPC services:

RuntimeService:
  +-- PodSandbox management
  |     RunPodSandbox
  |     StopPodSandbox
  |     RemovePodSandbox
  |     PodSandboxStatus
  |     ListPodSandbox
  |
  +-- Container management
  |     CreateContainer
  |     StartContainer
  |     StopContainer
  |     RemoveContainer
  |     ListContainers
  |     ContainerStatus
  |     UpdateContainerResources
  |
  +-- Streaming
  |     ExecSync
  |     Exec
  |     Attach
  |     PortForward
  |
  +-- Runtime info
        Status
        Version

ImageService:
  +-- PullImage
  +-- ListImages
  +-- ImageStatus
  +-- RemoveImage
  +-- ImageFsInfo

1.2 Socket Configuration

CRI socket:

containerd serves CRI on the same gRPC socket:
  /run/containerd/containerd.sock

kubelet configuration:
  --container-runtime-endpoint=unix:///run/containerd/containerd.sock

CRI plugin registers CRI services on the containerd server:
  Plugin ID: io.containerd.grpc.v1.cri

2. Pod Sandbox

2.1 Pod Sandbox Concept

A Pod Sandbox represents the isolation environment for a Pod:

Pod Sandbox composition:

Pod Sandbox = Pause container + shared namespaces

Shared resources:
  - Network namespace (same IP, port space)
  - IPC namespace (inter-process communication)
  - UTS namespace (hostname)
  - PID namespace (optional)

Isolated resources:
  - Mount namespace (per container)
  - cgroup (per container resource limits)

2.2 RunPodSandbox Flow

RunPodSandbox processing:

1. Create Sandbox metadata
   - Generate ID
   - Create log directory
        |
        v
2. Pull Pause image
   - Determine image from sandbox_image config
   - Default: registry.k8s.io/pause:3.9
        |
        v
3. Prepare Pause container snapshot
        |
        v
4. Generate OCI spec
   - Minimal spec for Pause container
   - Include hostname, DNS configuration
        |
        v
5. Create network namespace
   - Create namespace file at /var/run/netns/
        |
        v
6. Call CNI plugin
   - Create network interface
   - Allocate IP
        |
        v
7. Create and start Pause container Task
        |
        v
8. Set Sandbox state to SANDBOX_READY

2.3 Pause Container

Pause container role:

1. Namespace holder:
   - First process in network namespace
   - Namespace persists even if App containers exit
   - Binds namespace lifecycle to Pod

2. PID 1 role:
   - Init process of Pod PID namespace
   - Reaps zombie processes
   - Minimal resource usage (approx. 1MB)

3. Behavior:
   - Waits indefinitely via pause() system call
   - Exits on SIGTERM

3. Container Spec Translation

3.1 CRI Request to OCI Spec

Spec translation process:

CRI ContainerConfig:
  - Image
  - Command, Args
  - Envs
  - Mounts
  - Devices
  - SecurityContext
  - Resources
        |
        v
containerd CRI plugin translates
        |
        v
OCI Runtime Spec:
  - root (image snapshot path)
  - process (command, env, capabilities)
  - mounts (volumes, special filesystems)
  - linux.resources (cgroup settings)
  - linux.namespaces (shared with Sandbox)
  - hooks (OCI hooks)

3.2 Resource Translation

Kubernetes resources -> OCI resource translation:

CPU:
  requests.cpu: 250m
    -> linux.resources.cpu.shares = 256
       (based on 1000m = 1024 shares)

  limits.cpu: 500m
    -> linux.resources.cpu.quota = 50000
       linux.resources.cpu.period = 100000
       (500m/1000m * 100000us)

Memory:
  limits.memory: 512Mi
    -> linux.resources.memory.limit = 536870912
       (in bytes)

  requests.memory:
    -> Used for scheduling only, not reflected in OCI spec

Hugepages:
  limits.hugepages-2Mi: 100Mi
    -> linux.resources.hugepageLimits:
         pageSize: "2MB"
         limit: 104857600

3.3 Security Context Translation

SecurityContext -> OCI spec translation:

runAsUser: 1000
  -> process.user.uid = 1000

runAsGroup: 1000
  -> process.user.gid = 1000

readOnlyRootFilesystem: true
  -> root.readonly = true

privileged: true
  -> Grant all capabilities
  -> Allow all device access
  -> Disable AppArmor/SELinux/Seccomp

capabilities:
  add: ["NET_ADMIN"]
  drop: ["ALL"]
  -> process.capabilities configuration

seccompProfile:
  type: RuntimeDefault
  -> Apply linux.seccomp profile

4. Streaming API

4.1 ExecSync

ExecSync operation:

Synchronously execute command in container:

1. kubelet calls ExecSync(containerID, cmd, timeout)
        |
        v
2. containerd sends Exec request to shim
        |
        v
3. Shim executes runc exec
   - Create new process in container namespaces
        |
        v
4. Capture stdout/stderr
        |
        v
5. Wait for process exit
        |
        v
6. Return exit code + stdout + stderr

Use cases: liveness/readiness probes, kubectl exec (sync)

4.2 Exec (Async Streaming)

Exec streaming operation:

1. kubelet calls Exec(containerID, cmd, stdin, stdout, stderr)
        |
        v
2. containerd returns streaming URL
   - Streaming server address: https://node:10250/exec/...
        |
        v
3. kubelet passes URL to client
        |
        v
4. Client connects to streaming server via WebSocket/SPDY
        |
        v
5. Streaming server performs actual Exec via containerd
        |
        v
6. Bidirectional stdin/stdout/stderr streaming

Streaming protocols:
  - SPDY (legacy)
  - WebSocket (modern)

4.3 Attach

Attach operation:

Connect to a running container's main process:

1. Generate streaming URL (similar to Exec)
        |
        v
2. Connect to container's stdin/stdout/stderr
   - Does not create new process
   - Directly connects to existing process I/O
        |
        v
3. Bidirectional streaming

Use case: kubectl attach

4.4 PortForward

PortForward operation:

Forward local traffic to Pod port:

1. Generate streaming URL
        |
        v
2. Execute socat/nsenter in Pod's network namespace
   - Create TCP connection to specified port
        |
        v
3. Bidirectional data transfer between local port and Pod port

Implementation:
  containerd enters the Pod's network namespace and
  creates a TCP connection to the target port.

Use case: kubectl port-forward

5. RuntimeClass

5.1 RuntimeClass Mapping

RuntimeClass processing:

1. Kubernetes RuntimeClass resource:
   apiVersion: node.k8s.io/v1
   kind: RuntimeClass
   metadata:
     name: kata
   handler: kata

2. kubelet passes runtime_handler = "kata"
   when calling CRI RunPodSandbox

3. containerd maps handler to runtime config:
   [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata]
     runtime_type = "io.containerd.kata.v2"

4. Create Task with corresponding shim binary:
   containerd-shim-kata-v2

5.2 Default Runtime

Default runtime configuration:

[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

If Pod has no runtimeClassName, default runtime (runc) is used

5.3 RuntimeClass Overhead

RuntimeClass resource overhead:

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kata
handler: kata
overhead:
  podFixed:
    memory: "160Mi"
    cpu: "250m"

Overhead processing:
  - kubelet adds overhead to Pod resources
  - Scheduler includes overhead when selecting nodes
  - Reflects fixed costs of VM-based runtimes

6. NRI (Node Resource Interface)

6.1 NRI Overview

NRI is a plugin extension mechanism for containerd that allows registering hooks on container lifecycle events:

NRI architecture:

kubelet -> containerd
               |
               +-- NRI Plugin 1 (resource allocation)
               +-- NRI Plugin 2 (topology awareness)
               +-- NRI Plugin 3 (monitoring)

NRI plugins receive container lifecycle events and
can modify the OCI spec.

6.2 NRI Hook Points

NRI hook points:

1. RunPodSandbox:
   - Called on Pod creation
   - Pod-level resource allocation

2. CreateContainer:
   - Called on container creation
   - Can modify OCI spec
   - CPU pinning, memory NUMA allocation, etc.

3. StartContainer:
   - Called on container start

4. UpdateContainer:
   - Called on resource update

5. StopContainer:
   - Called on container stop
   - Resource release

6. RemoveContainer:
   - Called on container removal

6.3 NRI Use Cases

NRI use cases:

1. CPU/memory topology-aware allocation:
   - NUMA-aware CPU pinning
   - Allocate memory to specific NUMA nodes
   - Integration with topology manager

2. Device resource management:
   - GPU allocation optimization
   - RDMA resource management
   - Device plugin complementation

3. Security policy enforcement:
   - Dynamic Seccomp profiles
   - Runtime security rule injection

4. Monitoring/auditing:
   - Container start/stop event logging
   - Resource usage tracking

7. Image Service

7.1 Image Pull

CRI PullImage processing:

1. kubelet calls PullImage(imageSpec, authConfig)
        |
        v
2. containerd resolves image reference
   - Tag or digest
   - Apply registry auth credentials
        |
        v
3. Download image
   - Manifest, Config, Layers
   - Store in k8s.io namespace
        |
        v
4. Unpack layers
   - Create snapshot chain via Snapshotter
        |
        v
5. Return image reference (imageRef)

7.2 Image Caching

Image caching:

containerd image caching:
  - Skip download if layer already exists in Content Store
  - Skip unpacking if snapshot already exists in Snapshotter
  - Accurate deduplication based on digests

kubelet image policy:
  imagePullPolicy: Always
    -> Always check registry manifest (layers leverage cache)
  imagePullPolicy: IfNotPresent
    -> Pull only if not available locally
  imagePullPolicy: Never
    -> Use local images only

8. Monitoring and Debugging

8.1 CRI Metrics

containerd CRI-related metrics:

container_runtime_cri_operations_total:    CRI operation count
container_runtime_cri_operations_errors_total: CRI operation error count
container_runtime_cri_operations_latency_seconds: CRI operation latency

containerd internal metrics:
  containerd_task_count:                   Running Task count
  containerd_container_count:              Container count
  containerd_image_pull_duration_seconds:   Image pull duration

8.2 Debugging Tools

Debugging tools:

1. crictl (CRI CLI):
   crictl ps              # List containers
   crictl pods            # List pods
   crictl images          # List images
   crictl inspect CONTAINER_ID  # Container details
   crictl logs CONTAINER_ID     # Container logs
   crictl exec -it CONTAINER_ID /bin/sh  # exec

2. ctr (containerd CLI):
   ctr -n k8s.io containers list
   ctr -n k8s.io tasks list
   ctr -n k8s.io images list

3. containerd logs:
   journalctl -u containerd -f

9. Summary

containerd's CRI implementation is the core interface between Kubernetes and container runtimes. Pod-level isolation via Pod Sandbox, accurate CRI-to-OCI spec translation, WebSocket/SPDY-based streaming, multi-runtime support via RuntimeClass, and flexible extension via NRI are its key features. This layered design establishes containerd as a reliable container runtime for Kubernetes.