摸鱼心法——CI成就梦想

2023年 8月 10日 49.5k 0

前两篇讲到了服务如何适配容器化我们在服务里做的一系列改造,服务可以很优雅的适配容器化环境了,但是有一个前提是服务得容器化,也就是说如何打包成镜像。自己手动构建推送镜像可不可以?当然可以,不过老话说得好,一个月几百块,你玩儿什命啊。你天天手动,手不累么?肩膀不酸吗?身体受得了吗?别再自己用手了,通过Gitlab CI来解放你的手,用你的手去做些更快乐的事情。

首先聊聊我们面对的问题

  • 测试需要一个独立的测试环境,避免来自研发人员频繁提交代码带来的干扰,但是不想给测试人员带来额外的负担
  • 开发环境和测试环境构建流程需要一致化,开发人员在本地就能触发多个环境的构建和部署
  • 环境按照研发团队进行隔离,每个团队独立一套开发和测试环境,团队之间互不影响
  • 服务在开发环境能正常运行再交由测试同学
  • 部署生产环境时,保证部署的服务一定是测试后的版本,避免出现选择错误版本导致的线上问题
  • 需要对生产环境中服务所需的CPU和内存用量有一个大概预估
  • 生产环境服务出现问题,如何快速追溯到是哪个版本发布后出现的,从发布版本追溯到代码版本
  • 我们不想引入其他的平台来增加复杂度,运维维护成本
  • 针对上述几个问题,我们构建出了一个场景

    开发同学开发完成后先在开发环境里测试完成后自动部署至测试环境,测试同学进行多轮测试后标记可发布的服务版本,同时可能存在同一个服务根据不同的需求在多分支上的开发和测试问题。而生产环境部署时只能选择测试确认的服务版本进行发布上线,并且对于服务的资源配置要提供参考。线上运行过程中遇见的问题能追溯到发布版本和代码版本。

    结合问题、场景、容器化技术我们得出了以下的结论:

    • 基于k8s namespace策略做环境隔离、团队隔离,通过资源限制策略、调度策略进行控制不同环境的资源用量,减少资源成本、维护成本
    • 多个开发环境和测试环境在提交代码后均可完成自动构建和部署
    • 将代码分支和部署环境进行匹配,同时支持根据不同环境注入不同的环境变量值(前一篇文章分享过)
    • 通过监控数据向正式环境提供服务运行CPU和内存的参考值,可以考虑直接用k8s VPA的策略(生产环境暂时不推荐使用),也可以考虑参考VPA的算法再结合监控数据进行计算,不过这个带来的问题是需要人工调整服务的Request/Limit值
    • 线上部署的应用服务记录版本号用于问题追溯到代码
    • 在不引入其他平台的前提下完成整个流程,我们就把目光聚焦在了gitlab提供的ci能力上了

    为什么我们选择用gitlab ci?网上一搜索就有很多在讲优势劣势,这里说说我们看中的几个原因:

    1.轻量:内置在Gitlab平台中,和代码管理天然融合一体,而且上线的服务只用记录commit号在后续回溯代码时很方便

    2.易于配置:配置使用YAML文件进行定义,具有直观的语法。这使得构建、测试和部署流程可以以代码的方式进行管理,易于维护和版本控制

    3.扩展性强:如果标准任务不足以满足特定需求,可以无需侵入gitlab本身的代码,就能定制构建和部署流程

    总结下来,gitlab提供的ci从我们的角度看,够轻量,够简单,扩展性强。尤其是扩展性强这一点,这点让我们脸都笑开花了,可以低成本实现我们的想法,满足我们的想象力。

    先看看整体流程

    图片图片

    整套流程涵盖了开发阶段、线上运行阶段,首先开发阶段下,运维同学只需要在开发测试的k8s集群中为不同团队创建ns并做资源限制,后续的部署更新都是基于研发同学的代码提交触发,研发人员可在提交代码后通过gitlab pipeline查看ci构建、部署结果。开发环境中健康检查通过,研发测试没有问题后将该迭代版本的代码合并到对应的测试分支部署至测试ns交由测试人员进行测试,整体测试完成后标记服务镜像正式版本号。而后在平台上进行发布操作。后续运行过程中遇见的问题通过服务镜像号可以追溯到对应代码,修复后重复上述过程

    详细说说流程中的几个核心点

    1.代码分支和环境对应

    首先定义namespace名称困难不困难?困难,而且不只是这个名字困难,涉及到命名的时候都困难,方法名、变量名,尤其是变量名,当然如果说都是用i,j 这些来作为变量名也算的话那就不困难,但是别人看到了。。怕是要被刀。。

    所以namespace是基于gitlab组和分支规范较为方便,分支规范每家不一样没有对错之分,把握的原则只是分支与环境对应就好。举一个例子,分支命名dev作为开发分支前缀,test作为测试分支前缀,master作为主分支,gitlab上有两个组 team1,team2(team2和team1一样的逻辑图中就不多画了)

    图片图片

    这样做了之后,可以通过在ci中解析分支命名就可以在对应的namespace下创建有分支后缀的服务名了

    2.如何限制环境下的资源

    通过k8s提供的resourcequotas限制每个namespace的资源上限,通过监控集群资源池和namespace的资源用量,来调整集群的整体资源池,如果使用的公有云还可以通过k8s提供的CA(Cluster Autoscaler)进行伸缩

    3.线上问题如何追溯到代码版本

    在CI构建打包的时候,在gitlab runner中可以通过获取环境变量的方式来获取本次提交的commit值并自动添加到镜像版本号中,这样在后续通过镜像版本号便能追溯到对应的代码版本。

    4.为何只提ns,不提集群

    这是因为ns是一个逻辑概念,是为了考虑k8s集群出现灾难性故障时,可以方便我们快速在一个新的k8s集群中迅速重建所有服务。同时也让一次CI部署多套集群成为可能。

    5.如何实现自行实现上述流程

    从图中可知总共分成了4个大块,可以根据自己的需求去实现。

  • CI gitlab原生支持,只需要定义好一个ci.yml文件,然后其他的工程下引用这个文件就可以完成触发动作
  • 开发测试环境部署这个可以通过各类语言对接k8s就能完成,不过我们推荐采用operator的形式进行实现,这样对于服务版本,信息注入更方便
  • 生产环境部署目前市面上的k8s管理类平台不少,都是可以达成这个效果的
  • 运行监控监控从两个维度来做,指标和日志。指标监控首推prometheus,日志可以采用EFK套件,较为成熟不过我们觉得成本太贵,Loki是一个不错的替代方案。我们的平台则是采用公司自研的数据库实现了日志模块。
  • 相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论