几天前,跑的好好的 CI 突然 fail,报错信息看起来很奇怪,像是使用上的问题。
本地跑了一下这两个测试用例,并没有复现。以为是 CI 偶尔抽风了,就没管。
后来发现有点不对,怎么都跑不过。甚至直接在 develop 上跑 CI 都跑不过。这和 GraphQL 有什么关系啊?明明都能用的啊。让写这部分代码的同事帮忙看了下,发现他也能跑过。奇怪。
由于整套 CI 是跑在 concourse 上的,于是通过fly hijack
进去,在对应失败的 step 中成功复现了这个问题。
再后来同事发现出问题的是urllib3/util/retry.py
的 Retry
- max_retries = Retry(
- total=1,
- backoff_factor=0.1,
- status_forcelist=[500, 502, 503, 504],
- allowed_methods=None,
- )
去比对了下,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
之后也没有安装别的,怎么就版本不一致了?
后来经过一步一步测试,最终发现了这背后的原因。
根本原因
在builder/Dockerfile
中,我们安装了openssh-server
,先别管为啥……
openssh-server
有非常多的依赖,如下图中选中的地方,就有python3-urllib3
。
apt 中的 python package 的版本是相对而言比较老的,经过查看这种方式安装的 urllib3 的版本是 1.22
在 requirements.txt
中,我们安装的是requests==2.25.1
和gql==3.0.0b0
。这两个 package 对 urllib3 的版本要求比较宽泛,通过 apt 安装的这个版本恰巧能够满足。
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 安装其实也是 “共享” 的,因此…
修复方法
修复的办法包括
- patch 掉 graphql 的调用
requirements.txt
中强制安装新版本 urllib3- 把
builder/Dockerfile
中openssh-server
改成wget
(安装openssh-server
时会附带wget
,后续我们需要wget
)
总结
- 升级升级到 Ubuntu 18.04 是我搞的,我背锅。境外势力已经够忙了,请不要诬陷境外势力。
- Dockerfile 可以再更新一下了,把 PPA 去掉,一些重复的安装(指 apt 和 pip)可以只保留 pip 了。openssh-server 也可以去掉,历史遗留问题。
- 为啥不用 multi-stage build?估计也是历史遗留原因。
- 没事别在容器里安装 openssh-server,真的。除非你知道你在干嘛。或者装降低熊。
-- 本评论由 Telegram Bot 回复~❤️
-- 本评论由 Telegram Bot 回复~❤️