通过 Garden API 在 Runc 容器中执行进程

Execute process in Runc container via Garden API

我的本地开发机器上有一个 Cloud Foundry Bosh Lite install with Garden/Runc support 运行,上面托管了一个应用程序。我可以通过 SSH 进入 Diego 单元虚拟机并执行

cell_z1/0# runc exec 5f9c8b67-9170-4c53-4bab-bbb2e6a3acdf /usr/bin/printenv

这将产生以下输出:

INSTANCE_GUID=5f9c8b67-9170-4c53-4bab-bbb2e6a3acdf
INSTANCE_INDEX=0
CF_INSTANCE_GUID=5f9c8b67-9170-4c53-4bab-bbb2e6a3acdf
CF_INSTANCE_INDEX=0
LANG=en_US.UTF-8
CF_INSTANCE_CERT=/etc/cf-instance-credentials/instance.crt
CF_INSTANCE_KEY=/etc/cf-instance-credentials/instance.key
HOME=/root

我假设我可以通过 Garden API 通过调用

实现同样的效果
cell_z1/0# curl -X POST -d '{"path":"/usr/bin/printenv"}' localhost:7777/containers/5f9c8b67-9170-4c53-4bab-bbb2e6a3acdf/processes

但是,这将 return

{"Type":"","Message":"EOF","Handle":""}

不幸的是,这并没有告诉我任何信息。我尝试在 JSON 有效载荷中添加 "user":"vcap" 但结果是一样的。当我添加 -H "Content-Type: application/json" -d 我得到

curl: (56) Problem (2) in the Chunked-Encoded data

问题: 我如何通过 Garden API 在容器内执行任意命令并检索它的输出?

去图书馆

支持在 Garden 容器中执行命令的方式是通过 Go client library。例如:

gdnClient := client.New(connection.New("tcp", "127.0.0.1:7777"))

container, err := gdnClient.Create(garden.ContainerSpec{})
if err != nil {
  os.Exit(1)
}

buffer := &bytes.Buffer{}
process, err := container.Run(garden.ProcessSpec{
  Path: "/usr/bin/printenv",
}, garden.ProcessIO{
  Stdout: buffer,
  Stderr: buffer,
})
if err != nil {
  os.Exit(1)
}

exitCode, err := process.Wait()
if err != nil {
  os.Exit(1)
}

fmt.Printf("Exit code: %d, Process output %s", exitCode, buffer.String())

监狱 CLI

如果您不想编写任何 Go 代码,您可以使用不受支持(但非常有用)Gaol CLI。例如:

gaol create -n myContainer
gaol run -c "/usr/bin/printenv" myContainer

确保您适当地设置了 GAOL_TARGET,例如10.244.16.6:7777 on bosh-lite 如果你是 运行 来自你的开发机器。

HTTP 客户端

最后,通过任何 HTTP 客户端与整个花园 API 一起工作在技术上是可行的,但是支持的 client/server 库会进行一些连接劫持,这可能会使事情变得混乱。特别是,运行一个过程是最复杂的API交互。

首先,request is made to the run endpoint and then the connection is hijacked. The garden client starts streaming stdio for the process by using the hijacked connection for stdin and hitting two other endpoints.

在容器中获取进程 运行 应该不会太难,只需要在请求正文中使用 json 编码的 garden.ProcessSpec 但流式传输输出是相当有点棘手。