作者:卢运强,首要从事 Java、Python 和 Golang 相关的开发作业。热爱学习和运用新技术;有着十分强烈的代码洁癖;喜欢重构代码,长于分析和处理问题。原文链接。

我司从 2022 年 6 月开始运用 KubeSphere,到现在为止快一年时刻,简要记载下此进程中的经历堆集,供大家参阅。

布景

公司当前有接近 3000 人的规划,首要事务为轿车配套相关的软硬件开发,其间专门从事软件开发约有 800 人,这其间 Java 开发的约占 70%,余下的为 C/C++ 嵌入式和 C# 桌面程序的开发。

在 Java 开发部分,约 80% 的都是 Java EE 开发,因为公司的事务首要是给外部客户供给软硬件产品和咨询服务,在前期公司和部分更注重的是如何将产品销售给更多的客户、获得更多的订单和尽快回款,对软件开发流程这块没有过多的注重,故前期在软件开发部分不是特别标准化。软件开发依据项目首要选用敏捷开发或瀑布模型,而关于软件布置和运维仍旧选用的纯手艺方法。

跟着公司规划的扩展与软件产品线的增多,上述方法逐渐暴露出一些问题:

  • 存在大量重复性作业,在软件快速迭代时,需求频繁的手艺编译布置,消耗时刻,且此进程缺少日志记载,后续无法追踪审计;
  • 缺少审阅功用,关于测验环境和出产环境的操作需求审批流程,之前经过邮件和企业微信无法串联;
  • 缺少准入功用,跟着团队规划扩展,人员素质良莠不齐,需求对软件开发流程、代码风格都需求强制固化;
  • 缺少监控功用,后续不同团队、项目选用的监控计划不统一,不利于常识的堆集;
  • 不同客户的定制化功用太多(logo,字体,IP 地址,事务逻辑等),选用手艺打包的方法效率低,简单遗失出错。

在竞赛日益剧烈的市场环境下,公司需求把有限的人力资源优先用于事务迭代开发,处理上述问题变得愈发迫切。

选型阐明

依据前述原因,部分预备选用网络上开源的体系来尽可能的处理上述痛点,在技术选型时有如下考量点:

  • 选用尽量少的体系,最好一套体系能处理前述所有问题,防止多个体系保护和整合的本钱;
  • 选用开源版本,防止公司内部手艺开发,节约人力;
  • 装置进程简练,不需求杂乱的操作,能支撑离线装置;
  • 文档丰富、社区活泼、运用人员较多,遇到问题能较简单的找到答案;
  • 支撑容器化布置,公司和部分的事务中自动驾驶和云仿真相关的越来越多,此部分对算力和资源提出了更高的要求。

咱们最开始选用的是 Jenkins,经过 Jenkins 基本上能处理咱们 90% 的问题,但仍旧有如下问题影运用体验:

  • 关于云原生支撑不太好,不利于部分后续云仿真相关的事务运用;
  • UI 界面简陋,交互方法不友好(项目构建日志输出等);
  • 关于项目,资源的权限分配与阻隔过于简陋,不满意多项目多部分运用时细粒度的区分要求。

在网络上查找后发现类似的工具有许多,经过开始比照筛选后倾向于 KubeSphere、Zadig 这 2 款产品,它们的基本功用都类似,进一步比照如下:

KubeSphere Zadig
云原生支撑 一般
UI 漂亮度 一般
GitHub Star 12.4k 2k
社区活泼度 一般

经过比照,KubeSphere 较为契合咱们的需求,尤其是 KubeSphere 的 UI 界面十分漂亮,故最终选定 KubeSphere 作为部分内部的继续集成与容器化办理体系!

至此,部分内部阅历了手艺操作->Jenkins->KubeSphere这 3 个阶段,各阶段的首要运用点如下:

KubeSphere 助力提升研发效能的应用实践分享

实践进程

KubeSphere 在公司内部的整体布置架构如下图所示,其作为最顶层的使用程序直接与运用人员交互,供给主动/守时触发构建、使用监控等功用,运用人员不用关心底层的 Jenkins、Kubernetes 等依靠组件,只需求与 Gitlab 和 KubeSphere 交互即可。

KubeSphere 助力提升研发效能的应用实践分享

继续集成

初始完成

在最初的尝试阶段只规划了 4 套环境:dev(开发环境)、sit(调试环境)、test(测验环境)、prod(出产环境)。

KubeSphere 助力提升研发效能的应用实践分享

出于简化运用与保护的考虑,计划对每个工程模块只保护一条流水线,经过构建时选择不同的环境参数来完成定制化打包与布置。

KubeSphere 和 Kubernetes 现在在部分是以单机版方法装置的,故关于不同环境的区分首要是经过分配不同端口来完成,具体完成时需求能在 Jenkins 和 Kubernetes 的 yaml 文件中都能动态的获取对应的端口参数和项目名称,参阅完成代码如下:

  • 在依据Groovyscript中依据选择环境动态分配相关端口

    switch(PRODUCT_PHASE) {
        case "sit":
            env.NODE_PORT = 13003
            env.DUBBO_PORT = 13903
            break
        case "test":
            env.NODE_PORT = 14003
            env.DUBBO_PORT = 14903
            break
        case "prod":
            env.NODE_PORT = 15003
            env.DUBBO_PORT = 15903
            break
    }
    
  • script中读取参数

    print env.DUBBO_IP
    
  • shell中读取参数

    docker build -f kubesphere/Dockerfile \
    -t idp-data:$BUILD_TAG  \
    --build-arg  PROJECT_VERSION=$PROJECT_VERSION \
    --build-arg  NODE_PORT=$NODE_PORT \
    --build-arg  DUBBO_PORT=$DUBBO_PORT \
    --build-arg PRODUCT_PHASE=$PRODUCT_PHASE .
    
  • yaml文件中读取参数

    spec:
      ports:
        - name: http
          port: $NODE_PORT
          protocol: TCP
          targetPort: $NODE_PORT
          nodePort: $NODE_PORT
        - name: dubbo
          port: $DUBBO_PORT
          protocol: TCP
          targetPort: $DUBBO_PORT
          nodePort: $DUBBO_PORT
      selector:
        app: lucumt-data-$PRODUCT_PHASE
      sessionAffinity: None
      type: NodePort
    

运转作用类似下图:

KubeSphere 助力提升研发效能的应用实践分享

具体内容请参见KubeSphere 运用心得。

环境扩容

依据前述方法建立的 4 套环境一开始运用较为顺畅,但跟着项目的推动以及开发人员的增多,一起有多个功用模块需求并行开发与测验,导致原有的 4 套环境不够用。经过一番探索后,完成了结合 Nacos在 KubeSphere 中动态装备多套环境功用,经过修正 Nacos 中的JSON装备文件可很简单的从 4 套扩展为 16 套乃至更多。

结合项目实际情况以及防止后续再次修正 KubeSphere 流水线,为了完成灵敏的装备多套环境,拟定了如下 2 个规矩:

  1. 端口信息存放到装备文件中,KubeSphere 在构建时去流水线读取相关装备
  2. 当需求扩展环境或修正端口时,不需求修正 KubeSphere 中的流水线,只需求修正对应的端口装备文件即可

因为项目中选用 Nacos 作为装备中心与服务办理渠道,故决定选用 Nacos 作为端口的装备中心,完成流程如下:

KubeSphere 助力提升研发效能的应用实践分享

依据上述流程,在具体完成时面对如下问题:

  • 运用 Groovy 代码获取 Nacos 中特定的端口 JSON 装备文件,并能动态解析;
  • 运用 Groovy 代码依据输入输入参数动态的获取 Nacos 中对应的 namespace
  • 因为环境的增多,不可能每套环境都预备一个 YAML 文件,此刻需求动态的读取并更新 YAML 文件。

因为 Jenkins 默认不支撑 JSONYAML 的解析,需求在 Jenkins 中预先装置 Pipeline Utility Steps插件,该插件供给了对 JSONYAMLCSVPROPERTIES 等常见文件格局的读取与修正操作。

  • JSON 文件设计如下,经过 env、server、dubbo 等属性记载环境和端口信息,经过 project 来记载具体的项目名称,因为装备文件中的 key 都是固定的,后续 Groovy 解析时会较为便利,在需求扩展环境时只需求更新此 JSON 文件即可。

    {
        "portConfig":[
            {
                "project":"lucumt-system",
                "ports":[
                    {
                        "env":"dev-1",
                        "server":12001,
                        "dubbo":12002
                    },
                    {
                        "env":"dev-2",
                        "server":12201,
                        "dubbo":12202
                    }
                ]
            },
            {
                "project":"lucumt-idp",
                "ports":[
                    {
                        "env":"dev-1",
                        "server":13001,
                        "dubbo":13002
                    },
                    {
                        "env":"dev-2",
                        "server":13201,
                        "dubbo":13202
                    }
                ]
            }
        ]
    }
    
  • Nacos Open Api 中可知查询 namespace 的请求为 /nacos/v1/console/namespaces,查询装备文件的请求为 /nacos/v1/cs/configs,依据 Groovy 的读取代码如下:

    response = sh(script: "curl -X GET 'http://xxx.xxx.xxx.xxx:8848/nacos/v1/console/namespaces'", returnStdout: true)
    jsonData = readJSON text: response
    namespaces = jsonData.data
    for(nm in namespaces){
        if(BUILD_TYPE==nm.namespaceShowName){
            NACOS_NAMESPACE = nm.namespace
        }
    }
    response = sh(script: "curl -X GET 'http://xxx.xxx.xxx.xxx:8848/nacos/v1/cs/configs?dataId=idp-custom-config.json&group=idp-custom-config&tenant=0f894ca6-4231-43dd-b9f3-960c02ad20fa'", returnStdout: true)
    jsonData = readJSON text: response
    configs = jsonData.portConfig
    for(config in configs){
        project = config.project
        if(project!=PROJECT_NAME){
           continue
        }
        ports = config.ports
        for(port in ports){
            if(port.env!=BUILD_TYPE){
                continue
            }
            env.NODE_PORT = port.server
    	}
    }
    
  • 动态更新 yaml 文件

    yamlFile = 'src/main/resources/bootstrap-dev.yml'
    yamlData = readYaml file: yamlFile
    yamlData.spring.cloud.nacos.discovery.group = BUILD_TYPE
    yamlData.spring.cloud.nacos.discovery.namespace = NACOS_NAMESPACE
    yamlData.spring.cloud.nacos.config.namespace = NACOS_NAMESPACE
    sh "rm $yamlFile"
    writeYaml file: yamlFile, data: yamlData
    

具体内容请参见运用 Nacos 与 KubeSphere 创建多套开发与测验环境。

扩展功用

  • 在项目构建时增加审阅功用,关于 testprod 环境必须经过相关人的审阅才干进行后续构建流程,防止损坏相关版本的稳定性。

    KubeSphere 助力提升研发效能的应用实践分享

  • 在 KubeSphere 的容器组页面能够查看 pod 节点的 CPU 和内存消耗,可开始满意对代码潜在功用问题的排查。

    KubeSphere 助力提升研发效能的应用实践分享

  • 在项目构建完成时发送邮件告诉给相关人。

    KubeSphere 助力提升研发效能的应用实践分享

外部布置

部分内部的软件最终都会销售并交给给相关客户,因为客户网络与公司网络不通以及代码保密等要求,无法在客户现场运用原有的 Jenkins 流水线进行布置交给。依据此部分采取折中计划:在公司内部经过 KubeSphere 进行编译打包,导出 Docker 镜像,拷贝到客户处然后依据 Docker 镜像布置运转,具体请参见如下链接:

  • 在 Jenkins 中依据装备从不同的库房中 Checkout 代码
  • 运用 shell 脚本完成将微服务程序以 docker 容器方法自动布置

KubeSphere 助力提升研发效能的应用实践分享

运用帮忙

在运用进程中确实遇到了不少问题,首要经过如下三条途径处理:

  • 阅读官方文档,依据文档阐明操作;
  • 若官网文档没有,则去用户论坛查看是否有人遇到类似问题或直接发帖;
  • 经过微信群寻求帮忙。

依据部分运用经历,90% 的问题可经过官方文档或用户论坛获得答案。

运用作用

部分搭档习惯于原始的手艺操作或依据 Docker 布置,导致在推行进程中受到了一定的阻力,部分内部依据充沛交流和逐渐替换的方法引导相关搭档来渐渐习惯。经过约一年的时刻磨合,大家都认可了拥抱云原生和 KubeSphere 给咱们带来的便利,运用过的搭档都说很香!

对我司而言,有如下几个方面的进步:

  • 研制人员几乎不用消耗时刻在软件的布置和监控上,节约约 20% 时刻,产品迭代速度更快;
  • 定制化的功用经过脚本完成,完全杜绝了给客户交给软件时因为人工遗漏导致的偶发问题,在进步软件交给质量的一起也进步了客户我司的认可度;
  • 软件开发、测验流程更标准,经过在 Jenkins 流水线强制增加各种标准查看和审阅流程,完成了软件研制的标准统一,代码质量更高,更利于扩展保护,一起也在一定程序上减少了因为人员流失/改变对项目造成的影响;
  • 依据 KubeSphere 的云原生布置结合 Nacos 能够更快速的分配多套环境,有效的完成了开发测验出产环境的阻隔,在云仿真相关的事务场景中可依据事务场景更便利的对 pod 进行监控与调整,前瞻性的事务研制展开更顺畅。

KubeSphere 助力提升研发效能的应用实践分享

未来规划

结合公司与部分的实际情况,短期的规划依然是完善依据 Jenkins 的 CI/CD 运用来完善打包与布置流程,部分内部在进行全面 web 化,依据此中长期拥抱云原生。

  • 接入企业微信,将构建与运转结果随时告诉相关人,构建结果与项目监控更实时;
  • 将部分内部依据 Eclipse RCP 的桌面使用程序经过 Jenkins 完成标准化与自动化的构建;
  • 将底层的 Kubernetes 从单机晋级为集群,支撑更多 pod 的布置,支撑公司内部需求大量 pod 并发运转的云仿真项目;
  • 部分内部的 web 项目全部经过 KubeSphere 构建布置,完善其运用文档,发掘 KubeSphere 在部分事务中新的使用场景(如对设计文档、开发文档、bug 修复的守时与强制查看告诉等)。

本文由博客一文多发渠道 OpenWrite 发布!