当 运行 在 DC/OS 中的 docker 容器中时,ssh-agent 不记得身份
ssh-agent does not remember identities when running inside a docker container in DC/OS
我正在尝试 运行 使用 DC/OS 和 Docker 的服务。我使用 here 中适合我所在地区的模板创建了 Stack。我还创建了以下 Docker 文件:
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y expect openssh-client
WORKDIR "/root"
ENTRYPOINT eval "$(ssh-agent -s)" && \
mkdir -p .ssh && \
echo $PRIVATE_KEY > .ssh/id_rsa && \
chmod 600 /root/.ssh/id_rsa && \
expect -c "spawn ssh-add /root/.ssh/id_rsa; expect \"Enter passphrase for /root/.ssh/id_rsa:\" send \"\"; interact " && \
while true; do ssh-add -l; sleep 2; done
我有一个私有存储库,我想在 docker 容器启动时 clone/pull 使用它。这就是我尝试将私钥添加到 ssh-agent
.
的原因
如果我 运行 此图像作为本地 docker 容器并使用 PRIVATE_KEY
环境变量提供私钥,一切正常。我看到添加了身份。
我遇到的问题是,当我尝试使用 docker 图像在 DC/OS 上 运行 服务时,ssh-agent
似乎不记得使用私钥添加的身份。
我检查了 DC/OS 的错误日志。没有错误。
有谁知道为什么 运行 在 DC/OS 上安装 docker 容器与 运行 在本地安装它有什么不同?
编辑: 我添加了 DC/OS 服务描述的详细信息以防有帮助:
{
"id": "/SOME-ID",
"instances": 1,
"cpus": 1,
"mem": 128,
"disk": 0,
"gpus": 0,
"constraints": [],
"fetch": [],
"storeUrls": [],
"backoffSeconds": 1,
"backoffFactor": 1.15,
"maxLaunchDelaySeconds": 3600,
"container": {
"type": "DOCKER",
"volumes": [],
"docker": {
"image": "IMAGE NAME FROM DOCKERHUB",
"network": "BRIDGE",
"portMappings": [{
"containerPort": SOME PORT NUMBER,
"hostPort": SOME PORT NUMBER,
"servicePort": SERVICE PORT NUMBER,
"protocol": "tcp",
"name": “default”
}],
"privileged": false,
"parameters": [],
"forcePullImage": true
}
},
"healthChecks": [],
"readinessChecks": [],
"dependencies": [],
"upgradeStrategy": {
"minimumHealthCapacity": 1,
"maximumOverCapacity": 1
},
"unreachableStrategy": {
"inactiveAfterSeconds": 300,
"expungeAfterSeconds": 600
},
"killSelection": "YOUNGEST_FIRST",
"requirePorts": true,
"env": {
"PRIVATE_KEY": "ID_RSA PRIVATE_KEY WITH \n LINE BREAKS",
}
}
通过 PRIVATE_KEY
传递的密钥文件内容最初包含换行符。将 PRIVATE_KEY
变量内容回显到 ~/.ssh/id_rsa
后,换行符将消失。您可以通过用双引号将 $PRIVATE_KEY
变量括起来来解决该问题。
当容器在没有附加 TTY 的情况下启动时会出现另一个问题,通常是通过 -i -t
命令行参数到 docker run
。密码请求将失败,并且不会将 ssh 密钥添加到 ssh-agent。对于 运行 in DC/OS 的容器,交互可能没有意义,因此您应该相应地更改入口点脚本。这将要求您的 ssh 密钥是无密码的。
这个更改后的 Dockerfile 应该可以工作:
ENTRYPOINT eval "$(ssh-agent -s)" && \
mkdir -p .ssh && \
echo "$PRIVATE_KEY" > .ssh/id_rsa && \
chmod 600 /root/.ssh/id_rsa && \
ssh-add /root/.ssh/id_rsa && \
while true; do ssh-add -l; sleep 2; done
Docker版本
检查您的 Docker 本地版本是否与安装在 DC/OS 代理上的版本匹配。默认情况下,DC/OS 1.9.3 AWS CloudFormation 模板使用 CoreOS 1235.12.0, which comes with Docker 1.12.6。从那时起,入口点行为可能发生了变化。
Docker 命令
检查有问题的 Marathon 应用程序的 Mesos 任务日志,看看执行了什么 docker 运行 命令。在本地测试时,您可能会传递略有不同的参数。
脚本错误
如另一个答案中所述,您提供的脚本有几个错误,这些错误可能与失败有关,也可能无关。
echo $PRIVATE_KEY
应该是 echo "$PRIVATE_KEY"
以保留换行符。否则密钥解密将失败 Bad passphrase, try again for /root/.ssh/id_rsa:
.
expect -c "spawn ssh-add /root/.ssh/id_rsa; expect \"Enter passphrase for /root/.ssh/id_rsa:\" send \"\"; interact "
应该是 expect -c "spawn ssh-add /root/.ssh/id_rsa; expect \"Enter passphrase for /root/.ssh/id_rsa:\"; send \"\n\"; interact "
。它缺少分号和换行符。否则 expect 命令会失败而不会执行。
基于文件的秘密
Enterprise DC/OS 1.10(现在推出 1.10.0-rc1)有一个名为 File Based Secrets 的新功能,它允许注入文件(如 id_rsa 文件)而不将其内容包含在 Marathon 中应用程序定义,将它们安全地存储在 Vault using DC/OS Secrets.
中
- 创作:https://docs.mesosphere.com/1.10/security/secrets/create-secrets/
- 用法:https://docs.mesosphere.com/1.10/security/secrets/use-secrets/
基于文件的机密不会为您执行 ssh-add,但它应该可以更轻松、更安全地将文件放入容器。
Mesos 错误
Mesos 1.2.0 切换到使用 Docker --env_file 而不是 -e 来传递环境变量。这会触发 Docker env_file bug that it doesn't support line breaks. A workaround was put into Mesos and DC/OS,但修复可能不在您使用的次要版本中。
手动解决方法是将 Marathon 定义的 rsa_id 转换为 base64,然后返回到您的入口点脚本中。
我正在尝试 运行 使用 DC/OS 和 Docker 的服务。我使用 here 中适合我所在地区的模板创建了 Stack。我还创建了以下 Docker 文件:
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y expect openssh-client
WORKDIR "/root"
ENTRYPOINT eval "$(ssh-agent -s)" && \
mkdir -p .ssh && \
echo $PRIVATE_KEY > .ssh/id_rsa && \
chmod 600 /root/.ssh/id_rsa && \
expect -c "spawn ssh-add /root/.ssh/id_rsa; expect \"Enter passphrase for /root/.ssh/id_rsa:\" send \"\"; interact " && \
while true; do ssh-add -l; sleep 2; done
我有一个私有存储库,我想在 docker 容器启动时 clone/pull 使用它。这就是我尝试将私钥添加到 ssh-agent
.
如果我 运行 此图像作为本地 docker 容器并使用 PRIVATE_KEY
环境变量提供私钥,一切正常。我看到添加了身份。
我遇到的问题是,当我尝试使用 docker 图像在 DC/OS 上 运行 服务时,ssh-agent
似乎不记得使用私钥添加的身份。
我检查了 DC/OS 的错误日志。没有错误。
有谁知道为什么 运行 在 DC/OS 上安装 docker 容器与 运行 在本地安装它有什么不同?
编辑: 我添加了 DC/OS 服务描述的详细信息以防有帮助:
{
"id": "/SOME-ID",
"instances": 1,
"cpus": 1,
"mem": 128,
"disk": 0,
"gpus": 0,
"constraints": [],
"fetch": [],
"storeUrls": [],
"backoffSeconds": 1,
"backoffFactor": 1.15,
"maxLaunchDelaySeconds": 3600,
"container": {
"type": "DOCKER",
"volumes": [],
"docker": {
"image": "IMAGE NAME FROM DOCKERHUB",
"network": "BRIDGE",
"portMappings": [{
"containerPort": SOME PORT NUMBER,
"hostPort": SOME PORT NUMBER,
"servicePort": SERVICE PORT NUMBER,
"protocol": "tcp",
"name": “default”
}],
"privileged": false,
"parameters": [],
"forcePullImage": true
}
},
"healthChecks": [],
"readinessChecks": [],
"dependencies": [],
"upgradeStrategy": {
"minimumHealthCapacity": 1,
"maximumOverCapacity": 1
},
"unreachableStrategy": {
"inactiveAfterSeconds": 300,
"expungeAfterSeconds": 600
},
"killSelection": "YOUNGEST_FIRST",
"requirePorts": true,
"env": {
"PRIVATE_KEY": "ID_RSA PRIVATE_KEY WITH \n LINE BREAKS",
}
}
通过 PRIVATE_KEY
传递的密钥文件内容最初包含换行符。将 PRIVATE_KEY
变量内容回显到 ~/.ssh/id_rsa
后,换行符将消失。您可以通过用双引号将 $PRIVATE_KEY
变量括起来来解决该问题。
当容器在没有附加 TTY 的情况下启动时会出现另一个问题,通常是通过 -i -t
命令行参数到 docker run
。密码请求将失败,并且不会将 ssh 密钥添加到 ssh-agent。对于 运行 in DC/OS 的容器,交互可能没有意义,因此您应该相应地更改入口点脚本。这将要求您的 ssh 密钥是无密码的。
这个更改后的 Dockerfile 应该可以工作:
ENTRYPOINT eval "$(ssh-agent -s)" && \
mkdir -p .ssh && \
echo "$PRIVATE_KEY" > .ssh/id_rsa && \
chmod 600 /root/.ssh/id_rsa && \
ssh-add /root/.ssh/id_rsa && \
while true; do ssh-add -l; sleep 2; done
Docker版本
检查您的 Docker 本地版本是否与安装在 DC/OS 代理上的版本匹配。默认情况下,DC/OS 1.9.3 AWS CloudFormation 模板使用 CoreOS 1235.12.0, which comes with Docker 1.12.6。从那时起,入口点行为可能发生了变化。
Docker 命令
检查有问题的 Marathon 应用程序的 Mesos 任务日志,看看执行了什么 docker 运行 命令。在本地测试时,您可能会传递略有不同的参数。
脚本错误
如另一个答案中所述,您提供的脚本有几个错误,这些错误可能与失败有关,也可能无关。
echo $PRIVATE_KEY
应该是echo "$PRIVATE_KEY"
以保留换行符。否则密钥解密将失败Bad passphrase, try again for /root/.ssh/id_rsa:
.expect -c "spawn ssh-add /root/.ssh/id_rsa; expect \"Enter passphrase for /root/.ssh/id_rsa:\" send \"\"; interact "
应该是expect -c "spawn ssh-add /root/.ssh/id_rsa; expect \"Enter passphrase for /root/.ssh/id_rsa:\"; send \"\n\"; interact "
。它缺少分号和换行符。否则 expect 命令会失败而不会执行。
基于文件的秘密
Enterprise DC/OS 1.10(现在推出 1.10.0-rc1)有一个名为 File Based Secrets 的新功能,它允许注入文件(如 id_rsa 文件)而不将其内容包含在 Marathon 中应用程序定义,将它们安全地存储在 Vault using DC/OS Secrets.
中- 创作:https://docs.mesosphere.com/1.10/security/secrets/create-secrets/
- 用法:https://docs.mesosphere.com/1.10/security/secrets/use-secrets/
基于文件的机密不会为您执行 ssh-add,但它应该可以更轻松、更安全地将文件放入容器。
Mesos 错误
Mesos 1.2.0 切换到使用 Docker --env_file 而不是 -e 来传递环境变量。这会触发 Docker env_file bug that it doesn't support line breaks. A workaround was put into Mesos and DC/OS,但修复可能不在您使用的次要版本中。
手动解决方法是将 Marathon 定义的 rsa_id 转换为 base64,然后返回到您的入口点脚本中。