使用ansible 'Docker login'和_json_key登录到GCE的Docker

3

我正在尝试编写一个ansible角色,首先需要在从容器注册表中拉取镜像之前,对GCE实例执行docker login。我需要这样做是因为这里提到的问题。

首先,我尝试了下面的代码块:

- name: Docker Login
  docker_login:
    registry: https://eu.gcr.io
    username: _json_key
    debug: true
    password: "{{ lookup('file', 'pulse-psg-863d9955d8a1.json')}}"

我遇到的问题是(私钥已修改)。
fatal: [en1-a-sftp-delivery-0]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "api_version": null,
            "cacert_path": null,
            "cert_path": null,
            "config_path": "~/.docker/config.json",
            "debug": true,
            "docker_host": null,
            "email": null,
            "filter_logger": false,
            "key_path": null,
            "password": "{'private_key': '-----BEGIN PRIVATE KEY-----\\vU5K1MuTpTQGEzg\\nuywOlHw7ZLEj4u65vxrnzpiCOw6Pu7IVZq9R2JPhAoGAFnpxIA4RxuB7cRIOU6EY\\naqBaHT73gmw8ulCHYSUWw+/P9ZquFjsnF8p7hzZ8pCOMSUwaLCQaDfqZvfcEoMqI\\naz9cOJdyjsZjOb1DLd2YtLCUNWldu5Nmh621L51bNh+clYpiSwOnD+ZhN5jrkIK9\\nleeCdUVeg71+h2gzKJGHJBU=\\n-----END PRIVATE KEY-----\\n', 'private_key_id': '********', 'token_uri': '********', 'auth_provider_x509_cert_url': '********', 'auth_uri': '********', 'client_email': '********', 'client_id': '********', 'project_id': '********', 'type': '********', 'client_x509_cert_url': '********'}",
            "reauthorize": false,
            "registry": "https://eu.gcr.io",
            "registry_url": "https://eu.gcr.io",
            "ssl_version": null,
            "state": "present",
            "timeout": null,
            "tls": null,
            "tls_hostname": null,
            "tls_verify": null,
            "username": "_json_key"
        }
    },
    "msg": "Logging into https://eu.gcr.io for user _json_key failed - 500 Server Error: Internal Server Error (\"{\"message\":\"Get https://eu.gcr.io/v2/: unknown: Unable to parse json key.\"}\")"
}

我简直无法解析私钥。 我怀疑这可能与星号字符有关(我不知道这是否只是ansible在调试输出中掩盖它,还是发送给后续的内容)或\n字符有关。

因此,我尝试登录到GCE机器并尝试使用第二个答案中显示的命令。 所以首先我将密钥文件scp到机器上,然后:

JSON_KEY=$(cat keyfile.json)
sudo docker login  -u _json_key -p "$JSON_KEY" https://gcr.io

这个方法在有几个警告的情况下可行,但之后我能够成功登陆并拉取镜像。我得出结论,这是与 docker login Ansible 模块相关的问题,所以我决定尝试使用 shell 命令,于是:

- name: Docker Login using shell
  shell: docker login -u _json_key -p "{{ lookup('file', 'keyfile.json') |  replace('\n', '')}}" http://eu.gcr.io

这也没有成功。

snip
 "module_args": {
            "_raw_params": "docker login -u _json_key -p \"{\n  \"type\": \"service_account\",\n  \"project_id\": \"id\",\n  \"private_key_id\": \"863d9955d8a1e5e04a15b36ef80a787bc2\",\n  \"private_key\": \"-----BEGIN PRIVATE KEY-----MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2Z7c33lnCQDXFssGvg0t9xi9Aqk6x4cazQPUJ8j0Y+qWDBPL+ShHNSZwVykmAugC51KKInm5ik4IWTA5ict3VBRnWiutdxQK++icZ2yCuFlPMDFp2g2GQ4wl8bH1X3AtWgHO/nSWD3Rle7M/p9CUJq3K1EA07H9GKBJZmfGaoc4HA+OG8/j2Q7i8KmG9pFjKOAlQsHPdKKZqn4YeHPOTmARJgxw6PXbchAp+nPA7f7hpbmaK3XRNRxuB7cRIOU6EYaqBaHT73gmw8ulCHYSUWw+/P9ZquFjsnF8p7hzZ8pCOMSUwaLCQaDfqZvfcEoMqIaz9cOJdyjsZjOb1DLd2YtLCUNWldu5Nmh621L51bNh+clYpiSwOnD+ZhN5jrkIK9leeCdUVeg71+h2gzKJGHJBU=-----END PRIVATE KEY-----\",\n  \"client_email\": \"duh-compute@developer.gserviceaccount.com\",\n  \"client_id\": \"1115155168041\",\n  \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n  \"token_uri\": \"https://oauth2.googleapis.com/token\",\n  \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n  \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/879255832886-compute%40developer.gserviceaccount.com\"\n}\" http://eu.gcr.io",
            "_uses_shell": true,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "stdin": null,
            "warn": true
        }
msg": "non-zero return code",
    "rc": 1,
    "start": "2019-07-29 18:31:55.246592",
    "stderr": "\"docker login\" requires at most 1 argument.\nSee 'docker login --help'.\n\nUsage:  docker login [OPTIONS] [SERVER]\n\nLog in to a Docker registry",
    "stderr_lines": [
        "\"docker login\" requires at most 1 argument.",
        "See 'docker login --help'.",
        "",
        "Usage:  docker login [OPTIONS] [SERVER]",
        "",
        "Log in to a Docker registry"
    ],
SNIP

我怀疑这是因为它不喜欢密钥的格式,但这次是 docker login 命令而不是远程服务器(如早期情况),至少在那种情况下密钥是传输的。在这两种情况下,挑战似乎是获取以JSON格式存储在文件中的密钥,没有任何额外字符的传输方式,就像在命令行上直接运行命令时引用环境变量一样。

我已经花费了三天时间试图自动化GCE实例并使其与Docker一起使用,这应该是相当简单的事情。


就记录而言,对我有效的是 docker_login: registry: https://eu.gcr.io username: _json_key password: " {{ lookup('password', 'pulse-psg-863d9955d8a1.json') }}" 请注意引号后和左花括号前的空格。 - Devu
1个回答

4

lookup 解析你的 JSON 有问题。

解决方法是在密码字符串的开头插入空格 password: " {{ lookup('file', 'pulse-psg-863d9955d8a1.json')}}"


太棒了,它起作用了。这真是魔法。您介意解释一下空格实际上是如何使其工作的,并且如果您可以链接到一些解释它的文档吗?另外请注意,尝试使用shell模块(添加空格)shell:docker login -u _json_key -p“ {{lookup('file','pulse-psg-863d9955d8a1.json'}}}“http://eu.gcr.io不起作用。所以这更加神秘。也许空格对于docker login模块有某种含义。 - Devu
2
@Devu,有一个来自Ansible团队的家伙正在解释它:https://groups.google.com/d/msg/ansible-devel/2C7pl2_kxlY/Mjbki7wKAwAJ - Thyrst'
嗯...的确,我的JSON很像一个对象,以"{"字符开头。我已经阅读了这篇和其他类似的文章,但在与GCE和其他问题纠缠了3天后太累了,以至于没能注意到这一点。你简洁明了的一行代码效果更好。不确定他们是否已经修复了它。我更愿意删除掉这个空格的hack。有些东西在"{{ lookup('template','./bucket-public.json.j2', convert_data=False) |string}}"周围提到过,但我没有看到任何关于简单文件查找的选项。指定type=json或类似的东西会更加简洁,但我还没有看到这样的选项。 - Devu
这里还有一些关于它的讨论:链接 - Devu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接