Docker 내부 구조

https://koocci-dev.tistory.com/3

Docker 란?

https://medium.com/faun/docker-containerd-standalone-runtimes-heres-what-you-should-know-b834ef155426

Namespace 란? (리눅스)

  • 한덩어리의 데이터에 이름을 붙혀 충돌 가능성을 줄이고, 쉽게 참조할 수 있게하는 개념.

Linux 커널의 namespace 기능은 Linux의 오브젝트에 이름을 붙임으로써 다음과 같은 6개의 독립된 환경을 구축할 수 있다.

  1. PID namespace
    • 프로세스에 할당된 고유한 ID를 말하며 이를 통해 프로세스를 격리할 수 있다
    • namespace가 다른 프로세스 끼리는 서로 액세스할 수 없다
  2. Network namespace
    • 네트워크 디바이스, IP 주소, Port 번호, 라우팅 테이블, 필터링테이블 등의 네트워크 리소스를 namespace마다 격리시켜 독립적으로 가질 수 있다. 이 기능을 이용하면 OS 상에서 사용중인 Port가 있더라도 컨테이너 안에서 동일한 Port를 사용 가능하다.
  3. UID namespace
    • UID, GID를 namespace 별로 독립적으로 가질 수 있도록 한다.
    • namespace 안과 호스트 OS 상에서 서로 다른 UID, GID를 가질 수 있다.
  4. Mount namespace
    • 호스트 OS와 namespace가 서로 다른 격리된 파일시스템 트리를 가질 수 있도록 한다 (마운트는 컴퓨터에 연결된 기기나 기억장치를 OS에 인식시켜 사용가능한 상태로 만드는 것을 의미한다)
  5. UTS namespace
    • namespace 별로 호스트명이나 도메인 명을 독자적으로 가질 수 있다
  6. IPC namespace
    • 프로세스간 통신(IPC) 오브젝트를 namespace 별로 독립적으로 가질 수 있다

cGroups 란?

  • 리눅스의 프로세스는 하나 이상의 스레드 모음으로 동작한다. cGroups는 프로세스와 스레드를 그룹화하여 그 그룹안에 존재하는 프로세스와 스레드에 대한 관리를 수행하기 위한 기능이다. 예를 들어 호스트 OS의 CPU나 메모리와 같은 자원에 대해 그룹별로 제한을 둘 수 있다.
  • cGroups로 컨테이너 안의 프로세스에 대해 자원을 제한 함으로써 특정 컨테이너가 호스트 OS의 자원을 모두 사용하는 일을 막는다.

cGroups 서브 시스템

  1. CPU
    • CPU 사용량 제한
  2. CPUacct
    • CPU 사용량 통계
  3. CPUset
    • CPU나 메모리 배치를 제어
  4. memory
    • 메모리 사용량 제한
  5. devices
  • 디바이스 엑세스 허가/ 거부
  1. freezer
    • 그룹에 속한 프로세스 정지/ 재개
  2. net_cls
    • 네트워크 제어 태그를 부가
  3. blkio
    • 블록 디바이스 입출력량 제어

CRI(Container Runtime Interface )

그래서, kubelet의 코드를 수정하지 않고, 다양한 컨테이너 런타임을 지원하기 위해서, kubelet과 컨테이너 런타임 사이의 인터페이스를 통일화하는 스펙이 등장하였는데, 이것이 CRI (Container Runtime Interface)이다. 컨테이너의 생성,삭제 등의 생명 주기를 관리하는 스펙으로 gRPC 기반의 API 스펙으로 되어 있고, 새로운 컨테이너 런타임은 CRI 스펙에 맞춰서 CRI 컴포넌트를 구현하면 되는 구조가 되었다.

출처: https://bcho.tistory.com/1353 [조대협의 블로그]

OCI (Open Container Initiative)

그런데, 지원되는 컨테이너의 종류가 계속해서 늘어가고 있고, 그때마다, CRI를 다시 구현해야 하는 문제가 생김에 따라 컨테이너 런타임 자체를 표준화하고자 하는 노력이 있었는데, 그로 인해서 정해진 스펙이 OCI (Open Container Initiative) 이다. OCI 스펙을 맞춰서 구현된 컨테이너 런타임을 별도의 CRI 구현이 없이 OCI를 지원하는 CRI 구현체에 의해서 관리가 가능해진다. OCI 스펙에 따른 컨테이너 런타임을 관리하는 CRI 컴포넌트는 CRI-O 라는 컴포넌트로 구현되어 있다. 즉 OCI 스펙을 준수한다면, CRI-O를 통해서 kubelet으로 부터 명령을 받을 수 있는 구조가 된다.

출처: https://bcho.tistory.com/1353 [조대협의 블로그]

Containerd ?

runC를 제어하는 데몬으로 Docker engine에 내장. containerd는 업계 표준 컨테이너 런타임이며, 전체 컨테이너 life cycle(이미지 전송 및 저장, 컨테이너 실행 및 관리, low-level 저장 및 네트워크 첨부 등)을 관리 할 수 있다. runC를 활용하여 체크 포인트 및 복원, seccomp 및 userspace 지원과 같은 고급 기능을 제공한다.

Containerd 내 gRPC 모듈

  • containerd:shim
    • 컨테이너를 위한 IO 를 다루는 프로세스
  • containerd:execution
    • 컨테이너 생성 및 정보 획득을 위한 단순한 API
  • containerd:rootfs
    • 다운로드된 이미지를 압축 해제하고, 레이어 집합으로부터 루트 파일시스템을 준비한다. Mounts는 생성할 마운트 리스트를 반환한다.
  • containerd:content
    • 콘텐츠 주소 지정 저장소, Content는 요약(content hash)를 통해 식별된다. Status는 진행중인 write 트랜잭션의 상태를 제공한다.

Container Runtime Shim?

컨테이너 런타임 shim 은 컨테이너 관리자 ( containerd , cri-o , podman ) 와 컨테이너 런타임 ( runc , crun ) 사이에 상주하여 이러한 대응 물의 통합 문제를 해결하는 소프트웨어입니다.

  1. Docker (container) 의 작동 원리:
    1) namespaces
    2) cgroups
  2. cgroups
    • 메모리, CPU, I/O, 네트워크, device 노드(/dev/) 제어
  3. namespaces
    • 종류: mnt, uts, ipc, pid, net, user
    • namespace 사용법

      ps aux

      nsenter //cgroup 에 들어가지 않음. ㄹ소스 제한 영향 안 받음

      docker exec //cgroup 에 들어감. 리소스 제한 영향 받음

      cgcreate -a ssut -g memory:testgrp //ssut 유저 소유

      ls -alh /sys/fs/cgroup/memory/testgrp/ // /sys/fs/cgroup/{리소스}/{그룹이름}

      echo 2000000 > /sys/fs/cgroup/memory/testgrp/memory.kmem.limit_in_bytes //최대메모리 2MB

      cgexec -g memory:testgrp bash // bash 를 testgrp 그룹에 의해 제한 실행

    • unshare --fork --pid --mount-proc bash
  4. 런타임
    • lxc, libcontainer, runc
    • cgroup, namespaces 를 표준으로 정의해둔 OCI(Open Container Initative) 스펙을 구현한 컨테이너 기술의 구현체
      1) lxc : canonical 이 지원하는 프로젝트
      2) docker 에서의 runtime : lxc > libcontainer > runC(libcontainer 의 리팩토링 구현체) 로 자체 구현체를 갖게 됨.
  5. Docker 의 Process
                      Docker Engine
                                |
                          containerd
                                |
    |------------------------------|--------------------------|
    containerd-shim containerd-shim containerd-shim
    | | |
    runc runc runc
    • Docker-engine 과 containerd 완전히 분리
    • Docker engine 버전 올릴 때, 재시작해도 container 의 재시작 없이 사용할 수 있게 됩니다.
    • 4개의 독립적인 Process

      ps aux | grep docker

      docker
      docker-containerd
      docker-containerd-shim
      docker-runc
  6. 2) Docker Process 별 역할
    a) containerd : OCI 구현체(주로 runC) 를 이용해 container 관리하는 daemon
    b) Docker engine : 이미지,네트워크,디스크 등의 관리 역할
  7. 1) 구성도

출처: https://2infinity.tistory.com/46 [Learn and Run]

+ Recent posts