蚂蚁构建服务演进史

简介: 自动化构建和CI/CD往往是相辅相成的,可以理解为,自动化构建是温饱问题,解决了温饱就会有更多的提高生产力的诉求,也就是对应的CI平台,CI/CD本篇文章不做扩展。

image.png

作者 | 琉克
来源 | 阿里技术公众号

一 构建平台的由来

只要是软件开发就离不开构建,构建无处不在,构建是源代码和用户呈现之间的桥梁。

这里要澄清一点,构建 != 编译,构建的本质是把源代码翻译成运行环境能识别的产物(源代码可能是Java代码,也可能是配置文件、资源文件等,运行环境可能是物理机,也可能是虚拟机,也可能是mobile phone)。

所以工程师每天每时每刻都在构建,不构建就没法验证。随着规划的扩大,把构建自动化掉,提供一个“打包平台”也就是一个自然而然的事情,毕竟提高生产力是第一诉求吗,这也就是构建平台最开始的由来,把每天干的事情自动化掉,搬上平台。

自动化构建和CI/CD往往是相辅相成的,可以理解为,自动化构建是温饱问题,解决了温饱就会有更多的提高生产力的诉求,也就是对应的CI平台,CI/CD本篇文章不做扩展。

二 理解构建

构建 != 编译,构建本身是一个很复杂的编排过程。举两个例子:

1 Android APK的构建过程

image.png

上图中绿色部分为工具,浅蓝色部门为源代码+中间产物。可以看到是一系列的工具+输入的编排,最终生成运行环境可识别的产物。上诉构建过程生成的产物(APK)可被Android手机识别并运行。

2 Java Jar包的构建过程

image.png

可以看到jar包的构建过程和上面APK的差异非常大,相对来说也是更简单。

3 构建工具

上面两个case可以看出来,构建本身很复杂,要最终构建出一个可以运行的产物需要做很多事情,我们完全可以手动javac copy jar等等一系列操作实现构建过程。但当工程越来越大,文件越来越多,这个事情就不是那么地令人开心了。这些命令往往都是很机械的操作。所以我们可以把这些机械的操作交给机器去做。对应的构建工具也应运而生,毕竟提高生产力是第一诉求。

拿Java举例:

Ant

image.png

上面的示例中,Ant定义了五个任务:init、compile、build、test和clean。

每个任务做什么都定义清楚了。在打包之前要先编译,所以通过depends来指定依赖的路径。

如果在命令行里执行ant build,那就会先执行compile,而compile又依赖于init,所以就会先执行init。

执行命令:

ant test

通过命令就可以执行编程,打包,测试。为开发者带来了很大的便利,提供了工作效率。

但是Ant有一个很致命的缺陷,那就是没办法管理依赖。

我们一个工程,要使用很多第三方工具,不同的工具,不同的版本。

每次打包都要自己手动去把正确的版本拷到lib下面去,不用说,这个工作既枯燥还特别容易出错。为了解决这个问题,Maven如约而至。

Maven

Ant仅是一个构建工具,它并未对项目的中的工程依赖以及项目本身进行管理,并且Ant作为构建工具未能消除软件构建的重复性,因为不同的项目需要编写对应的Ant任务。
Maven作为后来者,继承了Ant的项目构建功能,并且提供了依赖关系,插件机制,项目管理的功能,因此它是一个项目管理和综合工具, 其核心的依赖管理, 项目信息管理, 中央仓库,Maven的核心理念是约定大于配置。每一种类型都有固定的构建生命周期。

和ant的build.xml相对的,maven项目的核心是pom.xml,java开发同学肯定都很熟。

Gradle

Gradle已经抛弃了Ant、Maven中Xml配置的形式,取而代之的是Gradle采用了领域特定语言Groovy的配置。Gradle继承了Maven中仓库,坐标,依赖这些核心概念。文件的布局也和Maven相同。但同时,又继承了Ant中target的概念,我们又可以重新定义自己的任务(在Gradle中叫做task)。

相比maven会更简洁,比如在maven中要引入依赖:

image.png

转换成gradle脚本:

dependencies {compile('org.springframework:spring-core:2.5.6')compile('org.springframework:spring-beans:2.5.6')compile('org.springframework:spring-context:2.5.6')compile('com.google.code.kaptcha:kaptcha:2.3:jdk15')testCompile('junit:junit:4.7')
}

配置从原来的28行缩减至7行!效果惊人。

同时gradle在构建性能上也碾压maven,gradle在maven的基础上额外增加了增量构建、build cache、daemon等特性,大大提升构建时间。

类似的构建工具其实还有很多,基本属于百花齐放,比如facebook的BUCK,Google的bazel等,国内也有一些厂商自己的构建工具,比如腾讯的blade。不同的工具都会有自己的优势和劣势。

三 构建平台的演进

1 原始时代

其实最开始的诉求非常简单,构建工具基本都是现成的,人少,功能简单。所有构建基本都是手动。

  • 移动端:支付宝一个应用,一个仓库,谁发版直接在个人电脑上拉取最新代码执行编译,发布app store。
  • 服务端:一台物理机,一套构建脚本,谁要发布,直接登录,输入仓库/分支信息,执行构建,然后发版。

2 自动化

显然,随着人员的增长,规模的扩大,原始时代根本无法支撑进一步发展,主要的矛盾:

  1. 多人协作困难。
  2. 多人抢占。
  3. 个人机器构建的不稳定性,成功率极低。

这一阶段最大的诉求:项目管理/多人协作/自动化构建。应运而生两个平台:CP SCM。

  • CP主要负责项目管理,多人协作。
  • SCM主要负责代码管理,构建任务调度,构建机器管理运维(SCM慢慢演变成一个大杂烩,jar包上传管理,客户端签名,各种)。

大概长下面这个样子:

初级阶段

image.png

这里构建比较大的难点还是在机器的管理和调度,其实做了很多事情:

  • 机器管理,增删机器。
  • 机器保活,可用性监控。
  • 机器环境一致性的保障。
  • 机器构建负载均衡。
  • 构建脚本的统一升级维护。

上面框架运行了一段时间后还是发生了很多问题,构建成功率越来越低,主要有几个问题:

  1. ssh通道是有连接数限制的,抽风性的ssh连接异常。
  2. 负载均衡控制困难,机器之间负载经常不一致,构建时快时慢。
  3. 机器配置管理难度大。

进阶阶段

其实这一块,开源有非常成熟的方案 -- jenkins。我们干的很多的事情jenkins都已经帮我们干了。也能很好的解决我们遇到的痛点:

  • C/S架构,无ssh通道限制。
  • 自动控制负载均衡,机器监控。
  • 灵活的构建和任务配置。
  • 强大的开放能力和丰富的API。

改造完大概长这样:

image.png

黑科技(填坑)

这里要抛出一个新的概念「制品库」。

Java开发中,大家对maven、gradle这些工具肯定不能再熟悉了。前面讲构建工具的时候讲过,Java构建工具有几代演进:Ant,Maven,Gradle。Maven之前的上古工具,用的人应该非常少了。

在Maven之前,是不存在版本管理,依赖管理这种概念的,所有的东西都在你的仓库。你的工程里面用到了gson,spring,log等开源框架和功能时,是需要去手动下载对应的jar包,然后放在代码库中。如果需要更新,需要不停去项目对应官网,下载最新发布的包。

Maven之后的工具,提供了强大的依赖管理功能,只要在pom.xml写上你要使用的依赖,maven会自动下载依赖,修改和升级只需要修改GAV坐标(groupid,artifactid,version),依赖的所有jar包都存储在「制品库」中。

此时的构建大概长这个样子:

image.png

  1. 物理机缓存使用overlay文件系统,每次构建缓存独立,防止公共缓存被刷入。
  2. 监控制品库的覆盖记录,生产delete task,快速通知物理机删除公共缓存。
  3. 记录overlay文件系统upper层的增加记录,记录add task,定时刷入物理机公共缓存。

存在的问题

  1. 环境一致性保证,环境升级。
  2. 复杂的脚本逻辑。

理解下这两个问题,随着业务的迅速发展,接入的系统越来越多,APP越来越多,构建的环境越来越“胖”。

比如:App除了支付宝,还有口碑,财富,香港钱包等,各个产品有自己的构建逻辑,也有自己的工具,比如支付宝用gradle4,口碑用gradle2。

其它的技术栈也越来越多,Java,GO,C++等,需要不同的JDK版本,GO环境等。

所有环境都塞进一台物理机,这里存在两个比较严重的问题:

  1. 频繁增加新的工具,如何确保不影响既有的环境和构建。
  2. 环境不可复制,新的构建机器,初始化困难,很难保证和旧有环境的一致性。

历史发生过的问题

  1. 新加的物理机编码异常,导致构建产物异常,运行时出现乱码。
  2. 升级IOT的AndroidSDK,影响支付宝,部分手机计步功能失效。
  3. 环境升级操作不当导致的各种构建失败。

3 容器化

构建是一件非常值得敬畏的事情,需要保证构建的绝对正确,一旦构建异常了,后果不堪设想。

最好的保证构建正确性的方式,就是什么都不要改,不要加机器,不要改环境,什么都不要动。

但是现实是总是有越来越多新的场景冒出了,今天要支持这个,明天要支持那个,这里是一个比较矛盾的点。

在容器技术出来之前,大家都是用的是虚拟机技术,我们可以模拟出来一台乃至多台电脑,但是太笨重了,也不好维护。2013年Docker开源,它轻量,高性能(秒级启动),隔离性,让他迅速成为焦点。

构建也尝试探索,docker技术非常适合在构建时使用,可以很好的解决上面的问题。改造后长下面这样:

image.png

之后升级环境再也不是痛,各种场景容器隔离,升级互不影响,物理机秒级扩容。运维人员基本只要维护Dockerfile就行。

当然也会带来新的问题:

  1. Mac构建没法虚拟化,仍然是传统物理机构建 + Ansible运维。
  2. 容器化之后缓存失效,构建时间暴增。
  3. 镜像本身的管理,物理机磁盘空间管理。

4 镜像化

前面讲的都是软件的构建过程和构建服务,这里其实还存在一个问题,除了构建的一致性,软件的运行环境一致性也至关重要。经常会发生,一个软件,在我的电脑可以,在别人的环境却跑不起来。

随着容器技术越来越火,serverless技术和应用微服务架构的演进。容器正迅速成为企业应用打包和部署的基本单位,可以真正的实现build once & run everywhere。
在蚂蚁的历史中也是如此,越来越多的场景开始镜像化部署,所以镜像构建本身也变得越来越重要,镜像构建的效率,稳定性,安全性等至关重要。

镜像构建也经过两次演进:

docker build

docker build是比较简单的,我们在之前的架构之上新增了一种镜像构建类型,主要存在下面几个弊端。

(1)对于multi-stage 的Dockerfile 构建 无法实现并行编译

image.png

(2)docker build 缓存利用效率低,改变Dockerfile 前面的一层,后面所有的层都需
要重新构建而无法使用缓存,这要求用户不得不认真控制写好自己的Dockerfile以确保镜像缓存复用。

buildkit + K8S

buildkit是从docker build分离出来的单独项目,目前buildkit已经集成到Docker 18.06之后的版本之中,核心特性:

  • 可扩展的前端格式:buildkit使用前后端分离的架构设计,除了Dockerfile也支持其他类型的前端格式。
  • 并行构建执行:对于multistage类型Dockerfile, buildkit可以实现不同stage之间的并行执行。
  • 支持构建缓存的多种处理方式:buildkit处理本地缓存snapshot,同时还提供了将构建缓存导入/导出到本地或者远程registry。
  • 多种输出格式:buildkit支持导出成tar包或者oci格式的镜像格式。
  • 引入Dockerfile新语法RUN --mount支持构建时挂载。

这里不进行扩展,有兴趣的同学可以查看buildkit的官方项目(蚂蚁目前每天运行着上万数量的高可用镜像构建服务)。

5 拥抱云原生

随着蚂蚁越来越多的业务serverless化,云原生慢慢成为了趋势。伴随着的是对K8s之上的构建和资源的使用诉求。

而K8s本身使用门槛又极高,同时也缺乏灵活的任务编排能力。相应的构建团队也开始调研和投入云原生的构建和调度解决方案。

背景

2019年3月份持续交付基金会(CDF)正式成立,它致力于使企业在多个 CI / CD 平台上更轻松地构建和复用 DevOps 管道。

第一批进入CDF项目的主要有四个:

image.png

Tekton 作为谷歌捐赠的 CDF 重要项目 ,是一组用于构建 CI/CD 系统的共享开源组件,与 Kubernetes 紧密相连,其重要性不言而喻。

并且jenkinsX底层也选择了tekton作为执行引擎。

Jenkins X is committing fully to Tekton as its pipeline execution engine. We are convinced that this is the right choice for Jenkins X, as a cloud-native CI/CD platform on Kubernetes, and for our users.

内部落地

综合权衡,采用tekton是一个比较合理的解决方案(站在巨人的肩膀,不重复造轮子)。

经过一段时间的探索和演进,逐步落地了云原生的资源调度和构建解决方案——ironman。服务内部每天几万的构建、代码扫描、CI任务等场景。

详细细节可以参考下面几篇文章:

  1. tektoncd github
  2. 持续交付基金会

下一步计划

tekton相比K8s,复杂度大大降低,并且提供了足够灵活的编排和调度能力,但是仍然有缺陷:

  1. 概念复杂,偏厚重,整体调度相比直接使用POD会更慢
  2. 使用上仍然有一些成本,对一线用户的接入使用不友好

目前正在投入POD预热等极简模式,解决上诉痛点。当然还有很多未解的难题,就不一一赘述。

6 构建中台

经历了自动化,容器化,镜像化等场景,发现用户的需求实在是千奇百怪,越来越多(只能说蚂蚁的业务发展太快)。

我们有越来越多的业务场景(IOT,小程序,大数据,...),构建的需求差异性也非常大。有Mac构建,Linux构建,Windows构建。应付还是有点吃力。尤其是在Mac和Windows两种无法虚拟化的场景,大量的机器分组,有点维护不动。现状大概长这样:

image.png

由于构建逻辑基本都是在构建团队维护,SCM和构建脚本中的代码逻辑也处于一个非常混乱的状态,基本就是大量的if else,伪代码大概长这样:

if (framework == "sofa") {buildCmd = "mvn clean package"if (app == "special") {buildCmd = "mvn clean package -Ptest=true"}
} else if (framework == "android") {buildCmd = "gradle clean assembleRelease"
} else if (framework == "jar") {buildCmd = "mvn clean install && mvn deploy"
} else if (xxx) {buildCmd = "xxx"
}

这个阶段在面对一些个性化的构建需求其实有点力不从心,需求千奇百怪:“我要加个额外的参数”,“我要更多的CPU”,“我需要用Mac来跑构建”,“我需要用某某软件的某某版本”。

当前阶段是没法继续支撑蚂蚁未来的业务发展的,在加上当前底下已经有非常多的资源(linux,windows,Mac,K8S)管理困难。

所以未来的构建平台,至少是可以做到下面两点:

  1. 构建可描述,逻辑回归业务方。
  2. 构建资源(机器)动态插拔,任意切换。

构建可描述

所有的构建逻辑是透明的,可配置化,可代码化,可描述内容包括:

  • 构建机器类型
  • 构建所需资源大小
  • 构建所需环境软件
  • 构建执行逻辑
  • 构建结果产物

构建资源动态插拔,任意切换

这里最关键的点是去掉大量分组维护带来的难点,让资源之间可以共用,互相流动。同时可以实现资源之间的任意切换,降级,保障构建服务的高可用(比如K8s资源降低到物理机构建)。

新的框架大概长下面这样:

image.png

业务使用方只要定义好buildspec.yaml文件,就可以实现任何个性化的构建需求。
底下执行构建的资源可以是K8S,可以是jenkins,可以是物理机,whatever,构建资源描述好自己支持的类型入场即可。

buildspec.yaml大概长下面这样:

name: android-aar-build
params:- name: productLinedefault: alipay- name: sprintIddefault: ${SPRINT_ID}
resources:- name: code-repotype: giturl: https://code.alipay.com/xxxxxref: master
environment:type: LINUX_CONTAINERimage: reg.docker.alibaba-inc.com/alipay/aarbuild:latest
buildTasks:- name: Download configimage: python:3commands:- python --version- name: Install Dependencyimage: ruby:2.6commands:- echo "-------2 in ruby:2.6"ruby -v
artifacts:- name: pod-for-alipaytype: iot-signpath: xxxx.zip

四 构建的挑战

1 统一构建中台

目前还在持续的开发和演进中,作为服务蚂蚁全栈的构建服务,其稳定性,高可用,灵活性至关重要。尤其是极限生存能力。

2 云原生调度基础设施

面向K8s的CI/CD,让K8s的资源使用简单优雅。tekton的优雅升级,极简的调度方案,友好的接入成本。

3 极致的构建效率和体验

深度定制构建工具

  • Java研发:Maven,Gradle,并发构建,缓存构建,增量构建,甚至秒级构建。
  • 终端研发:秒级构建,快速本地部署验证。
  • 镜像构建:目前仍然需要30+s的构建时间,需要持续做下去,缓存的命中率,镜像加速,remote cache,除了构建提效,还可以帮助部署提效。

制品库升级

  • 颠覆现有不合理模式,比如因为Jar release覆盖导致的“黑科技”,提升研发体验和研发效率。
  • 软件制品身份追踪,深入可信研发。

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/513607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

这个云原生开发的痛点你遇到了吗?

简介: 上云从来都不是一片坦途,在此过程中我们总会遇到一些困难和挑战,得益于云原生技术的日益成熟,这些问题一定会有相应的解法。 作者:纳海 背景 在云原生时代,国内外众多云厂商释放出强大的技术红利…

mysql安装pymyaql_python安装mysql的依赖包mysql-python操作

一般情况下,使用pip命令安装即可:[rootdthost27 ~]# pip install mysql-python但是在实际工作环境中,往往会安装失败,这是因为系统缺少mysql的相关依赖组件。所以必须先安装mysql-devel类的包,而且必须要对应好mysql客…

「技术人生」专题第1篇:什么是技术一号位?

前言 什么是技术一号位、有哪些关注点、怎么做技术一号位? 做了研发团队的技术 leader 以后,要处理的事情非常多,如果对自己扮演的角色没有一个清晰的认知,就会出现该做的事情没有做,不该做的事情投入了过多的精力&…

服务器之后加码存储,浪潮信息重磅发布新一代 G6 存储平台

作者 | 宋慧 出品 | CSDN云计算 提到浪潮,业界首先想到的是浪潮信息服务器占有的优势和市场份额。不过,其实浪潮在存储领域也持续深耕和发力中。据国际分析机构 Gartner 报告显示,2021 年第一季度,浪潮存储在全闪存存储、分布式存…

技术干货 | 轻松两步完成向 mPaaS 小程序传递启动参数

简介: 以传递 name 和 pwd 参数为例,分别介绍此场景在 Android 小程序和 iOS 小程序中的实现过程。 前言 在部分场景下,需要向小程序的默认接收页(pages/index/index)传递参数。 本文将以传递 name 和 pwd 参数为例&…

腾讯安全发布安全托管服务MSS,推动网络安全建设向服务驱动转变

近年来,随着黑产组织逐渐规模化、产业化,网络攻击态势愈发严峻;同时,由于DevOps、云原生等新技术的落地,以及IT架构的变化,企业研发和运营的模型随之改变,风险应对策略也越发复杂,越…

深入解读:获得 2021 Forrester 全球云数仓卓越表现者的阿里云数据仓库

简介: 阿里云在最新发布的 The Forrester Wave™: Cloud Data Warehouse, Q1 2021 全球云数据仓库技术评比中进入卓越表现者象限,成为国内唯一入选厂商。本文针对 Forrester 的报告,结合阿里云的以 MaxCompute 为核心的云数仓产品&#xff0c…

Azkaban业务流程如何转化为DataWorks业务流程

简介: 用户在迁移上云的时候,需要将云下的的Azkaban任务迁移上云,之前通过用户在DataWroks一步步创建对应的业务流程,其转化难度和转化时间都是一定的成本和时间,但如何能做到省时省力的方式迁移,为此本文提供了使用迁…

深度 | 数据湖分析算力隔离技术剖析

简介: 随着越来越多的企业开始做数据湖分析,数据量的持续增加,数据分析需求也会越来越多,在一个共享的数据湖分析引擎,如何防止多租户之间的查询相互影响是一个很通用的问题,本文以阿里云DLA Presto为例&am…

mfc链表中的数据如何排序输出_java程序员面试中最容易被问到的18个算法题(附答案!)...

算法是比较复杂又基础的学科,每个学编程的人都会学习大量的算法。而根据统计,以下这18个问题是面试中最容易遇到的,本文给出了一些基本答案,供算法方向工程师或对此感兴趣的程序员参考。1)请简单解释算法是什么&#x…

深度解析PolarDB数据库并行查询技术

简介: 随着数据规模的不断扩大,用户SQL的执行时间越来越长,这不仅对数据库的优化能力提出更高的要求,并且对数据库的执行模式也提出了新的挑战。本文将介绍基于代价进行并行优化、并行执行的云数据库的并行查询引擎的关键问题和核…

万物互联、应用现代化、云原生新范式,华为云为数字化转型提供最优解

10月27日,华为云TechWave全球技术峰会(应用现代化)在广州举办。华为云发布“云原生2.0”新范式,并分享应用现代化、万物互联等最新理念及产品进展。 华为云CTO张宇昕发表主题演讲 华为云CTO张宇昕表示:“云原生新范式…

动态游标for循环_【【动图算法】(动态规划篇):最长回文子串

本周继续做一道动态规划类型的题目,该题是阿里一面的一道算法题。【动图算法】(动态规划篇):最长回文子串leetcode 5 题:最长回文子串https://leetcode-cn.com/problems/longest-palindromic-substring/给定一个字符串 s,找到 s 中…

企业上云如何对SLS日志审计服务进行权限控制

简介: 日志审计是信息安全审计功能的核心部分,是企业信息系统安全风险管控的重要组成部分。SLS的日志审计服务针对阿里云的多种云产品(Actiontrail、OSS、SLB、RDS、PolarDB、SAS、WAF等)提供了一站式的日志收集、存储、查询、可视…

分区取模分库分表策略:多表事务分库内闭环解决方案

简介: 当表数据超过一定量级,就需要通过分表来解决单表的性能瓶颈问题;当数据库负载超过一定水平线,就需要通过分库来解决单库的连接数、性能负载的瓶颈问题。本文将阐述在不同情况下,让不同数量级表,在同一…

漫画:什么是“贪心算法”?如何求解“部分背包问题”?

作者 | 小灰来源 | 程序员小灰————— 第二天 —————————————————. . . . . . . .我们回到刚才的题目当中,假设背包的容量是10,有5个商品可供选择,每个商品的价值和重量如图所示:让我们来计算一下每件物品的…

高德 Serverless 平台建设及实践

简介: 高德为什么要搞 Serverless/Faas?是如何做 Serverless/Faas 的?技术方案是什么样的?目前进展怎么样?后续又有哪些计划?本文将和大家做一个简单的分享。 作者 | 邓学祥(祥翼) 来…

谷歌自研 Tensor 芯片,8核CPU,20核GPU……

作者 | 禾木木 出品 | CSDN云计算(ID:CSDNcloud) 10 月 20 日,谷歌在发布会上推出了全新 Pixel 6 和 Pixel 6 Pro 手机。虽然在推出之前,就已经知晓了外观,该说不说这款手机还是很吸引人的。 在这些变化…

云厂商下一块必争之地就是它了!

简介: 继容器编排、AI 工程化之后,全球顶级云厂商都瞄准了这块无人区。 作者 | 太浪 继容器编排、AI 工程化之后,全球顶级云厂商都瞄准了这块无人区。 1 回顾云计算十几年的历史,或者也可以视其为一部“为开发者服务简史”。 …

shell 如何调用多个脚本

简介 这篇文章主要描述如何通过主脚本去调用其他脚本中的方法,调用的过程中可能出现哪些坑,如何避免。 目录 1. 主脚本调用其他脚本的方法 1.1. bash方法 1.2. source方法 2. 避坑技巧 2.1. 路径配置无效 2.2. source变量冲突 3. 总结 1. 主脚本调…