Linux Bottlerocket 的 admin vs control 容器分离设计

2次阅读

admin容器无法直接访问control容器的/run/containerd/containerd.sock,因其运行在独立mount Namespace且未挂载该路径;应使用control-api.sock代理接口(如apiclient get /containers)安全调用。

Linux Bottlerocket 的 admin vs control 容器分离设计

admin 容器为什么不能直接访问 control 容器的 /run/dockershim.sock?

因为 Bottlerocket 的 admin 容器默认运行在独立的 mount namespace 和 cgroup 中,且未挂载 control 容器的 runtime socket 路径。control 容器才是真正管理容器运行时(containerd)和 kubelet 的主体,它的 /run/dockershim.sock(或更准确地说,/run/containerd/containerd.sock)根本不在 admin 的文件系统视图里。

常见错误现象:在 admin 容器里执行 crictl psnerdctl ps 报错 failed to connect: failed to dial "/run/containerd/containerd.sock": dial unix /run/containerd/containerd.sock: connect: no such file or Directory

  • admin 容器只预装了基础调试工具(bashcurljq 等),不包含 containerd 客户端或 kubectl
  • control 容器的 socket 路径是 /run/containerd/containerd.sock,不是旧版的 /var/run/dockershim.sock(Bottlerocket 从不使用 dockershim)
  • 即使你用 nsenter 进入 control 的命名空间,也要注意 SElinux 上下文限制,直接 bind-mount 可能被拒绝

怎么从 admin 容器安全调用 control 容器里的 containerd?

唯一受支持的方式是通过 control 容器暴露的 Unix domain socket 代理服务:control-api.sock。它监听在 /run/control-api.sock,由 control 容器内的 control-api 进程提供,专为 admin 容器设计的轻量级 API 网关。

使用场景:查 Pod 状态、列出容器、获取日志片段——所有只读运维操作都应走这个接口,而不是绕过隔离机制。

  • admin 容器里默认有 apiclient 工具,直接用 apiclient get /containers 即可获取容器列表
  • 该 API 返回的是 json,字段与 CRI 兼容,但不等价于 raw containerd;例如没有镜像层细节,也不支持 exec 或 attach
  • 不要尝试用 curl --unix-socket /run/control-api.sock http://localhost/containersapiclient 内部做了协议适配,裸 curl 会返回 404 或解析错误
  • 写操作(如重启节点)必须通过 apiclient post /reboot,且需满足节点处于 drain 状态等前置条件

control 容器里能跑自己的应用吗?

不能。control 容器是 Bottlerocket 的“控制平面容器”,只运行 kubeletcontainerdcontrol-api 和几个健康检查进程。它的 rootfs 是只读的,且被 systemd 严格管控生命周期。

容易踩的坑:有人尝试在 control 容器里 apk addpip install,结果发现包管理器不可用,或者 /usr 是只读挂载 —— 这不是 bug,是设计使然。

  • control 容器的镜像由 Bottlerocket 构建流程固化,更新只能通过 OTA 升级整个 host OS
  • 如果你需要自定义监控 agent 或 sidecar,必须放在用户容器(即 kubernetes Pod 中),而非 control 容器内
  • 试图用 nsenter -t $(pidof containerd) -m -u -n -i -p bash 进入 control 的命名空间并修改文件,大概率触发 SELinux denials 或 systemd 重启整个 control 服务

为什么 admin 容器默认没开 ssh,且禁止持久化写入?

因为 admin 容器的设计目标是“临时调试会话”,不是通用 shell 环境。它的根文件系统是 tmpfs,每次 reboot 后清空,且没有 sshd 服务——这是为了缩小攻击面,避免误配置导致长期后门。

性能与兼容性影响:禁用 SSH 意味着无法用传统方式做长连接运维;tmpfs 根目录则让任何 apt installgo build 都只能存活到下次 reboot。

  • 如需上传调试脚本,应通过 apiclient put /files 接口写入 /etc/admin-container/files/(该路径可持久化到 host disk)
  • admin 容器的 /home/admin 是 tmpfs,但 /etc/admin-container 是 bind-mounted 自 host 的 /etc/bottlerocket/admin-container,可用来存配置
  • 别指望在 admin 里跑 vimhtop:它们没预装,且安装后下次重启就消失;改用 vi(busybox 版)和 ps auxf 更实际

最常被忽略的一点:admin 和 control 的时间不同步不会报错,但会影响日志时间戳和证书校验逻辑——如果发现 apiclient 返回 401 或 TLS handshake failure,先检查两容器的 date 输出是否一致。

text=ZqhQzanResources