container runtime에 대하여 - part2 container runtime tools

양승현·2023년 9월 17일
0

kubernetes

목록 보기
13/18
post-thumbnail

container runtime

  • 컨테이너를 다루다 보면 자주 듣는 용어로 컨테이너 런타임이 있다.
  • runc, containerd, podman, cri-o 등 다양한 런타임이 있는데, 이 런타임들은 각각 다른 상황에 맞게 만들어졌으면 다른 기능을 구현하고 있다.
  • containerd와 cri-o는 이미지 관리와 api를 구현하고 runc를 사용하여 컨테이너를 실행한다.
  • 이미지 전송, 관리, 압축 & 해제 및 API를 포함하는 이러한 기능을 일반적으로 고수준의 컨테이너 런타임이라하며, runc와 같은 컨테이너를 실행 및 생성에만 초점을 맞춘 런타임을 일반적으로 저수준의 컨테이너 런타임이라한다.

container engine

podman(podman)

  • podman은 OCI 컨테이너 및 컨테이너 이미지를 사용하여 애플리케이션을 쉽게 찾고, 실행, 구축, 공유, 배포할 수 있도록 설계된 daemonless 형태인 open source이다.
  • podman은 docker 컨테이너 엔진을 사용한 사람들에게 친숙한 CLI를 제공하며, docker를 podman으로 alias(별칭) 지정할 경우 동일한 방식으로 사용할 수 있다.
  • 일반적으로 다른 컨테이너 엔진(docker, containerd, CRI-O)과 마찬가지로, podman은 운영체제와 인터페이스하고 실행중인 컨테이너를 만들기 위해 OCI 호환 컨테이너 런타임(runc)에 의존한다.
  • 이를 통해 podman이 만든 실행 중인 컨테이너를 다른 일반적인 컨테이너 엔진(docker, containerd, CRI-O)에 의해 만들어진 것과 거의 구별할 수 없다.
  • podman은 docker build를 대체한 buildah 유틸리티를 사용하여 컨테이너 이미지를 생성한다.
  • 이미지 레지스트리와 컨테이너 엔진 사이에 이미지 전송을 위한 docker push는 skopeo가 대체한다.

Podman과 docker의 차이(daemonless)

docker 동작 방식
  • docker와의 가장 큰 차이점은 podman은 데몬(daemon-less)이 필요 없다는 점이다.
  • docker는 docker daemon을 구동하며 모든 작업이 이루어지며, 사용자는 docker client 명령어를 사용하여 도커 데몬을 제어하였다.
podman 동작 방식
  • container daemon을 사용하는 docker와는 다르게 podman은 daemon 프로세스를 사용하지 않기 때문에, systemd에 서비스를 생성해서 관리하는 방법을 많이 사용한다.
  • systemd를 위한 서비스를 생성하기 위해서는 설정들을 담고 잇는 서비스 파일을 만들어야 한다.
# 컨테이너 생성
$ podman run -it nginx

# podman은 generate 명령을 이용하여 systemd 서비스 파일을 생성해 준다.
# 컨테이너 이름 혹은 ID를 사용하여 systemd 장치 파일을 생성하고 이를 ~/.config/systemd/user/container-myubi.service 경로로 파일을 보낸다.
$ podman generate systemd --name nginx > ~/.config/systemd/user/container-myubi.service

# 확인
$ cat ~/.config/systemd/user/container-myubi.service
# Restart=on-failure 행은 재시작 정책을 설정하고 서비스를 완전히 시작하거나 중지할 수 없거나 프로세스가 0이 아닌 경우 다시 시작하도록 systemd 에 지시
# ExecStart 행은 컨테이너를 시작하는 방법을 설명
# ExecStop 행은 컨테이너를 중지하고 제거하는 방법을 설명
  • 출력되는 내용을 기반으로 추가적인 설정을 변경하여 systemctl을 이용하여 서비스를 시작할 수 있다.
  • podman generate 명령을 이용하여 kubernetes yaml 파일 생성 가능하다.

root 권한 불필요(rootless)

  • docker는 docker daemon에 모든 권한이 집중되다 보니 아무나 docker client로 docker daemon을 제어하지 못하도록 root 사용자만 docker client를 사용하도록 했다.
  • 하지만 이 방식은 시스템 운영자가 컨테이너 운영자가 되어야 하므로 업무 분리가 제대로 안되며, 과도한 root 권한이 필요하여 보안에 취약하다.
  • podman은 fork/exec으로 개별 컨테이너를 실행할 수 있으므로 1024 이하의 well know 포트를 사용하는 등의 root 권한으로 싱행해야 하는 작업이 아니라면 일반 사용자로 실행할 수 있으므로 담당자 병로 권한을 분리 할 수 있어 시스템 운영자와 서비스/컨테이너 운영자로 전문화할 수 있어 보안 측면에서 docker 보다 뛰어나다.

사용 방법

# podman은 docker와 명령어가 완전히 호환되므로 docker를 사용할 줄 안다면 별도로 podman 명령어를 배울 필요가 없다. 
# docker 를 podman 으로 대체하려면 다음과 같이 alias 만 하나 적어주면 된다.
$ alias docker=podman
# 만약 이미 docker 를 설치했고 docker daemon 도 구동되었다면 먼저 중지해야한다. 중지 하지 않으면 충돌 발생
$ sudo systemctl stop docker
$ sudo systemctl disable docker

# 컨테이너 생성
$ podman run -it nginx

# 컨테이너 상태확인
$ podman ps -a

# 컨테이너 실행
$ podman start [conatainer ID]

# 컨테이너 중지
$ podman stop [container ID]

# 컨테이너 삭제
$ podman rm [container ID]

# 컨테이너 이미지 빌드
# 현재 작업 디렉토리에 dockerfile이 있다면 build 명령으로 컨테이너 이미지 빌드 가능
$ podman build -t dockerfile:1.0 .

# 컨테이너 이미지 조회
$ podman images

# 레지스트리에서 컨테이너 이미지 pull
$ podman pull docker.io/library/yangseunghyun:latest

# 컨테이너 이미지 삭제 
$ podman rmi [image ID]

# pod 생성
$ podman pod create --name yangseunghyun

# pod 조회
$ podman pod ls
$ podman ps -a --pod

# pod에 컨테이너 추가
$ podman run -dt --pod [pod name] [container name]

# pod 시작/중지/삭제
$ podman pod start [container ID]
$ podman pod stop [container ID]
$ podman pod rm [container ID]

저수준 고수준 컨테이너 런타임

저수준(Low-level) 컨테이너 런타임 툴

  • 컨테이너 실행에만 초점

runc(runc)

  • runc는 OCI 런타임 표준을 준수하며, 리눅스 재단의 런타임 사양(runtime-spec)을 기반으로 컨테이너를 생성 및 실행하기 위한 컨테이너 런타임이다.
  • Docker는 LXC등의 외부 드라이버에 의존하여 namespace 분리와 cgroups 관리 등의 시스템 제어를 하였으나, 이후 libcontainer라는 별도의 구현체를 개발하여 사용하였다.
  • runc는 이러한 libcontainer의 client wrapper로 Go 언어로 개발되었으며, 현재 Docker에서 저수준 컨테이너 런타임으로 사용되고 있다
  • runc는 docker, Podman 또는 CRI-O를 사용하든, runc를 사용할 가능성이 높다. 해당 패키지(docker, containerd, Podman, CRI-O)들에 runc가 포함되어 있으며, 패키지 설치시 runc가 함께 설치된다.
# runc만 설치하기
$ yum install runc -y
$ man runc
  • 위 명령어를 사용하여 확인해보면, 왜 runc를 사용할 가능성이 높은지 알수있다.
  • runc는 OCI(Open Container Initiative) 형식에 따라 패키지된 애플리케이션을 실행하기 위한 명령줄 클라이언트이며, Open Container Initiative 사양을 준수하는 구현한다고 설명하고 있다.
  • 이 외 저수준 런타임 gVisor, Kata Containers 또는 Nabla Containers등이 있다.

참고 자료
https://mkdev.me/posts/the-tool-that-really-runs-your-containers-deep-dive-into-runc-and-oci-specifications


고수준(high-level) 컨테이너 런타임 툴

  • 이미지 관리 및 gRPC/Web API와 같은 더 높은 수준의 기능을 지원
  • 높은 수준이라하면 컨테이너 이미지 전송 및 관리, 이미지 압축해제, 컨테이너를 실행하기 위해 낮은 수준의 런타임으로 전달하는 역할을 수행한다.

CRI-O(Open Container Initiative)(cri-o)

Docker VS Containerd VS CRI-O
  • CRI-O는 OCI(Open Container Initiative) 호환 런타임을 사용할 수 있는 쿠버네티스 CRI(컨테이너 런타임 인터페이스)의 구현입니다.
  • 쿠버네티스는 OCI 호환 런타임을 파드를 실행하기 위한 컨테이너 런타임으로 사용할 수 있게 해준다. 오늘날 그것은 runc와 Kata Containers를 컨테이너 런타임으로 지원하지만 OCI를 준수하는 모든 런타임은 원칙적으로 연결될 수 있다.
  • CRI-O는 OCI 컨테이너 이미지를 지원하며 모든 컨테이너 레지스트리에서 가져올 수 있습니다. 도커, 모비 또는 rkt를 쿠버네티스의 런타임으로 사용하는 것에 대한 가벼운 대안이다.
  • 로컬 쿠버네티스인 minikube에서 기본으로 사용한다.

containerd(containerd)

  • containerd는 Docker에서 moby project 와 함께 발표하여 CNCF에 기증한 오픈소스이다.
  • moby project는 Docker에서 2017 년에 발표 한 오픈소스 소프트웨어 프로젝트로서 Docker를 구성하는 기능들 중에 일부를 공개한 것이다.
  • Containerd 는 Kubernetes 의 하이 레벨 런타임 표준인 CRI 런타임으로 현재는 CRI-O 와 함께 두 가지 구현체가 있다.
  • docker build 커맨드로 생성된 이미지는 OCI image spec을 준수하기 때문에 kubernetes에서도 도커에서 생성한 이미지를 사용할 수 있다.
  • Docker는 2016년 12월 컨테이너 런타임 부분을 독립적인 오픈 소스 프로젝트인 “containerd”로 분리하여 마이크로 소프트, Google, AWS, IBM 등과 공동으로 개발하며 관리된다.

  • 2017년 12월 CNCF에서 v1.0에 도달한 containerd는 kubelet과 containerd사이에서 작동하려면 cri-containerd라는 데몬이 필요했다.

  • Cri-containerd는 Kubelet의 CRI (Container Runtime Interface) 서비스 요청을 처리하고 containerd를 사용하여 해당 컨테이너 및 컨테이너 이미지를 관리한다.

  • containerd v1.1에서는 cri-containerd 데몬이 이제 containerd CRI 플러그인으로 리팩터링된다.

  • CRI 플러그인은 containerd v1.1에 내장되어 있으며 기본적으로 활성화되어 있다.

  • cri-containerd와 달리 CRI 플러그인은 직접 함수 호출을 통해 containerd와 상호 작용한다.

  • 사용자는 이제 containerd1.1과 함께 Kubernetes를 직접 사용할 수 있다.

  • cri-containerd 데몬은 더 이상 필요하지 않다.

  • containerd v1.1부터는 Docker 18.03 CE와 dockershim의 통합과 비교하여 containerd v1.1이 pod 시작 지연 시간이 더 낮으며 전체 CPU와 메모리를 덜 소모한다.

  • 'sudo systemctl status containerd.service'를 통해 containerd 상태를 확인할 수 있다.

  • 위 커맨드에서 알 수 있듯이 containerd는 systemd의 자식 프로세스이다.

  • containerd 설정파일

# default path /etc/containerd/config.toml

container rumtime에 사용할 수 있는 commandline tool

ctr(containerd CLI tool -default)

  • ctr tool은 containerd 데몬과 상호작용하여 호스트 노드의 컨테이너 관리를 지원해주는 containerd의 커맨드라인 클라이언트 툴이다.
  • containerd 진영에서 개발 되어 동일 프로젝트 소스이나 Description을 보면 하위호환성이나 안정성을 보장하지 않는다.
  • containerd 패키지 설치시 하위 패키지로 함께 설치된다.

사용 예시

# 버전 확인
$ ctr version

# Ctr은 containerd에게 컨테이너 이미지를 pull하는데 사용할 수 있다.
$ sudo ctr images pull docker.io/library/yangseunghyun:latest

# 컨테이너 이미지 리스트 확인
$ sudo ctr images list

# 이미지를 기반으로 컨테이너를 실행
$ sudo ctr container create docker.io/library/yangseunghyun:latest yang

# namespace 확인
$ ctr ns list

# 실행 중인 컨테이너 목록 확인
$ sudo ctr container list

# 컨테이너 삭제
$ sudo ctr container delete yang
  • 위 사용 예시처럼 도커와 상호 작용하는 방식과 유사하다.
  • ctr 명령어는 containerd 프로세스와 상호작용하지만 containerd의 설정파일 자체는 ctr과 연관이 없다.
  • ctr은 도커와 달리 별도로 로그인 명령을 지원하지 않음으로, 이미지를 pull & push 할 경우 ctr 명령어에 별도로 계정 정보와 registry주소를 입력해 주어야 한다.
# ctr image pull --user 유저명:비밀번호 registry주소/이미지명(전체경로)

# 
$ ctr image pull --user yang:Password docker.io/nginx:latest

# private registry를 사용하며, https를 지원하지 않을때는 --plain-http를 명시해주어야 한다.
$ ctr image pull --plain-http --user yang:Password docker.io/nginx:latest

ctr containerd 연동하기

  • containerd endpoint의 default 경로는 /var/run/containerd/containerd.sock 이며, 해당 경로에서 ctr을 구성할 수 있다.
# default path - /var/run/containerd/containerd.sock
$ cat <<EOF | sudo tee /etc/ctr.yaml
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
EOF
  • 하지만 도커와는 대조적으로 컨테이너 실행에만 초점을 맞추고 있음으로 컨테이너를 구축하기 위한 메커니즘은 제공하지 않는다.
  • 도커는 최종 사용자 및 개발자 사용에 초점을 맞추었으나, containerd는 서버에서 컨테이너 실행하는 것과 같은 운영 사용에 초점을 맞추고 있다.
  • 컨테이너 이미지를 만드는 것(build)과 같은 작업은 다른 도구에 의해 실행된다.
    참고 자료
    https://cloudyuga.guru/hands_on_lab/containerd

nerdctl(containerd 진영)

  • ctr 명령어는 dockrt client 명령어를 대체하는 것처럼 보이나 완전히 호환되지 않는다.
  • 컨테이너 이미지를 확인하거나 pull,push,create와 같은 것은 가능하다.
  • containerd 진영에서는 ctr을 보완하는 방법으로, nerdctl tool을 개발하였다.
  • nerdctl은 containerd의 알파벳 끝 4개를 따와서 명명하였으며, docker명령어와 거의 동일하게 사용 가능하다.

crictl(kubernetes-sigs 진영)

  • ctr의 경우 containerd 전용 tool이지만 기능이 제한적이다.
  • 그렇기 때문에, 더 많은 기능을 제공하고 containerd 이외의 다양한 container runtime tool을 지원하는 crictl이 있다.
  • 쿠버네티스에서는 cri표준을 준수하는 컨테이너 런타임을 통합하여 관리하기 위해 crictl이란 명령어 툴을 제공한다.
  • 일반적으로 kubeadm으로 쿠버네티스를 설치했다면 자동으로 설치된다.

사용 예시

# 레지스트리에서 이미지 가져오기
$ crictl pull docker.io/library/yangseunghyun:latest

# 이미지 목록
$ crictl images

# 이미지 삭제
$ crictl rmi <imgae-id>

crictl containerd와 연동하기

  • containerd endpoint의 default 경로는 /var/run/containerd/containerd.sock 이며, 해당 경로에서 crictl을 구성할 수 있다.
# default path - /var/run/containerd/containerd.sock
$ cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
EOF

ctr과 crictl의 차이

  • cri-o의 command line tool인 crictl은 ctr과 마찬가지로 호스트 컨테이너 런타임과 상호 작용하며 컨테이너의 정보를 조회하고 관리할 수 있는 툴이다.
  • docker가 docker 서버와 통신을, ctr이 containerd와 통신을을 위한 반면 crictl은 특정적으로 containerd를 위한 툴은 아니며 ctr과 진영 또한 다르고 동일 프로젝트도 아니다.
  • crictl 은 kuberneetes-sigs 진영에서 만들어진 container runtime 에 대한 툴로 docker와 달리 container 레벨을 넘어 k8s 오브젝트의 관점에서 파드(Pods)를 생성하거나 조회할 수도 있다. 컨테이너 이미지 조회, 컨테이너 조회 등 ctr 과 유사한 기능은 제공한다.

0개의 댓글