美文网首页
你的 Python 镜像还好吗?

你的 Python 镜像还好吗?

作者: kong62 | 来源:发表于2021-01-14 12:04 被阅读0次

    随着 k8s 集群规模变大,以及弹性扩容的触发,导致 harbor 仓库的瓶颈问题逐渐暴露出来,目前也做了一些优化措施:

    1. 增大 harbor ECS 规格,网络带宽会增加
    2. 使用阿里 dragonfly p2p 镜像分发技术,多次测试下来难以应对大数据量分发场景,暂时放弃了
    3. 增加 Harbor Proxy Cache 提高网络并发
    4. 镜像优化,减少体积
    5. 镜像提前预热分发,目前正在考虑方案

    在做镜像优化的时候,发现之前我们的 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               
    ...
    

    如何提速:

    1. 使用内网 pip 源代替公网源
    2. 提前安装 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)
    ...

    如何解决:

    1. 将所有依赖一个不少的写入 requirements.txt 中,应该比较麻烦
    2. 做一个定时任务,每周重新构建一次依赖层镜像

    相关文章

      网友评论

          本文标题:你的 Python 镜像还好吗?

          本文链接:https://www.haomeiwen.com/subject/uifvaktx.html