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

更多文档

相关推荐
KubeSphere 云原生6 小时前
云原生周刊:在 Kubernetes 上运行机器学习
云原生·容器·kubernetes
码界奇点6 小时前
通往Docker之路从单机到容器编排的架构演进全景
docker·容器·架构
阿Y加油吧7 小时前
Docker从入门到实战——含容器部署、docker基础、项目部署
运维·docker·容器
不知道累,只知道类8 小时前
记一次诡异的“偶发 404”排查:CDN 回源到 OSS 导致 REST API 失败
java·云原生
victory04318 小时前
progen2 docker镜像打包命令文档
运维·docker·容器
AKAMAI9 小时前
Akamai推出Akamai Inference Cloud (AI推理云),重新定义人工智能的应用场景与实现方式
人工智能·云原生·云计算
算是难了10 小时前
Docker基础总结
运维·docker·容器
ityangs10 小时前
GitLab 私服(基于 Docker)搭建方案
git·docker·容器·gitlab
沐雨风栉12 小时前
告别设备限制!CodeServer+cpolar让VS Code随时随地在线编程
云原生·eureka·重构·pdf·开源
技术杠精13 小时前
Docker Swarm 的负载均衡和平滑切换原理
docker·容器·负载均衡·1024程序员节