登录
  • 人们都希望被别人需要 却往往事与愿违
  • 当你试图了解你的祖国, 你已经走上了犯罪道路!@艾未未 (艺术家 持不同政见者)

没事别在容器里装 openssh-server,真的

编程 Benny 小土豆 3877 次浏览 1971 字 7 个评论
文章目录 [显示]

几天前,跑的好好的 CI 突然 fail,报错信息看起来很奇怪,像是使用上的问题。

没事别在容器里装openssh-server,真的

本地跑了一下这两个测试用例,并没有复现。以为是 CI 偶尔抽风了,就没管。

后来发现有点不对,怎么都跑不过。甚至直接在 develop 上跑 CI 都跑不过。这和 GraphQL 有什么关系啊?明明都能用的啊。让写这部分代码的同事帮忙看了下,发现他也能跑过。奇怪。

由于整套 CI 是跑在 concourse 上的,于是通过fly hijack进去,在对应失败的 step 中成功复现了这个问题。

再后来同事发现出问题的是urllib3/util/retry.py的 Retry

  1. max_retries = Retry(
  2. total=1,
  3. backoff_factor=0.1,
  4. status_forcelist=[500, 502, 503, 504],
  5. allowed_methods=None,
  6. )

去比对了下,fly 进去的容器中的urllib3版本和我测试的版本确实不一样。把 fly 进去的容器中的urllib3升级了之后,test case 就可以过了。

啥?这啥情况?先在requirements.txt中写上urllib3==1.26.7临时解决一下这个问题。至少别耽误大家跑 CI 啊。

差异

fly 进去的容器是用名为builder/Dockerfile构建的,我测试的是 websvc 是websvc/Dockerfile构建的,两者基本没什么差别。

我自己跑测试用例是用的 websvc,而跑 CI 用的是 builder。

可是问题来了,二者明明用了一样的requirements.txt,怎么会安装出来不一样的 library?pip install -r requirements.txt 之后也没有安装别的,怎么就版本不一致了?

后来经过一步一步测试,最终发现了这背后的原因。

没事别在容器里装openssh-server,真的

根本原因

builder/Dockerfile中,我们安装了openssh-server,先别管为啥……

openssh-server有非常多的依赖,如下图中选中的地方,就有python3-urllib3

没事别在容器里装openssh-server,真的

apt 中的 python package 的版本是相对而言比较老的,经过查看这种方式安装的 urllib3 的版本是 1.22

没事别在容器里装openssh-server,真的

requirements.txt 中,我们安装的是requests==2.25.1gql==3.0.0b0。这两个 package 对 urllib3 的版本要求比较宽泛,通过 apt 安装的这个版本恰巧能够满足。

没事别在容器里装openssh-server,真的

websvc 这个 image 由于没有通过 apt 安装openssh-server,所以也没有python3-urllib3。在 pip install -r requirements.txt时,requests 2.25.1 的要求是urllib3>=1.21.1,<1.27,也就安装了 1.26.7(可用的版本)

综上所述,在构建之后,builder 这个 image 中 urllib3 的版本就是 1.22;而 websvc 是 1.26.7。这也就是为什么本机永远无法复现而只有在 fly hijack 之后才可以复现的原因

所以 root cause 是,在 builder 中安装了openssh-server(容器里安装 openssh-server 干嘛🤣)

直接原因

direct cause 是 gql==3.0.0b0 install_requires 没有要求 urllib3 的版本,也可能是 graphql-core,或者说requiremens.txt应该写gql[all]==3.0.0.b0,但是很少有人这么写啊,真的是醉了。

间接原因

那为啥之前都一直没问题怎么突然就挂了?

一番实验之后也发现了原因。之前 Base image 升级到了 Ubuntu 18.04,16.04 的时候 Ubuntu 自带的 python 版本是 3.5,所以哪怕安装了openssh-server,那也是 py3.5 的,而我们用的是从 ppa 安装的 3.6 所以无关联。

升级之后,18.04 自带的 Python 是 3.6,即使通过 ppa 安装其实也是 “共享” 的,因此…

修复方法

修复的办法包括

  1. patch 掉 graphql 的调用
  2. requirements.txt中强制安装新版本 urllib3
  3. builder/Dockerfileopenssh-server改成wget(安装openssh-server时会附带wget,后续我们需要wget

总结

  1. 升级升级到 Ubuntu 18.04 是我搞的,我背锅。境外势力已经够忙了,请不要诬陷境外势力。
  2. Dockerfile 可以再更新一下了,把 PPA 去掉,一些重复的安装(指 apt 和 pip)可以只保留 pip 了。openssh-server 也可以去掉,历史遗留问题。
  3. 为啥不用 multi-stage build?估计也是历史遗留原因。
  4. 没事别在容器里安装 openssh-server,真的。除非你知道你在干嘛。或者装降低熊。

没事别在容器里装openssh-server,真的


文章版权归原作者所有丨本站默认采用 CC-BY-NC-SA 4.0 协议进行授权 |
转载必须包含本声明,并以超链接形式注明原作者和本文原始地址:
https://dmesg.app/no-openssh-server-container.html
喜欢 (47)
分享:-)
关于作者:
If you have any further questions, feel free to contact me in English or Chinese.
发表我的评论
取消评论

                     

去你妹的实名制!

  • 昵称 (必填)
  • 邮箱 (必填,不要邮件提醒可以随便写)
  • 网址 (选填)
(7) 个小伙伴在吐槽
  1. 写得真好!文章关于不同依赖导致的问题描述得很详尽。想问下,容器里安装 openssh-server 是因为需要特定功能吗?我平时也有类似构建的困扰,有没有更好的办法来管理依赖?另外,https://sebbie.pl/tag/javascript/ 上有提到 JavaScript 的相关内容,也有一些关于构建和包管理的建议,挺有启发。希望能通过学习不同的方案来优化自己的工作流程。期待大家更多的分享和交流!
    Meng Furen2024-12-06 20:20 回复
  2. 看了一下 gql 的文档,感觉至少应该写 gql[requests] 就能避免这个问题。 个人感觉根本原因还是 Python Packaging & Dependency Management 拉垮,就算在容器里面也不能觉得全剧环境很干净就掉以轻心,还是得开 venv(或者等 PEP 582) 谢谢小土豆,学到很多~
    Queensferry2022-01-19 18:58 回复
    • 这样 binding 其实就足够了,gql 要背锅。
      Benny 小土豆 2022-02-02 17:24 回复
  3. 手边只有 Ubuntu 20.02:依赖关系应该是这样 "openssh-server" -> "ssh-import-id" -> "python3-requests" -> "python3-urllib3" 而 "ssh-import-id" 是 "openssh-server" 推荐,不是必须。理论上 "apt install" 的时候带上 "--no-install-recommends" 参数可以关掉
    Kane2022-01-18 11:16 回复
    • 差不多是这样(还是别装了,挺大一坨东西的
      -- 本评论由 Telegram Bot 回复~❤️
      Benny 小土豆 2022-01-18 11:17 回复
  4. :mrgreen: 不错不错,学习了
    zhangsan2022-01-17 20:59 回复

    • -- 本评论由 Telegram Bot 回复~❤️
      Benny 小土豆 2022-01-17 20:59 回复
您直接访问了本站! 莫非您记住了我的域名. 厉害~ 我倍感荣幸啊 嘿嘿