Docker RunC Runtime之OCI標準CLI操做深刻剖析-Docker商業環境實戰

專一於大數據及容器雲核心技術解密,可提供全棧的大數據+雲原平生臺諮詢方案,請持續關注本套博客。若有任何學術交流,可隨時聯繫。更多內容請關注《數據雲技術社區》公衆號。 node

1 OCI標準

  • 在2015年6月,由Docker以及其餘容器領域的領導者共同創建了圍繞容器格式和運行時的開放的工業化標準,即Open Container Initiative(OCI),OCI具體包含兩個標準:運行時標準(runtime-spec)和容器鏡像標準(image-spec)。
  • 容器鏡像標準定義了容器鏡像的打包形式(pack format)
  • 運行時標準定義瞭如何去運行一個容器。
  • 容器運行時(Container Runtime)是指管理容器和容器鏡像的軟件,當若是不一樣的運行時只能支持各自的容器,那麼顯然不利於整個容器技術的發展。
  • runC是一個遵循OCI標準的用來運行容器的命令行工具(CLI Tool),它也是一個Runtime的實現。

  • runC不只能夠被docker engine使用,它也能夠單獨使用(它自己就是命令行工具)

2 安裝runC

2.1 依賴準備

  • Go version 1.6或更高版本
  • libseccomp庫
yum install libseccomp-devel for CentOS
 apt-get install libseccomp-dev for Ubuntu
複製代碼

2.2 編譯

# 在GOPATH/src目錄建立github.com目錄
> go get github.com/opencontainers/runc
> cd $GOPATH/src/github.com/opencontainers/runc
> make
> sudo make install
複製代碼

2.3 運行RunC

  • 使用docker export命令將已有鏡像導出爲OCI Bundle的格式
# create the top most bundle directory
> mkdir /mycontainer
> cd /mycontainer

# create the rootfs directory
> mkdir rootfs

# export busybox via Docker into the rootfs directory
> docker export $(docker create busybox) | tar -C rootfs -xvf -
> ls rootfs 
bin  dev  etc  home  proc  root  sys  tmp  usr  var
複製代碼
  • 有了root filesystem,還須要config.json,runc spec能夠生成一個基礎模板
> runc spec
> ls
config.json rootfs
複製代碼
  • 建立一個config.json文件,這個文件是一個標準的OCI格式的文件,把 "terminal": true 改成 false,把 "args": ["sh"] 改成 "args": ["sleep", "30"]

{
    "ociVersion": "1.0.1-dev",
    "process": {
        "terminal": fasle,
        "user": {
            "uid": 0,
            "gid": 0
        },
        "args": [
            "sleep","30"
        ],
        "env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "TERM=xterm"
        ],
        "cwd": "/",
        "capabilities": {
            "bounding": [
                "CAP_AUDIT_WRITE",
                "CAP_KILL",
                "CAP_NET_BIND_SERVICE"
            ],
            "effective": [
                "CAP_AUDIT_WRITE",
                "CAP_KILL",
                "CAP_NET_BIND_SERVICE"
            ],
            "inheritable": [
                "CAP_AUDIT_WRITE",
                "CAP_KILL",
                "CAP_NET_BIND_SERVICE"
            ],
            "permitted": [
                "CAP_AUDIT_WRITE",
                "CAP_KILL",
                "CAP_NET_BIND_SERVICE"
            ],
            "ambient": [
                "CAP_AUDIT_WRITE",
                "CAP_KILL",
                "CAP_NET_BIND_SERVICE"
            ]
        },
        "rlimits": [
            {
                "type": "RLIMIT_NOFILE",
                "hard": 1024,
                "soft": 1024
            }
        ],
        "noNewPrivileges": true
    },
    "root": {
        "path": "rootfs",
        "readonly": true
    },
    "hostname": "runc",
    "mounts": [
        {
            "destination": "/proc",
            "type": "proc",
            "source": "proc"
        },
        {
            "destination": "/dev",
            "type": "tmpfs",
            "source": "tmpfs",
            "options": [
                "nosuid",
                "strictatime",
                "mode=755",
                "size=65536k"
            ]
        },
        {
            "destination": "/dev/pts",
            "type": "devpts",
            "source": "devpts",
            "options": [
                "nosuid",
                "noexec",
                "newinstance",
                "ptmxmode=0666",
                "mode=0620",
                "gid=5"
            ]
        },
        {
            "destination": "/dev/shm",
            "type": "tmpfs",
            "source": "shm",
            "options": [
                "nosuid",
                "noexec",
                "nodev",
                "mode=1777",
                "size=65536k"
            ]
        },
        {
            "destination": "/dev/mqueue",
            "type": "mqueue",
            "source": "mqueue",
            "options": [
                "nosuid",
                "noexec",
                "nodev"
            ]
        },
        {
            "destination": "/sys",
            "type": "sysfs",
            "source": "sysfs",
            "options": [
                "nosuid",
                "noexec",
                "nodev",
                "ro"
            ]
        },
        {
            "destination": "/sys/fs/cgroup",
            "type": "cgroup",
            "source": "cgroup",
            "options": [
                "nosuid",
                "noexec",
                "nodev",
                "relatime",
                "ro"
            ]
        }
    ],
    "linux": {
        "resources": {
            "devices": [
                {
                    "allow": false,
                    "access": "rwm"
                }
            ]
        },
        "namespaces": [
            {
                "type": "pid"
            },
            {
                "type": "network"
            },
            {
                "type": "ipc"
            },
            {
                "type": "uts"
            },
            {
                "type": "mount"
            }
        ],
        "maskedPaths": [
            "/proc/kcore",
            "/proc/latency_stats",
            "/proc/timer_list",
            "/proc/timer_stats",
            "/proc/sched_debug",
            "/sys/firmware",
            "/proc/scsi"
        ],
        "readonlyPaths": [
            "/proc/asound",
            "/proc/bus",
            "/proc/fs",
            "/proc/irq",
            "/proc/sys",
            "/proc/sysrq-trigger"
        ]
    }
}
複製代碼

3 RunC 命令

3.1 經常使用命令

$ runc -h

使用 create 命令建立容器
sudo runc create mybusybox

使用 list 命令查看當前存在的容器
sudo runc list

ID              PID         STATUS      BUNDLE                           CREATED                          OWNER
mycontainerid   12068       running     /mycontainer   2018-12-25T19:45:37.346925609Z   

使用 ps 命令看看容器內運行的進程
sudo runc ps mybusybox
複製代碼

3.2 高級命令

使用 state 命令查看容器的狀態
sudo runc state mybusybox

使用 ps 命令看看容器內運行的進程
sudo runc ps mybusybox

使用 start 命令執行容器中定義的任務,使用 start 命令啓動容器後,
讓咱們再用 ps 命令看看容器內運行了什麼進程
sudo runc start 

使用 exec 命令在容器中執行命令
sudo runc exec mybusybox ls

使用 delete 命令刪除容器
sudo runc delete mybusybox

使用 kill 命令中止容器中的任務
sudo runc kill mybusybox

使用 pause 命令暫停容器中的全部進程
sudo runc pause mybusybox

執行 pause 命令後,容器的狀態由 running 變成了 paused。而後咱們再經過 resume 命令恢復容器中進程的執行
sudo runc resume mybusybox

使用 events 命令獲取容器的資源使用狀況
sudo runc events mybusybox
複製代碼

前面咱們運行的全部命令都是以 root 權限執行的。能不能以普通用戶的權限運行容器呢?
答案是能夠的,並被稱爲 rootless。
要想以 rootless 的方式運行容器,須要咱們在生成容器的配置文件時就爲 spec 命令指定 rootless 參數:
runc spec --rootless

而且在運行容器時經過 --root 參數指定一個存放容器狀態的路徑:
runc --root /tmp/runc run mybusybox
複製代碼
  • 容器的熱遷移操做,所謂熱遷移就是將一個容器進行 checkpoint 操做,並得到一系列文件,使用這一系列文件能夠在本機或者其餘主機上進行容器的 restore 工做。這也是 checkpoint 和 restore 兩個命令存在的緣由。熱遷移屬於比較複雜的操做。
  • 目前 runC 使用了 CRIU 做爲熱遷移的工具。RunC 主要是調用 CRIU(Checkpoint and Restore in Userspace)來完成熱遷移操做。CIRU 負責凍結進程,並將做爲一系列文件存儲在硬盤上。並負責使用這些文件還原這個被凍結的進程。

4 總結

runC 做爲標準化容器運行時的一個實現目前已經被 docker 內置爲默認的容器運行時,暫時總結於此。linux

專一於大數據及容器雲核心技術解密,可提供全棧的大數據+雲原平生臺諮詢方案,請持續關注本套博客。若有任何學術交流,可隨時聯繫。更多內容請關注《數據雲技術社區》公衆號。 git

相關文章
相關標籤/搜索