几天前,跑的好好的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,真的。除非你知道你在干嘛。或者装降低熊。