• 优化jenkins on kubernetes构建性能慢问题


    前言

    现在大多数公司,都开始使用kubernetes开启云原生时代了,传统的jenkins在物理机构建场景已经越来越少见了,取而代之的是用jekins在kubernetes pod中动态构建我们的任务(Kubernetes plugin for Jenkins:Kubernetes | Jenkins plugin),充分利用了kubernetes集群弹性资源的能力,在这个场景下,我们可能会碰到一些构建性能慢的问题,下面来综合分析一下

    项目编译慢

    以maven为例,编译大型开源项目动辄几十分钟是很正常的,因为编译工程过要大量下载项目依赖,如果没有配置依赖缓存,那么每次构建耗时都会很久是非常影响开发迭代效率的。

    针对这个问题,我们可以加入依赖缓存,以maven为例:我们需要提供一个持久的.m2目录存储,在kubernetes里面实现这一点并不难,如果有ceph就可以直接挂PVC,如果没有ceph挂主机共享的卷也可以:

    1. #!groovy
    2. podTemplate(cloud: 'cloud-build', label: 'jenkins',
    3. containers: [
    4. containerTemplate(resourceRequestCpu: '1', resourceLimitCpu: '4', resourceRequestMemory: '4Gi', resourceLimitMemory: '8Gi', name: 'docker', image: 'xxxx.com/library/docker:17.05.0-ce', ttyEnabled: true, privileged: true, instanceCap: 1, command: 'cat', arg: "", alwaysPullImage: false),
    5. containerTemplate(resourceRequestCpu: '1', resourceLimitCpu: '4', resourceRequestMemory: '4Gi', resourceLimitMemory: '8Gi', name: 'maven', image: 'xxx.com/library/maven:3.8.3-adoptopenjdk-8', ttyEnabled: true, command: 'cat', arg: "", alwaysPullImage: false),
    6. ],
    7. volumes: [
    8. hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock'), //docker in docker
    9. hostPathVolume(hostPath: '/opt/maven/m2', mountPath: '/root/.m2') //持久化maven cache
    10. ]) {
    11. node('jenkins') {
    12. stage('Check code') {
    13. echo("gitCommitId value is: ${gitCommitId}")
    14. checkout([$class: 'GitSCM', branches: [[name: "${gitCommitId}"]], userRemoteConfigs: [[credentialsId: "${gitlabCredential}" , url: "${gitlabURL}"]]])
    15. }
    16. stage('Maven package') {
    17. container('maven') {
    18. sh "mvn clean package -DskipTests -Dmaven.test.skip"
    19. }
    20. }
    21. stage('Build Image') {
    22. container('docker') {
    23. // 此处尽量避免使用--pull,每次强制拉取镜像
    24. sh "docker build -t myproject:${env.BUILD_NUMBER} -f dockefile_dev ."
    25. }
    26. }
    27. }
    28. }

    这里面有一点需要注意,如果要使用maven的依赖cache,就必须把打包编译语句放在docker build镜像的外层,如果你放在build的dockfile内,虽然能保持编译和运行环境一致,但无法使用volume挂载,从而无法使用挂载的持久.m2 cache,这是docker的机制决定的。

    拉推镜像慢

    这里面分三部分:

    • 在网络带宽有限情况下,每次都去强拉镜像

    在kubernetes中运行的项目,都需要一个基础镜像,如果每次都去拉取镜像势必会影响构建效率,默认情况下就会使用缓存的,我们避免配置强制拉取就可以了,注意:alwaysPullImage: false

    containerTemplate(name: 'hdfs-client', image: 'harbor.xxxx/maven:latest', ttyEnabled: true, command: 'cat', arg: "", alwaysPullImage: false),

    • 构建镜像体积大:

    选用from镜像更小的镜像 + 自行构建控制新加入的依赖项,这个其实比较容易优化,尽量删除无用的包及cache

    • 重复推镜像

    很多公司都有习惯,在jenkins构建镜像完成后,除了有一个带版本号的镜像,还喜欢在打个tag:latest,

    例如:spark-3.1.0:44 和 spark-3.1.0:latest,其实完全没必要在打个latest的镜像,因为在kubernetes运行的Deployment中的镜像使用latest这种镜像是非常不推荐的,因为其废掉了项目发布版本概念,极端情况下会导致多个版本不同的副本同时存在,从而带来不稳定因素,所以最好避免使用这种方式,这样我们也不用重复推镜像,影响构建效率

    Pod调度慢

    在jenkins-slave运行在kubernetes上,每次发起的构建任务,都会拉起一个jnlp-agent POD来执行构建任务,但某些情况下,可能会出现:调度2分钟,构建30秒的情况。这种情况下是因为kube-scheduler这个集群的默认调度器,在经过过滤,打分计算后,评估出来集群中暂时没有存在多余资源的Node节点用来运行这个Agent,默认的调度器的资源评估具有滞后性,所以可能存在调度资源不均衡,或者调度分配不准确的问题。

    优化方法:

    1,调参数:调度器性能调优 | Kubernetes

    2,使用 实时资源打分插件 Trimaran scheduler-plugins/pkg/trimaran at master · kubernetes-sigs/scheduler-plugins · GitHub

    3,尽量减小Agent Pod里面容器使用的资源(jnlp是默认的容器,我们可能还会增加maven,docker等新的容器),以便于调度器更容易找到运行节点

    4,如果kubernetes集群经常出现调度延迟大,那么有可能是资源确实紧张,这个时候该考虑给集群扩容新的节点了

    总结

    优化的整体原则就是,能用cache的都用cache,能节省网络带宽的就节省网络带宽,如果集群资源紧张,那么就需要合理设置构建Pod的资源限制,方便kubernetes集群调度器,能够尽快的让我们的构建任务运行起来。

  • 相关阅读:
    辊轧机液压系统泵站比例阀放大器
    破局企业数字化采购难题,采购系统标准化采购结算流程,实现高效协同
    VSCode操作小技巧
    如何通过 Chainlink Price Feeds获得加密资产的历史价格
    永磁同步电机转子位置估算专题——正交锁相环
    alpakka-kafka(10)-用kafka实现分布式近实时交易
    猿创征文|Vue结合Vant-ui实现数据列表上拉加载更多,下拉刷新功能
    【Cherno的OpenGL视频】Batch rendering - An intro
    进程间通信
    web3.0的特点、应用和安全问题
  • 原文地址:https://blog.csdn.net/u010454030/article/details/126895111