【行云流水线实践】基于“OneBuild”方法对镜像进行快速装箱 | 京东云技术团队

在云原生领域,无论使用哪种编排调度平台,Kubernetes,DockerSwarm,OpenShift等,业务都需要基于镜像进行交付,我们在内部实践“Source-to-image”和链式构建,总而总结出“OneBuild”模式。

其核心思想是:一处构建,多处使用。

问题

一般,我们会使用类似Jenkins CI系统来构建镜像,以满足持续集成,持续开发,持续交付等场景。事实上,如果我们在某一方面能够提升效率或者解决镜像交付实践。

长期来看,将能够带来不少的成本收益,并且对于平台来讲,这种收益是一种可度量收益。假设我们在当前交付(git)分支中,需要fix或者feature已经release分支的,如何进行?如果在已经交付给用户的镜像中存在漏洞,需要批量交付,如何进行?为了解决这些问题,我们的团队必须重新构建镜像,并且找出基本镜像,构建过程有那些依赖关系。然后基于这些成熟的流程和规范进行快速交付。

解决方案

Docker build是大家比较常用的镜像构建方法,并且在构建中只需要声明自己的Dockerfile即可,就可以实现快速构建。但是这并不满足大型企业实践以及快速交付。

所以需要一套规范且能够直接生产的流程,帮助在云原生下进行快速交付。下面我们讲结合行云平台进行“OneBuild”方法的实践。

悬衡而知乎,没规而知圆。因此,我们在团队的流水线建立和改造的过程中,尤其注重标准化。

包括dockerfile的命名和设计,构建代码的设计。由此新项目加入时,我们只需复制,然后做小工作量的改造即可。

行云Build

行云是JDT生产效率的标准化产品,是一个比较成熟的产品。用于支撑内部研发,测试,交付的平台。

Build是行云中一个子系统,用于研发过程中的持续集成,持续测试,持续构建等任务。

团队日常开发语言主要是以golang为主,并且在上线或交付制品中,也以Docker镜像为主。并且由于大多数时间,我们必须在真实的K8S环境中运行。

所以稳定的构建平台,高效,快速的构建,对我们的日常开发和交付都是至关重要,在构建中往往需要构建多版本镜像。所以围绕行云流水线,主要就是发掘功能,适配改造。

Dockerfile标准化

接下来,我们设计的流程,将会使用上一级构建的产品,对下级镜像进行快速装箱。

Dockerfile命名


Dockerfile            # 标准版Dockerfile.kylinv10   # kylinv10 base 版本Dockerfile.oel22      # openeuler base 版本

下面我们继续看dockerfile中的细节。

首先是 Dockerfile


ARG ARCHARG BUILD_IMAGEARG BASE_IMAGEFROM ${BUILD_IMAGE} as builderARG ARCHENV GOPATH=/goCOPY go.mod go.modCOPY go.sum go.sumCOPY main.go main.goCOPY api/ api/COPY controllers/ controllers/COPY pkg/ pkg/COPY vendor/ vendor/# BuildRUN CGO_ENABLED=0 GO111MODULE=on GOOS=linux GOARCH=${ARCH} go build --mod=vendor -a -o manager main.goARG ARCHARG BASE_IMAGEFROM ${BASE_IMAGE}ENV PIP3_SOURCE=https://pypi.tuna.tsinghua.edu.cn/simpleENV DEFAULT_FORKS=50ENV DEFAULT_TIMEOUT=600ENV DEFAULT_GATHER_TIMEOUT=600ENV TZ=Asia/ShanghaiENV PYTHONWARNINGS=ignore::UserWarningWORKDIR /COPY --from=builder /manager .COPY inventory/ inventory/COPY roles/ roles/COPY etcd-restore.yml etcd-restore.ymlCOPY facts.yml facts.ymlCOPY requirements.txt requirements.txtCOPY inventory.tmpl.ini inventory.tmpl.iniCOPY ansible.cfg ansible.cfgRUN yum -y install kde-l10n-Chinese && \yum -y reinstall glibc-common && \localedef -c -f UTF-8 -i zh_CN zh_CN.UFT-8 && \echo 'LANG="zh_CN.UTF-8"' > /etc/locale.conf && \source /etc/locale.conf && \yum clean allENV LANG=zh_CN.UTF-8ENV LC_ALL=zh_CN.UTF-8RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \echo $TZ > /etc/timezone && \yum install python3 python3-devel sshpass openssh-clients -y && \yum clean all && \/usr/bin/python3 -m pip --no-cache-dir install pip==21.3.1 -U -i $PIP3_SOURCE && \/usr/bin/python3 -m pip --no-cache-dir install -r requirements.txt -i $PIP3_SOURCEUSER rootENTRYPOINT ["/manager"]

上述dockerfile中,分为两个阶段构建,第一个阶段builder构建出需要的二进制。这与正常的dockerfile相同。

唯一不同的是,我们讲构建镜像和base镜像进行了参数化,这也使得当变更构建镜像和base镜像,我们只需要在构建时控制参数即可。

再看dockerfile.kylinv10


ARG BASE_IMAGEFROM ${BASE_IMAGE}ENV PIP3_SOURCE=https://pypi.tuna.tsinghua.edu.cn/simpleENV DEFAULT_FORKS=50ENV LANG=en_US.UTF-8ENV DEFAULT_TIMEOUT=600ENV DEFAULT_GATHER_TIMEOUT=600ENV TZ=Asia/ShanghaiENV PYTHONWARNINGS=ignore::UserWarningWORKDIR /COPY --from=jdos-etcd-restore-helper:latest /manager /COPY inventory/ inventory/COPY roles/ roles/COPY etcd-restore.yml etcd-restore.ymlCOPY facts.yml facts.ymlCOPY requirements.txt requirements.txtCOPY inventory.tmpl.ini inventory.tmpl.iniCOPY ansible.cfg ansible.cfgRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \echo $TZ > /etc/timezone && \yum install python3 python3-devel python3-pip sshpass openssh-clients -y && \/usr/bin/python3 -m pip --no-cache-dir install pip==21.3.1 -U -i $PIP3_SOURCE && \/usr/bin/python3 -m pip --no-cache-dir install -r requirements.txt -i $PIP3_SOURCEUSER rootENTRYPOINT ["/manager"]

发现了什么?在dockerfile.kylinv10中少了builder这一步,COPY --from=jdos-etcd-restore-helper:latest 是从一个指定的临时镜像中直接做了拷贝。这就直接复用了第一步dockerfile中构建出的产物。效率提升比较明显。

在dockerfile设计中,COPY是可以从一个指定的镜像中,copy指定的文件的。

再看Dockerfile.oel22


ARG BASE_IMAGEFROM ${BASE_IMAGE}ENV PIP3_SOURCE=https://pypi.tuna.tsinghua.edu.cn/simpleENV DEFAULT_FORKS=50ENV LANG=en_US.UTF-8ENV DEFAULT_TIMEOUT=600ENV DEFAULT_GATHER_TIMEOUT=600ENV TZ=Asia/ShanghaiENV PYTHONWARNINGS=ignore::UserWarningWORKDIR /COPY --from=jdos-etcd-restore-helper:latest /manager /COPY inventory/ inventory/COPY roles/ roles/COPY etcd-restore.yml etcd-restore.ymlCOPY facts.yml facts.ymlCOPY requirements.txt requirements.txtCOPY inventory.tmpl.ini inventory.tmpl.iniCOPY ansible.cfg ansible.cfgRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \echo $TZ > /etc/timezone && \yum install python3 python3-devel python3-pip sshpass openssh-clients -y && \/usr/bin/python3 -m pip --no-cache-dir install pip==21.3.1 -U -i $PIP3_SOURCE && \/usr/bin/python3 -m pip --no-cache-dir install -r requirements.txt -i $PIP3_SOURCEUSER rootENTRYPOINT ["/manager"]

是不是与dockerfile.kylinv10的思路非常相似,事实上,这两个文件已经可以合并了(内部为了向后兼容,没有合并这两个文件)。

脚本标准化

还需要在行云流水线中将shell脚本进行固化,与dockerfile进行配合。


# 支持shell语言代码的多行输入cd  /sudo docker login -u $IMAGE_REPO_USER -p $IMAGE_REPO_PASSWD $(echo $IMAGE_REPO | awk -F '/' '{print $1}')git_commit=${output.Download_Code.GIT_LAST_COMMIT_SHA1}build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')image_tag="${env.GenerateNewVersion}-${git_commit:0:6}"echo "start build image - standard"new_image_repo="${IMAGE_REPO}"sudo docker build -t ${new_image_repo}:${image_tag} -f Dockerfile --build-arg ARCH="amd64" . sudo docker login -u $IMAGE_REPO_USER -p $IMAGE_REPO_PASSWD $(echo $IMAGE_REPO | awk -F '/' '{print $1}')sudo docker push ${new_image_repo}:${image_tag}echo "end to build image - standard"echo "amd64ImageName=${new_image_repo}:${image_tag}" > ./amd64_output# 重新命名一个新镜像,供下级dockerfile进行多阶段构建时直接copysudo docker tag ${new_image_repo}:${image_tag} jdos-etcd-restore-helper:latest# 条件性选择构建基于kylinv10OS的镜像if [[ -f Dockerfile.kylinv10 ]];thenecho "start build image - security - kylin base"new_image_repo="${IMAGE_REPO}-kylinv10-amd64"sudo docker build -t ${new_image_repo}:${image_tag} -f Dockerfile.kylinv10 --build-arg ARCH="amd64" . sudo docker login -u $IMAGE_REPO_USER -p $IMAGE_REPO_PASSWD $(echo $IMAGE_REPO | awk -F '/' '{print $1}')sudo docker push ${new_image_repo}:${image_tag}echo "end to build image - security - kylin base"echo "amd64KylinImageName=${new_image_repo}:${image_tag}" >> ./amd64_outputfi# 条件性选择构建基于欧拉OS的镜像if [[ -f Dockerfile.oel22 ]];thenecho "start build image - security - openeuler22 base"new_image_repo="${IMAGE_REPO}-openeuler22-amd64"sudo docker build -t ${new_image_repo}:${image_tag} -f Dockerfile.oel22 --build-arg ARCH="amd64" . sudo docker login -u $IMAGE_REPO_USER -p $IMAGE_REPO_PASSWD $(echo $IMAGE_REPO | awk -F '/' '{print $1}')sudo docker push ${new_image_repo}:${image_tag}echo "end to build image - security - openeuler22 base"echo "amd64Oel22ImageName=${new_image_repo}:${image_tag}" >> ./amd64_outputfi# 清理builder镜像,避免产生none垃圾镜像。sudo docker rmi jdos-etcd-restore-helper:latest --force

提升

基于以上,构建时间从21min缩短至7min,构建效率提升66%👊。我们总结出“OneBuild”方法:即构建一次,多处使用的思路。

标准化的shell与dockerfile进行配合,能够做到一次构建,多处使用。提升了构建效率。

讨论

上述完整介绍了多个镜像构建的流程和设计规范,也说明“OneBuild”可以进行快速构建的优点。所以OneBuild的对于中大型组织或者有快速交付需求的团队来讲,是非常有帮助的。

并且对效率的提升是可以看得见的。

作者:京东科技 王晓飞

来源:京东云开发者社区 转载请注明来源

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

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

相关文章

折纸达珠峰高度(forwhile循环、闭包函数循环)

对折0.1mm厚度的纸张多少次,高度可达珠峰高度8848180mm。 (本笔记适合熟悉循环和列表的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅…

搜维尔科技:Movella xsens助力国际足联,捕捉了一个90分钟的现场足球比赛

在塞维利亚6万人的拉卡图亚体育场的灯光下,安达路亚的两个球队开始了他们激烈的地方竞争的最新篇章。这也许是他们一生中最大的一场游戏,很快就会出现。开球后的一瞬间,咬着滑块的接球手飞了进来,对方的球员互相攻击对方的球。一个迟来的挑战赛点燃了触摸纸,两队互相平手,手臂伸…

【MATLAB】全网唯一的13种信号分解+FFT傅里叶频谱变换联合算法全家桶

有意向获取代码,请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有13种信号分解FFT傅里叶频谱变换联合算法,绝对不亏,知识付费是现今时代的趋势,而且都是我精心制作的教程,有问题可随时反馈~也可单独获取某一…

Idea去掉显示的测试覆盖率

一.启东时 误点击了 快捷键调出 【Ctrl 】【Alt】【F6】

【Java 进阶篇】Java Response 输出字符数据案例

在Java Web开发中,使用HTTP响应对象(Response)来向客户端发送数据是一项非常重要的任务。本篇博客将详细介绍如何使用Java中的Response对象来输出字符数据,并提供示例代码以帮助读者更好地理解和应用这一概念。不仅将讨论基础知识…

《Pytorch新手入门》第二节-动手搭建神经网络

《Pytorch新手入门》第二节-动手搭建神经网络 一、神经网络介绍二、使用torch.nn搭建神经网络2.1 定义网络2.2 torch.autograd.Variable2.3 损失函数与反向传播2.4 优化器torch.optim 三、实战-实现图像分类(CIFAR-10数据集)3.1 CIFAR-10数据集加载与预处理3.2 定义网络结构3.3…

uniapp黑马优购

配置tabbar 使用 npm install escook/request-miniprogram 进行http请求 挂载到 uni.$http 上 uniapp小程序分包 访问的时候 携带分包目录 /subpkg/goods_detail/goods_detail git分支使用 # 创建并使用分支 git checkout -b home git commit # 推送到远程的home分支…

分类预测 | Matlab实现SSA-ELM麻雀优化算法优化极限学习机分类预测

分类预测 | Matlab实现SSA-ELM麻雀优化算法优化极限学习机分类预测 目录 分类预测 | Matlab实现SSA-ELM麻雀优化算法优化极限学习机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现SSA-ELM麻雀优化算法优化极限学习机分类预测(Matlab完整…

基于Selenium+Python的web自动化测试框架详解

一、什么是Selenium? Selenium是一个基于浏览器的自动化测试工具,它提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。Selenium主要包括三部分:Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE:Firefo…

在excel中如何打出上标、下标

例如,想把A2的2变为下标。 在单元中输入内容: 选中2: 右键单击,然后点击“设置单元格格式”: 在特殊效果的下面勾选“下标”,然后点击下面的“确定”按钮: 就将2变为下标了:…

MySQL 基础学习笔记(一)

目录 1 SQL简介2 MySQL基本语法2.1 语法规则2.2 数据类型 3 DDL3.1 操作数据库3.2 操作表 4 DML4.1 添加数据4.2 修改数据4.3 删除数据 5 DQL5.1 基础查询5.2 条件查询5.3 排序查询5.4 聚合查询5.5 分组查询5.6 分页查询 1 SQL简介 SQL :Structured Query Language&…

【webrtc】 对视频质量的码率控制的测试与探索

目录 环境设置 transport-cc goog-remb (webrtc中的两种码率算法) 修改成remb算法 测试 效果 后续 可参考工程 环境设置 要到meshx上操作 telnet 112 然后执行factory_env show |grep meshx_ip 之后telnet meshx_ip 用户名admin 密码****.119 执行一下r…