前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >TAP 中的云原生构建服务

TAP 中的云原生构建服务

作者头像
Henry Zhang
发布于 2023-04-04 00:40:56
发布于 2023-04-04 00:40:56
68600
代码可运行
举报
文章被收录于专栏:亨利笔记亨利笔记
运行总次数:0
代码可运行

题图摄于美国大峡谷

本篇转发TAP系列文章之五,TAP云原生构建服务。

1

  背景  

通常的应用开发过程,是由开发人员使用某种计算机语言,比如 Java,开发特定项目然后提交到代码仓库。紧接着,源代码会被编译成二进制代码,被放置于特定的环境中运行,比如 Java 运行时或者 Web Server 等。随着容器以及容器编排技术的发展和成熟,越来越多的应用将从传统的虚拟机部署方式改为容器部署模式。

这就增加了一个关键的步骤:把应用打包成容器镜像,也称为应用容器化。

那么这个步骤还是由开发人员完成吗?开发人员的内心 os:我难道不应该专注于写业务逻辑吗?这个打包也要由我来完成?好吧,但是打包写 Dockerfile 我没有经验啊!要怎么避开里面的陷阱呢?以后源代码或者基础镜像更新了,还要由我来维护吗?

带着这些疑问,我们来仔细看看应用容器化的具体过程是怎么样的吧。

1

  从源代码到容器镜像  

当开发人员完成了一个应用项目并提交代码库之后,为了让代码能在容器环境中运行,需要把源代码转换成符合 OCI 标准的容器镜像,这个过程称为构建(build)。构建过程通常分为两个子步骤,第一步是将源代码编译成二进制文件,第二步是加上基础操作系统和相关依赖(比如 Java 运行时)合并成标准容器镜像。

第一步的编译取决于应用项目所采用的语言和框架,第二步常规的方法则是以撰写 Dockerfile 以及使用 docker build 来完成的。以使用 Spring 框架开发的项目为例,我们可以看到常规的构建过程是这样的:

·  首先,将源代码下载到本地,使用 Maven 命令对 Spring 项目进行 Java 编译:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
% mvn -Dmaven.test.skip=true package       [INFO] Scanning for projects...[INFO] [INFO] --------------------< io.buildpacks.example:sample >--------------------[INFO] Building sample 0.0.1-SNAPSHOT[INFO] --------------------------------[ jar ]---------------------------------[INFO] 。。。[INFO] [INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ sample ---[INFO] Building jar: /Users/mingjiex/git/samples/apps/java-maven/target/sample-0.0.1-SNAPSHOT.jar[INFO] [INFO] --- spring-boot-maven-plugin:2.1.18.RELEASE:repackage (repackage) @ sample ---[INFO] Replacing main artifact with repackaged archive[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time:  1.671 s[INFO] ------------------------------------------------------------------------

在编译过程中会自动下载大量的 Java 依赖包,如果没有编译错误,那么最终会在 target 目录下生成一个二进制可执行的 sample-0.0.1-SNAPSHOT.jar 包。

·  然后,撰写 Dockerfile 文件,声明构建的步骤和参数,样本文件如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
FROM openjdk:8-jre              ADD ./target/sample-0.0.1-SNAPSHOT.jar /               ENTRYPOINT ["java"]               CMD ["-jar", "/sample-0.0.1-SNAPSHOT.jar"]               EXPOSE 8080

其中 FROM 语句是引用的基础镜像名称,该镜像包含了底层的操作系统和依赖的 Java 运行环境,将被从公共或者私有镜像库中下拉。

ADD 语句说明在需要加入的文件,ENTRYPOINT 和 CMD 语句构成了启动命令,EXPOSE 语句说明了暴漏的端口。

这是一个最简单的 Dockerfile 样例,实际的要复杂得多。由于容器镜像采用的是 Overlay 型的文件系统,Dockerfile 中的每一个步骤将在最终镜像中产生一个层级(layer),所以 Dockerfile 撰写的好坏决定着应用镜像的运行效率。

·  最后,执行 docker build 命令,打包完成后得到最终的应用镜像。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
% docker build .              [+] Building 4.5s (7/7) FINISHED                                                                                         => [internal] load build definition from Dockerfile                                                               0.0s => => transferring dockerfile: 37B                                                                                0.0s => [internal] load .dockerignore                                                                                  0.0s => => transferring context: 2B                                                                                    0.0s => [internal] load metadata for docker.io/library/openjdk:8-jre                                                   4.4s => [internal] load build context                                                                                  0.0s => => transferring context: 82B                                                                                   0.0s => [1/2] FROM docker.io/library/openjdk:8-jre@sha256:59c47099aed504b2987fb5eea4376f96cf0f53d2c9081c30fd6a554c7a6  0.0s => CACHED [2/2] ADD ./target/sample-0.0.1-SNAPSHOT.jar /                                                          0.0s => exporting to image                                                                                             0.0s => => exporting layers                                                                                            0.0s => => writing image sha256:8335af64e29a7e69a047e424863ef3706349d5c5d325ff4f84447fa21a9fc496

1

  问题  

我们发现,在上述常规使用 docker build 的构建过程会存在一些问题,包括但不限于:

1.  需要为每种不同类别的项目准备合适的编译环境。

2.  不同的人员会撰写不同风格的 Dockerfile,一致性难以保证。

3.  撰写 Dockerfile 过于自由,可能会引入安全漏洞,包括不安全的基础镜像。

4.  如果要对安全漏洞进行修复,则需要更新 Dockerfile 为引用最新的基础镜像。

5.  需要为每个项目单独写一个 Dockerfile,在微服务架构中可能会有以百计的项目数,维护困难。

6.  Dockerfile 如果写的不够优化,那么最终产生的层级会很多,容器的运行效率也会打折扣。

·······

所以我们需要一种更为便捷,安全而且易维护的构建方法来避免以上的各种问题。

1

  Tanzu 构建服务  

基于云原生构建开源项目 Cloud Native Buildpacks(CNB),Tanzu 构建服务(以下简称 TBS)将为您解决以上提到的各种问题。开发人员将不再需要撰写 Dockerfile,而只需要使用一个简单的命令,就能把各种类型的源代码项目打包成最终的应用镜像。

而 Tanzu 构建服务,已经集成在 Tanzu Application Platform 的平台里,作为一个关键的企业级特性提供给用户来实现构建服务。

我们来看一个例子,还是使用上面的样例 Spring 项目。在下面使用的命令行里,kp 是Tanzu 构建服务的命令行工具,--git 参数指明源代码仓库地址,--git-revision 参数指明 git 分支名称,--sub-path 参数指明源代码子目录,--tag 参数指明最终应用镜像的推送仓库地址:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
% kp image create my-image --tag registry.tanzu.online:5000/tbs/test-app --git http://124.222.5.35:8888/mingjiex/samples.git --git-revision master --sub-path ./apps/java-maven --wait      Creating Image Resource...Image Resource "my-image" created===> PREPAREBuild reason(s): CONFIGCONFIG:resources: {}- source: {}+ source:+   git:+     revision: 1bf16cdcce9454d4922f20000efa1650c195b53b+     url: http://124.222.5.35:8888/mingjiex/samples.git+   subPath: ./apps/java-mavenLoading secret for "registry.tanzu.online:5000" from secret "my-registry-creds" at location "/var/build-secrets/my-registry-creds"Cloning "http://124.222.5.35:8888/mingjiex/samples.git" @ "1bf16cdcce9454d4922f20000efa1650c195b53b"...Successfully cloned "http://124.222.5.35:8888/mingjiex/samples.git" @ "1bf16cdcce9454d4922f20000efa1650c195b53b" in path "/workspace"===> ANALYZEPrevious image with name "registry.tanzu.online:5000/tbs/test-app" not found===> DETECT7 of 34 buildpacks participatingpaketo-buildpacks/ca-certificates   2.4.2paketo-buildpacks/bellsoft-liberica 8.9.0paketo-buildpacks/maven             5.7.0paketo-buildpacks/executable-jar    5.3.1paketo-buildpacks/apache-tomcat     6.4.0paketo-buildpacks/dist-zip          4.3.0paketo-buildpacks/spring-boot       4.7.0。。。。。。。。。Paketo Executable JAR Buildpack 5.3.1  https://github.com/paketo-buildpacks/executable-jar  Class Path: Contributing to layer    Writing env/CLASSPATH.delim    Writing env/CLASSPATH.prepend  Process types:    executable-jar: java org.springframework.boot.loader.JarLauncher (direct)    task:           java org.springframework.boot.loader.JarLauncher (direct)    web:            java org.springframework.boot.loader.JarLauncher (direct)          Paketo Spring Boot Buildpack 4.7.0  https://github.com/paketo-buildpacks/spring-boot  Launch Helper: Contributing to layer    Creating /layers/paketo-buildpacks_spring-boot/helper/exec.d/spring-cloud-bindings  Spring Cloud Bindings 1.8.0: Contributing to layer    Reusing cached download from buildpack    Copying to /layers/paketo-buildpacks_spring-boot/spring-cloud-bindings  Web Application Type: Contributing to layer    Servlet web application detected    Writing env.launch/BPL_JVM_THREAD_COUNT.default

TBS 会下载源代码,自动识别代码项目的类型而采用合适的编译打包工具,并编译打包成容器镜像,最终推送入指定的镜像仓库。

那么 TBS 究竟是如何完成这系列构建步骤的呢?我们来看一下 TBS 的组件。

TBS 依赖于几类关键资源:

·  ClusterStore:是云原生构建包的仓库,基于开源社区项目( Cloud Native    Buildpacks,CNB)。

·  ClusterStack:是用于构建和运行的操作系统镜像,需要不断更新以修复安全漏洞。

·  ClusterBuilder:是 ClusterStore 和      ClusterStack的组合所形成的构建器。

TBS 发布版自带了这些资源,以供客户开箱即用。如果客户有特殊需求,则可以根据要求定制。使用 TBS 的命令行工具 kp 查看可用资源,这些资源需要在准备就绪(Ready=True)的状态:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
% kp clusterstore list  NAME       READYdefault    True
% kp clusterstack list  NAME       READY    IDbase       True     io.buildpacks.stacks.bionicdefault    True     io.buildpacks.stacks.bionicfull       True     io.buildpacks.stacks.bionictiny       True     io.paketo.stacks.tiny
% kp clusterbuilder listNAME       READY    STACK                          IMAGEbase       true     io.buildpacks.stacks.bionic    registry.tanzu.online:5000/tbs/build-service:clusterbuilder-base@sha256:f7600c5e5864fa14bc1a6ba31fdd932cb2cec128d3d42cf0537f7d29e63c09d0default    true     io.buildpacks.stacks.bionic    registry.tanzu.online:5000/tbs/build-service:clusterbuilder-default@sha256:f7600c5e5864fa14bc1a6ba31fdd932cb2cec128d3d42cf0537f7d29e63c09d0full       true     io.buildpacks.stacks.bionic    registry.tanzu.online:5000/tbs/build-service:clusterbuilder-full@sha256:bb9b938e5534fe06279bfdeafb351d1c0466af50c2082495eeed258a7cb580f7tiny       true     io.paketo.stacks.tiny          registry.tanzu.online:5000/tbs/build-service:clusterbuilder-tiny@sha256:0c8c05b28fb57e69c0fe7c821d22634dc9fe42cd5368a02dc7f619560e44a69a

有了可用的构建器,就可以如同一开始使用的样例项目,使用 kp image create 命令创建 Image Resource,对源代码执行构建。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
% kp image create my-image --tag registry.tanzu.online:5000/tbs/test-app --githttp://124.222.5.35:8888/mingjiex/samples.git --git-revision master --sub-path ./apps/java-maven --wait

查看 Image Source 列表,后续可以执行更改、删除操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mingjiex@mingjiex-a01 java-maven % kp image listNAME        READY    LATEST REASON    LATEST IMAGE                            NAMESPACEmy-image    True     CONFIG           registry.tanzu.online:5000/tbs/test-app@sha256:5fabc1e1f968f5ad09566ce1cf74a28a67d65815b7e6518604160daa8abcd86a    default

当 Image Resource 被创建后,如果源代码有新的提交,或者基础镜像发生更新,或者 Image Resource 参数发生变化的时候(各种 REASON),新的构建任务将会被触发。每次构建都会产生一个 build 号,成功的构建会产生新的应用镜像并推送到应用镜像仓库。我们可以使用 kp build 命令查看每次 build 生成的镜像:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
% kp build listBUILD    STATUS     BUILT IMAGE                                                REASON    IMAGE RESOURCE1        SUCCESS    registry.tanzu.online:5000/tbs/test-app@sha256:0b660ee0af25b0bba80a76b31d82537eafd649c15bcb0ff08b0c06f8f6d40317    CONFIG    my-image2        SUCCESS    registry.tanzu.online:5000/tbs/test-app@sha256:72a19a7c37158a8fc56da7c4a36cc78bd33336a91d0b220cef17a7282d167eef    COMMIT    my-image3        SUCCESS    registry.tanzu.online:5000/tbs/test-app@sha256:5fabc1e1f968f5ad09566ce1cf74a28a67d65815b7e6518604160daa8abcd86a    CONFIG    my-image

为了达到优化目的,还可以对 Image Resource 施加特定参数来干预构建过程,比如指定构建器,改变缺省的 Java 版本,创建 cache 以加速后续的构建,等等。这些需要您在实践中去体会了。

1

  Tanzu 构建服务和 CI/CD 集成

Tanzu 构建服务和持续集成/持续交付(CI/CD)工具非常容易集成。通过 CI/CD 工具设置 Image Resource,然后触发 TBS 对提交入代码库的源代码项目执行构建服务,最后推入容器镜像仓库。

通常的集成方式如下图:

TBS 包含在 Tanzu Application Platform(简称 TAP )的发行版内,而且已经作为预制件集成进了 TAP 的软件供应链 Choreograph 里面,成为了开箱即用的构建工具。如下图所示,Tanzu 构建服务是 TAP  软件供应链的第一步,而和后续的安全扫描,部署,运行等等连接在一起组成完整的应用安全运维过程:

1

Tanzu 构建服务之价值总结

对于试图在商业环境中构建和部署容器的开发人员和运维人员来说,构建容器镜像并通过所需的依赖关系(例如运行库/二进制文件和基本操作系统镜像)对其进行修补是一件困难的事情。在大型企业环境中,挑战尤为严峻,在这种环境中,许多开发人员会构建各种应用,而这些应用必须严格遵守安全性和审核政策。

由于 IT 运维人员需要全面重新设计他们的系统以对容器的维护进行管理,因此,从基于虚拟机或基于 PaaS 的部署过程迁移到 Kubernetes 往往十分复杂。

Tanzu 构建服务在 Kubernetes 的固有对象之上添加了抽象层,以提高企业开发人员和 IT 运维人员的工作效率。客户通过持续集成/持续交付 (CI/CD) 系统使构建过程自动化,并可从 Tanzu Network 获取最新的堆栈和生成包版本。

VMware 旨在遵循行业最佳实践,及时提供 CVE 补丁,保障客户系统的安全。对于开发人员而言,这减轻了通过新的依赖关系来更新容器所造成的负担。对于运维人员而言,它可以集中控制所有容器的依赖关系,从而更好地满足安全性、合规性和审核需求。


要想了解云原生、机器学习区块链等技术原理,请立即长按以下二维码,关注本公众号亨利笔记 ( henglibiji ),以免错过更新。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 亨利笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Python中os与sys两模块的区别 原
os: This module provides a portable way of using operating system dependent functionality.
晓歌
2018/08/15
5030
python中的sys模块函数
Sys模块函数之多,我只能选取自己认为比较实用的一些函数列在此处。借马云找员工的说法,”找最合适的而不是最天才的”,这句话,我个人觉得在很多方面都能适应,学习也不在话下。Sys模块功能的确很多,但我们应该将重点放在那些功能才是最适合我们的,为此,我列的这些函数,就是我认为比较适合我以后开发的函数。 (1)sys.argv 很多人会想,我如何给我的程序在外部传递参数呢?这个,就可以实现。如: Tesy.py Import sys Print sys.argv[number] 一般情况下,number为0是这个脚本的名字,1,2…则为命令行下传递的参数.如: Test.py脚本内容: import sys
全栈程序员站长
2022/09/09
9740
Python 代码片段总结
生成的pyc可以跨平台使用,但是只能这样用python xxx.pyc,而不能使用./xxx.pyc执行,因为缺少了shebang的支持,不过貌似Binfmt_misc可以解决这个问题,ubuntu下apt-get install binfmt-support可以直接安装。
老高的技术博客
2022/12/28
6230
Python 代码片段总结
python模块—command and
  返回结果是一个tuple元组,第一个值为接收状态码,int类型,0表示正常,非0表示异常;第二个值为字符串,即shell命令执行的结果
py3study
2020/01/08
4980
Python基础教程(四)
上面是sys模块所有语法,我们看看就够了,了解下sys.argv和sys.path就足够了
润森
2020/04/08
7500
Python基础教程(四)
Python中标准输入(stdin)、标准输出(stdout)、标准错误(stdout)的用法
Python 3.x 中 input() 函数可以实现提示输入,python 2.x 中要使用 raw_input(),例如:
Python学习者
2023/08/01
4670
Python重定向标准输入、标准输出和标
UNIX用户已经对标准输入、标准输出和标准错误的概念熟悉了。这一节是为其它不熟悉的人准备的。
py3study
2020/01/09
4.1K0
python 守护进程(daemon)
通常,我们执行服务端程序的时候都会通过终端连接到服务器,成功连接后会加载shell环境,终端盒shell都是进程,shell进程是终端进程的子进程,通过ps命令可以很容易的查看到,在这个shell环境下一开始执行的程序都是shell进程的子进程,自然会受到shell进程的影响,在程序里fork子进程后,父进程退出,对于shell进程来说,这个父进程就算执行完毕,而产生的子进程会被init进程接管,从而也就脱离了终端控制。
py3study
2020/01/10
1.1K0
python sys模块的常见用法汇总
python的内置模块sys,提供了系统相关的一些变量和函数,在实际开发中,常见的有以下几种用法
生信修炼手册
2020/05/25
1.9K0
python标准输出 标准错误 重定向
2、ls > log 2>&1  标准输出和标准错误都输出到log,&> log也可以,但是会有版本限制
py3study
2020/01/08
2.8K0
22. Python 模块2
日志是我们排查问题的关键利器,写好日志记录,当我们发生问题时,可以快速定位代码范围进行修改。
py3study
2020/01/15
5790
Python 学习笔记 (8)—— sy
主要介绍用的比较多的sys的模块命令包括:sys.argv,sys.platform,sys.getdefaultencoding,sys.setdefaultencoding(),sys.getfilesystemencoding(),sys.exit(n),sys.path,sys.modules.keys(),sys.stdin,sys.stdout,sys.stderr 等。
py3study
2020/01/08
8930
Python unittest 测试输入(input)和输出(print)
测试输入输出的解决方法是: 将标准输入输出定向到一个StringIO类(python3是 io.StringIO)。
饶文津
2020/05/31
1.8K0
python3模块: sys
一.简介   sys模块用于提供对python解释器的相关操作。 二.常用函数 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.modules 返回系统导入的模块字段,key是模块名,value是模块 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sys.maxint 最大的Int值 sys.path 返回模块的搜索路径,初始化时使用PYTHO
程序员同行者
2018/06/22
5990
python sys.stdout
下面介绍几个我们经常不经意就会用到的sys包的命令 stdout/stderr/stdin
kirin
2020/10/27
9870
python中的print与sys.stdout
在python中,print语句实现打印,从技术角度来说,这是把一个或多个对象转换为其文本表达式形式,然后发送给标准输出流或者类似的文件流,更详细的说,打印与文件和流的概念紧密相连。
tnt阿信
2020/08/05
2K0
python中的print与sys.stdout
Python守护进程daemon实现
守护进程是系统中生存期较长的一种进程,常常在系统引导装入时启动,在系统关闭时终止,没有控制终端,在后台运行。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。 在这里,我们在Linux2.6内核的centos中,ps -ef |awk '{print $1"\t "$2"\t "$3"\t  "$8}'看到:PPID=0的进程有两个,分别是PID=1的/sbin/init进程和PID=2的[kthreadd]进程。
py3study
2020/01/07
7.8K0
python - sys模块
   sys.argv           命令行参数List,第一个元素是程序本身路径   sys.modules.keys() 返回所有已经导入的模块列表    sys.exc_info()     获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息   sys.exit(n)        退出程序,正常退出时exit(0)   sys.hexversion     获取Python解释程序的版本值,16进制格式如:0x020403F0   sys.version        获取Python解释程序的版本信息   sys.maxint         最大的Int值   sys.maxunicode     最大的Unicode值   sys.modules        返回系统导入的模块字段,key是模块名,value是模块   sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值   sys.platform       返回操作系统平台名称   sys.stdout         标准输出   sys.stdin          标准输入   sys.stderr         错误输出   sys.exc_clear()    用来清除当前线程所出现的当前的或最近的错误信息   sys.exec_prefix    返回平台独立的python文件安装的位置   sys.byteorder      本地字节规则的指示器,big-endian平台的值是'big',little-endian平台的值是'little'   sys.copyright      记录python版权相关的东西   sys.api_version    解释器的C的API版本   sys.version_info   >>> sys.version_info   (2, 4, 3, 'final', 0) 'final'表示最终,也有'candidate'表示候选,表示版本级别,是否有后继的发行   sys.displayhook(value)      如果value非空,这个函数会把他输出到sys.stdout,并且将他保存进__builtin__._.指在python的交互式解释器里,'_'代表上次你输入得到的结果,hook是钩子的意思,将上次的结果钩过来   sys.getdefaultencoding()    返回当前你所用的默认的字符编码格式   sys.getfilesystemencoding() 返回将Unicode文件名转换成系统文件名的编码的名字   sys.setdefaultencoding(name)用来设置当前默认的字符编码,如果name和任何一个可用的编码都不匹配,抛出LookupError,这个函数只会被site模块的sitecustomize使用,一旦别site模块使用了,他会从sys模块移除   sys.builtin_module_names    Python解释器导入的模块列表   sys.executable              Python解释程序路径   sys.getwindowsversion()     获取Windows的版本   sys.stdin.readline()        从标准输入读一行,sys.stdout.write("a") 屏幕输出a
py3study
2020/01/14
7660
[Python]基本概念与操作1(针对Python2)
原文链接:http://blog.csdn.net/humanking7/article/details/45276831
祥知道
2020/03/10
3270
C++017-C++文件读写应用
在线练习: http://noi.openjudge.cn/ https://www.luogu.com.cn/
用户2225445
2023/10/16
5120
C++017-C++文件读写应用
相关推荐
Python中os与sys两模块的区别 原
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档