Home 도커 엔진
Post
Cancel

도커 엔진

컨테이너 런타임, CRI, OCI 개념은 ‘(Cloud) 컨테이너 런타임, CRI, OCI’ 글 참고

Untitled

  • Docker는 Client-Server 모델을 구현한 애플리케이션입니다. Docker Engine은 Docker Components와 서비스를 제공하는 컨테이너를 구축하고 실행하는 기본 핵심 소프트웨어입니다.
  • Docker Engine은 Docker Daemon, REST API, API를 통해 도커 데몬과 통신하는 CLI로 모듈식으로 구성되어있습니다. 개발자들이 Docker라고 할 때, 주로 Docker engine을 의미합니다.
  • 컨테이너를 빌드, 실행, 배포하는 등의 무거운 작업은 Docker Daemon이 하며, Docker Client는 이러한 로컬 혹은 원격의 Docker Daemon과 통신합니다. 통신을 할 때에는 UNIX socket(/var/run/docker.sock) 또는 네트워크 인터페이스를 통한 REST API를 사용합니다.

docker client


  • Docker Client는 개발자들이 Docker를 사용하는 Docker CLI나 Docker Compose로, $ docker run 과 같은 명령어를 dockerd에게 REST API 형태로 전달합니다.
  • 유저가 Docker CLI를 통해 아래와 같은 명령어를 입력합니다.
    • (e.g. $ docker container run --name ctr1 -it alpine:latest sh )
  • Docker CLI에 입력하면 Docker client는 적절한 API Payload로 변환해서 Docker Daemon(이하 dockerd)에게 REST API로 POST 요청을 합니다.
    • (e.g. POST /containers/create HTTP/1.1 )

dockerd


  • 도커 데몬(dockerd)은 Docker API 요청을 수신
  • API는 Unix Socket을 통해 dockerd에게 전달됩니다.
    • Linux에서 socket은 /var/run/docker.sock
  • 새 컨테이너를 시작할 때, dockerd는 로컬 이미지가 있는지 확인하고 없다면 registry repository에서 해당하는 이름의 이미지를 가져옵니다. 또한 logging drivers와 volume이나 volume drivers를 설정하는 등 컨테이너에 필요한 대부분의 설정을 지정합니다.
  • dockerd가 ‘새로운 container를 생성하라’는 명령을 수신하면, containerd를 호출합니다.이때, dockerd는 CRUD 스타일 API를 통해 gRPC로 containerd와 통신합니다.
    • (e.g. client.NewContainer(context, ...) )

containerd


  • containerd는 Docker Engine v1.11 이후 Docker 코어 컨테이너 런타임 입니다. runc 기반이며, 컨테이너 표준인 OCI (Open Container Initiative)을 준수하고 있습니다.
  • containerd는 고수준 컨테이너 런타임으로 CRI API를 구현합니다.
  • containerd는 socket을 통해 전달된 gRPC 요청을 처리합니다. containerd는 실제로 containers를 생성하지 못하고, runc를 통해 생성합니다. 레지스트리에서 Docker 이미지를 가져와서 컨테이너 구성을 적용하여 runc가 실행할 수 있는 OCI 번들로 변환합니다.

runc


  • runc는 OCI container-runtime-spec의 구현체입니다. OCI(Open Container Initiative)는 kernel의 container 관련 기술을 다루는 interface를 표준화시킨 기준입니다. 그래서 runc가 동작하는 계층을 OCI Layer라고 부르기도 합니다.
  • runc는 OS 커널에 접속해서 컨테이너를 만드는 데 필요한 모든 구성 요소(네임스페이스, cgroup 등)를 하나로 묶습니다. runc는 새로운 container를 생성합니다.
  • 최초 이름은 libcontainer이였는데 docker project에서 OCI에 기부되었고, 이후 이름이 runc가 되었습니다. 즉, runc는 libcontainer의 리팩토링 구현체입니다. 이후 docker에서 자체 개발한 libcontainer Go library를 사용하면서 host kernel의 namesapce, cgroups에 의존되지 않고 OS에서 독립되어 동작할 수 있습니다. libcontainer에서 cgroups 관리 모듈로는 cgroupfs 또는 systemd 둘 중 하나를 사용할 수 있지만모든 모듈이 systemd를 사용하는 쪽으로 update되고 있습니다.

shim


  • 그 다음 컨테이너를 시작하기 위해 docker-containerd-shim과 같은 shim을 실행합니다.
  • 앞에서 containerd가 새로운 컨테이너를 만들기 위해 runc를 사용한다고 했는데, containerd는 생성되는 모든 container 당 runc의 새로운 인스턴스를 fork 합니다. 각 컨테이너가 생성되면, 상위 runc 프로세스가 종료됩니다.
  • 생성된 container의 stdin/out/err 및 Init Process의 Exit Code를 담당하는 Process가 필요한데, containerd-shim 프로세스를 subreaper로 만들어서 생성된 container의 stdin/out/err 및 Init Process의 Exit Code를 담당하는 Process가 containerd-shim이 되도록 합니다. 즉, container와 containerd의 모든 통신은 containerd-shim을 통해서 이루어 집니.
  • container가 생성된 후 containerd-shim을 통해 container를 관리하니 containerd가 종료되어도 container는 정상적으로 동작할 수 있고 runC가 종료되어도 container를 정상적으로 관리할 수 있게 됩니다.

Docker Shim Deprecation (v1.24 ~)


Docker Shim

Untitled

  • Docker shim의 동작 방식
    1. kubelet과 CRI:
      • kubelet은 Kubernetes 노드에서 실행되는 주요 에이전트로, 컨테이너를 실행하고 관리하는 역할을 합니다.
      • kubelet은 CRI를 통해 컨테이너 런타임과 상호작용합니다.
    2. dockershim:
      • Docker는 CRI를 직접 지원하지 않기 때문에, dockershim이 중개 역할을 합니다.
      • dockershim은 Docker API를 호출하여 컨테이너를 관리하고, 이를 통해 kubelet이 Docker 컨테이너를 제어할 수 있게 합니다.
  • Docker를 사용할 때의 구체적인 동작
    • Pod 생성: kubelet은 새로운 Pod을 생성할 때 dockershim을 통해 Docker를 사용하여 컨테이너를 시작합니다.
    • 이미지 풀링: Docker는 필요한 컨테이너 이미지를 Docker Hub 또는 다른 레지스트리에서 가져옵니다.
    • 컨테이너 관리: Docker는 컨테이너의 라이프사이클을 관리하며, kubelet은 Docker의 상태를 모니터링하고 필요한 작업을 수행합니다.
  • 현재 K8S 클러스터의 Container Runtime 확인
    1
    2
    3
    4
    
    kubectl get nodes -o wide
    
    NAME       STATUS   ROLES                  AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                           KERNEL-VERSION                 CONTAINER-RUNTIME
    woobin-vm1   Ready    control-plane,master   461d   v1.23.6   192.168.0.9   <none>        Rocky Linux 8.6 (Green Obsidian)   4.18.0-372.32.1.el8_6.x86_64   docker://20.10.11
    
    1
    2
    3
    4
    5
    6
    7
    8
    
    kubectl edit no woobin-vm1
    
    apiVersion: v1
    kind: Node
    metadata:
      annotations:
        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
        ...
    
  • Kubernetes는 v1.24부터 Docker shim 지원을 공식적으로 종료했습니다.

containerd

Untitled

  • 2017년 12월 CNCF에서 버전 1.0에 도달 한 containerd는 kubelet과 containerd사이에서 작동하려면 cri-containerd라는 데몬이 필요했습니다. Cri-containerd 는 Kubelet의 CRI (Container Runtime Interface) 서비스 요청을 처리하고 containerd를 사용하여 해당 컨테이너 및 컨테이너 이미지를 관리합니다.
  • containerd1.1에서는 cri-containerd 데몬이 이제 containerd CRI 플러그인으로 리팩터링됩니다. CRI 플러그인은 containerd1.1에 내장되어 있으며 기본적으로 활성화되어 있습니다. cri-containerd와 달리 CRI 플러그인은 직접 함수 호출을 통해 containerd와 상호 작용합니다. 사용자는 이제 containerd1.1과 함께 Kubernetes를 직접 사용할 수 있습니다. cri-containerd 데몬은 더 이상 필요하지 않습니다.
This post is licensed under CC BY 4.0 by the author.