runc中文翻译系列一 runc入门

runc 是一个 CLI 工具,用于根据 OCI 规范在 Linux 上孕育和运行容器。

发布

你可以在 release 页面找到 runc 的正式发布版本。

构建

runc 仅支持 Linux。它必须使用 Go 1.19 或更高版本构建。

为了启用 seccomp 支持,你需要在你的平台上安装 libseccomp

例如 CentOS 的 libseccomp-devel 或 Ubuntu 的 libseccomp-dev

bash 复制代码
# 在 GOPATH/src 中创建 "github.com/opencontainers
cd github.com/opencontainers
git clone https://github.com/opencontainers/runc
cd runc

make
sudo make install

你也可以使用 go get 安装到你的 GOPATH,前提是你已经在 src 下创建了一个 github.com 父文件夹:

bash 复制代码
go get github.com/opencontainers/runc
cd $GOPATH/src/github.com/opencontainers/runc
make
sudo make install

runc将被安装到系统中的/usr/local/sbin/runc`。

编译标志

runc 支持可选的编译标志,以编译支持各种特性、 其中一些标签默认已启用(参见顶级 Makefile 中的 BUILDTAGS)。

要更改默认的联编标志,请为 make 设置 BUILDTAGS 变量、 例如,禁用 seccomp:

bash 复制代码
make BUILDTAGS=""
构建标志 特性 默认开启 依赖
seccomp 使用 libseccomp 过滤系统调用。 libseccomp
!runc_nodmz 通过使用小型 C 二进制文件减少 CVE-2019-5736 保护的内存使用量,[更多详情请参见 memfd-bind][contrib-memfd-bind]。runc_nodmz 会禁用此功能,并导致 runc 使用不同的保护机制,这将在容器启动期间暂时进一步增加内存使用量。也可以通过设置 RUNC_DMZ=legacy 环境变量在运行时禁用此功能。
runc_dmz_selinux_nocompat 禁用 SELinux DMZ 解决方法(新发行版应设置此项)。详情请参阅 [dmz README] 。

以下构建标记曾在早期使用,但现已过时:

  • nokmem(自 runc v1.0.0-rc94 版起内核内存设置被忽略)
  • apparmor(自 runc v1.0.0-rc93,该功能始终处于启用状态)
  • selinux(自 runc v1.0.0-rc93 起始终启用该功能)

contrib-memfd-bind

dmz README

运行测试套件

runc 目前支持通过 Docker 运行测试套件。 要运行测试套件,只需键入 make test

bash 复制代码
make test

有一些额外的 make target 可用于在容器外运行测试,但不建议这样做,因为编写测试时希望它们能在任何地方写入和删除。

你可以通过设置 TESTFLAGS 变量来运行特定的测试用例。

bash 复制代码
# make test TESTFLAGS="-run=SomeTestFunction"

您可以通过设置 TESTPATH 变量来运行特定的集成测试。

bash 复制代码
# make test TESTPATH="/checkpoint.bats"

通过设置 ROOTLESS_TESTPATH 变量,可以运行特定的无根集成测试。

bash 复制代码
# make test ROOTLESS_TESTPATH="/checkpoint.bats"

您可以通过设置 CONTAINER_ENGINE_BUILD_FLAGSCONTAINER_ENGINE_RUN_FLAGS 变量,使用容器引擎的标志运行测试。

bash 复制代码
# make test CONTAINER_ENGINE_BUILD_FLAGS="--build-arg http_proxy=http://yourproxy/" CONTAINER_ENGINE_RUN_FLAGS="-e http_proxy=http://yourproxy/"

依赖关系管理

runc 使用 Go Modules 进行依赖管理。 请参阅 Go Modules,了解如何添加或更新新的依赖项。

bash 复制代码
# 更新供应商依赖关系
make vendor
# 验证全部依赖
make verify-dependencies

使用 runc

请注意,runc 是一个低级工具,在设计时并没有考虑最终用户的需求。 它主要由其他更高级别的容器软件使用。

因此,除非有某些特定用例阻止使用 Docker 或 Podman 等工具,否则不建议直接使用 runc。

如果你仍然想使用 runc,下面是使用方法。

创建 OCI Bundle

要使用 runc,你的容器必须是 OCI Bundle格式。 如果你已经安装了 Docker,可以使用它的 export 方法从现有的 Docker 容器中获取根文件系统。

bash 复制代码
# 创建最顶层的目录
mkdir /mycontainer
cd /mycontainer

# 创建rootfs目录
mkdir rootfs

# 通过docker把busybox导出到rootfs目录
docker export $(docker create busybox) | tar -C rootfs -xvf -

在填充根文件系统后,您只需在 bundle 中以 config.json 文件的格式生成规范。 runc 提供了一个 spec 命令来生成基本模板规范,然后您就可以对其进行编辑。 要查找规范中字段的功能和文档,请参阅 specs 资源库。

bash 复制代码
runc spec

运行容器

假设你在上一步中获得了一个 OCI Bundle,你可以用两种不同的方式执行容器。

第一种方式是使用便捷命令 run,它将处理容器的创建、启动和退出后的删除。

bash 复制代码
# 以root用户运行
cd /mycontainer
runc run mycontainerid

如果你使用未修改的 runc spec 模板,就会在容器内生成一个 sh 会话。

启动容器的第二种方法是使用规范生命周期操作。 这使您对容器运行时的创建和管理方式拥有更多权力。 这也将在后台启动容器,因此您必须编辑 config.json,删除下面简单示例中的 terminal 设置。 请参阅 runc 终端处理 的更多详情。 您在 config.json 中的进程字段应该如下所示,其中包含 "terminal": false"args": ["sleep", "5"]

json 复制代码
        "process": {
                "terminal": false,
                "user": {
                        "uid": 0,
                        "gid": 0
                },
                "args": [
                        "sleep", "5"
                ],
                "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
        },

现在,我们可以在 shell 中进行生命周期操作了。

bash 复制代码
# 以root用户身份运行
cd /mycontainer
runc create mycontainerid

# 查看容器是否已创建并处于 "created "状态
runc list

# 启动容器内的进程
runc start mycontainerid

# 5 秒后查看容器是否已退出并处于停止状态
runc list

# 现在删除容器
runc delete mycontainerid

这样,高层系统就可以在容器创建后和/或删除前设置各种设置,从而增强容器的创建逻辑。例如,容器的网络堆栈通常是在 "创建 "之后但在 "启动 "之前设置的。

无 root 权限的容器

runc 可以在没有 root 权限的情况下运行容器。这被称为 rootless。要运行无根容器,需要向 runc 传递一些参数。请参见下文并与之前的版本进行比较。

注意: 要使用此功能,必须在内核中编译并启用 "User Namespace"。根据发行版的不同,有多种方法可以做到这一点:

  • 确认内核配置中设置了 CONFIG_USER_NS=y(通常在 /proc/config.gz)。
  • Arch/Debian: echo 1 > /proc/sys/kernel/unprivileged_userns_clone.
  • RHEL/CentOS 7: echo 28633 > /proc/sys/user/max_user_namespaces `. 以普通用户身份运行以下命令:
bash 复制代码
# 和第一个例子一样
mkdir ~/mycontainer
cd ~/mycontainer
mkdir rootfs
docker export $(docker create busybox) | tar -C rootfs -xvf -

# --rootless参数指示 runc spec 生成无根容器的配置,这将允许你以非 root 用# 户身份运行容器。
runc spec --rootless

# 根参数告诉 runc 在哪里存储容器状态。用户必须可以写入目录。
runc --root /tmp/runc run mycontainerid

监督

runc 可以与进程监管程序和 init 系统一起使用,以确保容器在退出时重新启动。 systemd 单元文件的示例如下。

systemd 复制代码
[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

[Install]
WantedBy=multi-user.target

更多文档

相关推荐
唐大爹9 小时前
项目实战:k8s部署考试系统
云原生·容器·kubernetes
wusam12 小时前
螺蛳壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习03(网络及IP规划)
运维·服务器·网络·docker·容器
一直在进步的派大星12 小时前
Docker 从安装到实战
java·运维·docker·微服务·容器
Zl15975315975316 小时前
k8s基础环境部署
云原生·容器·kubernetes
陌殇殇殇18 小时前
使用GitLab CI构建持续集成案例
运维·ci/cd·云原生·容器·kubernetes·gitlab
技术钱18 小时前
docker简介
运维·docker·容器
roman_日积跬步-终至千里18 小时前
【docker】docker常见命令
运维·docker·容器
Gogeof19 小时前
云原生化 - 基础镜像(简约版)
微服务·云原生·基础镜像
Gogeof21 小时前
云原生化 - 旅程(简约版)
微服务·云原生
爱吃龙利鱼21 小时前
网络基础知识笔记(四)
运维·网络·笔记·云原生·智能路由器