k8s 로 인프라를 구축하여도 일반적으로 docker hub 에서 이미지를 가져와 사용하기 때문에 k8s 내부적으로 docker 가 컨테이너를 관리하는 것으로 오해할 수 있다. 실제로 kubernetes 1.24 버전 미만에서는 k8s 가 내부적으로 dockershim -> dockerd( daemon)을 통해 컨테이너를 실행/관리하였다. 하지만 dockerd 는 인프라 환경에서 필요 없는 GUI, CLI, 빌드 기능 등이 포함되어있기 때문에 비효율적이었고, 따라서 k8s 는 1.24 버전부터 컨테이너 런타임으로 containerd 을 사용하게 되었다.

 

1. k8s 에서 컨테이너를 구동하는 주체

현재 k8s 는 CRI(Container Runtime Interface)라는 표준 규격을 만족하는 가벼운 컨테이너 런타임을 사용한다. 가장 대표적인 것이 containerd 와 CRI-O 인데, 대부분의 클라우드 서비스나 최신 클러스터는 containerd 를 기본으로 한다.

 

2. contauner registry 에 올라가는 이미지 규격

docker hub 에 올리던, 사내 nexus registry 나 harbor 에 올리던간에 그 이미지는 docker 로 빌드했더라도 docker 전용 규격이 아니라, 표준 규격인 OCI(Open Container Initiative) 규격을 따르는 이미지이다. 따라서 docker 데몬뿐 아니라 containerd 같은 다른 컨테이너 런타임도 이미지를 컨테이너화 할 수 있는 것이다.

 

3. k8s 에서의 컨테이너 실행흐름

k8s 에서 파드를 띄울 때 실제 일어나는 일은 다음과 같다.

  1. kubelet 의 요청: 해당 노드의 관리자인 kubelet 이 CRI 규격(gRPC)을 통해 containerd(고수준 런타임)에게 컨테이너 실행을 요청한다.
  2. 이미지 다운로드: containerd 가 container image registry 에서 OCI 규격의 이미지를 pull 한다.
  3. 실제 컨테이너 생성: containerd 가 직접 컨테이너를 실행하지 않고, 저수준 런타임인 runc 에게 컨테이너 실행을 요청한다. runc 는 리눅스 커널과 직접 소통한다.
  4. 리눅스 커널 격리: runc 가 리눅스 커널의 namespace, cgroups 기능을 활용해 격리된 프로세스로 컨테이너를 구동시킨다.

 

4. docker 로 컨테이너 구동시 dockerd 가 죽으면 어떻게 될까?

dockerd 가 죽으면 실행중이던 컨테이너들도 종료된다. 이는 dockerd 가 컨테이너 프로세스의 직속 부모 프로세스이기 때문이다.(Live Restore 라는 기능을 사용하면 dockerd 가 죽어도 컨테이너를 유지할 수 있긴 하다)

[ systemd ]
   │
   └─ [ dockerd (Docker 데몬) ] ── (부모-자식 관계) ──> [ 컨테이너 프로세스 ]

 

 

 

5. k8s 에서 컨테이너 구동시 containerd 가 죽으면 어떻게 될까?

containerd 가 죽어도 실행중이던 컨테이너들은 종료되지 않는다. 이는 containerd 가 컨테이너 프로세스의 직속 부모가 아니기 때문이다. containerd 가 컨테이너 생성을 요청받으면 containerd-shim 이라는 프로세스를 컨테이너 갯수만큼 생성하고, 각각의 프로세스 하위로 컨테이너 프로세스를 두게 된다. containerd 자신은 부모가 아닌 관리자 프로세스로 남게 된다.

[ systemd ]
   │
   ├─ [ containerd (데몬) ]  ── (독립된 관계)
   │
   ├─ [ containerd-shim ] ── (실질적 부모) ──> [ 컨테이너 프로세스 ]
   └─ [ containerd-shim ] ── (실질적 부모) ──> [ 컨테이너 프로세스 ]

 

단, containerd가 죽었을 때 일어나는 일은 아래와 같다.

  • 상태 모니터링 불가: kubelet 이 containerd 를 통해 파드의 상태를 확인(Health Check)할 수 없으므로, 쿠버네티스 마스터 노드 입장에서는 해당 노드의 파드들이 일시적으로 Unknown 상태로 보일 수 있다.
  • 새로운 작업 불가: 새로운 파드를 띄우거나, 기존 파드를 삭제하는 등의 제어 명령이 동작하지 않는다.
블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,