云原生DevOps实践与落地 | 第十四期社群图文直播

by June 2021-10-12

云原生概述

Pivotal 对于云原生的定义:

  • DevOps – CI/CD、开发运维协同
  • 持续交付 – 快速交付、反馈
  • 微服务 – RESTful、独立管理
  • 容器化 – 微服务的最佳载体

 云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。 这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。 云原生DevOps的挑战新的挑战:

  • 自动化应用在多环境间的推进
  • 控制应用在生产环境上的发布
  • 提高应用的平均部署/恢复时间
  • 更快地定位故障、复现和回滚
  • 更快地将应用状态反馈给干系人

智领云的云原生DevOps落地

一、 架构设计1、架构设计 – 云平台 

基础设施层

PaaS层

应用层 

2、架构设计 – CI/CD流水线

3、架构设计 – CI/CD流水线

  • 目前支撑内部近百个构建/发布作业,日均运行100+次构建/发布任务
  • 构建/发布策略支持webhook、on demand、nightly等等
  • 自建的私有仓库,支持docker、maven、pypi、npm、raw等格式的构建产物管理
  • 自建的内部镜像源,极大提高构建的稳定性
  • 基于Mesos/K8S的DevOps系统和微服务的弹性伸缩,提供多用户支持
  • 统一的构建日志收集机制,提高CI/CD debug效率

二、源码构建SDK – 团队早期的痛点“庞大”项目CI构建的问题

团队早期CI的痛点

  • “庞大”项目的CI构建: 

– 全量or部分构建           

 – 模块间的依赖关系

  • 构建日志分散,查看历史日志很麻烦
  • 构建行为的共同需求和细分需求实现,需要各个项目自己维护
  • 团队早期各小组对于CI/CD系统使用的能力参差不齐

 基于以上痛点,在团队早期我们很难通过开放jenkins-ci或者gitlab-ci流水线的能力让各个小组自己去定义持续构建作业,我们决定开发统一的CI SDK工具: BDOS SDK其开发语言涉及到了Python/Java/Shell等,后面还涉及到开源的考虑。 所以这里还有加密(Cython)的设计artifact的构建比较复杂,好多artifact还有公共库依赖,其中还有worker构建需要依赖master构建等工作要完成后续还有其它的演进工作,比如同样一个tgz文件,前期可能只需要简单的压缩下,后续又增加新的逻辑,比如要支持maven打包。image构建也较多,也有相关artifact的依赖关系。

 1、源码构建SDK – 版本迭代 

BDOS SDK目前支持主要功能有:

  • 全量/增量构建
  • 按需构建,自助定义构建模块
  • 日志和构建元数据归档
  • Auto Tagging,镜像自动打上Git SHA
  • 自定义pre/post脚本
  • Python模块代码混淆开关
  • Sonarqube流程集成
  • … 

从2019年到现在2021年,从最早的 1.0版本目前迭代到了2.5.1 ,后续还会根据实际来进行优化迭代 

2、源码构建SDK – 声明式配置定义 

源码项目通过在项目根目录定义一个BDOS SDK配置文件(类似.gitlab-ci.yml),即可通过SDK来进行CI构建集成,主要参数包括: 

  • 构建阶段, artifacts or docker
  • 构建上下文路径
  • Git探针路径
  • 构建产物信息:名称、版本号、类型
  • 自定义Presintall/Postinstall脚本
  • Docker构建参数

内部WIKI文档提供了简化的struct.settings.json文件模板,新入职的员工可以直接用最简单的的Image模板文件直接套用。 后面再慢慢的熟悉和了解我们的CI体系以后,就可以稍微更复杂和深入的应用了。 

3、源码构建SDK – 增量构建实现 

最早期的CI SDK主要是以增量构建/全量构建为主,全量构建实现较简单,就是将所有的artifact/image全部打包完成即可。增量构建CI SDK的程序会执行git相关命令操作,git diff –name-only HEAD~ HEAD抓取匹配的目录,最终得出此次需要构建的应用。 

4、源码构建SDK – 按需构建实现 

按需构建一般都会配合Jenkins UI指定分支或Tag构建一起使用,也可以指定固定分支(例如dev或release)构建 

5、源码构建SDK – 构建元数据和日志归档 

6、源码构建SDK – Auto Tagging功能 

这个功能在我们的CI/CD流水线体系中较为重要。 有了此功能以后,由于Docker镜像tag在整个CI/CD体系中有唯一标识性,这样就再也不能担心后面的build会覆盖掉前面的build镜像了,这个功能在开发密集阶段及多项目分支并行开发时是非常有用的功能。 

CI SDK的Auto Tagging功能介绍 

7、源码构建SDK – 自定义脚本

SDK支持自定义脚本功能,提供preinstall_command和post_command配置项,功能类似于gitlab-ci的before_script和after_script语法。 

  • preinstall_command在构建前执行,一般的使用场景是模板渲染、配置拉取、构建上下文准备等;
  • post_command在构建后执行,一般的使用场景是二次打包、上下文清理等。

 SDK配置文件中的自定义脚本配置项

内部私有仓库搭建 

经过调研和对比,我们选用了开源社区较成熟的软件Nexus3作为内部的私有仓库和代理仓库。 我们分别在私有云和公有云上各搭建了一套Nexus3私有仓库,每一个类型的仓库均配置了三套repo,分别对应test/staging/prod环境。 

内部Nexus3的各种仓库明细

内部镜像源加速 – 问题 

为了达到更好的CI持续集成效果及缩短CI时间,我们发现CI构建有个较大的问题,就是本地的测试环境/包括阿里云JKS环境都有因为网络的原因及远程加速源更新了Cache,CI JOB出现失败。

随着构建任务涉及到的操作系统版本、开发语言版本越来越多,基于公网镜像源构建的不稳定性会越来越高;同时,基于单个公网镜像源会有单点失效的情况。 

内部自建源的工作流程

内部镜像源加速 – 优势 

我们选用Nexus3来搭建了公司内部的镜像源,其优势在于: 

  • 覆盖公司所有开发语言、操作系统源,所有源码项目无需自己解决镜像加速
  • 代理国内、外多镜像站,大大降低了单个公网镜像源失效后导致的CI构建失败几率
  • 有效缓存了开发语言、操作系统开源社区停止维护版本的软件包,保证“新”、“老”项目均能正常构建
  • 本身可以形成一套产品外部项目实施的解决方案,解决客户在air-gapped环境中CI/CD构建难的问题

持续部署 – Ansible 

利用了Ansible的特性来进行多环境的分布式部署 

  • 性能优异
  • Jinja2模板功能强大,能够区分多环境
  • API强大,能够较方便生成动态inventory File文件
  • Ansible-playbook功能灵活

 Mesos/Kubernetes的版本回滚是利用其自带机制实现 

持续部署 – Argo CD 

Argo CD是云原生时代的新产物,它是K8S生态下一种声明式的GitOps持续交付工具。我们目前主要还是基于Ansible来实现持续部署,同时在K8S环境下也正在探索ArgoCD的集成,未来会持续关注。 

三、基于GitLab CI/CD的演进 

演进的原因: 

  • 团队整体DevOps能力提升
  • 内部SDK功能迭代的局限性
  • 开放CI/CD流水线定义模式
  • DevOps团队专注于平台能力交付

GitLab CI/CD的优势:

  • 一个界面集成了代码托管、持续构建、持续发布等完整DevOps生命周期的管理
  • 代码质量、代码规范检查支持
  • 内置的CI/CD流水线支持
  • 强大而灵活的gitlab-runner,甚至可以将任何能运行 Docker的机器作为其载体,资源的灵活性相对Jenkins而言非常灵活
  • K8S集群管理
  • 展示所有部署的应用程序的性能指标
  • 敏捷管理
  • 安全检查

演进路径 

Phase 1 – 将Jenkins Jobs改造为GitLab流水线,构建过程还是通过BDOS SDK完成 Phase 2 – 逐步使用GitLab-CI原生语法来改造构建和发布流程 Phase 3 – 在GitLab流水线上逐步引入高阶特性例如安全检查、漏洞扫描等等 Phase 4 – 敏捷开发流程集成,完成基于GitLab的整个DevOps生命周期管理 

关于我们10 + :企业级大数据平台建设及产品化实践30 + :为国内外几十家知名企业和上市公司提供云原生数据中台系统解决方案千万 +:19、20年分别获得投资机构数千万融资

留言

评论

${{item['author_name']}} 回复 ${{idToContentMap[item.parent] !== undefined ? idToContentMap[item.parent]['author_name'] : ''}} · ${{item.date.slice(0, 10)}} 回复

暂时还没有一条评论.