使用 containerd 的 ctr 作为容器中的另一个用户执行命令

Execute command as another user in container using containerd's ctr

我已经在 Ubuntu 上安装了 microk8s,以便有一个简单的 Kubernetes 集群用于测试目的。

我有一个用例,我必须在容器中(在 kubernetes pod 中)与另一个用户而不是用于 运行 容器的用户一起执行命令。

由于 kubectl 不提供这种可能性,docker 环境的解决方法是使用 docker exec -u。但是microk8s安装的Kubernetes集群并没有使用docker as container 运行时间,而是只有containerd.

我没有找到在容器中作为另一个用户使用 containerd 的 ctr cli 执行命令的可能性(因为使用 docker 是可能的)。

有可能吗?

如评论中所述:

@buderu I'm afraid this will not be possible with containerd's ctrl cli as per this documentation.

引用以上文档:

Mapping from docker cli to crictl

The exact versions for below mapping table are for docker cli v1.40 and crictl v1.19.0.

docker cli crictl Description Unsupported Features
attach attach Attach to a running container --detach-keys, --sig-proxy
exec exec Run a command in a running container --privileged, --user, --detach-keys

解决该问题的方法如下: 使用 crictl exec 到 运行 一个 UID 更改程序,该程序又 运行s 所需的有效负载;例如,对于 运行 登录 bash shell 作为 UID 1000 的用户:

  • $ crictl exec -i -t gosu 1000 bash -l

关于 gosu 的一句话。它是基于 Go 的 setuid+setgid+setgroups+exec 程序:

$ gosu
Usage: ./gosu user-spec command [args]
   eg: ./gosu tianon bash
       ./gosu nobody:root bash -c 'whoami && id'
       ./gosu 1000:1 id

./gosu version: 1.1 (go1.3.1 on linux/amd64; gc)

您可以通过关注它的 github 页面阅读更多相关信息:

值得注意的是,上面的解决方案不适用于通用容器。

用户需要通过以下任一方式安装上述程序:

  • 创建容器镜像时包含 installation part in Dockerfile
  • 下载到容器中(前提是容器有curlwget下载文件的能力):
    • $ crictl exec my-container wget -O /gosu https://github.com/tianon/gosu/releases/download/1.12/gosu-amd64
    • $ crictl exec -i -t my-container /gosu 1000 some-other-command

A side note!

Using second option (downloading straight into the container) required also to run:

  • $ chmod +x ./gosu

需要考虑的其他注意事项:

  • susudo 用于成熟的 UNIX 系统,除非安装 PAM 并且要切换到的用户列在/etc/passwd

  • gosusetpriv就简单多了,基本上只会运行Linuxsetuid()系统调用然后执行指定的payload

  • gosu,作为Go程序,可以轻松静态编译,简化部署(只需复制容器中的二进制文件)