随着 k8s 集群规模变大,以及弹性扩容的触发,导致 harbor 仓库的瓶颈问题逐渐暴露出来,目前也做了一些优化措施:
- 增大 harbor ECS 规格,网络带宽会增加
- 使用阿里 dragonfly p2p 镜像分发技术,多次测试下来难以应对大数据量分发场景,暂时放弃了
- 增加 Harbor Proxy Cache 提高网络并发
- 镜像优化,减少体积
- 镜像提前预热分发,目前正在考虑方案
在做镜像优化的时候,发现之前我们的 python 提速方案还有一些瑕疵,所以有了这里的分析。
在 Python 项目构建 Docker 镜像时,经常遇到项目源码才几百 KB,但是安装的依赖能高达数百 MB,甚至 GB,这不仅使镜像体积变的很大,而且因为网络安装依赖包导致严重拖慢构建速度。
项目环境:
注意:这里仅关系依赖问题,所以忽略源码部分
# tree
.
├── code
│ └── requirements.txt
└── Dockerfile
# cat code/requirements.txt
oss2==2.9.0
keras==2.3.1
numpy==1.18.1
Pillow==5.2.0
Flask==1.1.1
requests==2.22.0
gevent==1.4.0
gunicorn==19.9.0
tensorflow==2.0.0b1
常规构建:
示例 1:
# cat Dockerfile
FROM python:3.6.8
COPY code/requirements.txt /code/requirements.txt
RUN set -eux \
&& pip3 install --no-cache-dir -r /code/requirements.txt \
&& rm -rf /tmp/*
相当糟糕,依赖安装了 713MB,花了 5 分钟,太慢了。
# time docker build -t test:v1.0 .
real 5m6.002s
user 0m0.089s
sys 0m0.073s
# docker history test:v1.0
IMAGE CREATED CREATED BY SIZE COMMENT
fbdec4c33473 About a minute ago /bin/sh -c set -eux && pip3 install --no… 713MB
...
如何提速:
- 使用内网 pip 源代替公网源
- 提前安装 pip 依赖,我们这里选择该方案
基于刚才已经构建过的依赖镜像,再次去构建时间工作的镜像
示例 2:
# cat Dockerfile
FROM test:v1.0
COPY code /code
RUN set -eux \
&& pip3 install --no-cache-dir -r /code/requirements.txt \
&& rm -rf /tmp/*
EXPOSE 8080
CMD ["xxx"]
为什么这里再次安装 requirements.txt,直接删掉该步骤不就好了吗?
实际情况下,研发人员可能会在仓库中修改 requirements.txt,如果这里不再次安装下,最终发版可能就要提示缺少包而报错了。这里再次安装下依赖,就是防止该问题。
再次构建,相当好,8 秒,再次安装的依赖层 0B(我们这里没有模拟研发人员修改 requirements.txt 的情况),我们取得了巨大的进步。
# time docker build -t test:v2.0 .
real 0m8.205s
user 0m0.063s
sys 0m0.056s
# docker history test:v2.0
IMAGE CREATED CREATED BY SIZE COMMENT
c2375fd5cd9e 44 seconds ago /bin/sh -c set -eux && pip3 install --no… 0B
...
fbdec4c33473 9 minutes ago /bin/sh -c set -eux && pip3 install --no… 713MB
...
3 个月以后
这个词有点像电影里的镜头,以示例 2 中的 Dockerfile 再次构建:
示例 3:
# time docker build -t test:v3.0 .
real 2m3.205s
user 0m0.063s
sys 0m0.056s
# docker history test:v3.0
IMAGE CREATED CREATED BY SIZE COMMENT
c2375fd5cd9e 44 seconds ago /bin/sh -c set -eux && pip3 install --no… 173MB
...
fbdec4c33473 3 months ago /bin/sh -c set -eux && pip3 install --no… 713MB
...
问题来了,随着岁月的流逝,构建时间怎么变成了 2 分钟,再次安装的依赖层 173MB(我们这里没有模拟研发人员修改 requirements.txt 的情况)
为什么呢?
原来安装依赖的时候除了上面 requirements.txt 中写好的依赖,还有一些没有出现在 requirements.txt 中的依赖,而这些依赖的版本如 grpcio>=1.8.6 会随着时间的推移,而产生不同的版本
...
Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/site-packages (from tensorflow==2.0.0b1->-r /code/requirements.txt (line 9)) (1.34.1)
Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/site-packages (from tensorflow==2.0.0b1->-r /code/requirements.txt (line 9)) (0.33.4)
...
如何解决:
- 将所有依赖一个不少的写入 requirements.txt 中,应该比较麻烦
- 做一个定时任务,每周重新构建一次依赖层镜像
网友评论