containerd 아키텍처 분석 및 실전 운영 가이드

1. containerd 개요 및 아키텍처

1.1 발전 배경

초기 Docker Engine의 내부 컴포넌트로 시작되었으나, 현재는 독립적인 오픈소스 프로젝트로 분리되어 경량화된 컨테이너 런타임 인프라를 제공합니다. 최종 사용자를 직접 타겟팅하기보다는 Kubernetes, Swarm과 같은 상위 오케스트레이션 시스템에 통합되어 핵심 런타임 역할을 수행합니다. 데몬 형태로 실행되며 gRPC API를 통해 상위 시스템과 통신합니다. 실제 컨테이너 프로세스 실행은 OCI 표준을 준수하는 runc가 담당합니다.

1.2 핵심 아키텍처

containerd는 C/S 아키텍처를 채택하고 있으며, 기능별 디커플링을 위해 다양한 서브시스템과 플러그인 모듈로 구성됩니다.

  • Bundle Subsystem: 컨테이너의 루트 파일시스템, 메타데이터, 설정을 포함하는 번들을 추출하고 패키징합니다.
  • Runtime Subsystem: 번들을 실행하여 실제 컨테이너 프로세스를 생성하고 관리합니다.
  • Content Plugin: 변경 불가능한 이미지 레이어 및 콘텐츠를 저장하고 주소 지정 가능한 액세스를 제공합니다.
  • Snapshot Plugin: Docker의 graphdriver와 유사하게 파일시스템 스냅샷을 관리합니다.

2. containerd 설치 및 환경 구성

2.1 패키지 매니저(YUM) 설치

# 1. 공식 YUM 레포지토리 추가
curl -o /etc/yum.repos.d/containerd.repo https://download.docker.com/linux/centos/docker-ce.repo

# 2. 패키지 캐시 업데이트 및 가용 버전 확인
yum makecache fast
yum list available | grep containerd.io

# 3. containerd 설치
yum install -y containerd.io-1.7.11

# 4. 기본 설정 파일 생성 및 서비스 시작
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
systemctl enable --now containerd

# 5. CLI 도구 버전 확인
ctr version

2.2 바이너리 수동 설치

Kubernetes 환경에서는 CNI 및 runc가 포함된 번들 패키지를 사용하는 것이 편리합니다.

# 1. CRI 및 CNI 포함 바이너리 다운로드
wget https://github.com/containerd/containerd/releases/download/v1.7.11/cri-containerd-cni-1.7.11-linux-amd64.tar.gz

# 2. 파일 압축 해제 및 시스템 디렉토리로 이동
tar -C / -xzf cri-containerd-cni-1.7.11-linux-amd64.tar.gz

# 3. systemd 데몬 리로드 및 서비스 실행
systemctl daemon-reload
systemctl enable --now containerd

# 4. runc 독립 설치 (seccomp 호환성 확보)
wget https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc
runc --version

3. 컨테이너 및 이미지 라이프사이클 관리

3.1 이미지 관리

# 이미지 목록 조회
ctr images list

# 특정 플랫폼 지정하여 이미지 풀(Pull)
ctr images pull --platform linux/amd64 docker.io/library/httpd:alpine

# 이미지 마운트하여 내부 파일시스템 탐색
ctr images mount docker.io/library/httpd:alpine /mnt/httpd
ls /mnt/httpd
umount /mnt/httpd

# 이미지 내보내기 및 가져오기
ctr images export --all-platforms httpd-backup.tar docker.io/library/httpd:alpine
ctr images import httpd-backup.tar

# 이미지 태그 변경
ctr images tag docker.io/library/httpd:alpine internal-registry/httpd:v1

3.2 컨테이너 및 태스크 관리

containerd에서는 정적 리소스 할당(Container)과 동적 프로세스 실행(Task)을 분리하여 관리합니다.

# 정적 컨테이너 생성 (프로세스 실행 안 됨)
ctr container create docker.io/library/httpd:alpine web-app-01
ctr container list

# 태스크 시작 (동적 컨테이너로 전환)
ctr task start -d web-app-01
ctr task list

# 컨테이너 내부 접속 (고유한 exec-id 부여)
ctr task exec --exec-id shell-$(date +%s) -t web-app-01 /bin/sh

# 호스트 네트워크 모드로 원스텝 실행
ctr run -d --net-host docker.io/library/redis:alpine cache-node-01

# 태스크 일시 중지 및 재개
ctr task pause cache-node-01
ctr task resume cache-node-01

# 컨테이너 종료 및 리소스 삭제
ctr task kill cache-node-01
ctr task delete cache-node-01
ctr container delete cache-node-01

4. 고급 운영 및 네트워크 구성

4.1 프라이빗 레지스트리 연동

자체 서명 인증서를 사용하는 사내 하버(Harbor) 레지스트리와 연동하기 위한 설정입니다.

# /etc/containerd/config.toml 파일 수정
# [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.dev.local".tls]
#   insecure_skip_verify = true
# [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.dev.local".auth]
#   username = "ci-pipeline"
#   password = "SecurePass123!"

systemctl restart containerd

# 이미지 푸시 테스트
ctr images tag docker.io/library/httpd:alpine harbor.dev.local/library/httpd:latest
ctr image push --user "ci-pipeline:SecurePass123!" --skip-verify harbor.dev.local/library/httpd:latest

4.2 네임스페이스 격리

네임스페이스를 활용하여 동일한 호스트 내에서 멀티 테넌시 환경을 구성할 수 있습니다.

# 네임스페이스 생성 및 목록 확인
ctr namespace create staging-env
ctr namespace list

# 특정 네임스페이스 컨텍스트에서 이미지 풀 및 컨테이너 실행
ctr -n staging-env images pull docker.io/library/memcached:alpine
ctr -n staging-env run -d docker.io/library/memcached:alpine memcached-svc

4.3 CNI 네트워크 플러그인 적용

기본적으로 containerd는 루프백 네트워크만 제공하므로, 외부 통신을 위해 CNI를 구성해야 합니다.

# CNI 플러그인 바이너리 다운로드 및 설치
wget https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz
mkdir -p /opt/cni/bin
tar -xzf cni-plugins-linux-amd64-v1.4.0.tgz -C /opt/cni/bin

# 네트워크 구성 파일 작성 (/etc/cni/net.d/20-bridge.conf)
cat <<EOF > /etc/cni/net.d/20-bridge.conf
{
  "cniVersion": "1.0.0",
  "name": "custom-bridge",
  "type": "bridge",
  "bridge": "br-int0",
  "isGateway": true,
  "ipMasq": true,
  "ipam": {
    "type": "host-local",
    "subnet": "172.18.0.0/16",
    "routes": [
      { "dst": "0.0.0.0/0" }
    ]
  }
}
EOF

# CNI 네트워크 초기화 (테스트 스크립트 활용)
CNI_PATH=/opt/cni/bin /opt/cni/scripts/priv-net-run.sh echo "Network Initialized"

# 컨테이너에 네트워크 적용
pid=$(ctr task list | grep web-app-01 | awk '{print $2}')
netns=/proc/$pid/ns/net
CNI_PATH=/opt/cni/bin /opt/cni/scripts/exec-plugins.sh add $pid $netns

5. 스토리지 마운트 및 네임스페이스 공유

5.1 호스트 볼륨 마운트 (Bind Mount)

# 호스트의 /var/log/app 디렉토리를 컨테이너의 /app/logs로 마운트
mkdir -p /var/log/app
ctr container create docker.io/library/alpine:latest log-collector \
  --mount type=bind,src=/var/log/app,dst=/app/logs,options=rbind:rw

ctr task start -d log-collector sh
ctr task exec --exec-id write-log-$(date +%s) -t log-collector sh -c "echo 'Error: connection timeout' > /app/logs/app.err"

# 호스트에서 파일 확인
cat /var/log/app/app.err

5.2 PID 네임스페이스 공유

사이드카 패턴 등에서 기존 컨테이너의 프로세스 공간을 공유해야 할 때 유용합니다.

# 기존 실행 중인 컨테이너의 PID 확인
target_pid=$(ctr task list | grep web-app-01 | awk '{print $2}')

# PID 네임스페이스를 공유하는 새 컨테이너 생성
ctr container create --with-ns "pid:/proc/$target_pid/ns/pid" \
  docker.io/library/busybox:latest sidecar-monitor

ctr task start -d sidecar-monitor sh

# 공유된 프로세스 목록 확인
ctr task exec --exec-id ps-check-$(date +%s) -t sidecar-monitor ps aux

6. Docker 데몬과 containerd 통합

Docker CLI의 풍부한 생태계를 활용하면서 백엔드 런타임으로 독립적인 containerd를 사용할 수 있습니다.

# Docker 데몬 설치
yum install -y docker-ce

# Docker systemd 서비스 파일 수정 (/usr/lib/systemd/system/docker.service)
# ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

systemctl daemon-reload
systemctl enable --now docker

# Docker CLI로 컨테이너 실행
docker run -d --name api-gateway nginx:alpine

# containerd CLI에서 Docker가 생성한 네임스페이스(moby) 확인
ctr -n moby namespace list
ctr -n moby container list
ctr -n moby task list

태그: containerd kubernetes oci runc CNI

5월 27일 21:06에 게시됨