RunC

v1.0

CLI tool for spawning and running containers according to the OCI specification

  • CLI (Command Line Interface) tool : runc는 커맨드라인툴 이구나
  • spawning (산란하다) : 왜 spawn이라는 표현을 썼을까?
    • process가 child를 만드는 전통적인 방법은 fork : 부모의 모든 것을 복제해서 만드는 방법
    • fork의 단점은 모든 것을 물려주려다 보니 무겁다는 것 (오버헤드)
      • 그리고 바로 exec 하는 경우(fork-exec) 복제한 걸 쓰지도 않아 너무도 아깝다는 것 (비효율)
    • 그래서 fork-exec 보다 세밀한 조작과 선택적 복제를 지원하는 방법을 고안
    • posix_spawn : fork-exec + 선택적 복제를 지원
    • Container Spawning : 컨테이너를 (새로) “생성”의 의미
      • Forking은 “복제”의 의미
  • OCI (Open Container Initiative) Runtime Spec.
    • 컨테이너 포맷과 런타임에 대한 개방형 산업 표준
    • https://opencontainers.org/about/overview/
    • runtime-spec : how to run a “filesystem bundle”
      • OCI implementation —(download) —> OCI Image
      • OCI Image —(unpack)—> OCI Runtime filesystem bundle
      • OCI Runtime —(run)—> OCI Runtime filesystem bundle
      • this entire workflow should support the UX users have come to expect from container engines (docker, rkt)
    • image-spec

Release: https://github.com/opencontainers/runc/releases

Goal

  • The goal of runc is to make standard containers available everywhere.
    • runc의 목표는 어디서나 사용가능한 표준 컨테이너를 만드는 것이다.

Features

  • Full support Linux namespaces including user namespaces
  • Native support for all security features available in Linux —> If linux can do it, runc can do it
    • Selinux
    • Apparmor
    • seccomp
    • control groups
    • capability drop
    • pivot_root
    • uid/gid dropping
  • Native support for live migration, /w the help of the CRIU team at Parallels
  • Native support for Windows 10 containers is being contributed directly by MS engineers
  • Planned native support for Arm, Power, Sparc /w direct participation and support from Arm, Intel, Qualcomm, IBM, and the entire hardware manufacturers ecosystem.
  • Planned native support for bleeding edge hardware features - DPDK, sr-iov, tpm, secure enclave, etc.
  • Portable performance profiles, contributed by Google engineers based on their experience deploying containers in production.
  • A formally specified configuration format, governed by the Open Container Project under the auspices of the Linux Foundation. In other words: it’s a real standard.

실습 준비

git 참고: https://github.com/opencontainers/runc

Pre-requisite (ubuntu 18.04 기준)

Golang 설치 (golang-go 13+)

curl -O https://storage.googleapis.com/golang/go1.15.7.linux-amd64.tar.gz > /dev/null 2>&1
tar xf go1.15.7.linux-amd64.tar.gz
sudo mv go /usr/local/
echo "PATH=$PATH:/usr/local/go/bin" | tee ~/.bash_profile
source ~/.bash_profile

gcc 설치

sudo apt update && sudo apt install gcc

make 설치

sudo apt install make

pkg-config 설치

sudo apt install pkg-config

pkg-config: exec: "pkg-config": executable file not found in $PATH

libseccomp-dev 설치

sudo apt install libseccomp-dev

seccomp (secure computing mode) ? 리눅스 보안 메커니즘. linux sandbox 기반 “시스템콜 허용/차단”

git clone (runc)

git clone https://github.com/opencontainers/runc

Build

sudo -Es
cd runc
make
make install

Test

make test
  • test 를 돌리려면 docker 설치 필요
  • 일반 계정에서 수행하려면 docker 그룹 권한 필요

실습

Creating an OCI Bundles

mkdir /mycontainer
cd /mycontainer
mkdir rootfs
docker export $(docker create busybox) | tar -C rootfs -xvf -
runc spec
cat config.json
  • docker export
  • docker create
  • runc spec : create a new “specification file” : The spec command creates the new specification file named “config.json” for the bundle.

Running Containers

cd /mycontainer
runc run mycontainerid
  • runc run : create and start a container

/w lifecycle operations

vi config.json
### . . .
  "terminal": false,
### . . .
  "args": [
    "sleep", "5"
  ]
### . . .

cd /mycontainer
runc create mycontainerid
runc list
runc start mycontainerid
runc list
runc delete mycontainerid
  • create, start, stop, delete 등 lifecycle 단계를 구분: 상위 시스템에서 쉽게 각 단계 사이에 로직 삽입 가능
  • 예) 네트웍 셋업을 컨테이너의 생성과 기동 사이에 처리

Rootless containers

root 권한 없이도 “일반 계정으로 컨테이너를 생성”

mkdir ~/mycontainer
cd ~/mycontainer
mkdir rootfs
docker export $(docker create busybox) | tar -C rootfs -xvf -
runc spec --rootless
runc --root /tmp/runc run mycontainerid

확인

cat /proc/sys/kernel/unprivileged_userns_clone
echo 1 > /proc/sys/kernel/unprivileged_userns_clone

supervisor

vi /etc/systemd/system/runc.service

[Unit]
Description=Start my container

[Service]
Type=forking
ExecStart=/usr/local/sbin/runc run -d --pid-file /run/mycontainerid.pid mycontainerid
ExecStopPost=/usr/local/sbin/runc delete mycontainerid
WorkingDirectory=/mycontainer
PIDFile=/run/mycontainerid.pid
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

### 적용 및 리스타트
systemctl daemon-reload
systemctl start runc.service
  • config.json: terminal mode를 false 해줄 것
vi config.json

### . . .
"process": {
  "terminal" : false 
}
### . . .