본문 바로가기
클라우드/쿠버네티스

쿠버네티스는 왜 도커를 버렸나? — 배신인가, 진화인가 🐋

by gasbugs 2026. 3. 31.

"도커가 죽었다!"
2020년 말, 이 소식이 퍼지자 커뮤니티는 패닉에 빠졌다.
그런데 실제로 무슨 일이 있었던 걸까?

🎯 이 글에서 다루는 것

  • 쿠버네티스가 왜 도커를 제외했는지 (진짜 이유)
  • dockershim이 뭔지, 왜 문제가 됐는지
  • containerd, CRI-O 등 대안 런타임이 뭔지
  • 도커 이미지(docker build)는 여전히 쓸 수 있는지
  • 개발자·운영자가 실제로 뭘 바꿔야 하는지

📌 도입 / 배경

2020년 12월, Kubernetes 공식 블로그에 폭탄 같은 글 하나가 올라왔습니다.

"Kubernetes is deprecating Docker as a container runtime."

 

 

이 한 문장이 트위터, Reddit, 슬랙 채널을 불태웠습니다. Kubernetes의 공동 창시자 Joe Beda조차 트위터에 이렇게 적었습니다.

"Fascinating how this docker/docker-shim deprecation has created mass confusion."

 

 

많은 사람들이 "이제 도커 못 쓰는 거야?", "내 docker build로 만든 이미지가 다 죽는 거야?" 하며 패닉에 빠졌습니다.

결론부터 말씀드리면: 패닉할 필요 없습니다. 하지만 정확히 무슨 일이 일어났는지는 알아야 합니다.


🔍 dockershim이 뭐길래?

쿠버네티스 초창기: 도커밖에 없었다

쿠버네티스가 처음 나왔을 때(2014년경), 컨테이너 런타임은 Docker Engine 하나뿐이었습니다. 그래서 쿠버네티스는 도커 지원을 코드에 하드코딩했는데, 이 컴포넌트를 dockershim이라고 부릅니다.

shim이란 원래 기계 조립할 때 두 부품 사이 간격을 메우는 얇은 쐐기를 말합니다. 소프트웨어에서도 마찬가지로, 서로 다른 API 사이를 연결해주는 어댑터 역할을 합니다.

 

 

CRI의 등장: 표준화의 시작

시간이 지나면서 rkt, CRI-O, containerd 같은 다양한 컨테이너 런타임이 등장했습니다. 쿠버네티스는 이들을 모두 지원하기 위해 CRI(Container Runtime Interface) 라는 표준 API를 만들었습니다.

문제는 도커가 이 CRI를 지원하지 않았다는 점입니다. 도커는 CRI보다 먼저 나왔으니 당연한 일이기도 했습니다.

 

 

그래서 호출 경로가 이렇게 됐습니다:

kubelet → dockershim → Docker Daemon → containerd → runc → 컨테이너

 

실제로 도커는 이미지 다운로드나 컨테이너 시작을 직접 하지 않습니다. 내부의 containerd가 그 일을 합니다. 즉, 쿠버네티스는 컨테이너를 실행하기 위해 kubelet → dockershim → Docker → containerd로 이어지는 긴 중간 과정을 거쳐야 했습니다.


🔍 왜 도커를 걷어냈나? 진짜 이유 3가지

1️⃣ 유지보수 부담이 너무 커졌다

dockershim은 처음부터 임시 해결책(hence the name: shim)이었습니다. 유지보수 부담이 커지면서 Kubernetes 메인테이너들이 "CRI 표준을 구현하지 않는 Docker 때문에 이 짐을 계속 지고 가야 하나?"라는 의문을 갖기 시작했습니다.

2️⃣ 불필요한 중간 단계

Kubernetes 개발자들이 Docker를 제거하고 싶었던 큰 이유 중 하나는 중간 단계가 너무 많았다는 것입니다. 컨테이너 하나를 시작하는데 너무 많은 메시지가 앱에서 앱으로 전달되었습니다.

containerd를 직접 연결하면 경로가 이렇게 단순해집니다:

kubelet → containerd (CRI plugin 내장) → runc → 컨테이너

 

컨테이너 하나 시작하는 데 0.1초씩만 아껴도, 수백 개의 컨테이너를 다루는 환경에서는 체감 성능 차이가 납니다.

3️⃣ 새로운 기술과의 비호환성

cgroups v2, 사용자 네임스페이스(user namespaces) 같은 새로운 기능들이 dockershim과 대체로 호환되지 않았습니다. dockershim 지원을 제거하면 이런 영역에서 추가 개발이 가능해집니다.


🗓️ 타임라인: 이 모든 일이 언제 벌어졌나?

시점 사건
2016년 Kubernetes CRI 스펙 발표
2020년 12월 Kubernetes v1.20: dockershim Deprecation 공식 선언
2021년 커뮤니티 반발로 제거 일정 한 차례 연기
2022년 4월 Kubernetes v1.24: dockershim 완전 제거

 

v1.20에서 deprecation을 공식화했지만, 공지가 제대로 되지 않아 커뮤니티에 패닉이 발생했습니다. 혼란의 상당 부분은 "Docker라는 회사가 사라지는 건가?", "Docker로 만든 이미지가 실행이 안 되는 건가?" 같은 오해에서 비롯됐습니다.


🔍 그래서 지금은 뭘 쓰나?

containerd — 사실상 표준

containerd는 원래 Docker가 개발했다가 CNCF(Cloud Native Computing Foundation)에 기증한 범용 컨테이너 런타임입니다. 컨테이너의 생명주기를 관리하며 Kubernetes 내외부 모두에서 사용 가능합니다.

AWS EKS, Azure AKS, Google GKE 같은 주요 관리형 쿠버네티스 서비스들은 이미 containerd를 기본 런타임으로 사용하고 있습니다. 만약 Azure를 쓰신다면, AKS 노드는 이미 containerd가 돌고 있습니다.

CRI-O — 쿠버네티스 전용 경량 런타임

Red Hat이 주도하는 프로젝트로, 쿠버네티스에서만 쓰기 위해 만들어진 경량 런타임입니다. OpenShift 환경에서 주로 볼 수 있습니다.

cri-dockerd — 도커를 계속 쓰고 싶다면

Mirantis와 Docker가 dockershim이 Kubernetes에서 제거된 후에도 이를 독립적인 오픈소스 CRI 인터페이스로 유지 관리하기로 했습니다. cri-dockerd를 설치하면 여전히 Docker를 런타임으로 사용할 수 있지만, 추가 설치 부담이 생깁니다.


💻 실제로 뭐가 달라졌나? (운영자 관점)

컨테이너 확인 명령어 변화

# ❌ 이제 노드에서 이걸 해도 아무것도 안 나온다
docker ps

# ✅ containerd 환경에서는 이걸 써야 한다
crictl ps

# ✅ 또는 네임스페이스 지정해서
ctr -n k8s.io containers list

런타임 확인 방법

# 노드에서 사용 중인 런타임 확인
kubectl get node -o wide
# CONTAINER-RUNTIME 컬럼에서 확인 가능
# 예: containerd://1.7.x

containerd 설치 및 기본 설정 (Ubuntu 기준)

# containerd 설치
sudo apt-get update
sudo apt-get install -y containerd

# 기본 설정 파일 생성
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# systemd cgroup driver 활성화 (Kubernetes 권장)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' \
  /etc/containerd/config.toml

sudo systemctl restart containerd
sudo systemctl enable containerd

이미지 빌드는 여전히 도커로 해도 된다 ✅

# 이건 여전히 완벽하게 유효하다
docker build -t myapp:v1.0 .
docker push myregistry.io/myapp:v1.0

# 쿠버네티스에 배포할 때 이미지 형식은 동일
kubectl apply -f deployment.yaml

⚠️ 주의사항 / 흔한 실수

1. docker ps로 파드 디버깅하려고 하면 안 된다

containerd를 쓰는 노드에서 docker ps를 실행하면 파드 컨테이너가 보이지 않습니다. containerd 같은 다른 런타임을 사용하면, docker ps나 docker inspect 명령으로 컨테이너 정보를 얻을 수 없습니다. kubectl exec, kubectl logs, crictl ps를 활용하세요.

2. 도커 데몬에 의존하는 도구들 점검 필요

Kubernetes 인프라 외부에서 Docker 명령을 실행하는 스크립트나 데몬, 예를 들어 모니터링 에이전트나 보안 에이전트가 설치되어 있다면 확인이 필요합니다.

3. private registry 설정 위치가 다르다

Docker에서 daemon.json으로 관리하던 private registry 미러 설정을, containerd에서는 /etc/containerd/config.toml에서 해야 합니다.

# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."myregistry.io"]
      endpoint = ["https://myregistry.io"]

✅ 정리 / 마무리

도커는 죽지 않았습니다. 역할이 분리되었을 뿐입니다.

역할 도구 상태
이미지 빌드 docker build ✅ 여전히 유효
이미지 푸시 docker push ✅ 여전히 유효
로컬 개발 Docker Desktop ✅ 여전히 유효
K8s 컨테이너 런타임 containerd / CRI-O ✅ 현재 표준
dockershim 제거됨 ❌ v1.24부터 없음

 

Docker는 개발 작업 중 인간이 상호작용하기 매우 쉽게 만들어주는 UX 개선 기능이 많습니다. 하지만 쿠버네티스는 인간이 아니기 때문에 그 UX 개선 기능이 필요하지 않습니다. 그래서 쿠버네티스는 도커의 핵심 엔진인 containerd와 직접 대화하는 길을 선택한 것입니다.

 

다음 단계로 추천드리는 내용:

  • 현재 운영 중인 쿠버네티스 클러스터의 런타임 확인: kubectl get node -o wide
  • crictl 명령어 익히기 (containerd 환경 디버깅 필수)
  • AKS/EKS/GKE 사용 시 런타임 기본값 문서 확인