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

相关文章
相关标签/搜索