rkt 容器内部探秘:用 strace、procfs 与 cgroups 检查 rkt 的工作原理
发布时间:2026/9/25 5:46:02来源:尧图网络
容器运行时云原生网络【免费下载链接】rkt[Project ended] rkt is a pod-native container engine for Linux. It is composable, secure, and built on standards.项目地址https://gitcode.com/gh_mirrors/rk/rkt点击查看免费下载导读本文是一份面向开发者的实战指南围绕 rktpod-native Linux 容器引擎的 stage0/stage1/stage2 三阶段执行模型系统讲解如何用 Linux 自带的 proc 文件系统、cgroup 文件系统以及 strace 工具逐层观察 rkt 在创建容器时真正执行的系统调用、命名空间与资源隔离细节。读完本文你将能够复现完整的strace追踪流程通过/proc与systemd-cgls/systemd-cgtop独立检查任意 rkt 容器的命名空间、能力集、seccomp 状态与 cgroup 归属并把观察到的行为精确对应到本仓库的源码实现。需要说明的是原文档作者明确指出这不是对 rkt 内部机制的全方位分析而是面向希望学习容器工作原理的读者的一个起点。本文在此之上结合仓库源码做了进一步延伸帮助你把看到的现象与代码的实现一一对上。rkt 的三阶段执行模型先建立坐标系在开始追踪之前先回顾 rkt 的执行链。根据 rkt architecture 文档rkt 把一个 pod 的生命周期切分为三个阶段这也是本文反复出现的概念Stage 0stage0即rkt命令本身。负责发现、拉取、校验、存储镜像生成 Pod UUID 与 Pod Manifest在/var/lib/rkt/pods/下建立 pod 文件系统并把 stage1、stage2 镜像展开到对应目录。Stage 1stage1由 stage0exec进入的、用户信任的二进制默认是 stage1 rootfs 中的/init。它负责读取 manifest、创建命名空间与挂载、配置网络最终拉起 pod 内的隔离环境。Stage 2stage2真正运行在容器内的各个应用镜像App ACI。stage1 有多种实现flavorcoreos/src/host使用 systemd systemd-nspawnfly只做简单 chrootkvm则提供完全虚拟化隔离。本文追踪的是默认的 systemd/nspawn 路径其完整执行链ld-linux 动态链接器 → systemd-nspawn → systemd → 应用如下stage1 的run入口点、接口参数与预留目录约定详见 Stage1 ACI implementors guide后续阅读源码时会频繁引用到它。第一部分用 strace 追踪 rkt 的系统调用strace 可以记录进程发起的每一个系统调用。为了聚焦容器创建相关的核心动作我们只追踪unshare、clone、mount、chroot、execve这几类系统调用并把输出重定向到文件以便分析$ sudo strace -f -s 512 -e unshare,clone,mount,chroot,execve -o out.txt rkt run coreos.com/etcd:v2.0.10 ... ^]^]Container rkt-e6d92625-aa3f-4449-bf5d-43ffed440de4 terminated by signal KILL.参数说明-f同时追踪 fork/clone 出来的子进程-s 512把每个字符串参数的截断长度放宽到 512 字节挂载参数往往很长-e只追踪指定系统调用避免默认全量追踪产生的海量输出。容器终止后所有线索都在out.txt中。下面按阶段逐一解读。stage0overlay 挂载与 treestore首先看到的是 rkt 命令本身的执行5710 execve(/home/iaguis/work/go/src/github.com/rkt/rkt/build-rkt/target/bin/rkt, [rkt, run, coreos.com/etcd:v2.0.10], 0x7ffce2052be8 /* 22 vars */) 0由于镜像此前已被拉取且我们过滤掉的系统调用占多数stage0 阶段最值得关注的是两处 overlay 挂载5710 mount(overlay, /var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/stage1/rootfs, overlay, 0, lowerdir/var/lib/rkt/cas/tree/deps-sha512-cc076d6c508223cc3c13c24d09365d64b6d15e7915a165eab1d9e87f87be5015/rootfs,upperdir/var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/overlay/deps-sha512-cc076d6c508223cc3c13c24d09365d64b6d15e7915a165eab1d9e87f87be5015/upper,workdir/var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/overlay/deps-sha512-cc076d6c508223cc3c13c24d09365d64b6d15e7915a165eab1d9e87f87be5015/work) 0 5710 mount(overlay, /var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/stage1/rootfs/opt/stage2/etcd/rootfs, overlay, 0, lowerdir/var/lib/rkt/cas/tree/deps-sha512-c0de11e9d504069810da931c94aece3bcc5430dc20f9a5177044eaef62f93fcc/rootfs,upperdir/var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/overlay/deps-sha512-c0de11e9d504069810da931c94aece3bcc5430dc20f9a5177044eaef62f93fcc/upper/etcd,workdir/var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/overlay/deps-sha512-c0de11e9d504069810da931c94aece3bcc5430dc20f9a5177044eaef62f93fcc/work/etcd) 0关键信息有两点lowerdir来自/var/lib/rkt/cas/tree/deps-sha512-.../rootfs这正是 tree storetreestore中渲染好的镜像目录。stage2 的树是挂载在 stage1 树之内的stage1 rootfs 下的/opt/stage2/etcd/rootfs挂载了另一个 overlay。stage2 各应用在 pod 目录中统一出现在stage1/rootfs/opt/stage2/$appname这与 Stage1 ACI implementors guide 的 filesystem layout 约定一致。treestore 是如何生成deps-sha512-...的从 strace 输出可以看出deps-sha512-cc076d...形式的目录名是 treestore 的 ID。查看 treestore 实现可以确认其生成逻辑GetID(key)先把镜像 key 交给acirenderer.CreateDepListFromImageID展开完整的依赖树把所有层级的镜像 key 拼接后做 sha512 哈希得到deps-sha512-half-sha512形式的 ID见GetID与hashToKey的实现。这意味着同一镜像若依赖变化treestore ID 也会变化因此一个 ACI 可能对应多个渲染树。Render(key, rebuild)负责把镜像连同依赖渲染到$dir/tree/$id通过写入rendered标记文件标识渲染完成并在hash文件中记录整棵树的哈希供Check校验。GetRootFS(id)返回$id/rootfs正是 strace 中lowerdir指向的路径。这种设计带来一个直接后果同一棵 treestore 被所有使用它的 pod 以 copy-on-writeCOW方式共享容器对文件系统的修改只会落到各自 pod 目录下的upperdirstrace 中可以看到upperdir按deps-sha512-.../upper结构组织并魔术般地出现在挂载点中。有关 overlayfs 挂载参数lowerdir/upperdir/workdir的含义可参考内核 overlayfs 文档。stage1容器隔离的建立最精彩的部分接下来 stage0 通过execve进入 stage1 的 run 入口点也就是/init5710 execve(/var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/stage1/rootfs/init, [/var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/stage1/rootfs/init, --netdefault, --local-config/etc/rkt, d5513d49-d14f-45d1-944b-39437798ddda], 0xc42009b040 /* 25 vars */ unfinished .../init接收的参数--net、--local-config、pod UUID正是 Stage1 ACI implementors guide 中定义的 run 入口点参数对应的解析逻辑可以在 stage1/init/init.go 的 parseFlags 函数 中看到还包括--interactive、--mutable、--hostname、--private-users、--ipc、--dns-conf-mode等。/init的主要职责是解析 pod manifest、生成 systemd-nspawn 参数、写好各应用的 systemd unit 文件然后execsystemd-nspawn。网络命名空间的创建与 CNI 插件/init先创建容器的网络命名空间并在宿主文件系统上挂载一个指向它的引用5723 unshare(CLONE_NEWNET) 0 5723 mount(/proc/5710/task/5723/ns/net, /var/run/netns/cni-eee014d2-8268-39cc-c176-432bbbc9e959, 0xc42017c6a8, MS_BIND, NULL) 0随后在该网络命名空间内执行对应的 CNI 插件。默认网络由ptp插件 host-localIPAM构成5725 execve(stage1/rootfs/usr/lib/rkt/plugins/net/ptp, [stage1/rootfs/usr/lib/rkt/plugins/net/ptp], 0xc4201ac000 /* 32 vars */ unfinished ... 5730 execve(stage1/rootfs/usr/lib/rkt/plugins/net/host-local, [stage1/rootfs/usr/lib/rkt/plugins/net/host-local], 0xc42008e240 /* 32 vars */ unfinished ...这两个插件在本次追踪中来自 rkt 自带的 stage1 镜像但 rkt 也支持从外部加载 CNI 插件详见 networking 文档的自定义插件章节插件二进制可放在/usr/lib/rkt/plugins/net或$LOCAL_CONFIG_DIRECTORY/net.d/。默认网络的行为在 networking 概览中有明确描述分配172.16.28.0/24网段中的 IPv4 地址、在 pod 内设置默认路由、在宿主上开启 IP 伪装masquerade做 egress NATptp的具体配置字段mtu、ipMasq与host-local的 IPAM 字段subnet、rangeStart、rangeEnd、gateway、routes也都在该文档中列明。插件随后调用 iptables 配置网络规则5739 execve(/usr/bin/iptables, [iptables, --version], 0xc42013e000 /* 32 vars */ unfinished ... 5740 execve(/usr/bin/iptables, [/usr/bin/iptables, -t, nat, -N, CNI-7a59ad232c32bcea94ee08d5, --wait], 0xc4200b0a20 /* 32 vars */ unfinished ... ...cgroup 挂载为什么不让 systemd-nspawn 来做网络配置完成后rkt 选择自己挂载容器 cgroup而不是交给 systemd-nspawn目的是完全掌控挂载方式。它同时会把宿主 cgroup 挂好如果宿主是老发行版或非 systemd 发行版cgroup 未按 systemd-nspawn 期望的方式挂载例如 Void Linux。这些动作发生在一个新的挂载命名空间中避免污染宿主挂载并且容器退出时挂载会自动清理。CLONE_NEWNS这个标志名带有历史遗留色彩——它是 Linux 上第一个实现的命名空间5710 unshare(CLONE_NEWNS) 0挂载策略很有讲究容器的 cgroup 层次以读写方式挂载pod 可以修改自己的 cgroup但控制器以只读方式挂载pod 不能动其他 cgroup5710 mount(stage1/rootfs/sys/fs/cgroup/freezer/machine.slice/machine-rkt\\x2dd5513d49\\x2dd14f\\x2d45d1\\x2d944b\\x2d39437798ddda.scope/system.slice, stage1/rootfs/sys/fs/cgroup/freezer/machine.slice/machine-rkt\\x2dd5513d49\\x2dd14f\\x2d45d1\\x2d944b\\x2d39437798ddda.scope/system.slice, 0xc42027d2a8, MS_BIND, NULL) 0 ... 5710 mount(stage1/rootfs/sys/fs/cgroup/freezer, stage1/rootfs/sys/fs/cgroup/freezer, 0xc42027d2b8, MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND, NULL) 0这一段在源码里有完整对应。看 stage1/init/init.go 的 stage1 函数第 706 行syscall.Unshare(syscall.CLONE_NEWNS)建立新的挂载命名空间随后把/递归设置为 slave shared使挂载事件不会反向传播到宿主mountHostV1Cgroups第 815 行起负责补齐宿主侧 cgroup包括缺失的namesystemd层次mount(cgroup, ..., none,namesystemd)以及各控制器mountContainerV1Cgroups第 843 行起调用v1.CreateCgroupsv1.RemountCgroups即 strace 中看到的先 bind mount 容器子 cgroup 为读写、再把控制器 remount 为只读getContainerSubCgroup第 857 行起计算 pod 应归属的 cgroup 路径未注册到 machined 时形如machine.slice/machine-rkt\x2duuid.scope\x2d是-的转义形式——这正是 strace 输出中machine-rkt\x2dd5513d49...的来历。从源码注释可以读出设计意图rkt 通过环境变量SYSTEMD_NSPAWN_USE_CGNSno明确要求 systemd-nspawn 不要使用 cgroup 命名空间cgroup v1 cgns 组合在当时的 systemd 下会出问题见getArgsEnv中的注释这也是后面 procfs 部分能看到容器与宿主共享 cgroup 命名空间的原因之一。启动 systemd-nspawn挂载就绪后正式拉起 pod 的时刻到来5710 execve(stage1/rootfs/usr/lib/ld-linux-x86-64.so.2, [stage1/rootfs/usr/lib/ld-linux-x86-64.so.2, stage1/rootfs/usr/bin/systemd-nspawn, --boot, --notify-readyyes, --registertrue, --link-journaltry-guest, --quiet, --uuidd5513d49-d14f-45d1-944b-39437798ddda, --machinerkt-d5513d49-d14f-45d1-944b-39437798ddda, --directorystage1/rootfs, --capabilityCAP_AUDIT_WRITE,CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FSETID,CAP_FOWNER,CAP_KILL,CAP_MKNOD,CAP_NET_RAW,CAP_NET_BIND_SERVICE,CAP_SETUID,CAP_SETGID,CAP_SETPCAP,CAP_SETFCAP,CAP_SYS_CHROOT, --, --default-standard-outputtty, --log-targetnull, --show-status0], 0xc4202bc0f0 /* 29 vars */ unfinished ...注意一个细节systemd-nspawn 的命令行里没有--private-network——因为网络已经由 rkt 用 CNI 提前创建并配置好了网络命名空间由--netdefault建立的独立 netns 提供。这些参数正是 init.go 的 getArgsEnv 函数生成的--boot让 systemd-nspawn 引导 pod 内的 systemd 作为 supervisor--notify-readyyes、--registertrue注册到宿主 systemd-machined若可用、--link-journaltry-guest链接日志--capability列表则是 stage0 按 pod manifest 计算的、容器 PID 1 持有的能力集。--之后是传给 pod 内 systemd 的参数--log-targetnull、--show-status0用于在非 debug 模式下静默。systemd-nspawn 随后把 stage1 的文件系统树整体移动到/再 chroot5747 mount(/var/lib/rkt/pods/run/d5513d49-d14f-45d1-944b-39437798ddda/stage1/rootfs, /, NULL, MS_MOVE, NULL) 0 5747 chroot(.) 0并通过一次clone创建其余命名空间mount新的、UTS、IPC、PID5747 clone(child_stackNULL, flagsCLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWPID|SIGCHLD) 5748各命名空间的语义可参考 Linuxnamespaces(7)手册页。pod 内的 systemd 与日志容器创建完成后PID 1 由 systemd 担任5748 execve(/usr/lib/systemd/systemd, [/usr/lib/systemd/systemd, --default-standard-outputtty, --log-targetnull, --show-status0], 0x7f904604f250 /* 8 vars */) 0systemd 接着启动 systemd-journald 处理日志5749 execve(/usr/lib/systemd/systemd-journald, [/usr/lib/systemd/systemd-journald], 0x5579c5d79d50 /* 8 vars */ unfinished ... ...prepare-app把合理环境搬运进 stage2在启动应用服务之前systemd 会先执行该应用配套的prepare-app依赖5751 execve(/prepare-app, [/prepare-app, /opt/stage2/etcd/rootfs], 0x5579c5d7d580 /* 7 vars */) 0prepare-app从 stage1 向 stage2 bind-mount 大量文件让应用获得符合 appc OS-SPEC 要求的合理环境/proc、/dev、/sys、/run/systemd/journal 等5751 mount(/dev/null, /opt/stage2/etcd/rootfs/dev/null, 0x49006f, MS_BIND, NULL) 0 5751 mount(/dev/zero, /opt/stage2/etcd/rootfs/dev/zero, 0x49006f, MS_BIND, NULL) 0 ...这一环节的实现细节非常值得一看完整的 bind-mount 清单就写在 stage1/prepare-app/prepare-app.c 中dirs_mount_table递归 bind 宿主/procbind/dev/shm、/dev/pts、/run/systemd/journaldevnodes数组逐个 bind/dev/null、/dev/zero、/dev/full、/dev/random、/dev/urandom、/dev/tty、/dev/net/tun、/dev/console刻意不整体 bind/dev以免遮蔽 stage0 通过rkt run --volume做的单独 bind 挂载files_mount_table把/etc/rkt-resolv.conf、/etc/rkt-hosts、/etc/hosts-fallback、/proc/sys/kernel/hostname、/run/systemd/notify等文件 bind 到应用视图中的对应路径还会处理/dev/ptmx根据可用性决定 symlink 到dev/pts/ptmx或 mknod、把卷设备 symlink 复制到/dev/.rkt以便 systemd 的DeviceAllow使用并创建/dev/log - /run/systemd/journal/dev-log。每个应用独立的挂载命名空间与安全指令strace 的结尾部分揭示了另一个设计由于应用 unit 文件里使用了InaccessiblePaths、SystemCallFilter等安全指令systemd 会为 pod 内的每个应用再创建一个挂载命名空间并把 stage2 文件系统移动到/5753 unshare(CLONE_NEWNS) 0 ... 5753 mount(/opt/stage2/etcd/rootfs, /, NULL, MS_MOVE, NULL) 0 5753 chroot(.) 0这一行为与 stage1/init/common/units.go 生成 unit 文件的逻辑完全吻合除非用户显式传入--insecure-optionspaths每个应用的 service unit 都会写入InaccessiblePathssystemd ≥ 231路径用-前缀表示不存在则忽略、ReadOnlyPaths以及MountFlagsshared注释明确说明这会创建新的挂载命名空间并使其成为 slaveshared。此外还会设置DevicePolicyclosed加DeviceAllow列表kvm flavor 除外以及CapabilityBoundingSet与 seccomp 相关的SystemCallFilter选项。stage2应用最终执行一切就绪etcd 二进制被最终执行5753 execve(/etcd, [/etcd], 0x5579c5dbd660 /* 9 vars */) 0这就是 strace 追踪的完整旅程stage0 拉镜像挂 overlay → stage1 建网络命名空间、挂 cgroup、启动 systemd-nspawn → systemd 引导 pod 内 systemd → prepare-app 准备环境 → 应用在自己的挂载命名空间中启动。第二部分用 procfs 检查运行中的容器strace 看的是创建时的动作/proc则能让你查看运行中的状态。下面启动一个受限容器CPU 限制为 200 毫核millicores、内存限制 100MB$ sudo rkt run --interactive kinvolk.io/aci/busybox --memory100M --cpu200m / #定位容器内进程的 PID先用rkt status拿到容器对应的宿主 PID$ sudo rkt status 567264dd staterunning created2018-01-03 17:17:39.653 0100 CET started2018-01-03 17:17:39.749 0100 CET networksdefault:ip4172.16.28.37 pid10985 exitedfalsepid10985是 pod 在宿主上的进程systemd-nspawn 的宿主侧进程。通过进程树往下找能看到sh的 PID 是11026$ ps auxf | grep [1]0985 -A 3 root 10985 0.0 0.0 54204 5040 pts/2 S 17:17 0:00 \_ stage1/rootfs/usr/lib/ld-linux-x86-64.so.2 stage1/rootfs/usr/bin/systemd-nspawn --boot --notify-readyyes --registertrue --link-journaltry-guest --quiet --uuid567264dd-f28d-42fb-84a1-4714dde9e82c --machinerkt-567264dd-f28d-42fb-84a1-4714dde9e82c --directorystage1/rootfs --capabilityCAP_AUDIT_WRITE,CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FSETID,CAP_FOWNER,CAP_KILL,CAP_MKNOD,CAP_NET_RAW,CAP_NET_BIND_SERVICE,CAP_SETUID,CAP_SETGID,CAP_SETPCAP,CAP_SETFCAP,CAP_SYS_CHROOT -- --default-standard-outputtty --log-targetnull --show-status0 root 11021 0.0 0.0 62280 7392 ? Ss 17:17 0:00 \_ /usr/lib/systemd/systemd --default-standard-outputtty --log-targetnull --show-status0 root 11022 0.0 0.0 66408 8812 ? Ss 17:17 0:00 \_ /usr/lib/systemd/systemd-journald root 11026 0.0 0.0 1212 4 pts/0 Ss 17:17 0:00 \_ /bin/sh注意这个进程树与第一部分 strace 的 exec 链一一对应ld-linux → systemd-nspawn → systemd → systemd-journald → shexec 掉被替换的进程不会出现在树中。命名空间对比容器 vs 宿主查看容器内sh的命名空间$ sudo ls -l /proc/11026/ns/ total 0 lrwxrwxrwx 1 root root 0 Jan 3 17:19 cgroup - cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Jan 3 17:19 ipc - ipc:[4026532764] lrwxrwxrwx 1 root root 0 Jan 3 17:19 mnt - mnt:[4026532761] lrwxrwxrwx 1 root root 0 Jan 3 17:19 net - net:[4026532702] lrwxrwxrwx 1 root root 0 Jan 3 17:19 pid - pid:[4026532765] lrwxrwxrwx 1 root root 0 Jan 3 17:19 pid_for_children - pid:[4026532765] lrwxrwxrwx 1 root root 0 Jan 3 17:19 user - user:[4026531837] lrwxrwxrwx 1 root root 0 Jan 3 17:19 uts - uts:[4026532763]再与宿主 PID 1 的命名空间对比$ sudo ls -l /proc/1/ns/ total 0 lrwxrwxrwx 1 root root 0 Jan 3 17:20 cgroup - cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Jan 3 17:20 ipc - ipc:[4026531839] lrwxrwxrwx 1 root root 0 Jan 3 17:20 mnt - mnt:[4026531840] lrwxrwxrwx 1 root root 0 Jan 3 17:20 net - net:[4026532009] lrwxrwxrwx 1 root root 0 Jan 3 17:20 pid - pid:[4026531836] lrwxrwxrwx 1 root root 0 Jan 3 17:20 pid_for_children - pid:[4026531836] lrwxrwxrwx 1 root root 0 Jan 3 17:20 user - user:[4026531837] lrwxrwxrwx 1 root root 0 Jan 3 17:20 uts - uts:[4026531838]对比结果cgroup与user命名空间与宿主相同cgroup:[4026531835]两边一致因为 rkt 不使用 cgroup 命名空间回忆第一部分的SYSTEMD_NSPAWN_USE_CGNSnouser 命名空间在本次运行中未启用未使用--private-usersmnt、net、pid、uts、ipc均为新命名空间各402653276x编号与宿主的40265318xx/2009不同如果换一种网络模式例如--nethost你会观察到net命名空间与宿主完全一致。lsns可以更直观地列出这些信息并附带创建各命名空间的进程 sudo lsns -p 11026 NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 231 1 root /sbin/init 4026531837 user 231 1 root /sbin/init 4026532702 net 4 10945 root stage1/rootfs/usr/lib/ld-linux-x86-64.so.2 stage1/rootfs/usr/bin/systemd-nspawn --boot --notify-readyyes --registertrue --link-journal 4026532761 mnt 1 11026 root /etcd 4026532763 uts 3 11021 root /usr/lib/systemd/systemd --default-standard-outputtty --log-targetnull --show-status0 4026532764 ipc 3 11021 root /usr/lib/systemd/systemd --default-standard-outputtty --log-targetnull --show-status0 4026532765 pid 3 11021 root /usr/lib/systemd/systemd --default-standard-outputtty --log-targetnull --show-status0注意mnt命名空间只有 1 个进程11026这正是第一部分的每个应用独立挂载命名空间在运行态的证据net命名空间则包含了 systemd-nspawn 在内的 4 个进程。进程安全状态能力集与 seccomp/proc/PID/status里藏着进程的安全属性$ sudo cat /proc/11026/status Name: sh Umask: 0022 State: S (sleeping) ... CapBnd: 00000000a80425fb ... NoNewPrivs: 0 Seccomp: 2 ...NoNewPrivs: 0容器没有启用no_new_privs特性Seccomp: 2处于 seccomp filter 模式值 2 表示有自定义过滤规则生效说明 rkt 的 seccomp 隔离已作用于该进程。rkt 默认启用rkt/default-whitelist白名单相关预设过滤组appc.io/all、rkt/default-blacklist、systemd/*系列可参考 Seccomp Isolators GuideCapBnd: 00000000a80425fb能力边界集。用capsh解码$ capsh --decode00000000a80425fb 0x00000000a80425fbcap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap这 14 项能力对应 systemd-nspawn 命令行中--capability...传入的集合与第一部分 strace 输出一致。关于 rkt 的能力模型默认集合、retain-set/remove-set隔离器、--caps-retain/--caps-remove、非 root 运行时的注意点详见 Capabilities Isolators Guide。环境变量$ sudo cat /proc/11026/environ | tr \0 \n PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOME/root LOGNAMEroot USERroot SHELL/bin/sh INVOCATION_IDd5d94569d482495c809c113fca55abd4 TERMxterm AC_APP_NAMEbusybox其中AC_APP_NAMEbusybox是 appc/rkt 注入的应用标识环境变量配合/rkt/env/$app中的环境文件使用stage1 的 env 目录约定见 Stage1 ACI implementors guide。cgroup 归属$ sudo cat /proc/11026/cgroup 11:freezer:/ 10:rdma:/ 9:cpu,cpuacct:/machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice/busybox.service 8:devices:/machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice/busybox.service 7:blkio:/machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice 6:memory:/machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice/busybox.service 5:perf_event:/ 4:pids:/machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice/busybox.service 3:net_cls,net_prio:/ 2:cpuset:/ 1:namesystemd:/machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice/busybox.service 0::/machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice/busybox.service观察到的结构非常有层次感应用的 cgroup 路径形如machine.slice/machine-rkt\x2duuid.scope/system.slice/busybox.service——machine-rkt\x2duuid.scope是 pod 级 cgroup\x2d是-的转义system.slice/busybox.service是 pod 内 systemd 为该应用建立的 service unit cgroupcpu,cpuacct、devices、memory、pids、namesystemd都挂到了 pod 的.scope之下而freezer、rdma、perf_event、net_cls,net_prio、cpuset仍是/——这反映了第一部分 cgroup 挂载策略的结果只有被选中的控制器被绑定进容器视图rkt status显示networksdefault:ip4172.16.28.37对应默认网络从172.16.28.0/24分配的 IP。第三部分用 systemd 工具与 cgroup 文件系统检查容器资源由于 rkt 的 systemd/nspawn flavor 会把 pod 注册到宿主的 systemd-machined--registertrue你可以直接用 systemd 自带的工具查看容器的 cgroup 树与资源消耗。machinectl容器作为机器出现$ machinectl MACHINE CLASS SERVICE OS VERSION ADDRESSES rkt-97910fdc-13ec-4025-8f93-5ddea0089eff container rkt - - 172.16.28.25... 1 machines listed.systemd-cgls查看容器 cgroup 层次systemd-cgls -M按机器名展开整个 cgroup 树pid 与进程一一对应$ systemd-cgls -M rkt-97910fdc-13ec-4025-8f93-5ddea0089eff Control group /machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope: -.slice ├─init.scope │ └─12474 /usr/lib/systemd/systemd --default-standard-outputtty --log-targetnull --show-status0 └─system.slice ├─busybox.service │ └─12479 /bin/sh └─systemd-journald.service └─12475 /usr/lib/systemd/systemd-journald这里可以清楚看到 pod 内的 systemdinit.scope中的 PID 1、journald 服务以及busybox.service与systemd-cgtop输出下图中的条目相互印证。systemd-cgtop实时资源消耗在容器内执行yes本质是一个无限输出字符y的死循环会占满 CPU时宿主上的systemd-cgtop输出Control Group Tasks %CPU Memory Input/s Output/s /machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope 4 19.6 7.6M - - /machine.slice/machine-rkt\x2d97910fdc\x2d13ec\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice 3 19.6 5.1M - - /machine.slice/machine-rkt\x2d979…c\x2d4025\x2d8f93\x2d5ddea0089eff.scope/system.slice/busybox.service 2 19.6 476.0K - - /machine.slice/machine-rkt\x2d979…d8f93\x2d5ddea0089eff.scope/system.slice/system-prepare\x2dapp.slice - - 120.0K - - /machine.slice/machine-rkt\x2d979…\x2d8f93\x2d5ddea0089eff.scope/system.slice/systemd-journald.service 1 - 4.5M - -注意%CPU只有约 19.6%而不是 100%——这正是--cpu200m200 毫核 0.2 核这一 CPU 限制生效的直接证据rkt 通过 systemd 的 cgroup CPU quota 把它翻译成了实际约束。同时还能看到system-prepare\x2dapp.sliceprepare-app 的 slice与systemd-journald.service各自的内存占用。直接从 cgroup 文件系统读取systemd-cgls/systemd-cgtop最终读的还是 cgroup 文件系统。以 busybox 应用的内存用量为例$ /sys/fs/cgroup/memory/machine.slice/machine-rkt\\x2d97910fdc\\x2d13ec\\x2d4025\\x2d8f93\\x2d5ddea0089eff.scope/system.slice/busybox.service/ $ cat memory.usage_in_bytes 487424内存控制器的统计文件直接给出了当前用量约 487KB与systemd-cgtop中的 476.0K 基本一致差异来自取样时刻。CPU、pids、devices 等控制器也有各自的可读文件例如 CPU 配额对应的cpu.cfs_quota_us/cpu.cfs_period_us。cgroup v1 各控制器的完整语义可查阅内核 cgroup 文档本仓库中也保留了对应的封装实现见 common/cgroupv1/cgroup.go与v2/cgroup.go分别对应 legacy 与 unified 层次。小结把现象映射到源码把三部分观察汇总成一张现象 → 实现的对照表便于后续深入阅读观察到的现象源码/文档位置stage0 用 overlay 挂载lowerdir来自deps-sha512-*treestore 实现、rkt architecture/init接收--net/--local-config等参数Stage1 ACI implementors guide、init.go parseFlags默认网络 ptp host-local iptables NATnetworking 概览新挂载命名空间中挂 cgroup控制器只读init.go stage1 函数systemd-nspawn 的--boot/--capability...等参数init.go getArgsEnvprepare-app 的系列 bind-mountprepare-app.c每个应用独立挂载命名空间 InaccessiblePaths/seccomp 指令units.go 生成 unit 的逻辑能力边界集与 seccomp 状态Capabilities Guide、Seccomp Guidecgroup 层次machine-rkt\x2duuid.scopeinit.go getContainerSubCgroup、common/cgroup这套方法论是通用的strace 回答做了什么/proc回答处于什么状态cgroup 文件系统回答资源如何被记账与限制。掌握它之后你不仅能看懂 rkt 的每一层启动细节也能用它去剖析任何基于命名空间 cgroup systemd 的容器实现。赞分享容器运行时云原生网络【免费下载链接】rkt[Project ended] rkt is a pod-native container engine for Linux. It is composable, secure, and built on standards.项目地址https://gitcode.com/gh_mirrors/rk/rkt点击查看免费下载相关推荐DBeaver驱动包终极指南一站式解决30数据库连接配置难题DBeaver驱动包终极指南一站式解决30数据库连接配置难题 还在为每次连接数据库都要下载驱动而烦恼吗DBeaver驱动包为您提供了一站式解决方案让数据数据库客户端数据库在 rkt 容器内自举构建 rktcoreos.com/rkt/builder 构建指南在 rkt 容器内自举构建 rktcoreos.com/rkt/builder 构建指南 Documentation/rkt build rkt.md 介绍了容器运行时云原生网络Home Assistant智能家居打破品牌壁垒打造你的个性化全屋智能系统Home Assistant智能家居打破品牌壁垒打造你的个性化全屋智能系统 你是否曾为不同品牌的智能设备无法协同工作而烦恼小米的灯、苹果的家庭、谷歌的语音文档教程智能家居物联网上一篇tf-rnn-attention快速入门3步实现基于TensorFlow的注意力机制文本分类下一篇react-slingshot 状态管理设计模式案例真实项目实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网